目录
一、SpringMVC的拦截器
1.1拦截器简介
1.2Interceptor和Filter的区别
1.3拦截器快速入门
1.4拦截器方法说明
二、SpringMVC的异常处理机制
2.1SpringMVC异常处理的两种方式
2.2简单异常处理器
2.3自定义异常处理
Spring MVC 的拦截器Interceptor类似于 Servlet 开发中的过滤器Filter,用于对处理器进行预处理和后处理。
将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(Interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体实现。
区别 |
过滤器 |
拦截器 |
使用范围 |
是 servlet 规范中的一部分,任何 Java Web 工程都可以使用 |
是 SpringMVC 框架自己的,只有使用了 SpringMVC 框架的工程才能用 |
拦截范围 |
在 url-pattern 中配置了/*之后,可以对所有要访问的资源拦截 |
只会拦截访问的控制器方法,如果访问的是 jsp,html,css,image 或者 js 是不会进行拦截的 |
我们可以试着自己创建一个拦截器,用于对处理器进行预处理和后处理。其主要步骤如下:
首先我们新建一个拦截器类,实现HandlerInterceptor接口,
class InterceptorTest implements HandlerInterceptor {
//在目标方法执行之前执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle......");
return true;//执行拦截方法后继续执行后续方法。如果返回false,则后续方法都不执行
}
//在目标方法执行之后 视图对象返回之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle......");
}
//在整个流程都执行完毕后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion......");
}
}
然后我们对拦截器进行配置,
最后我们在controller层创建一个资源以供访问,尝试进行拦截,
@RequestMapping("/target")//配置映射地址
public ModelAndView show(){
System.out.println("目标资源执行......");
ModelAndView modelAndView=new ModelAndView();//创建模型视图对象
modelAndView.addObject("name","test");//添加属性
modelAndView.setViewName("/index.jsp");//设置视图,即要跳转显示数据的界面,这里是webapp/index.jsp
return modelAndView;
}
启动服务器,访问http://localhost:8080/target,
可以看到拦截器成功拦截了资源,并执行了前后的处理方法。
方法名 |
说明 |
preHandle() |
方法将在请求处理之前进行调用,该方法的返回值是布尔值Boolean类型的,当它返回为false 时,表示请求结束,后续的Interceptor 和Controller 都不会再执行;当返回值为true 时就会继续调用下一个Interceptor 的preHandle 方法 |
postHandle() |
该方法是在当前请求进行处理之后被调用,前提是preHandle 方法的返回值为true 时才能被调用,且它会在DispatcherServlet 进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作 |
afterCompletion() |
该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行,前提是preHandle 方法的返回值为true 时才能被调用 |
对于preHandle,我们一般读取请求里面的参数决定是否继续执行后续方法,
//在目标方法执行之前执行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle......");
String param = (String) request.getParameter("param");//获取参数
if ("yes".equals(param)){
return true;//执行完拦截方法后,继续执行后续方法
}else{
request.getRequestDispatcher("/error.jsp");//跳转到错误界面
return false;//不执行后续方法
}
}
如果有多个拦截器,我们一般根据配置拦截器的顺序来决定执行的顺序,例如:
启动服务器查看调用顺序,
系统中异常包括两类:预期异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发、测试等手段减少运行时异常的发生。
在javeSE和web的学习中,我们一般处理异常就是try catch语句,但是在框架中我们希望异常处理能和业务代码解耦,并且对于同样的异常处理程序,我们希望能抽取称为一个组件,增加代码的复用性。所以在SpringMVC框架中,异常处理是抛出的形式。
系统的Dao、Service、Controller出现都通过throws Exception向上抛出,最后由SpringMVC前端控制器交由异常处理器进行异常处理,如下图:
在使用SpringMVC框架时,有两种处理异常的方式:
SpringMVC提供了一种简单的异常处理器,我们可以直接配置进行使用。
在配置的时候,我们主要配置的是异常类型和视图的映射关系,即发生这种异常了要跳到什么界面。
首先我们在Service模拟写几种类型的异常方法,
@Service("exceptionService")
class ExceptionServiceImpl implements ExceptionService {
public void exceptionTest1() {
System.out.println("类型转换异常");
Object str="test";
Integer num= (Integer) str;
}
public void exceptionTest2() {
System.out.println("除零异常");
int i=1/0;
}
public void exceptionTest3() throws FileNotFoundException {
System.out.println("找不到文件异常");
InputStream in=new FileInputStream("C:/sadwadnmkw/ad.txt");
}
public void exceptionTest4() {
System.out.println("空指针异常");
String str=null;
str.length();
}
public void exceptionTest5() throws MyException {
System.out.println("自定义异常");
throw new MyException();
}
}
然后我们在Controller层通过注解的方法获取ExceptionService对象,并调用其中的异常方法,
@Controller
class ExceptionController {
@Autowired//自动注入
private ExceptionService exceptionService;
@RequestMapping("/exception1")
public void test1(){
exceptionService.exceptionTest1();
}
@RequestMapping("/exception2")
public void test2(){
exceptionService.exceptionTest2();
}
@RequestMapping("/exception3")
public void test3() throws FileNotFoundException {
exceptionService.exceptionTest3();
}
@RequestMapping("/exception4")
public void test4(){
exceptionService.exceptionTest4();
}
@RequestMapping("/exception5")
public void test5() throws MyException {
exceptionService.exceptionTest5();
}
}
接着我们配置简单异常处理器SimpleMappingExceptionResolver,
然后我们启动服务器访问url,分别触发几种异常
自定义异常处理步骤如下:
第一步我们先创建异常处理器类,实现HandlerExceptionResolver接口中的异常处理方法,
class MyExceptionResolver implements HandlerExceptionResolver {
/**
*
* @param httpServletRequest
* @param httpServletResponse
* @param o
* @param e:异常对象
* @return ModelAndView:跳转到错误视图信息
*/
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView=new ModelAndView();
if (e instanceof MyException){//如果是自定义异常
modelAndView.addObject("info","自定义异常");
}else if (e instanceof ClassCastException) {//如果是类型转换异常
modelAndView.addObject("info", "类型转换异常");
}else{//如果是其他类型的异常
modelAndView.addObject("info", "其他异常");
}
modelAndView.setViewName("/error.jsp");//统一跳转到通用错误异常视图
return modelAndView;
}
}
第二步我们在spring-mvc.xml中配置异常处理器,直接可以用bean标签指定类即可,因为我们已经在异常处理方法中指定了不同的异常跳转界面的映射关系。
第三步我们编写异常显示界面,在异常处理方法中,我们写入了info数据,我们在error.jsp中取出信息并显示。
通用的错误提示界面
${info}
第四步我们启动服务器进行测试,