2016-11-17 3 views
0

私は春には新しいので、私の無知を許してください。 "required"であるメソッドパラメータがnullの場合、カスタムレスポンスを返すようにしています。 春からの電流応答は、次のとおりです。カスタムパラメータ注釈でカスタムスプリングエラー応答を返す方法は?

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

この実装に関する助けやこれを行う方法の他の提案は素晴らしいでしょう。おかげで、すべての:)私は、コントローラまたはコントローラの助言にこれを追加するカスタムMissingServletRequestParameterException取り扱いが必要な場合は

+2

を表示するための属性を定義します。このaproachは、表示する必要のある属性を持つerrorDTO objetに基づいて、必要な処理を実行する必要のある例外処理をキャッチし、必要に応じてカスタムエラー応答を作成します。 – johnnynemonic

+0

resolveArgument(){}にエラーを投げて、提案した方法をキャッチしてください。あなたは、私が少し失われている、明らかに明らかであるように、例を提供することができますか?私は500エラーで何を投げるかは、春のラップのように見えます。 –

+1

ボディのエラー状態をカスタマイズするには、カスタムのJava Beanを '@ControllerAdvice'の' @ExceptionHandler'で返すことができます。私が書いた[この小さな例](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

@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

私は遅刻します。これは、rumtimeエラーをキャッチして簡単な方法でレスポンスを変換する簡単な例です。

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クラスは、簡単にデ応答を処理したい場合は、@ControllerAdviceを使用してtrasnlationコントローラを使用することができます

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 + '}'; 
    } 
} 
関連する問題