Spring 引导 - 错误控制器处理 JSON 或 HTML
Spring Boot - Error Controller to handle either JSON or HTML
我有一个 spring 启动应用程序。
我有一个自定义错误控制器,它使用 ErrorPage
映射映射到。映射主要基于 HTTP 状态代码,通常只是适当地呈现 HTML 视图。
比如我的映射:
@Configuration
class ErrorConfiguration implements EmbeddedServletContainerCustomizer {
@Override public void customize( ConfigurableEmbeddedServletContainer container ) {
container.addErrorPages( new ErrorPage( HttpStatus.NOT_FOUND, "/error/404.html" ) )
}
还有我的错误控制器:
@Controller
@RequestMapping
public class ErrorController {
@RequestMapping( value = "/error/404.html" )
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public String pageNotFound( HttpServletRequest request ) {
"errors/404"
}
这工作正常 - 如果我只是随机输入一个不存在的 URL 然后它呈现 404 页面。
现在,我想要我网站的一个部分,假设 /api/..
专用于我的 JSON api 以将错误作为 JSON,所以如果我在 /api/.. 下输入一个随机的不存在的 URL 然后它 returns 404 JSON 响应。
有什么standard/best方法可以做到这一点吗?我尝试的一个想法是有一个 @ControllerAdvice
专门捕获 class 我定义和 returned JSON 的自定义 API 异常,并且在我的标准 ErrorController 检查 URL 并在 API URL space 下抛出适当的 API 异常(但这没有用,因为 ExceptionHandler 方法可以不会被调用,因为它是与原始控制器方法不同的 return 类型。
这件事已经解决了吗?
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).
我认为您需要重新考虑您在这里尝试做的事情。根据 HTTP 响应代码 here
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.
因此,当您随机输入 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);
}
}
构建满足您需要的ResponseEntity
。
问题是我自己的错。我试图弄清楚为什么我的 @ExceptionHandler
无法捕获我的异常和 return JSON - 正如我在问题末尾所建议的那样,我认为我遇到了问题因为冲突 return 类型 - 这是不正确的。
我在尝试让我的异常处理程序 return JSON 时遇到的错误是:
"exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
"message": "Could not find acceptable representation"
我做了更多 digging/experimenting 来尝试缩小问题范围(认为问题是因为我在 Spring 错误处理流程中并且在 ErrorController
导致问题),但是问题只是因为内容协商 Spring 确实如此。
因为我在 web.xml
中的 errorPage 映射映射到 /error/404.html
,Spring 使用后缀来解析适当的视图 - 所以当我尝试 return json.
我已经通过将 web.xml 更改为 /error/404
或关闭内容协商后缀选项来解决问题。
我有一个 spring 启动应用程序。
我有一个自定义错误控制器,它使用 ErrorPage
映射映射到。映射主要基于 HTTP 状态代码,通常只是适当地呈现 HTML 视图。
比如我的映射:
@Configuration
class ErrorConfiguration implements EmbeddedServletContainerCustomizer {
@Override public void customize( ConfigurableEmbeddedServletContainer container ) {
container.addErrorPages( new ErrorPage( HttpStatus.NOT_FOUND, "/error/404.html" ) )
}
还有我的错误控制器:
@Controller
@RequestMapping
public class ErrorController {
@RequestMapping( value = "/error/404.html" )
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public String pageNotFound( HttpServletRequest request ) {
"errors/404"
}
这工作正常 - 如果我只是随机输入一个不存在的 URL 然后它呈现 404 页面。
现在,我想要我网站的一个部分,假设 /api/..
专用于我的 JSON api 以将错误作为 JSON,所以如果我在 /api/.. 下输入一个随机的不存在的 URL 然后它 returns 404 JSON 响应。
有什么standard/best方法可以做到这一点吗?我尝试的一个想法是有一个 @ControllerAdvice
专门捕获 class 我定义和 returned JSON 的自定义 API 异常,并且在我的标准 ErrorController 检查 URL 并在 API URL space 下抛出适当的 API 异常(但这没有用,因为 ExceptionHandler 方法可以不会被调用,因为它是与原始控制器方法不同的 return 类型。
这件事已经解决了吗?
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).
我认为您需要重新考虑您在这里尝试做的事情。根据 HTTP 响应代码 here
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.
因此,当您随机输入 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);
}
}
构建满足您需要的ResponseEntity
。
问题是我自己的错。我试图弄清楚为什么我的 @ExceptionHandler
无法捕获我的异常和 return JSON - 正如我在问题末尾所建议的那样,我认为我遇到了问题因为冲突 return 类型 - 这是不正确的。
我在尝试让我的异常处理程序 return JSON 时遇到的错误是:
"exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
"message": "Could not find acceptable representation"
我做了更多 digging/experimenting 来尝试缩小问题范围(认为问题是因为我在 Spring 错误处理流程中并且在 ErrorController
导致问题),但是问题只是因为内容协商 Spring 确实如此。
因为我在 web.xml
中的 errorPage 映射映射到 /error/404.html
,Spring 使用后缀来解析适当的视图 - 所以当我尝试 return json.
我已经通过将 web.xml 更改为 /error/404
或关闭内容协商后缀选项来解决问题。