spring boot动态响应式

问题描述 投票:0回答:1

我正在使用 @ControllerAdvice 进行全局异常处理。但如果请求是 ajax(xhr),我想以 Json 格式返回异常,如果不是,我想将异常显示为 html

所以响应类型是动态的。它可能是 html 或 json。我正在使用 thymleaf 来生成我的 html 页面。

如何在 Spring Boot 中做到这一点?

    @ResponseBody
    @ExceptionHandler(Exception.class)
    public ModelAndView handle(Exception exception, WebRequest request) {
        this.logException(exception, request);
        var model = getErrorPageModel(exception);
        return new ModelAndView("exception", model, HttpStatus.OK);
    }
ajax spring-boot exceptionhandler controller-advice
1个回答
0
投票

WebRequest
,您必须检索必要的信息以返回 JSON 或 HTML。一种可能的方法是解析
Accept
标头:

List<MediaType> mediaTypes = MediaType.parseMediaTypes(request.getHeader("Accept"));
if (mediaTypes.contains(MediaType.TEXT_HTML)) {
   // TODO: implement
} else {
    // TODO: implement
}

更好的选择是使用 Spring 的

ContentNegotiationManager
:

// TODO: Autowire a bean of `ContentNegotiationManager` into your ControllerAdvice class
List<MediaType> mediaTypes = contentNegotiationManager.resolveMediaTypes(request);
if (mediaTypes.contains(MediaType.TEXT_HTML)) {
   // TODO: implement
} else {
    // TODO: implement
}

现在您要做的就是为 HTML 和 JSON 视图实现模型和视图。

对于 HTML 视图,您可以使用 Thymeleaf 模板,例如

error.html
:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<p><strong>Error:</strong> <span th:text="${message}"></span></p>
</body>

之后,您可以从异常处理程序返回以下

ModelAndView

return new ModelAndView("error", Map.of("message", ex.getMessage()));

对于 JSON 部分,您可以使用

MappingJackson2JsonView
视图类:

// TODO: Autowire a bean of `ObjectMapper` into your ControllerAdvice class
return new ModelAndView(new MappingJackson2JsonView(objectMapper), Map.of("message", ex.getMessage()));

一切结合起来你会得到:

@ExceptionHandler(Exception.class)
public ModelAndView handleException(IllegalArgumentException ex, NativeWebRequest request) throws HttpMediaTypeNotAcceptableException {
    List<MediaType> mediaTypes = contentNegotiationManager.resolveMediaTypes(request);
    Map<String, String> model = Map.of("message", ex.getMessage());
    if (mediaTypes.contains(MediaType.TEXT_HTML)) {
        return new ModelAndView("error", model);
    } else {
        return new ModelAndView(new MappingJackson2JsonView(objectMapper), model);
    }
}

注意:在此示例中,我假设如果

Accept
标头包含
text/html
,您希望返回 HTML 视图,而在其他情况下,您希望返回 JSON 视图。您可以将此逻辑更改为您想要的任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.