Spring 详解(三)------- SpringMVC拦截器使用


不拦截静态资源

  • 若是配置拦截相似于*.do格式的拦截规则,则对静态资源的访问是没有问题的,可是若是配置拦截了全部的请求(如咱们上面配置的“/”),就会形成js文件、css文件、图片文件等静态资源没法访问。css

  • 拦截器的主要做用是是用于权限管理,拦截不合理的URL,因此不对静态资源进行拦截。html

  • 使用<mvc:resources/> (mapping:请求,location:映射地址,注意必须是webapp根目录下的路径。) java

spring配置文件:applicationContext-mvc.xml
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/images/**" location="/img/"/>
<mvc:resources mapping="/js/**" location="/js/"/>


使用拦截器

在实际应用中,我们通常都是经过实现 HandlerInterceptor 接口或者继承 HandlerInterceptorAdapter 抽象类,复写 preHandle()postHandle()afterCompletion()这 3 个方法来对用户的请求进行拦截处理的。web

  1. 实现 HandlerInterceptor 接口(须要实现三个方法)

在 HandlerInterceptor 接口中,定义了 3 个方法,分别为 preHandle()postHandle()afterCompletion(),我们就是经过复写这 3 个方法来对用户的请求进行拦截处理的。所以,我们能够经过直接实现 HandlerInterceptor 接口来实现拦截器的功能。spring

public interface HandlerInterceptor {
    //该方法在请求处理以前进行调用。
    boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
    void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;
    void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
}
  • preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) 方法,该方法在请求处理以前进行调用。SpringMVC 中的 Interceptor 是链式调用的,在一个应用中或者说是在一个请求中能够同时存在多个 Interceptor 。每一个 Interceptor 的调用会依据它的声明顺序依次执行,并且最早执行的都是 Interceptor 中的 preHandle 方法,因此能够在这个方法中进行一些前置初始化操做或者是对当前请求作一个预处理,也能够在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回值是布尔值 Boolean 类型的,当它返回为 false 时,表示请求结束,后续的 Interceptor 和 Controller 都不会再执行;当返回值为 true 时,就会继续调用下一个 Interceptor 的 preHandle 方法,若是已是最后一个 Interceptor 的时候,就会是调用当前请求的 Controller 中的方法。
  • postHandle(HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法,经过 preHandle 方法的解释我们知道这个方法包括后面要说到的 afterCompletion 方法都只能在当前所属的 Interceptor 的 preHandle 方法的返回值为 true 的时候,才能被调用。postHandle 方法在当前请求进行处理以后,也就是在 Controller 中的方法调用以后执行,可是它会在 DispatcherServlet 进行视图返回渲染以前被调用,因此我们能够在这个方法中对 Controller 处理以后的 ModelAndView 对象进行操做。postHandle 方法被调用的方向跟 preHandle 是相反的,也就是说,先声明的 Interceptor 的 postHandle 方法反而会后执行。
  • afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex) 方法,也是须要当前对应的 Interceptor 的 preHandle 方法的返回值为 true 时才会执行。所以,该方法将在整个请求结束以后,也就是在 DispatcherServlet 渲染了对应的视图以后执行,这个方法的主要做用是用于进行资源清理的工做。


  1. 继承 HandlerInterceptorAdapter(通常使用此种方式)

须要哪一个方法重写便可,不须要实现全部方法spring-mvc

afterConcurrentHandlingStarted()方法用于处理异步请求,当 Controller 中有异步请求方法的时候会触发该方法时,异步请求先支持 preHandle、而后执行 afterConcurrentHandlingStarted。异步线程完成以后执行preHandlepostHandleafterCompletionmvc

public class TestHandlerInterceptorAdapter extends HandlerInterceptorAdapter {
    public TestHandlerInterceptorAdapter() {
        super();
    }
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return super.preHandle(request, response, handler);
    }
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }
    @Override
    public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        super.afterConcurrentHandlingStarted(request, response, handler);
    }
}


拦截器使用测试

建立拦截器app

public class LoginHandlerInterceptor implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle ------- Intercepter1" );
        return true;
    }
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ------- Intercepter1");
    }
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion ------- Intercepter1");
    }
public class LoginHandlerIntercepter2 implements HandlerInterceptor {

    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        System.out.println("preHandle ------- Intercepter2" );
        return true;
    }

    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle ------- Intercepter2" );
    }

    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("afterCompletion ------- Intercepter2" );
    }
}

在 spring-mvc.xml 声明拦截器webapp

<mvc:interceptors>
     <!--使用 bean 定义一个 Interceptor,直接定义在 mvc:interceptors 下面的 Interceptor 将拦截全部的请求 -->
    <bean class="com.anqi.testHandlerInterceptor.LoginHandlerInterceptor"></bean>
    <mvc:interceptor>
        <mvc:mapping path="/testip"/>
        <!-- 定义在 mvc:interceptor 下面的 Interceptor,表示对特定的请求进行拦截 -->
        <bean class="com.anqi.testHandlerInterceptor.LoginHandlerIntercepter2"></bean>
    </mvc:interceptor>
</mvc:interceptors>

测试结果1(第一个拦截器的 preHandle 返回 true)

preHandle ------- Intercepter1
preHandle ------- Intercepter2
postHandle ------- Intercepter2
postHandle ------- Intercepter1
afterCompletion ------- Intercepter2
afterCompletion ------- Intercepter1
页面上正常返回

测试结果2(第一个拦截器的 preHandle 返回 false)

preHandle ------- Intercepter1

页面没有返回 controller 返回的页面


SimpleMappingExceptionResolver 拦截异常

官方文档描述:

A mapping between exception class names and error view names. Useful for rendering error pages in a browser application.

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
   <property name="exceptionMappings">
      <props>
         <prop key="java.lang.Exception">/errors/404</prop>
      </props>
   </property>
</bean>
<html>
<head>
   <title>404</title>
   <link href="${basePath}/css/system/404.css" type="text/css" rel="stylesheet">
   <script type="text/javascript">
   </script>
</head>
<body>
   <div class="errorPage">
      <div class="errorImg"></div>
      <a href="${basePath}/index" class="ui-button ui-button-positive ui-button-large">返回首页</a>
   </div>
</body>
</html>
相关文章
相关标签/搜索