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

标签 java spring spring-mvc content-negotiation

为了全局处理可能在 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;
    }

}

关于java - Spring MVC 3.2 - 错误页面的内容协商?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14715640/

相关文章:

java - Swing 中 "Container c=getContentPane();"的用途是什么?

java - Spring NamedParameterJdbcTemplate 查询的性能非常慢

java - 从 postman Spring Mvc 获取时未从resttemplate.exchange 获取响应正文

java - mustache 和 Internalviewresolvers - Spring MVC

java - 从Android设备上的后台服务监听联系人数据库的变化

java - 使用 SelectionMode.MULTI 将行添加/创建点击事件到 Vaadin 网格?

java - CardView cardElevation 在 CardView 内部绘制随机方 block

java - hibernate/HSQLDB : User lacks priviledges to create constraints

java - 尽管组件扫描是正确的,但无法 Autowiring 字段

spring-mvc - spring 3.0 中如何绑定(bind)请求参数?