java - Spring MVC 3.2 - 错误页面的内容协商?

为了全局处理可能在 Controller 之外发生的错误(例如 HTTP 404),我的 web.xml 中有类似于以下内容的条目:

<error-page>
    <error-code>404</error-code>
    <location>/errors/404</location>
</error-page>

在我的 ErrorController 中,我有类似以下的相应方法:

@Controller
@RequestMapping("/errors")
public class ErrorController {

    @RequestMapping(value = "/404", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<ErrorResponse> error404() {

        ErrorResponse errorBody = new ErrorResponse(404, "Resource Not Found!");

        return new ResponseEntity<ErrorResponse>(errorBody, HttpStatus.NOT_FOUND);
    }
}

我面临的问题是我配置的 ContentNegotiationManager 和消息转换器在这种情况下没有被使用。我怀疑由于请求被重定向到错误页面,内容协商中使用的原始请求属性丢失了,这被视为一个完全独立的请求。 (即对/mycontroller/badresource.json 的原始请求 -->/errors/404(无文件扩展名))

在这样的错误处理程序中是否有任何方法可以确定和/或响应原始请求中请求的适当内容类型?

最佳答案

Spring MVC 3.2 现在包含一个有用的注释,称为 @ControllerAdvice。您可以添加一个 ExceptionHandler 方法,该方法将全局处理您定义的任何异常。

对我来说,我只关心返回给客户端的两种可能的内容类型 - application/jsontext/html

这是我将如何设置它 -

@ControllerAdvice
public class ExceptionControllerAdvice {

    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private static final MediaType JSON_MEDIA_TYPE = new MediaType("application", "json", DEFAULT_CHARSET);

    //I decided to handle all exceptions in this one method
    @ExceptionHandler(Throwable.class)
    public @ResponseBody String handleThrowable(HttpServletRequest request, HttpServletResponse response, Throwable ex) throws IOException {

        ...

        if(supportsJsonResponse(request.getHeader("Accept"))) {

            //return response as JSON
            response.setStatus(statusCode);
            response.setContentType(JSON_MEDIA_TYPE.toString());

                    //TODO serialize your error in a JSON format
                    //return ...

        } else {

            //return as HTML
            response.setContentType("text/html");
            response.sendError(statusCode, exceptionMessage);
            return null;
        }
    }

    private boolean supportsJsonResponse(String acceptHeader) {

        List<MediaType> mediaTypes = MediaType.parseMediaTypes(acceptHeader);

        for(MediaType mediaType : mediaTypes) {
            if(JSON_MEDIA_TYPE.includes(mediaType)) {
                return true;
            }
        }

        return false;
    }

}

https://stackoverflow.com/questions/14715640/

相关文章:

spring - jar 如何在使用它的 Web 应用程序中传播漏洞?

java - Spring 验证与 Hibernate 验证

java - 单个 hibernate session 中的多个事务(使用 Spring)

java - 使用spring boot(安全)和keycloak启用角色身份验证?

java - 使用具有不同 AuthenticationProviders 的多个 WebSecur

java - 在 Spring Hibernate java 项目中使用 "Envers"审计表

java - Spring WS : How to get and save XSD validat

java - Spring Integration Kafka Consumer Listener

spring - 如何在运行时将新用户添加到 Spring Security

spring - Spring JUnit 测试中的自动模拟实例化