本文由作者三汪首发于简书。
近来开始着手基于Spring Boot的Java后端开发,纠结过应该如何优雅地向前端抛异常。幸而发现Spring提供了异常处理的手段。
Spring通过@ExceptionHandler来拦截系统运行时抛出的相应异常。其有效作用域是其所处的Controller,即它声明的异常处理方法无法拦截、处理其他Controller类中抛出的异常。
但是我们还可以通过在类上使用@ControllerAdvice(控制器增强。该注解可以把其声明的类中使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法应用到所有的 @RequestMapping注解的方法)声明一个拦截全局异常的@ExceptionHandler。这样做可以有效减少代码冗余。具体如何使用,应该视具体业务需求而定。
下面上代码:
ErrorInfo.java(这个类是用来返回给前端的实体)
public class ErrorInfo {
private boolean success;
private String msg;
private Object errors;
public boolean isSuccess(){
return this.success;
}
public String getMsg() {
return this.msg;
}
public Object getErrors() {
return this.errors;
}
public void setSuccess(boolean success)
{
this.success = success;
}
public void setMsg(String msg) {
this.msg = msg;
}
public void setErrors(Object errors) {
this.errors = errors;
}
}
BizException.java(BizException是我们自定义的业务异常类)
public class BizException extends Exception{
/**
* @fields serialVersionUID
*/
private static final long serialVersionUID = -2420754730135049197L;
private Object data;
public BizException() {
super();
}
public BizException(String message) {
super(message);
}
public Object getData() {
return this.data;
}
public void setData(Object data) {
this.data = data;
}
}
GlobalExceptionHandler.java(这个类用于处理所有Controller中抛出的BizException)
@RestController
@ControllerAdvice
public class GlobalExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(getClass());
@ExceptionHandler({BizException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorInfo handleBizException(BizException e){
this.logger.info("------------全局捕获BIZ异常开始------------");
ErrorInfo r = new ErrorInfo();
r.setSuccess(false);
r.setMsg(e.getMessage());
this.logger.info("ErrorInfo==" + ToStringBuilder.reflectionToString(r));
this.logger.info("------------全局捕获BIZ异常结束------------");
return r;
}
}
在这里,我们只声明拦截了BizException,不过,ExceptionHandler中支持声明拦截多个 Exception,只需要在花括号中增加新的声明即可。
@ResponseStatus用于设置返回给前端的Http状态码,个人建议设置成BAD_REQUEST,即400。
当我们不需要全局拦截异常的时候,我们可以这样写:
AssociationController .java(普通Controller类)
@RestController
public class AssociationController {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
IStudentService studentService;
//其余方法略...
@RequestMapping(value = "/student/get" , method = RequestMethod.GET)
public Student getStudent(@RequestParam(value="name",required=false)String name) throws BizException{
Student student = null;
if (name != null) {
if (name.equals("Chaves")) {
throw new BizException("Chaves is invalid!");
}
student = studentService.findByName(name);
}
return student;
}
@ExceptionHandler({BizException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public ErrorInfo handleBizException(BizException e){
this.logger.info("------------当前类AssociationController捕获BIZ异常开始------------");
ErrorInfo r = new ErrorInfo();
r.setSuccess(false);
r.setMsg(e.getMessage());
this.logger.info("ErrorInfo==" + ToStringBuilder.reflectionToString(r));
this.logger.info("------------当前类AssociationController捕获BIZ异常结束------------");
return r;
}
}
此时,该ExcetionHandler只能拦截当前类中产生的BizException。
以上。
希望我的文章对你能有所帮助。
我不能保证文中所有说法的百分百正确,但我能保证它们都是我的理解和感悟以及拒绝复制黏贴。
有什么意见、见解或疑惑,欢迎留言讨论。