1

を拡張してエラー処理を実装する Spring 3.2 MVC REST サービスがありますResponseEntityExceptionHandler。これは、標準の Spring 例外を処理し、クライアントからの要求に応じて、適切な HTTP ステータスと XML または JSON のカスタム「エラー」 ResponseEntity オブジェクトで応答します。これは、を除くすべての標準例外でうまく機能しますHttpMediaTypeNotAcceptableException

この例外で私が抱えている問題は、最初にスローされた理由は、応答のメディア タイプ (application/xml、application/json など) を要求から判断できなかったためです。この例外に対して「エラー」ResponseEntityオブジェクトを返そうとすると、応答メディアタイプを特定できなかったため失敗します(これが、この例外が最初に処理されている理由です)...そして基本的に別のものがHttpMediaTypeNotAcceptableExceptionスローされます私のExceptionHandler。

HttpMediaTypeNotAcceptableException処理時に有効な応答メディア タイプを指定する方法を理解する必要があるため、ResponseEntity はそれをクライアントに送信します。要求されたメディア タイプを特定できないため、これがおそらく私のサービスのデフォルト (application/xml) になります。

何か案は?

4

2 に答える 2

0

私は自分の開発で同じ問題を見つけたので、この問題を解決するには、あなたのすべてのメソッドの注釈付きのエラーメッセージのレスポンスボディで指定する必要があり@ExceptionHandlerます:controllerAdvicercontentType

例:受信ヘッダーAccept: application/pdfですが、アプリケーションはapplication/json.

特定の体の反応を管理するためのGlobalExceptionHandler クラス:@ControllerAdvice

    package com.obs.sfu.exception;

