2016-11-17 56 views
0

我是新来的春天,所以请原谅我的无知。 我试图“返回”自定义响应时,给定的方法参数,这是“必需”,为空。 当前响应,从春季是:如何使用自定义参数注释返回自定义弹簧错误响应?

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

这个实现的任何帮助或任何其他如何做到这一点的建议将是太棒了。感谢所有:)

+2

如果你想处理响应德很容易就可以使用使用@ControllerAdvice一个trasnlation控制器;这个aproach会捕捉你想要处理的rumtime异常,并根据你需要创建一个自定义错误响应,并以errorDTO objet和你需要显示的属性为基础。 – johnnynemonic

+0

所以我应该在resolveArgument(){}中抛出一个错误,并且按照你的建议抓住它。你能提供一个例子吗?我有点失落,这一点很明显。无论我在500错误中抛出什么,它看起来像春天的rap。 –

+1

要为错误状态自定义主体,您可以在'@ ControllerAdvice'的'@ ExceptionHandler'中返回一个自定义java bean。你可以看看[这个小例子](https://github.com/growlingchaos/update-msg/blob/custom-error/src/main/java/org/damage/rest/GeneralExceptionAdvice.java)我写的。 – growlingchaos

回答

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); 
    } 
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使用。我个人建议你使用原始错误处理,除非你有真正的理由。

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