spring mvc中的Interceptor可以理解为是Spring MVC框架对AOP的一种实现方式。一般简单的功能又是通用的,每个请求都要去处理的,比如判断token是否失效可以使用spring mvc的HanlderInterceptor, 复杂的,比如缓存,需要高度自定义的就用spring aop。一般来说service层更多用spring aop,controller层有必要用到request和response的时候,可以用拦截器。

servlet filter和spring mvc Interceptor区别:
1.拦截器是基于java的反射机制的,而过滤器是基于函数回调。
2.拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
3.拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
5.在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6.拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
servlet filter和spring mvc Interceptor执行顺序:

===========before doFilter1
===========before doFilter2
===========HandlerInterceptorAll preHandle
===========HandlerInterceptor1 preHandle
===========HandlerInterceptor2 preHandle
执行Controller
Controller return前
===========HandlerInterceptor2 postHandle
===========HandlerInterceptor1 postHandle
===========HandlerInterceptorAll preHandle
Controller return后,Jsp加载完成
===========HandlerInterceptor2 afterCompletion
===========HandlerInterceptor1 afterCompletion
===========HandlerInterceptorAll preHandle
===========before doFilter2
===========before doFilter1

Filter:
Java中的Filter并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应。 主要用于对HttpServletRequest 进行预处理,也可以对HttpServletResponse 进行后处理,是个典型的处理链。完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest。根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。在HttpServletResponse 到达客户端之前,拦截HttpServletResponse。根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。

Filter随web应用的启动而启动,只初始化一次,随web应用的停止而销毁。
1.启动服务器时加载过滤器的实例,并调用init()方法来初始化实例;
2.每一次请求时都只调用方法doFilter()进行处理;
3.停止服务器时调用destroy()方法,销毁实例。

自定义Servlet Filter:

    import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; public class ErrorHandleFilter implements Filter { @Override
public void destroy() {
// ...
} @Override
public void init(FilterConfig filterConfig) throws ServletException {
//
} @Override
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain chain)
throws IOException, ServletException { try {
long before = System.currentTimeMillis();
System.out.println("===========before doFilter")
chain.doFilter(request, response);
long after = System.currentTimeMillis();
System.out.println("===========after doFilter")
} catch (Exception ex) {
request.setAttribute("errorMessage", ex);
request.getRequestDispatcher("/WEB-INF/views/jsp/error.jsp")
.forward(request, response);
} } }

上面程序实现了doFilter()方法,实现该方法就可实现对用户请求进行预处理,也可实现对服务器响应进行后处理——它们的分界线为是否调用了chain.doFilter(),执行该方法之前,即对用户请求进行预处理;执行该方法之后,即对服务器响应进行后处理。调用Servlet的doService()方法是就是在chain.doFilter(request, response)这个方法中进行的。

在web.xml中配置:

<filter>
<filter-name>errorHandlerFilter</filter-name>
<filter-class>com.mkyong.form.web.ErrorHandleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>errorHandlerFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

使用Spring进行管理:
DelegatingFilterProxy就是一个对于servlet filter的代理,它没有实现过滤器的任何逻辑。通过spring容器来管理ServletFilter的生命周期。如果filter中需要一些Spring容器的实例,可以通过spring直接注入。
在web.xml中配置:

    <filter>