import javax.validation.ConstraintViolationException;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import org.springframework.ws.soap.client.SoapFaultClientException;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    private static final String SIZE_MUST_BE_FROM_1_TO_15_CHARACTERS = "Size must be from 1 to 15 characters";
    private static final int CODE_INTERNAL_SERVER_ERROR = 1;
    private static final String MESSAGE_INTERNAL_SERVER_ERROR = "Internal error";
    private static final String DESCRIPTION_INTERNAL_SERVER_ERROR = "Generic failure message";

    private static final int CODE_SERVICE_UNAVAILABLE = 5;
    private static final String MESSAGE_SERVICE_UNAVAILABLE = "The service is temporarily unavailable";
    private static final String DESCRIPTION_SERVICE_UNAVAILABLE = "The service can not handle the call.";

    private static final int CODE_UNSUPPORTED_MEDIA_TYPE = 68;
    private static final String MESSAGE_UNSUPPORTED_MEDIA_TYPE = "Unsupported Media Type";
    private static final String DESCRIPTION_UNSUPPORTED_MEDIA_TYPE = "The format of the posted body is not supported by the endpoint.";

    private static final int CODE_NOT_FOUND = 60;
    private static final String MESSAGE_NOT_FOUND = "Resource not found";
    private static final String DESCRIPTION_NOT_FOUND = "The Requested URI or the requested resource does not exist.";

    private static final int CODE_METHOD_NOT_ALLOWED = 61;
    private static final String MESSAGE_METHOD_NOT_ALLOWED = "Method not allowed";
    private static final String DESCRIPTION_METHOD_NOT_ALLOWED = "The URI does not support the requested method. The available methods should be set in the response header 'Allow'";

    private static final int CODE_NOT_ACCEPTABLE = 62;
    private static final String MESSAGE_NOT_ACCEPTABLE = "Not acceptable";
    private static final String DESCRIPTION_NOT_ACCEPTABLE = "The Accept incoming header does not match any available content-type.";

    private static final int CODE_CONSTRAINT_VIOLATION_FIELD = 20;
    private static final String MESSAGE_INVALID_BODY_FIELD = "Invalid Via field";

    private static final String HEADER_ALLOW = "Allow";
    private static final String HEADER_ALLOW_VALUE = "GET, OPTIONS";

    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(request.getContextPath(), MESSAGE_NOT_FOUND, DESCRIPTION_NOT_FOUND,
                CODE_NOT_FOUND);
        return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(errorDetails);
    }

    @Override
    protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(request.getContextPath(), MESSAGE_METHOD_NOT_ALLOWED,
                DESCRIPTION_METHOD_NOT_ALLOWED, CODE_METHOD_NOT_ALLOWED);
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set(HEADER_ALLOW, HEADER_ALLOW_VALUE);
        return ResponseEntity.status(status).headers(responseHeaders).contentType(MediaType.APPLICATION_JSON)
                .body(errorDetails);
    }

    @Override
    protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(HttpMediaTypeNotSupportedException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(request.getContextPath(), MESSAGE_UNSUPPORTED_MEDIA_TYPE,
                DESCRIPTION_UNSUPPORTED_MEDIA_TYPE, CODE_UNSUPPORTED_MEDIA_TYPE);
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.set("Accept", MediaType.APPLICATION_JSON_VALUE);
        return ResponseEntity.status(status).headers(responseHeaders).contentType(MediaType.APPLICATION_JSON)
                .body(errorDetails);
    }

    @Override
    protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(HttpMediaTypeNotAcceptableException ex,
            HttpHeaders headers, HttpStatus status, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(request.getContextPath(), MESSAGE_NOT_ACCEPTABLE,
                DESCRIPTION_NOT_ACCEPTABLE, CODE_NOT_ACCEPTABLE);
        return ResponseEntity.status(status).contentType(MediaType.APPLICATION_JSON).body(errorDetails);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(request.getContextPath(), MESSAGE_INVALID_BODY_FIELD,
                SIZE_MUST_BE_FROM_1_TO_15_CHARACTERS, CODE_CONSTRAINT_VIOLATION_FIELD);
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON).body(errorDetails);
    }

    @ExceptionHandler(SoapFaultClientException.class)
    public ResponseEntity<Object> handleSoapFaultClient(Exception ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(request.getContextPath(), MESSAGE_SERVICE_UNAVAILABLE,
                DESCRIPTION_SERVICE_UNAVAILABLE, CODE_SERVICE_UNAVAILABLE);
        return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).contentType(MediaType.APPLICATION_JSON)
                .body(errorDetails);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleGlobalException(Exception ex, WebRequest request) {
        ErrorDetails errorDetails = new ErrorDetails(request.getContextPath(), MESSAGE_INTERNAL_SERVER_ERROR,
                DESCRIPTION_INTERNAL_SERVER_ERROR, CODE_INTERNAL_SERVER_ERROR);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).contentType(MediaType.APPLICATION_JSON)
                .body(errorDetails);
    }
}

ファイルapplication.propertiesを管理するには、次のプロパティが必要ですNoHandlerFoundException( throwExceptionIfNoHandlerFound):

spring:
  mvc: 
    throw-exception-if-no-handler-found: true
    static-path-pattern: /swagger* # to available swagger-ui.html
于 2021-02-05T09:12:11.770 に答える
0

編集:この答えはかなり役に立ちません。以下のコメントを参照してください。ごめん。

この場合、とにかく通信がかなり混乱しているため、ステータス コードを に設定するだけで十分で400 - Bad Requestあり、クライアントがサーバーに認識されていない形式で機械可読な応答を実際に期待しないことを願っています。応答本文が送信された場合、おそらく使用しますContent-Type: text/plain-それはクライアントには役に立たないでしょうが、おそらく状況をデバッグしている人には役に立たないでしょう;)まあ、またはあなたの気分に合ったものなら何でも。

更新:より適切な解決策は、マニュアルで説明されている方法を使用することです。at: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-customer-servlet-container-error-pageただし、認めざるを得ないそれが機能するかどうかは実際には試していません。

于 2013-02-07T22:48:00.690 に答える