SpringMVC拦截器

 

一、工程构建

1.引入SpringMVC需要的jar包

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>5.0.8.RELEASE</version>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

2.配置web.xml文件

<!--静态资源的处理,设置必须在SpringMVC的Dispatcher前面-->
<servlet-mapping>
    <servlet-name>default</servlet-name>
    <url-pattern>*.jpg</url-pattern>
    <url-pattern>*.js</url-pattern>
    <url-pattern>*.css</url-pattern>
    <url-pattern>*.png</url-pattern>
    <url-pattern>*.gif</url-pattern>
    <url-pattern>*.json</url-pattern>
    <url-pattern>*.html</url-pattern>
    <url-pattern>*.htm</url-pattern>
    <url-pattern>*.swf</url-pattern>
</servlet-mapping>

<!--加载SpringMVC-->
<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>

        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!-- >=0容器会初始化此servlet,否则使用时才初始化 -->
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <!--拦截路径,/为拦截所有,*为通配符,不能设置成*,启动会报错-->
    <url-pattern>/</url-pattern>
</servlet-mapping>

3.配置SpringMVC配置文件

<!--注解驱动-->
<mvc:annotation-driven/>

<!--包扫描-->
<context:component-scan base-package="controller" annotation-config="true"/>

<!--过滤静态资源-->
<mvc:default-servlet-handler/>

<!--拦截器-->
<mvc:interceptors>
    <!-- 定义在这里的,所有的都会拦截-->
    <mvc:interceptor>
        <!--manage/a.do -> /manage/*-->
        <!--manage/product/save.do -> /manage/**-->
        <mvc:mapping path="/**"/>
        <!--<mvc:exclude-mapping path="/manage/user/login.do"/>-->
        <bean class="interceptor.AuthorityInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

二、创建拦截器类

只有一个要求,实现HandlerInterceptor接口即可,然后在SpringMVC配置文件中添加下一,实现后要重写三个方法

方法名称 说明
preHandle 在请求处理之前进行调用,若该请求存在多个Interceptor ,依据声明顺序依次执行,返回为false表示请求结束,后续的Interceptor和Controller都不会执行;返回true会继续调用下一个 Interceptor的preHandle方法,如果已经是最后一个Interceptor,就会请求Controller中的方法
postHandle preHandle方法返回true时才会执行。postHandle方法在Controller中的方法调用之后执行,在视图返回渲染之前被调用,所以可以在这个方法中对Controller处理之后的ModelAndView对象进行操作。postHandle方法被调用的方向跟preHandle是相反的,先声明的 Interceptor的postHandle方法反而会后执行
afterCompletion preHandle方法返回true时才会执行。该方法在整个请求结束之后,也就是在渲染了视图之后执行
@RestController
public class UserController {
    @RequestMapping(value = "/login.do", method = RequestMethod.GET)
    public String login(String name){
        return name;
    }
}

1.通过拦截器获取访问的接口和参数

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    HandlerMethod handlerMethod = (HandlerMethod) handler;
    //解析HandlerMethod
    String methodName = handlerMethod.getMethod().getName();
    String className = handlerMethod.getBean().getClass().getName();
    StringBuffer requestBuffer = new StringBuffer();
    Map paramMap = request.getParameterMap();
    Iterator it = paramMap.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry entry = (Map.Entry) it.next();
        String mapKey = (String) entry.getKey();
        String mapValue = Arrays.toString((String[]) entry.getValue());
        requestBuffer.append(mapKey).append("=").append(mapValue);
    }
    System.out.println("路径:" + className);
    System.out.println("方法:" + methodName);
    System.out.println("参数:" + requestBuffer);
    return true;
}

img

2.修改返回类容

在做一些验证时不通过如果直接返回一个false对前端并不友好,前后端分离项目通常都是返回Json,而方法的返回值不能修改,这样就只能通过其它方式实现了,比如修改Response

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    response.reset();//要先reset,否则报异常
    response.setCharacterEncoding("UTF-8");//设置编码,否则会乱码
    response.setContentType("application/json;charset=UTF-8");//这里要设置返回值的类型,因为是json接口。
    PrintWriter out = response.getWriter();
    Map resultMap = new HashMap();
    resultMap.put("success", false);
    resultMap.put("msg", "请登录管理员");
    out.print(JsonUtil.obj2String(resultMap));
    out.flush();
    out.close();//写完要关闭

    return false;
}

img

附上Demo