我使用以下代码来处理使用Spring MVC的休息调用。
@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代码。如何修改现有代码以将这些错误代码发送给客户端?
答案 0 :(得分:6)
您可以使用控制器建议将控制器内抛出的异常映射到运行时的某些客户端特定数据。 例如,如果找不到用户,您的控制器应该抛出一些异常(自定义或现有的)
@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 UserNotFoundException(username); //or another exception, it's up to you
return user;
}
}
然后你应该添加@ControllerAdvice,它将捕获控制器异常并进行'异常到状态'映射(专业人士:你将对'异常到状态映射'有单一的责任点):
@ControllerAdvice
public class SomeExceptionResolver {
@ExceptionHandler(Exception.class)
public void resolveAndWriteException(Exception exception, HttpServletResponse response) throws IOException {
int status = ...; //you should resolve status here
response.setStatus(status); //provide resolved status to response
//set additional response properties like 'content-type', 'character encoding' etc.
//write additional error message (if needed) to response body
//for example IOUtils.write("some error message", response.getOutputStream());
}
}
希望这有帮助。
答案 1 :(得分:1)
一种方法是添加一些额外的类来返回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
响应状态码
我希望有所帮助
答案 2 :(得分:0)
您可以返回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类看起来像这样(受http://www.w3.org/TR/soap12-part1/#soapfault启发):
/**
* 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());
}
}
您可以在Java框架中使用现有的SOAPFaults之一,但我发现它们在REST中不能很好地发挥作用。创建我自己的简单版本变得更简单。
答案 3 :(得分:0)
您可以定义自己的状态代码并返回对象。在您的代码中抛出自定义异常,然后按如下方式定义异常处理程序:
@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);
}
}
在你的情况下,用UserNotFoundException.class替换MyExeption.class并构建你的客户错误响应对象和错误代码