本文由作者三汪首發(fā)于簡書。
近來開始著手基于Spring Boot的Java后端開發(fā),糾結(jié)過應(yīng)該如何優(yōu)雅地向前端拋異常。幸而發(fā)現(xiàn)Spring提供了異常處理的手段。
Spring通過@ExceptionHandler來攔截系統(tǒng)運(yùn)行時(shí)拋出的相應(yīng)異常。其有效作用域是其所處的Controller,即它聲明的異常處理方法無法攔截、處理其他Controller類中拋出的異常。
但是我們還可以通過在類上使用@ControllerAdvice(控制器增強(qiáng)。該注解可以把其聲明的類中使用@ExceptionHandler、@InitBinder、@ModelAttribute注解的方法應(yīng)用到所有的 @RequestMapping注解的方法)聲明一個(gè)攔截全局異常的@ExceptionHandler。這樣做可以有效減少代碼冗余。具體如何使用,應(yīng)該視具體業(yè)務(wù)需求而定。
下面上代碼:
ErrorInfo.java(這個(gè)類是用來返回給前端的實(shí)體)
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是我們自定義的業(yè)務(wù)異常類)
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(這個(gè)類用于處理所有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異常結(jié)束------------");
return r;
}
}
在這里,我們只聲明攔截了BizException,不過,ExceptionHandler中支持聲明攔截多個(gè) Exception,只需要在花括號中增加新的聲明即可。
@ResponseStatus用于設(shè)置返回給前端的Http狀態(tài)碼,個(gè)人建議設(shè)置成BAD_REQUEST,即400。
當(dāng)我們不需要全局?jǐn)r截異常的時(shí)候,我們可以這樣寫:
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("------------當(dāng)前類AssociationController捕獲BIZ異常開始------------");
ErrorInfo r = new ErrorInfo();
r.setSuccess(false);
r.setMsg(e.getMessage());
this.logger.info("ErrorInfo==" + ToStringBuilder.reflectionToString(r));
this.logger.info("------------當(dāng)前類AssociationController捕獲BIZ異常結(jié)束------------");
return r;
}
}
此時(shí),該ExcetionHandler只能攔截當(dāng)前類中產(chǎn)生的BizException。
以上。
希望我的文章對你能有所幫助。
我不能保證文中所有說法的百分百正確,但我能保證它們都是我的理解和感悟以及拒絕復(fù)制黏貼。
有什么意見、見解或疑惑,歡迎留言討論。