Spring @ExceptionHandler 和 HttpMediaTypeNotAcceptableException

2022-09-02 21:45:10

我有一个带注释的类,其中有此方法:@ControllerAdvice

@ExceptionHandler(ResourceNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
@ResponseBody
public ExceptionInfo resourceNotFoundHandler(ResourceNotFoundException ex) {
    List<ErrorContent> errors = new ArrayList<>();
    errors.add(new ErrorContent(ExceptionsCodes.NOT_FOUND_CODE, null,
            "test"));
    return fillExceptionInfo(HttpStatus.NOT_FOUND, errors, ex);
}

这里是:fillExceptionInfo

public ExceptionInfo fillExceptionInfo(HttpStatus status, List<ErrorContent> errors, 
        Exception ex) {
    String msg = ex.getMessage();

    return new ExceptionInfo(status.toString(), errors, (msg != null && !msg.equals(""))
            ? ex.getMessage()
            : ExceptionUtils.getFullStackTrace(ex));
}

当 Web 客户端发送对某些 json 数据的请求时,找不到这些数据,此方法工作正常。但是,当服务器收到对映像的请求时,将抛出 a 而不是我的异常。我知道这是由于错误的内容类型而发生的,但是我该如何解决此问题?HttpMediaTypeNotAcceptableException

更新

我的目标是为json数据和文件提供这两种情况。ResourceNotFoundException

我得到的异常(所以它是从):AbstractMessageConverterMethodProcessor

ERROR o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - doResolveHandlerMethodException - Failed to invoke @ExceptionHandler method: public com.lia.utils.GlobalExceptionHandler$ExceptionInfo com.lia.utils.GlobalExceptionHandler.resourceNotFoundHandler(com.lia.app.controllers.exceptions.ResourceNotFoundException) 
    org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:168) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:101) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.handleReturnValue(RequestResponseBodyMethodProcessor.java:198) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:71) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:122) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:362) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:60) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:138) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1167) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1004) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:955) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:687) [javax.servlet-api-3.1.0.jar:3.1.0]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [javax.servlet-api-3.1.0.jar:3.1.0]
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:717) [jetty-servlet-9.1.1.v20140108.jar:9.1.1.v20140108]
        at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1644) [jetty-servlet-9.1.1.v20140108.jar:9.1.1.v20140108]
....

答案 1

问题在于所请求的内容类型和返回的对象不兼容。请参阅我关于如何配置的回复,以便Spring根据您的需要确定请求的内容类型(查看路径扩展,URL参数或标题)。ContentNegotiationConfigurerAccept

根据所请求内容类型的确定方式,当客户端请求图像时,您有以下选项:

  • 如果请求的内容类型由标头确定,并且客户端可以/想要处理 JSON 响应而不是图像数据,则客户端应使用 发送请求。这样,Spring就知道它可以安全地返回图像字节数据或错误的JSON消息。AcceptAccept: image/*, application/json
  • 在任何其他情况下,最好的解决方案是只返回HTTP错误代码,没有任何错误消息。您可以通过以下几种方式在控制器中执行此操作:

直接在响应上设置错误代码

public byte[] getImage(HttpServletResponse resp) {
    try {
        // return your image
    } catch (Exception e) {
        resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
}

ResponseEntity

public ResponseEntity<?> getImage(HttpServletResponse resp) {
    try {
        byte[] img = // your image
        return ReponseEntity.ok(img);
    } catch (Exception e) {
        return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

在该控制器中使用单独的方法,该方法将覆盖默认的Spring异常处理。这假设您有一个专用的异常类型用于映像请求,或者有一个单独的控制器仅用于提供映像。否则,异常处理程序也将处理来自该控制器中其他终结点的异常。@ExceptionHandler


答案 2

你的班级是什么样的?在注释类中定义了一些异常处理程序后,我遇到了非常相似的问题。当异常发生时,它被捕获,尽管响应未返回并被抛出。ExceptionInfo@ControllerAdviceorg.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

我发现问题是由这样一个事实引起的,即我错过了将getter方法添加到我的类中。添加 getter 方法(此类是不可变的,因此没有 setter 方法)后,一切都像一个 charm 一样工作。ErrorResponse


推荐