Spring Boot Rest Controller:返回默认错误 JSON
Posted
技术标签:
【中文标题】Spring Boot Rest Controller:返回默认错误 JSON【英文标题】:Spring Boot Rest Controller: Return default Error JSON 【发布时间】:2019-09-26 03:36:34 【问题描述】:在我的 API 中,我喜欢保护用户详细信息端点,以便正常登录的用户只能访问他们的用户资料。因此我正在编写控制器:
@RequestMapping(value = URL_USER + "/id", method = RequestMethod.GET)
@ResponseBody
public PersistentEntityResource get(PersistentEntityResourceAssembler persistentEntityResourceAssembler, @PathVariable Long id)
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
ApplicationUser loggedInUser = applicationUserService.findByUsername(authentication.getName());
ApplicationUser applicationUser = applicationUserService.findById(id);
if (applicationUser.getId().equals(loggedInUser.getId()))
return persistentEntityResourceAssembler.toFullResource(applicationUser);
throw new IllegalAccessException();
与其引发导致InternalServerExcetption
的异常,我更喜欢返回默认的spring boot 错误json,如下所示:
"timestamp": "2019-05-08T11:42:23.064+0000",
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/user/2"
我希望有一个解决方案,它也适用于 404 等其他错误。实现该目标的最简单方法是什么?
【问题讨论】:
您可以使用@ControllerAdvice
和@ExceptionHandler
来实现这一点,就像我在this question 中提到的那样
这行不通,因为我喜欢继续返回 PersistentEntityResource
而不是 ResponseEntity
这样的换行有什么问题吗? ResponseEntity<PersistentEntityResource>
还没试过,不过找到了一个解决方案,貌似最优雅
【参考方案1】:
你也可以使用下面的方法
public class FooController
//...
@ExceptionHandler( CustomException1.class, CustomException2.class )
public String handleException()
return "the intended body";
或者,您可以使用@ControllerAdvice
将此逻辑作为全局异常处理程序放入
@ControllerAdvice
public class RestResponseEntityExceptionHandler
extends ResponseEntityExceptionHandler
@ExceptionHandler(value
= IllegalArgumentException.class, IllegalStateException.class )
protected ResponseEntity<Object> handleConflict(
RuntimeException ex, WebRequest request)
String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse,
new HttpHeaders(), HttpStatus.CONFLICT, request);
【讨论】:
【参考方案2】:经过一番研究,我找到了一个看起来相当优雅的解决方案:
RestController 方法长这样:
@RequestMapping(value = URL_USER + "/id", method = RequestMethod.GET)
@ResponseBody
public PersistentEntityResource get(PersistentEntityResourceAssembler persistentEntityResourceAssembler, @PathVariable Long id)
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
ApplicationUser loggedInUser = applicationUserService.findByUsername(authentication.getName());
ApplicationUser applicationUser = applicationUserService.findById(id);
if (applicationUser.getId().equals(loggedInUser.getId()))
return persistentEntityResourceAssembler.toFullResource(applicationUser);
throw new ForbiddenRequestException("Access not allowed");
另外我已经实现了ForbiddenRequestException
类:
@ResponseStatus(value = HttpStatus.FORBIDDEN)
public class ForbiddenRequestException extends RuntimeException
public ForbiddenRequestException(String message)
super(message);
至少要通过在属性中设置 server.error.include-stacktrace=never
从 JSON 中删除 trace
,这可能并不理想,但我认为在生产中你应该这样做。
【讨论】:
以上是关于Spring Boot Rest Controller:返回默认错误 JSON的主要内容,如果未能解决你的问题,请参考以下文章
列出所有已部署的 REST 端点(spring-boot、tomcat)
初入spring boot(八 )Spring Data REST
Spring Boot测试中使用REST Assured(转)