Spring MVC拦截器
在Spring MVC中,拦截器Interceptor和过滤器的Filter的作用是一样的,都是对某些资源的拦截。并且如果有多个拦截器对同一个资源进行拦截的时候,那么这时候就形成了拦截器链,此时是根据在spring-mvc.xml中配置拦截器的顺序,按照顺序执行preHandle方法,然后当目标资源执行完毕之后,就根据配置的顺序,倒序执行postHandle操作,当postHandle操作执行完毕之后,在根据配置的顺序,倒叙执行afterCompletion操作。
而Spring MVC拦截器和Filter的区别是: 所以执行拦截器的相关操作主要有3个步骤:
-
自定义拦截器XXInterceptor,使得这个类实现了HandlerInterceptor,然后重写它的方法preHandle,postHandle,afterCompletion,其中主要是重写preHandle方法。 -
在spring-mvc.xml中配置拦截器,对应的格式为: <mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="xxx"/>
<mvc:exclude-mapping path="zzz">
<bean class="yyyy"></bean>
</mvc:interceptor>
<mvc:interceptor>
......
</mvc:interceptor>
</mvc:interceptors>
-
进行相应的测试
所以Interceptors自定义类对应的代码为:
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle is running......");
String param = request.getParameter("param");
if("yes".equals(param)){
return true;
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle is running......");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion is running.....");
}
}
public class MyInterceptor2 implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor2 preHandle is running.........");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor2 postHandle is running........");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor2 afterCompletion is running........");
}
}
对应的spring-mvc.xml文件中配置拦截器的代码为:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/interceptorController/**"/>
<bean class="day6.demo.interceptors.MyInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"></mvc:mapping>
<bean class="day6.demo.interceptors.MyInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
对应的测试类:
@Controller
@RequestMapping("/interceptorController")
public class InterceptorController {
@RequestMapping("/test")
public ModelAndView test(ModelAndView modelAndView){
System.out.println("InterceptorController is running....");
modelAndView.addObject("name","大大怪");
modelAndView.setViewName("/index.jsp");
return modelAndView;
}
}
所以,如果输入的是localhost:8080/interceptorController/test?param=yes 的时候,2个拦截器都进行拦截同一个资源,这时候preHandle操作时根据sprng-mvc中配置的顺序来执行的是,当所有的拦截器的preHandle方法都执行之后,才可以放行去执行目标资源,当目标资源执行完毕之后,先去执行postHandle操作,但是这时候是根据拦截器配置的顺序的倒序执行的,当所有的拦截器都执行了postHandle方法之后,再根据拦截器配置的顺序的倒序执行afterCompletion方法。所以多个拦截器对同一资源进行拦截的时候,执行顺序也是如此。所以对应的结果如下所示:
Spring MVC中请求映射发生404错误
当Spring MVC请求映射发生404错误的时候,情况可能有很多种:
- controller中没有使用注解@Controller,将这个xxxController添加到Spring MVC容器中;
- 虽然已经使用了注解@Controller,但是spring-mvc.xml中没有配置
<context:component-scan base-package="xxx"/> 来扫描controller层的组件; - 有可能请求的资源路径错误了;
- 可能web.xml中配置错误
但是如果上面的配置都没有错误的情况下,那么我们需要看一下spring-mvc.xml中是否已经添加了<mvc:annotation-driven/> ,如果没有,那么尝试将这一句添加到spring-mvc.xml中,再次请求的时候,发现能够正常映射了(我的情况就是这个,😭😭😭)
但是为什么加上这个之后,就可以映射了呢?
原来,<mvc:annotation-driver/> 是Spring MVC用来提供Controller请求转发,json自动转换,配置内部资源解析器等功能的类,会默认帮我们注册处理请求,参数和返回值的类。
参考资料:springmvc 中 注解驱动:<mvc:annotation-driven>的作用和使用
Spring MVC的异常处理
利用Spring MVC中,我们可以在service.dao层通过throws来声明可能出现的异常,如果抛出了异常,那么将会有controller来通过try-catch来处理。但是我们可以利用Spring MVC来处理异常,所以并不需要我们在controller层中来try-catch异常。所以对应的异常处理步骤如下所示: 所以我们在利用Spring MVC来处理异常的时候,需要配置异常处理器HandlerExceptionResolver.而配置异常处理器可以有2种方式:
-
直接在spring-mvc.xml中配置Spring MVC中的SimpleMappingExceptionResolver(简单映射异常解析器),对应的代码为: <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView" value="error.jsp"></property>
<property name="exceptionMappings">
<map>
<entry key="java.lang.ArithmeticException" value="error2.jsp"></entry>
<entry key="java.lang.NumberFormatException" value="error1.jsp"></entry>
<entry key="java.lang.NullPointerException" value="error3.jsp"></entry>
</map>
</property>
</bean>
-
自定义一个类,使得这个类实现了Spring MVC中的HandlerExceptionResolver接口,并且实现它的resolveException方法,在这个方法中,根据对应的异常,从而做出相应的处理,然后将返回一个ModleAndView对象。之后再spring mvc中将这个自定义类添加到Spring MVC容器中,对应的代码为: 自定义类MyExceptionResolver代码: public class MyHandlerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
ModelAndView modelAndView = new ModelAndView();
if(e instanceof NumberFormatException){
modelAndView.setViewName("error1.jsp");
}else if(e instanceof NullPointerException){
modelAndView.setViewName("error3.jsp");
}else if(e instanceof ArithmeticException){
modelAndView.setViewName("error2.jsp");
}else{
modelAndView.setViewName("error.jsp");
}
return modelAndView;
}
}
在spring-mvc.xml中配置自定义类 <bean class="day7.demo.exceptions.MyHandlerException"></bean>
|