在身体异常弹簧休息中添加新字段

Posted

技术标签:

【中文标题】在身体异常弹簧休息中添加新字段【英文标题】:Add new field in body exception spring rest 【发布时间】:2017-11-06 14:40:33 【问题描述】:

我想在我的 Rest spring boot 应用程序中处理异常。我知道使用 @ControllerAdvice 和 ResponseEntity 我可以返回一个自定义对象来代表我的错误,但我想要的是在现有异常的主体中添加一个新字段。

我创建了一个自定义异常,它继承了带有额外属性的 RuntimeException,一个字符串列表:

@ResponseStatus(HttpStatus.CONFLICT)
public class CustomException extends RuntimeException 

    private List<String> errors = new ArrayList<>();

    public CustomException(List<String> errors) 
        this.errors = errors;
    

    public CustomException(String message) 
        super(message);
    

    public CustomException(String message, List<String> errors) 
        super(message);
        this.errors = errors;
    

    public List<String> getErrors() 
        return errors;
    

    public void setErrors(List<String> errors) 
        this.errors = errors;
    

在我的控制器中,我只是以这种方式抛出这个自定义异常:

@GetMapping("/appointment")
public List<Appointment> getAppointments() 
    List<String> errors = new ArrayList<>();
    errors.add("Custom message");
    throw new CustomException("This is my message", errors);

当我用邮递员测试我的 Rest 端点时,似乎 spring boot 没有编组我的错误字段,响应是:


  "timestamp": "2017-06-05T18:19:03",
  "status": 409,
  "error": "Conflict",
  "exception": "com.htech.bimaristan.utils.CustomException",
  "message": "This is my message",
  "path": "/api/agenda/appointment"

如果我可以从异常中获取“路径”和“时间戳”字段,我可以使用 @ControllerAdvice 获取自定义对象,但是这两个属性没有 getter。

谢谢。

【问题讨论】:

【参考方案1】:

好吧!这是 DefaultErrorAttributes 中“路径”和“时间戳”的实现,您也可以在自定义实现中实现:

路径:

String path = getAttribute(requestAttributes, "javax.servlet.error.request_uri");
if (path != null) 
    errorAttributes.put("path", path);

时间戳:

errorAttributes.put("timestamp", new Date());

spring boot 中错误定制的文档是here。

@Bean
public ErrorAttributes errorAttributes() 
    return new DefaultErrorAttributes() 
        @Override
        public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) 
            Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
            // customize here
            return errorAttributes;
        

   ;

或者您可以编写自定义实现:

@Component
public class CustomErrorAttributes extends DefaultErrorAttributes 

    @Override
    public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) 
        Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
        // customize here
        return errorAttributes;
    

ErrorAttributes bean 自定义错误响应如下:


   "timestamp": 1413883870237,
   "status": 500,
   "error": "Internal Server Error",
   "exception": "org.example.ServiceException",
   "message": "somthing goes wrong",
   "path": "/index"

"exception" 属性可以使用@ExceptionHandler 进行自定义。 @ControlerAdvice 可用于跨控制器自定义异常。要在控制器级别进行自定义,您可以将它们放在控制器中。

在你的情况下:

   @ResponseStatus(value=HttpStatus.BAD_REQUEST, reason="Invalid Inputs")
    @ExceptionHandler(CustomException.class)
    private void errorHanlder() 
        //Log exception
    


  public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) 
    Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
    Throwable error = getError(requestAttributes);
    if (error instanceof CustomException) 
        errorAttributes.put("errorList", ((CustomException)error).getErrors());
    
    return errorAttributes;

【讨论】:

我尝试将此功能集成到我的控制器中,但每次调用我的端点时都会出现此异常:org.thymeleaf.exceptions.TemplateInputException: Error resolve template "generic/error", template任何配置的模板解析器可能不存在或可能无法访问 我认为您正在实现 REST 端点。所以,使用 ResponseEntity。 这个解决方案是我在问题帖子中谈到的。我可以使用它,但是如何从异常主体中获取路径和时间戳属性,以便我可以将它们添加到自定义错误对象中? 对不起!我忽略了。更新了答案。 谢谢@YuVi。方法errorAttributes应该在控制器类中声明吗?这个声明将为所有异常添加一个新的键值对,还是我应该在每个异常处理程序中单独自定义它?【参考方案2】:

以前的答案确实有这一切,但不知何故我花了一段时间才弄明白,所以总的来说,实现这一点的最简单方法是拥有这样的 bean:

@Bean
public ErrorAttributes errorAttributes() 
    return new DefaultErrorAttributes() 
        @Override
        public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes,
                boolean includeStackTrace) 
            Map<String, Object> errorAttributes = super.getErrorAttributes(requestAttributes, includeStackTrace);
            Throwable error = getError(requestAttributes);
            if (error instanceof CustomExceptionthere) 
                errorAttributes.put("errorList", ((CustomException)error).getErrors());
            
            return errorAttributes;
        

    ;

【讨论】:

以上是关于在身体异常弹簧休息中添加新字段的主要内容,如果未能解决你的问题,请参考以下文章

身体健康为本

能天天跑步吗?跑多久对身体是最好的?

SpriteKit 节点旋转问题

2017--生活和锻炼

健康增胖和调理好身体

位置固定的css在角度材料中添加身体标签