1

我有一个 Spring 3.2 MVC REST 服务,它通过扩展ResponseEntityExceptionHandler. 这会处理标准的 Spring 异常,并将响应客户端请求的 XML 或 JSON 中的适当 HTTP 状态和自定义“错误”ResponseEntity 对象。这适用于除HttpMediaTypeNotAcceptableException.

我遇到的这个异常的问题是它首先抛出的原因是因为无法从请求中确定响应媒体类型(应用程序/xml、应用程序/json 等)。如果我尝试为此异常返回“错误”ResponseEntity 对象,它将失败,因为无法确定响应媒体类型(这就是首先处理此异常的原因)......并且基本上HttpMediaTypeNotAcceptableException从我的异常处理程序。

HttpMediaTypeNotAcceptableException在处理指定有效的响应媒体类型时,我需要找出一种方法,因此 ResponseEntity 将其发送给客户端。由于无法确定请求的媒体类型,这可能只是我的服务(应用程序/xml)的默认值

有任何想法吗?

4

2 回答 2

0

编辑:这个答案非常没用,请参阅下面的评论。对不起。

在这种情况下,无论如何通信都非常混乱,也许将状态代码设置为400 - Bad Request并希望客户端并不真正期望服务器不知道格式的机器可读答案就足够了。如果发送了响应正文,则可能使用Content-Type: text/plain- 这对客户端没有用,但可能是调试情况的人;)好吧,或者任何适合您心情的东西。

更新:更好的解决方案可能是使用手册中解释的方法;在: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 回答
0

我在我的开发中发现了同样的问题,所以要解决这个问题,你需要在你的所有方法中注释的错误消息的响应体@ExceptionHandlercontrollerAdvicer指定contentType

例如:您的接收标头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需要这些属性来管理NoHandlerFoundExceptionthrowExceptionIfNoHandlerFound):

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