Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 341|回复: 0

[默认分类] java 拦截器、过滤器

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-9 16:39:30 | 显示全部楼层 |阅读模式

    过滤器和拦截器:两者有很大的相似性。但似乎Struts2的拦截器在功能上不如Servlet的过滤器强大。原因有以下两点:
    ① interceptor只能对action(相当于servlet)进行拦截,而对jsp页面无效
    ② interceptor只能在提交表单之后发挥作用,而对于直接在地址栏输入的url无能为力。从而导致不能进行完整的身份验证。
    一、理解Struts2拦截器
    1. Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.
    2. 拦截器栈(Interceptor Stack)。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
    二、实现Struts2拦截器原理
    Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的 拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器
    三、定义Struts2拦截器。
    Struts2规定用户自定义拦截器必须实现com.opensymphony.xwork2.interceptor.Interceptor接口。该接口声明了3个方法,

      
       
        void init(); void destroy(); String intercept(ActionInvocation invocation) throws Exception;
       
      

    其中,init和destroy方法会在程序开始和结束时各执行一遍,不管使用了该拦截器与否,只要在struts.xml中声明了该Struts2拦截器就会被执行。
    intercept方法就是拦截的主体了,每次拦截器生效时都会执行其中的逻辑。
    不过,struts中又提供了几个抽象类来简化这一步骤。

      
       
       
    1. public abstract class AbstractInterceptor implements Interceptor;
    2. public abstract class MethodFilterInterceptor extends AbstractInterceptor;
    复制代码
       
      

    都是模板方法实现的。
    其中AbstractInterceptor提供了init()和destroy()的空实现,使用时只需要覆盖intercept()方法;
    而MethodFilterInterceptor则提供了includeMethods和excludeMethods两个属性,用来拦截执行该拦截器的action的方法。可以通过param来加入或者排除需要拦截的方法。
    一般来说,拦截器的写法都差不多。看下面的示例:

      
       
       
    1. package interceptor;
    2. import com.opensymphony.xwork2.ActionInvocation;
    3. import com.opensymphony.xwork2.interceptor.Interceptor;
    4. public class MyInterceptor implements Interceptor {
    5. public void destroy() {
    6. // TODO Auto-generated method stub
    7. }
    8. public void init() {
    9. // TODO Auto-generated method stub
    10. }
    11. public String intercept(ActionInvocation invocation) throws Exception {
    12. System.out.println("Action执行前插入 代码");      
    13. //执行目标方法 (调用下一个拦截器, 或执行Action)   
    14. final String res = invocation.invoke();   
    15. System.out.println("Action执行后插入 代码");   
    16. return res;   
    17. }
    18. }
    复制代码
       
      


    四、配置Struts2拦截器
    Struts2拦截器需要在struts.xml中声明,如下struts.xml配置文件

      
       
       
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <!DOCTYPE struts PUBLIC
    3. "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    4. "[url=http://struts.apache.org/dtds/struts-2.0.dtd]http://struts.apache.org/dtds/struts-2.0.dtd[/url]">
    5. <struts>
    6. <constant name="struts.objectFactory" value="spring" />
    复制代码
    <package name="default" extends="struts-default"> <interceptors> <interceptor name="MyInterceptor" class="interceptor.MyInterceptor"></interceptor> <interceptor-stack name="myInterceptorStack"> <interceptor-ref name="MyInterceptor"/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <action name="loginAction" class="loginAction"> <result name="fail">/index.jsp </result> <result name="success">/success.jsp</result> <interceptor-ref name="myInterceptorStack"></interceptor-ref> </action> </package> </struts>
       
      




      
       
        拦截器
        名字
        说明
       
       
        Alias Interceptor
        alias
        在不同请求之间将请求参数在不同名字件转换,请求内容不变
       
       
        Chaining Interceptor
        chain
        让前一个Action的属性可以被后一个Action访问,现在和chain类型的result()结合使用。
       
       
        Checkbox Interceptor
        checkbox
        添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而HTML默认情况下不提交没有选中的checkbox。
       
       
        Cookies Interceptor
        cookies
        使用配置的name,value来是指cookies
       
       
        Conversion Error Interceptor
        conversionError
        将错误从ActionContext中添加到Action的属性字段中。
       
       
        Create Session Interceptor
        createSession
        自动的创建HttpSession,用来为需要使用到HttpSession的拦截器服务。
       
       
        Debugging Interceptor
        debugging
        提供不同的调试用的页面来展现内部的数据状况。
       
       
        Execute and Wait Interceptor
        execAndWait
        在后台执行Action,同时将用户带到一个中间的等待页面。
       
       
        Exception Interceptor
        exception
        将异常定位到一个画面
       
       
        File Upload Interceptor
        fileUpload
        提供文件上传功能
       
       
        I18n Interceptor
        i18n
        记录用户选择的locale
       
       
        Logger Interceptor
        logger
        输出Action的名字
       
       
        Message Store Interceptor
        store
        存储或者访问实现ValidationAware接口的Action类出现的消息,错误,字段错误等。
       
       
        Model Driven Interceptor
        model-driven
        如果一个类实现了ModelDriven,将getModel得到的结果放在Value Stack中。
       
       
        Scoped Model Driven
        scoped-model-driven
        如果一个Action实现了ScopedModelDriven,则这个拦截器会从相应的Scope中取出model调用Action的setModel方法将其放入Action内部。
       
       
        Parameters Interceptor
        params
        将请求中的参数设置到Action中去。
       
       
        Prepare Interceptor
        prepare
        如果Acton实现了Preparable,则该拦截器调用Action类的prepare方法。
       
       
        Scope Interceptor
        scope
        将Action状态存入session和application的简单方法。
       
       
        Servlet Config Interceptor
        servletConfig
        提供访问HttpServletRequest和HttpServletResponse的方法,以Map的方式访问。
       
       
        Static Parameters Interceptor
        staticParams
        从struts.xml文件中将中的中的内容设置到对应的Action中。
       
       
        Roles Interceptor
        roles
        确定用户是否具有JAAS指定的Role,否则不予执行。
       
       
        Timer Interceptor
        timer
        输出Action执行的时间
       
       
        Token Interceptor
        token
        通过Token来避免双击
       
       
        Token Session Interceptor
        tokenSession
        和Token Interceptor一样,不过双击的时候把请求的数据存储在Session中
       
       
        Validation Interceptor
        validation
        使用action-validation.xml文件中定义的内容校验提交的数据。
       
       
        Workflow Interceptor
        workflow
        调用Action的validate方法,一旦有错误返回,重新定位到INPUT画面
       
       
        Parameter Filter Interceptor
        N/A
        从参数列表中删除不必要的参数
       
       
        Profiling Interceptor
        profiling
        通过参数激活profile
       
      



    ===============================过滤器===========================================================
           过滤器,它可以在请求到达Servlet/JSP之前对其进行预处理,而且能够在响应离开Servlet/JSP之后对 其进行后处理,是在Java Web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集,或者去除掉一些非法字符
    拦截器,是在面向切面编程的就是在你的service或者一个方法,前调用一个方法,或者在方法后调用一个方法比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业务逻辑的操作),也可以在你调用方法后打印出字符串,甚至在你抛出异常的时候做业务逻辑的操作。
    拦截器与过滤器的区别 :

      拦截器是基于java的反射机制的,而过滤器是基于函数回调。
      拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
      拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
      拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
      在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

    执行顺序 :过滤前 - 拦截前 - Action处理 - 拦截后 - 过滤后。个人认为过滤是一个横向的过程,首先把客户端提交的内容进行过滤(例如未登录用户不能访问内部页面的处理);过滤通过后,拦截器将检查用户提交数据的验证,做一些前期的数据处理,接着把处理后的数据发给对应的Action;Action处理完成返回后,拦截器还可以做其他过程(还没想到要做啥),再向上返回到过滤器的后续操作。
    一个Filter 可负责拦截多个请求或响应:一个请求或响应也可被多个Filter拦截。
    创建一个Filter 只需两个步骤:
    (1)创建Filter 处理类:
    (2)在web.xml 文件中配置Filter 。
    创建Filter 必须实现javax.servlet.Filter 接口,在该接口中定义了三个方法。
    • void init(FilterConfig config): 用于完成Filter 的初始化。
    • void destroy(): 用于Filter 销毁前,完成某些资源的回收。
    • void doFilter(ServletRequest request, ServletResponse response,FilterChain chain): 实现过滤功能,该方法就是对每个请求及响应增加的额外处理。
    过滤器Filter也具有生命周期:init()->doFilter()->destroy(),由部署文件中的filter元素驱动。在servlet2.4中,过滤器同样可以用于请求分派器,但须在web.xml中声明,<dispatcher>INCLUDE或FORWARD或REQUEST或ERROR</dispatcher>该元素位于filter-mapping中。
    Filter常用的场景:
    例一、 日志的记录,当有请求到达时,在该过滤器中进行日志的记录。处理完成后,进入后续的Filter或者处理。
    步骤1:编写Filter类
    package test.filter;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.http.HttpServletRequest;


    public class LogFilter implements Filter {
    private FilterConfig config;
    // 实现初始化方法
    public void init(FilterConfig config) {
    this.config = config;
    }
    // 实现销毁方法
    public void destroy() {
    this.config = null;
    }
    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) {
    // 获取ServletContext 对象,用于记录日志
    ServletContext context = this.config.getServletContext();
    long before = System.currentTimeMillis();
    System.out.println("开始过滤... ");
    // 将请求转换成HttpServletRequest 请求
    HttpServletRequest hrequest = (HttpServletRequest) request;
    // 记录日志
    context.log("Filter已经截获到用户的请求的地址: " + hrequest.getServletPath());
    try {
    // Filter 只是链式处理,请求依然转发到目的地址。
    chain.doFilter(request, response);
    } catch (Exception e) {
    e.printStackTrace();
    }
    long after = System.currentTimeMillis();
    // 记录日志
    context.log("过滤结束");
    // 再次记录日志
    context.log(" 请求被定位到" + ((HttpServletRequest) request).getRequestURI()
    + "所花的时间为: " + (after - before));
    }
    }
    在上面的请求Filter中,仅在日志中记录请求的URL,对所有的请求都执行chain.doFilter(request,reponse)方法,当Filter 对请求过滤后,依然将请求发送到目的地址。
    步骤2:在web.xml中配置Filter
    <!-- 定义Filter -->
    <filter>
    <!-- Filter 的名字 -->
    <filter-name>log</filter-name>
    <!-- Filter 的实现类 -->
    <filter-class> test.filter.LogFilter</filter-class>
    </filter>
    <!-- 定义Filter 拦截地址 -->
    <filter-mapping>
    <!-- Filter 的名字 -->
    <filter-name>log</filter-name>
    <!-- Filter 负责拦截的URL -->
    <url-pattern>/filter/*</url-pattern>
    <!-- 过滤器的类型,参数包括:REQUEST,FORWARD,INCLUDE,ERROR,不配置默认是request-->
    <dispatcher></dispatcher>
    </filter-mapping>
    过滤器一般应用:
    1、对用户请求进行统一验证
    2、结合request.setCharacterEncoding(编码格式)和filter的filterconfig.getInitParameter(编码格式名称)获取filter的param中配置的编码方式对请求进行编码转换;
    3、对用户发送的数据进行过滤替换
    4、转换图像格式
    5、对相应的内容进行压缩
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-3-29 14:16 , Processed in 0.359954 second(s), 50 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表