如何使用自定义参数注释返回自定义弹簧错误响应?

时间:2016-11-17 10:42:52

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

我是春天的新人,所以请原谅我的无知。 我试图"返回"当给定的方法参数(" required")为空时,自定义响应。 从春天开始,目前的反应是:

{
  "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());

  }
}

我还注册了&#34;这个解析器与webConfig:

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

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

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

3 个答案:

答案 0 :(得分:2)

谢谢@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);
  }

答案 1 :(得分:2)

我迟到了,这是一个简单的例子,说明如何捕捉朗姆酒错误并以简单的方式翻译响应。

TranslationController:

@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 + '}';
    }
 }

答案 2 :(得分:1)

如果您需要自定义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的用法。我个人建议你使用原始的错误处理,除非你有真正的理由。