REST JHipsterで生成されたAPIで、いくつかの404例外をスローしたいのですが、通常は
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
実際には、xhrリクエストに対して404レスポンスが返されます。問題は、フロントサイドで、JHipsterが応答を解析することです。
angular.fromJson(result)
そして、404が実際の応答である場合、そのような結果は空であり、解析が失敗します。
マップされていないURIを指す場合は、コントローラーが/api/user
(複数形に注意)にマップしている間に/api/users
と言ってみましょう。APIから取得した404には本体があります。
{
"timestamp": "2016-04-25T18:33:19.947+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/api/user/myuser/contact"
}
これは角度で正しく解析されます。
このようなボディを作成するにはどうすればよいですか?この例外は春にスローされますか、それともTomcatがスローしますか?
私はこれを試しました: Spring-MVCコントローラーのトリガー404? ですが、応答のパラメーターを設定できません。
最初のオプションは、エラーオブジェクトを定義し、それらを404 Not Found
本体として返すことです。次のようなもの:
Map<String, String> errors = ....;
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(errors);
典型的なResponseEntity
を返す代わりに、404 Not Found
に解決されるException
をスローできます。次のようなNotFoundException
があるとします。
@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {}
次に、この例外をコントローラーでスローすると、次のようになります。
{
"timestamp":1461621047967,
"status":404,
"error":"Not Found",
"exception":"NotFoundException",
"message":"No message available",
"path":"/greet"
}
メッセージおよび本文の他の部分をカスタマイズする場合は、ExceptionHandler
にNotFoundException
を定義する必要があります。
RESTful APIを作成していて、さまざまな例外ケースに異なるエラーコードおよびエラーメッセージを設定したい場合は、それらのケースを表す例外の階層を作成し、メッセージを抽出できます。そしてそれぞれからのコード。
たとえば、コントローラがスローする他のすべての例外のスーパークラスであるAPIException
などの例外を導入できます。このクラスは、次のようなコード/メッセージのペアを定義します。
public class APIException extends RuntimeException {
private final int code;
private final String message;
APIException(int code, String message) {
this.code = code;
this.message = message;
}
public int code() {
return code;
}
public String message() {
return message;
}
}
例外の性質に応じた各サブクラスは、このペアに適切な値を提供できます。たとえば、InvalidStateException
を使用できます。
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class InvalidStateException extends APIException {
public InvalidStateException() {
super(1, "Application is in invalid state");
}
}
またはその悪名高い見つからないもの:
@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class SomethingNotFoundException extends APIException {
public SomethingNotFoundException() {
super(2, "Couldn't find something!");
}
}
次に、これらの例外をキャッチして意味のあるJSON表現に変換するErrorController
を定義する必要があります。そのエラーコントローラは次のようになります。
@RestController
public class APIExceptionHandler extends AbstractErrorController {
private static final String ERROR_PATH = "/error";
private final ErrorAttributes errorAttributes;
@Autowired
public APIExceptionHandler(ErrorAttributes errorAttributes) {
super(errorAttributes);
this.errorAttributes = errorAttributes;
}
@RequestMapping(path = ERROR_PATH)
public ResponseEntity<?> handleError(HttpServletRequest request) {
HttpStatus status = getStatus(request);
Map<String, Object> errors = getErrorAttributes(request, false);
getApiException(request).ifPresent(apiError -> {
errors.put("message" , apiError.message());
errors.put("code", apiError.code());
});
// If you don't want to expose exception!
errors.remove("exception");
return ResponseEntity.status(status).body(errors);
}
@Override
public String getErrorPath() {
return ERROR_PATH;
}
private Optional<APIException> getApiException(HttpServletRequest request) {
RequestAttributes attributes = new ServletRequestAttributes(request);
Throwable throwable = errorAttributes.getError(attributes);
if (throwable instanceof APIException) {
APIException exception = (APIException) throwable;
return Optional.of(exception);
}
return Optional.empty();
}
}
したがって、SomethingNotFoundException
をスローすると、返されるJSONは次のようになります。
{
"timestamp":1461621047967,
"status":404,
"error":"Not Found",
"message":"Couldn't find something!",
"code": 2,
"path":"/greet"
}
メッセージを返すか、エラーコードでテストしたい場合は、これを行うことができると思います
@ResponseBody
public ResponseEntity somthing() {
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type", "application/json; charset=utf-8");
return new ResponseEntity<>(new Gson().toJson("hello this is my message"), headers, HttpStatus.NOT_FOUND);
}