< filter-name>myFilter</filter-name>
< filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
< filter-name>myFilter</filter-name>
< url-pattern>/*</url-pattern>
</filter-mapping>

在contextApplication.xml中,配置具体的Filter类的实例。在Spring中配置的bean的name要和web.xml中的<filter-name>一样

    <bean name="myFilter" class="com.*.MyFilter"></bean>

Interceptor:
spring mvc中的Interceptor可以理解为是Spring MVC框架对AOP的一种实现方式。一般简单的功能又是通用的,每个请求都要去处理的,比如判断token是否失效可以使用spring mvc的HanlderInterceptor, 复杂的,比如缓存,需要高度自定义的就用spring aop。一般来说service层更多用spring aop,controller层有必要用到request和response的时候,可以用拦截器。

spring mvc中的Interceptor拦截请求是通过HandlerInterceptor来实现的。所以HandlerInteceptor拦截器只有在Spring Web MVC环境下才能使用。在SpringMVC中定义一个拦截器主要有两种方式,第一种方式是要实现Spring的HandlerInterceptor接口,或者是其它实现了HandlerInterceptor接口的类,比如HandlerInterceptorAdapter。第二种方式是实现WebRequestInterceptor接口,或者其它实现了WebRequestInterceptor的类。

HandlerInterceptor接口中定义了三个方法preHandle, postHandle, 和afterCompletion:

  • preHandle:预处理回调方法,实现处理器的预处理(如登录检查),返回值:true表示继续流程(如调用下一个拦截器或处理器),false表示流程中断(如登录检查失败),不会继续调用其他的拦截器或处理器,此时我们需要通过response来产生响应。
  • postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。
  • afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调。该方法也是需要当前对应的Interceptor 的preHandle方法的返回值为true时才会执行。这个方法的主要作用是用于进行资源清理工作的,如性能监控中我们可以在此记录结束时间并输出消耗时间。

流程如下:
先声明的Interceptor 的postHandle 方法反而会后执行。

有时候我们可能只需要实现三个回调方法中的某一个,如果实现HandlerInterceptor接口的话,三个方法必须实现。spring提供了一个HandlerInterceptorAdapter适配器(一种适配器设计模式的实现),允许我们只实现需要的回调方法。
HandlerInterceptor1,HandlerInterceptor2:

    public class HandlerInterceptor1 extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("===========HandlerInterceptor1 preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("===========HandlerInterceptor1 postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("===========HandlerInterceptor1 afterCompletion");
}
}

HandlerInterceptor2同理,只是输出内容为“HandlerInterceptor2”。

TestController:

    public class TestController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) throws Exception {
System.out.println("===========TestController");
return new ModelAndView("test");
}
}

Spring配置文件:

    <bean id="handlerInterceptor1" class="cn.javass.chapter5.web.interceptor.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="cn.javass.chapter5.web.interceptor.HandlerInterceptor2"/> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
//拦截器的执行顺序就是此处添加拦截器的顺序。
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>

如果使用了<mvc:annotation-driven />, 它会自动注册BeanNameUrlHandlerMapping这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。推荐使用mvc:interceptors标签来声明需要加入到SpringMVC拦截器链中的拦截器。

在SpringMVC的配置文件中加上支持MVC的schema:

    <beans xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation=" http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd" > <mvc:interceptors>
<!-- 使用bean定义一个Interceptor,直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求
<bean class="com.host.app.web.interceptor.HandlerInterceptorAll"/> -->
<mvc:interceptor>
<mvc:mapping path="/test/number.do"/>
<mvc:exclude-mapping path="/test/goLogin.*"/>
<!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->
<bean class="com.host.app.web.interceptor.HandlerInterceptor1"/>
<!-- <ref bean="handlerInterceptor1"/> -->
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/test/number.do"/>
<mvc:exclude-mapping path="/test/goLogin.*"/>
<bean class="com.host.app.web.interceptor.HandlerInterceptor2"/>
<!-- <ref bean="handlerInterceptor2"/> -->
</mvc:interceptor>
</mvc:interceptors>

在mvc:interceptors标签下声明interceptor主要有两种方式:
1.直接定义一个Interceptor实现类的bean对象。使用这种方式声明的Interceptor拦截器将会对所有的请求进行拦截。
2.使用mvc:interceptor标签进行声明。这种方式进行声明的Interceptor可以通过mvc:mapping子标签来定义需要进行拦截的请求路径。

视图页面WEB-INF/jsp/test.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%System.out.println("==========test.jsp");%>

转:https://www.jianshu.com/p/685c65ed6944

Spring 梳理 - filter、interceptor、aop实现与区别 -第二篇的更多相关文章

  1. spring boot: filter/interceptor/aop在获取request/method参数上的区别(spring boot 2.3.1)

    一,filter/interceptor/aop在获取参数上有什么区别? 1,filter可以修改HttpServletRequest的参数(doFilter方法的功能), interceptor/a ...

  2. Spring 梳理 - filter、interceptor、aop实现与区别 -第一篇

    前言 项目中我们经常需要对RESTful api进行拦截,主流实现方法有filter.interceptor.aop,先说一下他们各自的实现. Filter AnimalFilter实现javax.s ...

  3. Filter ,Interceptor,AOP

    一.Filter: Filter也称之为过滤器,它是Servlet技术中比较激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态 ...

  4. Spring整合AspectJ的AOP

    学而时习之,不亦说乎!                              --<论语> 看这一篇之前最好先看前面关于AOP的两篇. http://www.cnblogs.com/z ...

  5. Spring框架IOC和AOP介绍

    说明:本文部分内容参考其他优秀博客后结合自己实战例子改编如下 Spring框架是个轻量级的Java EE框架.所谓轻量级,是指不依赖于容器就能运行的.Struts.Hibernate也是轻量级的. 轻 ...

  6. Spring切面编程之AOP

    AOP 是OOP 的延续,是Aspect Oriented Programming 的缩写,意思是面向切面编程.可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种 ...

  7. Spring的IOC和AOP之深剖

    今天,既然讲到了Spring 的IOC和AOP,我们就必须要知道 Spring主要是两件事: 1.开发Bean:2.配置Bean.对于Spring框架来说,它要做的,就是根据配置文件来创建bean实例 ...

  8. Spring(6)—— AOP

    AOP(Aspect-OrientedProgramming)面向切面编程,与OOP完全不同,使用AOP编程系统被分为切面或关注点,而不是OOP中的对象. AOP的引入 在OOP面向对象的使用中,无可 ...

  9. spring+mybatis利用interceptor(plugin)兑现数据库读写分离

    使用spring的动态路由实现数据库负载均衡 系统中存在的多台服务器是"地位相当"的,不过,同一时间他们都处于活动(Active)状态,处于负载均衡等因素考虑,数据访问请求需要在这 ...

随机推荐

  1. UVA 10699 Count the factors 题解

    Time limit 3000 ms OS Linux Write a program, that computes the number of different prime factors in ...

  2. Ion内存的带cahce与不带cache问题分享

    一次开发中,遇到一个问题:YUV图像(由本地磁盘文件读到ION内存中)缩放时,对于缩放模块的输入源来说,使用带cache的方式要比不带cache的方式速度快数10倍. 为什么会出现这个情况呢? 在解释 ...

  3. Leetcode之回溯法专题-78. 子集(Subsets)

    Leetcode之回溯法专题-78. 子集(Subsets) 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集). 说明:解集不能包含重复的子集. 示例: 输入: nums = ...

  4. 玩转 SpringBoot 2 快速整合 | 丝袜哥(Swagger)

    概述 首先让我引用 Swagger 官方的介绍: Design is the foundation of your API development. Swagger makes API design ...

  5. Mysql系列 - 第3天:管理员必备技能(必须掌握)

    这是mysql系列第3篇文章. 环境:mysql5.7.25,cmd命令中进行演示. 在玩mysql的过程中,经常遇到有很多朋友在云上面玩mysql的时候,说我创建了一个用户为什么不能登录?为什么没有 ...

  6. Java 前后端分离项目:微人事

    本文适合刚学习完 Java 语言基础的人群,跟着本文可了解和运行项目,本示例是在 Windows 操作系统下演示. 本文作者:HelloGitHub-秦人 大家好!这里是 HelloGitHub 推出 ...

  7. Docker容器技术的核心

    容器技术的核心 所谓容器,其实是由Linux Namespace.Linux Cgroups和rootfs三种技术构建出来的进程的隔离环境 对于Docker项目来说,其实最核心就是为待创建的用户进程: ...

  8. Python数据类型详解——字典

    Python数据类型详解--字典 引子 已经学习了列表,现在有个需求--把公司每个员工的姓名.年龄.职务.工资存到列表里,你怎么存? staff_list = [ ["Kwan", ...

  9. POJ-2387 Til the Cows Come Home ( 最短路 )

    题目链接: http://poj.org/problem?id=2387 Description Bessie is out in the field and wants to get back to ...

  10. codeforces 764 C. Timofey and a tree(dfs+思维)

    题目链接:http://codeforces.com/contest/764/problem/C 题意:给出一个树,然后各个节点有对应的颜色,问是否存在以一个点为根节点子树的颜色都一样. 这里的子树颜 ...