前言
采用 Spring AOP 方式实现
采用 Spring3.2之后提供的 @ControllerAdvice 注解 和 @ExceptionHandler 实现
关于 Controller 层异常的处理
如果你是想处理关于Controller层的异常(<strong>不仅限于是controller层自身主动抛出/catch的异常,只要是最终由controller层抛出的异常都可以使用 @ControllerAdvice 方式</stron>),那么以上两种方式均可由你选择。
@ControllerAdvice + @ExceptionHandler 方式
见名知意,@ControllerAdvice 是对于 使用@Controller的建议,那么凡是使用了@RequestMapping的地方的异常均可该种方式处理。
下面我以一个demo来说明一下,如何使用吧。
controller
层
public class UserController {
value = "/update", method = RequestMethod.POST) (
public R update( User user){
userService.update(user);
return R.success(null);
}
}
注意:在调用的service中,我手动模拟抛出了一个异常,如下所示:
public class UserServiceImpl implements UserService {
public void update(User user) {
userMapper.update(user);
throw new RuntimeException("运行时易出错");
}
}
关于类似这种controller层的异常我们就可以构造一个全局controller异常的处理工具,如下:
// 使用 @ControllerAdvice 方式来实现对 @RequestMapping 的异常拦截 // 缺点很明显,是对于 controller 的建议,只能对controller起作用
public class ControllerException {
private static final Logger log = LoggerFactory.getLogger(ControllerException.class);
value = Exception.class) (
public Map<String, String> getMsg(HttpServletRequest request, HttpServletResponse response, Exception e){
log.error("该服务可能出错了");
return Collections.singletonMap("msg", "服务出错");
}
}
这样当调用 /update
接口时,service层会报错,从而传递到controller层,从而被 ControllerException 异常处理类拦截,就可以在这里解决了,可以down下代码,自行测试一下,这里不做演示了。
这种方式的缺点很明显:只能处理 controller 层抛出的异常,对例如 Interceptor(拦截器)层的异常、定时任务中的异常、异步方法中的异常,不会进行处理。
Spring AOP 动态代理方式
上面的controller层和service代码不用作任何修改。只需要再新增一个异常处理类即可。
package com.example.study_source.transaction.exception;
// 使用 aop 来全局拦截异常,可以作用于你自定义的任何包路径下 // 相比 @ControllerAdvice 有优势
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
public class AOPGlobalException {
"execution(* com.example.study_source.transaction..*.*(..))") (
public void point1(){
}
pointcut = "point1()") (
public void afterReturn(JoinPoint joinPoint){
log.error("全局捕获到异常了..............");
//纪录错误信息
// todo 想要执行的操作
}
}
如上方式不仅可以实现controller层的异常处理,只要符合切点包的定义的方法,都可以拦截。
0 Comments