Java 使用SpringMVC定制http代码

Java 使用SpringMVC定制http代码,java,spring,spring-mvc,Java,Spring,Spring Mvc,我使用以下代码使用SpringMVC处理rest调用 @RequestMapping(value = "login", method = RequestMethod.GET) public @ResponseBody User login(@RequestParam String username, @RequestParam String password) { User user = userService.login(username, password); if (use

我使用以下代码使用SpringMVC处理rest调用

@RequestMapping(value = "login", method = RequestMethod.GET)
public @ResponseBody
User login(@RequestParam String username, @RequestParam String password) {
    User user = userService.login(username, password);
    if (user == null)
        ...
    return user;
} 

我想向客户发送错误用户名、错误密码、密码更改和密码过期条件的http代码。如何修改现有代码以将这些错误代码发送到客户端?

一种方法是添加一些用于返回HTTP错误的附加类。您的代码如下所示:

@RequestMapping(value = "login", method = RequestMethod.GET)
@ResponseBody
public User login(@RequestParam String username, @RequestParam String password) {
    User user = userService.login(username, password);
    if (user == null)
        throw new UnauthorizedException();
    return user;
   } 
}

@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
public class UnauthorizedException extends RuntimeException{
}
在这种情况下,用户将获得
401
响应状态代码


我希望这会有所帮助

您可以使用控制器建议在运行时将控制器中抛出的异常映射到一些特定于客户端的数据。 例如,如果找不到用户,控制器应该抛出一些异常(自定义或已存在的异常)

然后,您应该添加@ControllerAdvice来捕获控制器异常并进行“异常到状态”映射(优点:您将对“异常到状态映射”承担单一责任):


希望这有帮助。

您可以返回HTTP 500或您选择的代码(从org.springframework.HTTP.HttpStatus枚举中),并使用自定义错误模拟JSON响应中的SOAP错误

例如:

@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(YourTargetException.class)
@ResponseBody
Fault caughtYourTargetException(HttpServletRequest req, Exception ex) {

    String code = ex.getClass().getName();
    String reason = "Caught YourTargetException."
    return new Fault(code, reason);
}
Fault类可以是这样的(受以下启发):

/**
*错误是一个对象,当出现预期错误时,可以将其序列化为JSON。
*/
公共类过失{
@JsonProperty(“故障代码”)
私有最终字符串代码;
@JsonProperty(“故障原因”)
私人最终字符串原因;
@JsonProperty(“faultDetails”)
私有最终列表详细信息=新建ArrayList();
公共错误(字符串代码、字符串原因){
this.code=代码;
这个。原因=原因;
}
公共错误(字符串代码、字符串原因、字符串…详细条目){
this.code=代码;
这个。原因=原因;
addAll(Arrays.asList(detailEntries));
}
公共字符串getCode(){
返回码;
}
公共字符串getReason(){
返回原因;
}
/**
*零个或多个详细信息可能与故障相关。它携带
*与故障相关的附加信息。例如,详细信息
*元素信息项可能包含有关消息的信息
*未包含正确的凭据、超时等。
*@返回零个或多个详细信息条目。
*/
公共Iterable getDetails(){
退货详情;
}
@凌驾
公共字符串toString(){
返回String.format(“出现错误%s。原因是%s.”,getCode(),
getReason());
}
}

您可以在Java框架中使用现有的SOAPFaults之一,但我发现它们在REST中不能很好地发挥作用。创建自己的简单版本变得更简单。

您可以定义自己的状态代码和返回对象。在代码中,抛出自定义异常,然后定义异常处理程序,如下所示:

@ControllerAdvice
public class GlobalControllerExceptionHandler {

@ExceptionHandler(MyException.class)
public ResponseEntity<MyRetObject> handleControllerError(HttpServletRequest req, MyException ex) {
    LOG.warn("My error", ex);
    MyRetObject errorMessage = new MyRetObject(ex.getMessage());
    return ResponseEntity.status(600).body(errorMessage);
}
@ControllerAdvice
公共类GlobalControllerExceptionHandler{
@ExceptionHandler(MyException.class)
公共响应句柄控制器错误(HttpServletRequest请求,MyException ex){
LOG.warn(“我的错误”,例如);
MyRetObject errorMessage=新的MyRetObject(例如getMessage());
返回响应状态(600)正文(错误消息);
}
}

在您的情况下,用UserNotFoundException.class替换MyExeption.class,并生成客户错误响应对象和错误代码

@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(YourTargetException.class)
@ResponseBody
Fault caughtYourTargetException(HttpServletRequest req, Exception ex) {

    String code = ex.getClass().getName();
    String reason = "Caught YourTargetException."
    return new Fault(code, reason);
}
/**
 * A Fault is an object that can be serialized as JSON when expected errors    occur.
*/
public class Fault {

  @JsonProperty("faultCode")
  private final String code;

  @JsonProperty("faultReason")
  private final String reason;

  @JsonProperty("faultDetails")
  private final List<String> details = new ArrayList<>();

  public Fault(String code, String reason) {
    this.code = code;
    this.reason = reason;
  }

  public Fault(String code, String reason, String... detailEntries) {
    this.code = code;
    this.reason = reason;
    details.addAll(Arrays.asList(detailEntries));
  }

  public String getCode() {
      return code;
  }

  public String getReason() {
      return reason;
  }

  /**
   * Zero or more details may be associated with the fault. It carries 
   * additional information relative to the fault. For example, the Detail
   * element information item might contain information about a message
   * not containing the proper credentials, a timeout, etc.
   * @return Zero or more detail entries.
   */
  public Iterable<String> getDetails() {
      return details;
  }

  @Override
  public String toString() {
      return String.format("Fault %s occurred. The reason is %s.", getCode(), 
          getReason());
  }
}
@ControllerAdvice
public class GlobalControllerExceptionHandler {

@ExceptionHandler(MyException.class)
public ResponseEntity<MyRetObject> handleControllerError(HttpServletRequest req, MyException ex) {
    LOG.warn("My error", ex);
    MyRetObject errorMessage = new MyRetObject(ex.getMessage());
    return ResponseEntity.status(600).body(errorMessage);
}