【问题标题】:how to return a custom spring error response with custom parameter annotations?如何使用自定义参数注释返回自定义弹簧错误响应?
【发布时间】:2017-03-31 20:48:25
【问题描述】:

我是春天的新手,所以请原谅我的无知。 当“必需”的给定方法参数为空时,我试图“返回”自定义响应。 来自 spring 的当前响应是:

{
  "timestamp": 1477060294961,
  "status": 400,
  "error": "Bad Request",
  "exception": "org.springframework.web.bind.MissingServletRequestParameterException",
  "message": "Required String parameter 'bookname' is not present",
  "path": "/getbook"
}

我正试图达到它“回归”的地步:

{
  "status": 400,
  "error": {
    // custom error body
  }
}

我认为这样做的一个好方法是有一个自定义的“参数注释”。这也将使代码更具可读性并存储有关此端点参数的有用信息。

我按照here 给出的示例进行操作,但我不确定在哪里或如何返回自定义响应?

到目前为止我有注释:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface customParameter {

String value() default "";
boolean required() default false;
String defaultValue() default ValueConstants.DEFAULT_NONE;
String customInfo() default  "blar blar";
}

“端点”:

  @RequestMapping(value = "/getbook", method = {RequestMethod.POST})
  public ResponseEntity<BookResponse> getBookInfo(
      @customParameter(value = "bookname", required = true, customInfo = "extremely valuable book")
      final String bookname
   ) {
    return new bookRequest(bookname).getResponse;
}

并有一个自定义解析器:

public class CustomAnnotationResolver implements HandlerMethodArgumentResolver {


  @Override
  public boolean supportsParameter(MethodParameter parameter) {
    return parameter.getParameterAnnotation(customParameter.class) != null;
  }


  @Override
  public Object resolveArgument(MethodParameter methodparameter, ModelAndViewContainer mavContainer,
      NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

    CustomParameter customParameter = methodparameter.getParameterAnnotation(CustomParameter.class);

    String parameter = webRequest.getParameter(CustomParameter.value());

    // todo: do Validation here
    if (customParameter == null) {
      if (Parameter.required()) {
        String customInfo = customParameter.customInfo();
        String body getBody(customInfo);
        new ResponseEntity(body, 400); // so the problem is here!! how do I return this response??  
      }
    }

    return webRequest.getParameter(customParameter.value());

  }
}

我还用 webConfig“注册”了这个解析器:

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

  @Override
  public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    argumentResolvers.add(new CustomAnnotationResolver());
  }
}

对此实现的任何帮助或有关如何执行此操作的任何其他建议都会很棒。谢谢大家:)

【问题讨论】:

  • 如果您想轻松处理响应,您可以使用@ControllerAdvice 使用翻译控制器;这种方法捕获您想要处理的 rumtime 异常,并根据您需要显示的属性基于 errorDTO 对象创建您想要的自定义错误响应。
  • 所以我应该在 resolveArgument(){} 中抛出一个错误并按照您的建议捕获它吗?您能否提供示例,我有点迷茫,这很明显。无论我在 500 错误中抛出什么,它看起来就像弹簧说唱。
  • 要为错误状态自定义正文,您可以在@ControllerAdvice 的@ExceptionHandler 中返回自定义Java bean。你可以看看我写的this little example。

标签: java spring spring-mvc spring-boot spring-annotations


【解决方案1】:

谢谢@growlingchaos,太棒了,这就是解决方案。

@ControllerAdvice
@RestController
public class customExceptionAdvice {

  @ExceptionHandler(Exception.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public ResponseEntity handleConflict(BadRequestException e, HttpServletResponse response)
      throws IOException {

    return new ResponseEntity(e.getErrorBody(), HttpStatus.BAD_REQUEST);
  }

【讨论】:

    【解决方案2】:

    我迟到了,这是一个简单的示例,说明如何捕获 rumtime 错误并以简单的方式翻译响应。

    翻译控制器:

    @ControllerAdvice
    public class ExceptionTranslator {
    
    private final Logger log = LoggerFactory.getLogger(ExceptionTranslator .class);
    
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<ErrorDTO> processRuntimeException(HttpServletRequest req, RuntimeException ex) throws Exception {
        ErrorDTO errorDTO;
        ResponseStatus responseStatus = AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
        if (responseStatus != null) {
            errorDTO = new ErrorDTO(req.getRequestURI(), responseStatus.value().toString(), ex.getMessage());
        } else {
            errorDTO = new ErrorDTO(req.getRequestURI(), HttpStatus.INTERNAL_SERVER_ERROR.toString(), ex.getMessage());
        }
        log.debug(errorDTO.toString());
        return new ResponseEntity(errorDTO, HttpStatus.valueOf(Integer.valueOf(errorDTO.getCode())));
    }
    }
    

    DTO 类来定义要显示的属性

    public class ErrorDTO implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private final String uri;
        private final String code;
        private final String description;
    
        public ErrorDTO(String message) {
            this(null, message, null);
        }
    
        public ErrorDTO(String uri, String code, String description) {
            this.uri = uri;
            this.code = code;
            this.description = description;
        }
    
        public String getUri() {
           return uri;
        }
    
        public String getCode() {
           return code;
        }
    
        public String getDescription() {
            return description;
        }
    
        @Override
        public String toString() {
            return "ErrorDTO{" + "uri=" + uri + ", code=" + code + ", description=" + description + '}';
        }
     }
    

    【讨论】:

      【解决方案3】:

      如果您需要自定义 MissingServletRequestParameterException 处理,我会将其添加到控制器或控制器建议中:

      @ExceptionHandler
      @ResponseStatus(HttpStatus.BAD_REQUEST)
      public Map<String, Object> handleMissingParam(MissingServletRequestParameterException e) {
      
      
          Map<String, Object> result = new HashMap();
      
          result.put("status", Integer.toString(400));
      
          Map<String, String> error = new HashMap();
          error.put("param", e.getParameterName());
      
          result.put("error", error);
          return result;
      }
      

      您当然可以用 java 对象替换 Map 的用法。我个人建议您使用原始错误处理,除非您有真正的理由。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-08
        • 2022-06-20
        • 2013-08-08
        • 1970-01-01
        • 1970-01-01
        • 2018-08-26
        • 1970-01-01
        • 2017-03-26
        相关资源
        最近更新 更多