在项目中,我们不可能能够预知并catch所有的异常,为了避免非期望异常抛给客户端,Spring为我们提供了统一异常处理的机制@RestControllerAdvice,能够让我们在逻辑抛出异常时,能够将异常友好化或者指定返回的数据结构给前台。
用法示例如下:
@RestControllerAdvice
public class ExceptionHandleAdvice {
private final Logger logger = LoggerFactory.getLogger(ExceptionHandleAdvice.class);
@ExceptionHandler(Exception.class)
public String exceptionHandle(Exception e){
logger.error("系统异常:", e);
return "系统异常!";
}
}
以上的代码放在Spring工程中,就会将Controller中抛出的异常在这里集中处理,打印日志后返回“系统异常!”给用户端。
写个Controller例子体会一下使用之前和之后的区别:
@RestController
@RequestMapping("/time")
public class TimeController {
@GetMapping("/now")
public LocalDateTime now(){
return LocalDateTime.now();
}
/**
* 返回当前时间+count后的时间字符串
*
* @param count 未来天数
* @return 时间字符串
*/
@GetMapping("/oneDay")
public LocalDateTime now(@RequestParam Long count){
return LocalDateTime.now().plusDays(count);
}
}
这是个很简单的controller,就是返回当前时间+count后的时间字符串,我们只需要使用get请求将count传给服务端,那么服务端将返回现在时间+count天的时间字符串。
浏览器测试一下:
当然,这个接口漏洞也很明显,当我们传一个不是Long类型的count值过去就会出现异常:
很不友好的异常报错信息,没学过编程的人还以为自己电脑出问题了。所以我们要对用户友好一点,加入上文写的ExceptionHandleAdvice 统一异常处理类再次启动试一下:
very 友好
这个用法只是@RestControllerAdvice的小实例,我们可以在这个统一异常处理类中添加其他逻辑如:
@RestControllerAdvice
public class ExceptionHandleAdvice {
private final Logger logger = LoggerFactory.getLogger(ExceptionHandleAdvice.class);
@ExceptionHandler(Exception.class)
public String exceptionHandle(Exception e) {
logger.error("系统异常:", e);
return "系统异常!";
}
// 处理自定义异常
@ExceptionHandler(TermException.class)
public String exceptionHandle(TermException termException) {
logger.error("自定义异常:", termException);
return termException.getMessage();
}
// 处理正常请求,对时间进行格式化
@ResponseStatus(HttpStatus.ACCEPTED) // 值为202
public <T> String sendSuccessResponse(T data) {
if (data instanceof LocalDateTime) {
return "时间为" + ((LocalDateTime) data).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
return data.toString();
}
}
当你的Controller抛出了你自定义的异常TermException时,它就会被上面的第二个方法捕获,并将message返回给用户端。测试一下:
先在controller中抛出该异常:
@GetMapping("/oneDay")
public LocalDateTime now(@RequestParam Long count){
if (count < 0L){
throw new TermException("count不能小于0!");
}
return LocalDateTime.now().plusDays(count);
}
重启服务后,请求后结果如下: