java Spring Boot - 处理 JSON 或 HTML 的错误控制器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29703903/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 15:45:43  来源:igfitidea点击:

Spring Boot - Error Controller to handle either JSON or HTML

javaspringspring-mvcspring-boot

提问by rhinds

I have a spring boot application.

我有一个弹簧启动应用程序。

I have a custom error controller, that is mapped to using ErrorPagemappings. The mappings are largely based on HTTP Status codes, and normally just render a HTML view appropriately.

我有一个自定义错误控制器,它映射到使用ErrorPage映射。映射主要基于 HTTP 状态代码,通常只是适当地呈现 HTML 视图。

For example, my mapping:

例如,我的映射:

@Configuration
class ErrorConfiguration implements EmbeddedServletContainerCustomizer {

  @Override public void customize( ConfigurableEmbeddedServletContainer container ) {
      container.addErrorPages( new ErrorPage( HttpStatus.NOT_FOUND, "/error/404.html" ) )
  }

And my error controller:

还有我的错误控制器:

@Controller
@RequestMapping
public class ErrorController {

    @RequestMapping( value = "/error/404.html" )
    @ResponseStatus(value = HttpStatus.NOT_FOUND)
    public String pageNotFound( HttpServletRequest request ) {
        "errors/404"
    }

This works fine - If I just enter a random non-existent URL then it renders the 404 page.

这工作正常 - 如果我只是输入一个随机的不存在的 URL,那么它会呈现 404 页面。

Now, I want a section of my site, lets say /api/..that is dedicated to my JSON api to serve the errors as JSON, so if I enter a random non-existent URL under /api/.. then it returns 404 JSON response.

现在,我想要我的网站的一部分,假设/api/..它专用于我的 JSON api 以将错误作为 JSON 提供服务,所以如果我在 /api/.. 下输入一个随机的不存在的 URL,那么它会返回 404 JSON 响应。

Is there any standard/best way to do this? One idea I tried out was to have a @ControllerAdvicethat specifically caught a class of custom API exceptions I had defined and returned JSON, and in my standard ErrorController checking the URL and throwing an apprpriate API exception if under that API URL space (but that didn't work, as the ExceptionHandler method could not be invoked because it was a different return type from the original controller method).

有没有标准/最好的方法来做到这一点?我尝试过的一个想法是有一个@ControllerAdvice专门捕获我定义并返回 JSON 的一类自定义 API 异常,并在我的标准 ErrorController 中检查 URL 并在该 API URL 空间下抛出一个适当的 API 异常(但没有t 工作,因为无法调用 ExceptionHandler 方法,因为它与原始控制器方法的返回类型不同)。

Is this something that has been solved?

这是已经解决的事情了吗?

采纳答案by rhinds

The problem was my own fault. I was trying to work out why my @ExceptionHandlerwas not able to catch my exception and return JSON - As I suggested at the end of my question, I thought I was having problems because of conflicting return types - this was incorrect.

问题是我自己的错。我试图弄清楚为什么我@ExceptionHandler无法捕获我的异常并返回 JSON - 正如我在问题结束时所建议的那样,我认为我因为返回类型冲突而遇到了问题 - 这是不正确的。

The error I was getting trying to have my exception handler return JSON was along the lines of:

我试图让我的异常处理程序返回 JSON 的错误是:

  "exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
  "message": "Could not find acceptable representation"

I did some more digging/experimenting to try to narrow down the problem (thinking that the issue was because I was in the Spring error handling flow and in an ErrorControllerthat was causing the problem), however the problem was just because of the content negotiation stuff Spring does.

我做了更多的挖掘/实验以试图缩小问题的范围(认为问题是因为我在 Spring 错误处理流程中并且在ErrorController导致问题的流程中),但是问题只是因为内容协商的东西春天可以。

Because my errorPage mapping in the web.xmlwas mapping to /error/404.html, Spring was using the suffix to resolve the appropriate view - so it then failed when I tried to return json.

因为我的 errorPage 映射web.xml映射到/error/404.html,Spring 使用后缀来解析适当的视图 - 所以当我尝试返回 json 时它失败了。

I have been able to resolve the issue by changing my web.xml to /error/404or by turning off the content negotiation suffix option.

我已经能够通过将我的 web.xml 更改为/error/404或关闭内容协商后缀选项来解决该问题。

回答by mushfek0001

Now, I want a section of my site, lets say /api/.. that is dedicated to my JSON api to serve the errors as JSON, so if I enter a random non-existent URL under /api/.. then it returns 404 JSON response.

Is there any standard/best way to do this? One idea I tried out was to have a @ControllerAdvice that specifically caught a class of custom API exceptions I had defined and returned JSON, and in my standard ErrorController checking the URL and throwing an apprpriate API exception if under that API URL space (but that didn't work, as the ExceptionHandler method could not be invoked because it was a different return type from the original controller method).

现在,我想要我的网站的一部分,比如说 /api/.. 专门用于我的 JSON api 以将错误作为 JSON 提供服务,所以如果我在 /api/.. 下输入一个随机的不存在的 URL,那么它会返回404 JSON 响应。

有没有标准/最好的方法来做到这一点?我尝试过的一个想法是有一个 @ControllerAdvice 专门捕获我定义并返回 JSON 的一类自定义 API 异常,并在我的标准 ErrorController 中检查 URL 并在该 API URL 空间下抛出适当的 API 异常(但那不起作用,因为无法调用 ExceptionHandler 方法,因为它与原始控制器方法的返回类型不同)。

I think you need to rethink what you are trying to do here. According to HTTP response codes here

我认为您需要重新考虑您在这里尝试做的事情。根据此处的HTTP 响应代码

The 404 or Not Found error message is an HTTP standard response code indicating that the client was able to communicate with a given server, but the server could not find what was requested.

404 或 Not Found 错误消息是一个 HTTP 标准响应代码,表明客户端能够与给定的服务器通信,但服务器找不到请求的内容。

So when typing a random URL you may not want to throw 404 all the time. If you are trying to handle a bad request you can do something like this

因此,在输入随机 URL 时,您可能不想一直抛出 404。如果你试图处理一个错误的请求,你可以做这样的事情

@ControllerAdvice
public class GlobalExceptionHandlerController {   

    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseEntity<ErrorResponse> noRequestHandlerFoundExceptionHandler(NoHandlerFoundException e) {
        log.debug("noRequestHandlerFound: stacktrace={}", ExceptionUtils.getStackTrace(e));

        String errorCode = "400 - Bad Request";
        String errorMsg = "Requested URL doesn't exist";

        return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.BAD_REQUEST);
    }
}

Construct ResponseEntitythat suites your need.

构建ResponseEntity适合您的需求。