• java 拦截器、过滤器、监听器


    一、理解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中又提供了几个抽象类来简化这一步骤。

    public abstract class AbstractInterceptor implements Interceptor;
    public abstract class MethodFilterInterceptor extends AbstractInterceptor;

    都是模板方法实现的。

    其中AbstractInterceptor提供了init()和destroy()的空实现,使用时只需要覆盖intercept()方法;

    而MethodFilterInterceptor则提供了includeMethods和excludeMethods两个属性,用来过滤执行该过滤器的action的方法。可以通过param来加入或者排除需要过滤的方法。

    一般来说,拦截器的写法都差不多。看下面的示例:

    package interceptor;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.Interceptor;
    public class MyInterceptor implements Interceptor {
    public void destroy() {
    // TODO Auto-generated method stub
    }
    public void init() {
    // TODO Auto-generated method stub
    }
    public String intercept(ActionInvocation invocation) throws Exception {
    System.out.println("Action执行前插入 代码");      
    //执行目标方法 (调用下一个拦截器, 或执行Action)    
    final String res = invocation.invoke();    
    System.out.println("Action执行后插入 代码");    
    return res;    
    }
    }
    
    

    四、配置Struts2拦截器

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

    
    
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
    <struts>
    <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>
    
    

    这里写图片描述

    ===============================过滤器===========================================================

    过滤器,是在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 只需两个步骤:
    (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中声明,INCLUDE或FORWARD或REQUEST或ERROR该元素位于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>
    
    </filter-mapping>
    
    
  • 相关阅读:
    移动端a标签点击图片有阴影处理
    sublime vue 语法高亮插件安装
    mongodb 命令
    MongoDB给数据库创建用户
    windows32位系统 安装MongoDB
    ES6之主要知识点(十)Proxy
    ES6之主要知识点(九)Set和Map
    ES6之主要知识点(八)Symbol
    ES6之主要知识点(七)对象
    Ueditor 1.4.3 插入表格后无边框无颜色,不能正常显示
  • 原文地址:https://www.cnblogs.com/lllini/p/11955382.html
Copyright © 2020-2023  润新知