エキサイト株式会社の中尾です。
SpringBootでexceptionが発生したとき、特定のエラーレスポンスで返す方法を記載します。
以下、コードになります。
@RestControllerAdvice @Slf4j public class ExceptionController { @ExceptionHandler({BadRequestException.class}) @ResponseStatus(HttpStatus.BAD_REQUEST) public String handleBindException(Exception exception) { this.writeLog(exception.getStackTrace()); return exception.getMessage(); } @ExceptionHandler({NoHandlerFoundException.class}) @ResponseStatus(HttpStatus.NOT_FOUND) public String handleNotFoundException(Exception exception) { this.writeLog(exception.getStackTrace()); return "404 Not Found"; } private void writeLog(StackTraceElement[] stackTraceElements){ Arrays.stream(stackTraceElements) .limit(10L) .forEach(e -> log.error(e.toString())); } }
public class BadRequestException extends RuntimeException { public BadRequestException(String s) { super(s); } }
spring: mvc: throw-exception-if-no-handler-found: true resources: add-mappings: false
解説します。
RestControllerAdviceはRestControllerと違ってGetMapping/PostMappingとかは記載せず、ExceptionHandlerで該当のExceptionが発生したときResponseStatusを返します、
動作検証
shogo.nakao@localhost: $ curl http://localhost:8080 [/Users/shogo.nakao] XXXX must not be empty
404の場合、springの設定ファイルにthrow-exception-if-no-handler-found: trueとadd-mappings: falseをプロパティファイルに設定した上でRestControllerAdviceに追加してください。
shogo.nakao@localhost: $ curl http://localhost:8080/aaa [/Users/shogo.nakao] 404 Not Found
うまくいきました。
なお、以下のようにExceptionHandlerになにも指定しない場合、全てのエラーをキャッチすることができます。
@ExceptionHandler @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public String handleNotFoundException(Exception exception) { this.writeLog(exception.getStackTrace()); return "all Exception catch"; }
RestControllerAdviceには関係ありませんが、writeLogにstackTraceのエラーを10行ぐらいまで出力する設定になります。
Arrays.stream(stackTraceElements) .limit(10L) .forEach(e -> log.error(e.toString()));