我使用Spring MVC为一个简单的JSON API,使用@ResponseBody的方法,如下所示。(我已经有了一个直接生成JSON的服务层。)
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
// TODO: how to respond with e.g. 400 "bad request"?
}
return json;
}
在给定的场景中,响应HTTP 400错误的最简单、最干净的方法是什么?
我确实遇到过这样的方法:
return new ResponseEntity(HttpStatus.BAD_REQUEST);
...但我不能在这里使用它,因为我的方法的返回类型是字符串,而不是ResponseEntity。
这样的方法应该是可行的,但我不确定是否有更简单的方法:
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId, @RequestBody String body,
HttpServletRequest request, HttpServletResponse response) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
response.setStatus( HttpServletResponse.SC_BAD_REQUEST );
}
return json;
}
在控制器中处理异常而无需显式返回ResponseEntity的最简单、最干净的方法是添加@ExceptionHandler方法。
使用Spring Boot 2.0.3.RELEASE的示例片段:
// Prefer static import of HttpStatus constants as it's cleaner IMHO
// Handle with no content returned
@ExceptionHandler(IllegalArgumentException.class)
@ResponseStatus(BAD_REQUEST)
void onIllegalArgumentException() {}
// Return 404 when JdbcTemplate does not return a single row
@ExceptionHandler(IncorrectResultSizeDataAccessException.class)
@ResponseStatus(NOT_FOUND)
void onIncorrectResultSizeDataAccessException() {}
// Catch all handler with the exception as content
@ExceptionHandler(Exception.class)
@ResponseStatus(I_AM_A_TEAPOT)
@ResponseBody Exception onException(Exception e) {
return e;
}
题外话:
如果在所有上下文/用法中,matchService.getMatchJson(matchId) == null是无效的,那么我的建议是让getMatchJson抛出一个异常,例如,IllegalArgumentException,而不是返回null,并让它冒泡泡到控制器的@ExceptionHandler。
如果用null来测试其他条件,那么我将有一个特定的方法,例如matchService.hasMatchJson(matchId)。一般来说,我尽可能避免null,以避免意外的NullPointerException。
将您的返回类型更改为ResponseEntity<>,然后您可以使用下面的400:
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
对于正确的请求:
return new ResponseEntity<>(json,HttpStatus.OK);
Spring 4.1之后,ResponseEntity中有了帮助方法,可以用作:
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
and
return ResponseEntity.ok(json);
这里有一个不同的方法。创建一个带有@ResponseStatus注解的自定义Exception,如下所示。
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Not Found")
public class NotFoundException extends Exception {
public NotFoundException() {
}
}
需要的时候扔出去。
@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public String match(@PathVariable String matchId) {
String json = matchService.getMatchJson(matchId);
if (json == null) {
throw new NotFoundException();
}
return json;
}