我使用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。


当前回答

这不是最紧凑的方式,但在我看来很干净:

if(json == null) {
    throw new BadThingException();
}
...

@ExceptionHandler(BadThingException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public @ResponseBody MyError handleException(BadThingException e) {
    return new MyError("That doesn’t work");
}

如果使用Spring 3.1+,您可以在异常处理方法中使用@ResponseBody,否则使用ModelAndView或其他东西。

@ResponseBody不能与@ExceptionHandler [sp -6902] #11567一起工作

其他回答

使用带有状态代码的自定义响应。

是这样的:

class Response<T>(
    val timestamp: String = DateTimeFormatter
            .ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS")
            .withZone(ZoneOffset.UTC)
            .format(Instant.now()),
    val code: Int = ResultCode.SUCCESS.code,
    val message: String? = ResultCode.SUCCESS.message,
    val status: HttpStatus = HttpStatus.OK,
    val error: String? = "",
    val token: String? = null,
    val data: T? = null
) : : ResponseEntity<Response.CustomResponseBody>(status) {

data class CustomResponseBody(
    val timestamp: String = DateTimeFormatter
            .ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS")
            .withZone(ZoneOffset.UTC)
            .format(Instant.now()),
    val code: Int = ResultCode.SUCCESS.code,
    val message: String? = ResultCode.SUCCESS.message,
    val error: String? = "",
    val token: String? = null,
    val data: Any? = null
)

override fun getBody(): CustomResponseBody? = CustomResponseBody(timestamp, code, message, error, token, data)

这不是最紧凑的方式,但在我看来很干净:

if(json == null) {
    throw new BadThingException();
}
...

@ExceptionHandler(BadThingException.class)
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public @ResponseBody MyError handleException(BadThingException e) {
    return new MyError("That doesn’t work");
}

如果使用Spring 3.1+,您可以在异常处理方法中使用@ResponseBody,否则使用ModelAndView或其他东西。

@ResponseBody不能与@ExceptionHandler [sp -6902] #11567一起工作

这样的方法应该是可行的,但我不确定是否有更简单的方法:

@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;
}

我在Spring Boot应用程序中使用这个:

@RequestMapping(value = "/matches/{matchId}", produces = "application/json")
@ResponseBody
public ResponseEntity<?> match(@PathVariable String matchId, @RequestBody String body,
            HttpServletRequest request, HttpServletResponse response) {

    Product p;
    try {
      p = service.getProduct(request.getProductId());
    } catch(Exception ex) {
       return new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
    }

    return new ResponseEntity(p, HttpStatus.OK);
}

这里有一个不同的方法。创建一个带有@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;
}