mvc框架中@ControllerAdvice全局异常处理和@ModelAtrribute全局异常绑定

一、@ControllerAdvice
1、作用:配合一个或者多个自定义异常类(如下文:BusinessException),实现全局或者某个控制器(如下文:TestController)的异常处理功能。
2、原理:顾名思义,它其实是利用AOP(面向切面),实现在调用controller中的方法后织入后置异常通知。(因AOP主要还是利用动态代理模式,想深入了解可以看这篇https://www.jianshu.com/p/95970b089360,大概意思就是:控制器其实是一个代理对象,在调用里面的方法时进入代理方法中,在method.invoke(target,arg)执行时捕捉异常,利用反射生成@ControllerAdvice注解声明的类的对象,再调用对应的@ExceptionHandler方法进行处理)----本人才疏学浅,这只是实战类的博客就不多说了。
示例:
a、自定义异常类

public class BusinessException extends RuntimeException {
	private String message;
	//最好定义带参构造器
	public BusinessException(String message) {
		super();
		this.message = message;
	}
	public String getMessage() {
		return message;
	}
	public void setMessage(String message) {
		this.message = message;
	}
}

b、异常处理器

//这里指定切入的controller ----不指定情况下,默认所有控制器抛出的异常都会在这个类进行处理 
@ControllerAdvice(assignableTypes={TestController.class})
public class ExceptionAdvice {
	//指定异常处理器所处理的异常(可自定义也可使用java自带的)
	@ExceptionHandler(BusinessException.class)
	public ModelAndView businessExceptionAdvice(Exception e){
	//参数e其实是BusinessException的对象,可以获取其中的属性。
		//跳转到异常页面
		 ModelAndView modelAndView = new ModelAndView("testException");
		 //返回到界面的数据
		 modelAndView.addObject("errMsg", message);
		return modelAndView;
		//也可以使用@ResponseBody 返回json格式数据
	} 
}

c、控制器

@Controller
@RequestMapping("/")
public class TestController {
	/**
	 * 全局异常捕捉测试
	 * @param map
	 * @param request
	 * @param response
	 */
	@RequestMapping(value="exception",method=RequestMethod.GET)
	@ResponseBody
	public void exceptionTest(ModelMap map,HttpServletRequest request,HttpServletResponse response)  throws Exception{
		throw new BusinessException("发生运行时异常!");
	}
}

d、异常jsp界面主要部分

     <h4>异常:${errMsg}</h4>

------------------------到此简易的全局异常处理demo完成----------------------------
下面再说一下,在@ControllerAdvice注解下ExceptionAdvice 类中,使用@ModelAtrribute实现全局控制器数据绑定
好处:可以在路由到对应方法前,进行数据预先处理(添加的情况下,就是在controller方法前,调用一下这些方法使之注入到modelMap中)
缺点:因为每次路由都会先进入,@ModelAtrribute注解的方法,因此会牺牲一部分性能
(另外:@ModelAttribute标注的方法的执行是在所有拦截器的preHandle()方法执行之后才会执行。)

	/**
	 * 全局数据绑定---1、指定名称
	 * @return
	 */
    @ModelAttribute(value="testModel")
    public String mydata() {
        return "这是一个全局绑定数据的测试";
    }
	/**
	 * 全局数据绑定 2、对象绑定 ---默认的key就是user
	 * @return
	 */
    @ModelAttribute  
    public User addAccount() {  
    	User user = new User();
    	user.setId("333");
    	user.setName("啊啊");
        return user;  
    }  

	/**
	 * 全局数据绑定 3、直接在ModelMap中设置 ---默认的key就是user
	 * @return
	 */
    @ModelAttribute  
    public void addMap(ModelMap map) {  
        map.put("id", 99);
        map.put("name", "老王");
    } 
	/**
	 * 全局异常捕捉测试
	 * @param map
	 * @param request
	 * @param response
	 */
	@RequestMapping(value="exception",method=RequestMethod.GET)
	@ResponseBody
	public void exceptionTest(@ModelAttribute("user") User user,ModelMap map,@ModelAttribute("testModel") String msg,HttpServletRequest request,HttpServletResponse response)  throws Exception{
		//获取方式1、指定名称
		System.out.println("msg1:"+msg);
		//获取方式2、指定对象
		System.out.println("user:"+user.getName()+" "+user.getId());

		//获取方式3、ModelMap中获取数据
		Integer id = (Integer)map.get("id");
		String name = (String)map.get("name");
		System.out.println("id:"+id+" name:"+name);
		//向前台返回异常
		throw new BusinessException("发生运行时异常!");
	}

运行结果:
msg1:这是一个全局绑定数据的测试
user:啊啊 333
id:99 name:老王

然后跳转界面。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值