• contextparam 监听器 过滤器 servlet 拦截器的区别


    前言:一句话概括启动的顺序

    context param上下文参数——>listener监听器——>filter过滤器——>servlet——>intercept拦截器

                        生命周期

    context-param上下文参数

    当容器tomcat启动的时候会读取web.xml中的<context-param>标签和<listener>标签并初始化ServletContext(上下文)对象(ServletContext代表当前web项目,当前web项目中的所有内容都共享此对象)

    然后容器tomcat将<context-param>中的内容解析为键值对赋予ServletContext(这也就是为什么我们可以通过context-param的键获得context-param的值)

    之后容器创建<listener></listener>中的类实例,即创建监听器,在监听中会有contextInitialized(ServletContextEvent args)初始化方法,通过在这个方法中的参数获得ServletContext = ServletContextEvent.getServletContext();

    最后得到context-param的值 = ServletContext.getInitParameter("context-param的键");

    listener监听器得到参数后就可以进行换句话说,这个时候,对<context-param>中的键值对做的操作,将在的WEB项目完全启动之前被执行,常通过在web.xml中的配置来加载spring的配置文件

    <listener>
            <!-- 继承于ServletContextListener,在tomcat启动和关闭时会调用 -->
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 要读取到servletContext容器中的spring配置文件的路径 -->
            <param-value>classpath:ApplicationContext.xml</param-value>
    </context-param>

    listener监听器

    根据执行的时机不同划分,常用的监听器一共有三类,都是继承于父接口EventListener的子接口

    ServletContextListener接口

      Tomcat启动和关闭时调用的监听器,也就是说在tomcat启动时创建tomcat关闭时销毁

    • public void contextInitialized(ServletContextEvent evt)ServletContext对象被创建后调用;
    • public void contextDestroyed(ServletContextEvent evt)ServletContext对象被销毁前调用;

     HttpSessionListener接口

      开始会话和结束会话时调用的监听器,也就是说开启session时创建session失效时销毁

    • public void sessionCreated(HttpSessionEvent evt)HttpSession对象被创建后调用;
    • public void sessionDestroyed(HttpSessionEvent evt)HttpSession对象被销毁前调用;

      关于session失效有两种情况,一种是session.invalidate()方法注销session,另一种是超过了session的存活时间,tomcat中默认是30分钟,可以到tomcat/conf/web.xml文件中更改设置

     ServletRequestListener接口

      开始请求和结束请求时调用的监听器,也就是说接收request请求时创建完成request请求后销毁

    • public void requestInitiallized(ServletRequestEvent evt)ServletRequest对象被创建后调用;
    • public void requestDestroyed(ServletRequestEvent evt)ServletRequest对象被销毁前调用。

    filter过滤器

    init(FilterConfig):在服务器启动时会创建Filter实例并且每个类型的Filter只创建一个实例,从此不再创建!在创建完Filter实例后,会马上调用init()方法完成初始化工作,这个方法只会被执行一次;

    doFilter(ServletRequest req,ServletResponse res,FilterChain chain):这个方法会在用户每次访问指定过滤范围时都会执行doFileter,如果需要“放行”,那么需要调用FilterChain的doFilter(ServletRequest,ServletResponse)方法,如果不调用FilterChain的doFilter()方法,那么目标资源将无法执行;

    destroy():服务器会在创建Filter对象之后,把Filter放到缓存中一直使用,通常不会销毁它。一般会在服务器关闭时销毁Filter对象,在销毁Filter对象之前,服务器会调用Filter对象的destory()方法。

    servlet

    默认在第一次接受浏览器请求时创建servlet实例对象,在tomcat关闭时销毁

    javax.servlet.Servlet接口中,有三个方法说明了Servlet的生命周期:

    void init(ServletConfig):创建后马上调用init()完成初始化;

    void service(ServletRequest,ServletResponse):每次处理请求时调用service()方法;

    void destroy():当Tomcat要销毁Servlet实例时,先调用destroy()方法;

    可以在web.xml文件中将servlet的创建时机改为和服务器同步

     interceptor拦截器

    和过滤器类似,但是只拦截用户对action的请求,tomcat启动时创建,拦截到用户对action的请求时执行前置拦截器栈,放行后执行action逻辑并返回页面视图,最后再执行后置拦截器栈进行收尾工作

    void init():创建后马上调用init()完成初始化;

    String intercept(ActionInvocation invocation):通过invocation.invoke()方法继续执行拦截器栈中的其他拦截器

    void destroy():当Tomcat要销毁Interceptor实例时,先调用destroy()方法;

    前置拦截——>action——>页面执行——>后置拦截

    实际应用

    过滤器filter 
    过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 struts的action前统一设置字符集, 或者去除掉一些非法字符(聊天室经常用到的,一些骂人的话)。

    最常用的过滤器就是登陆过滤器LoginFilter,过滤器一般都是继承Filter 接口

    监听器listener 
    当你要触发一个事件,但这件事既不是过滤,又不是拦截,那很可能就是监听。 联想到Windows编程里的,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。监听器的概念类似于这些。

    上下文参数context-param

    用来存储要应用在web项目全局中的参数

    servlet

    用来处理tomcat等容器解析后的请求

    拦截器interceptor: 
    进行权限验证,或者是来判断用户是否登陆,日志记录,或者限制时间点访问。我自己用过拦截器,是用户每次登录时,都能记录一个登录时间。 (这点用拦截器明显合适,用过滤器明显不合适,因为没有过滤任何东西)

    作用范围

    代码和配置

    context-param  要读取到servletContext中的配置文件+web.xml配置

    listener,filter,servlet  java类+web.xml配置

    interceptor  java类+struts.xml配置

     

    context-param上下文参数

    context-param在web.xml文件中配置要读取的xml文件路径即可,一般都是读取spring的ApplicationContext.xml文件

    <listener>
            <!-- 继承于ServletContextListener,在tomcat启动和关闭时会调用 -->
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <!-- 要读取到servletContext容器中的spring配置文件的路径 -->
            <param-value>classpath:ApplicationContext.xml</param-value>
        </context-param>

    listener监听器

    java类:根据监听范围需求的不同实现ServletContextListener或HttpSessionListener或ServletRequestListener三者之一

    package com.rl.listener;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    /**
     * 自定义监听器实现了ServletContextListener接口,也会在服务器启动时初始化
     */
    public class MyServletContextListener implements ServletContextListener {
    
        /**
         * 服务器停止时销毁
         */
        public void contextDestroyed(ServletContextEvent sce) {
            System.out.println("MyServletContextListener被销毁");
        }
        
        /**
         * 服务器启动时创建
         */
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("MyServletContextListener被创建");
            ServletContext sc = sce.getServletContext();
        }
    }

    配置listener:在web.xml文件中配置listener类的路径即可

    <listener>
            <!--指定作为监听器的类-->
        <listener-class>com.rl.listener.MyRequestListener</listener-class>
    </listener>

    filter过滤器

    java类:作为过滤器的类要实现Filter接口

    package com.rl.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 HelloFilter implements Filter {
    
        /**
         * 当服务器关闭当前方法被调用,实例被销毁
         */
        public void destroy() {
            System.out.println("过滤器被销毁...");
        }
    
        /**
         * 过滤器的执行方法
         */
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            System.out.println("过滤器开始....");
            //让过滤器往下走,放行,如果后面还有过滤器,那么就执行下一个过滤器,如果是最后一个过滤器就去执行Controller
            chain.doFilter(request, response);
            System.out.println("过滤器结束....");
        }
    
        /**
         * 当服务器启动的时候被执行,说明过滤器的实例是在服务器启动时被创建的
         */
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("过滤器被创建...");
        }
    }

    配置filter:filter要在web.xml文件中配置filter类的路径和filter过滤的范围

     <filter>
          <filter-name>helloFilter</filter-name>
          <!--指定作为过滤器的类-->
          <filter-class>com.rl.filter.HelloFilter</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>helloFilter</filter-name>
          <!--过滤器过滤的范围-->
          <url-pattern>/*</url-pattern>
      </filter-mapping>

    servlet

    java类:实现Servlet接口或继承HttpServlet类(HttpServlet的父类GenericServlet实现了Servlet接口)

    package com.rl.servlet;
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * doGet是给get方式的http的请求做相应的
     * doPost是给post方式的http的请求做相应的
     */
    public class HttpServletDemo extends HttpServlet {
        @Override
        public void init() throws ServletException {
            System.out.println("HttpServletDemo实例被创建了");
        }
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            System.out.println("doGet方法被调用了");
            resp.getOutputStream().write("doGet方法被调用了".getBytes());
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp)
                throws ServletException, IOException {
            System.out.println("doPost方法被调用了");
            doGet(req, resp);
        }
    }

    配置servlet:要在web.xml文件中配置servlet类的路径和servlet的浏览器访问路径

    <servlet>
          <!-- 设置servlet的名字 -->
          <servlet-name>helloServlet</servlet-name>
          <!-- 具体的servlet的类 -->
          <servlet-class>com.rl.servlet.ServletDemo1</servlet-class>
          <!-- 将servlet的启动时机设置为和服务器同步 -->
          <load-on-startup>1</load-on-startup>
      </servlet>
      
      <servlet-mapping>
          <!-- 指定要映射 的servlet的名字 -->
          <servlet-name>helloServlet</servlet-name>
          <!-- servlet的具体映射路径 -->
          <url-pattern>/hello</url-pattern>
      </servlet-mapping>

    interceptor过滤器

    java类:作为Interceptor拦截器的类要继承于AbstractInterceptor类或继承于MethodFilterInterceptor,要想排除对指定的action的拦截,就一定要继承MethodFilterInterceptor类(它的父类也是AbstractInterceptor)

    package com.rl.interceptor;
    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    public class MyInterceptor extends AbstractInterceptor {
        @Override
        public void init() {
            System.out.println("创建拦截器");
        }
        @Override
        public void destroy() {
            System.out.println("销毁拦截器");
        }
        @Override
        public String intercept(ActionInvocation invocation) throws Exception {
            System.out.println("前置拦截执行....");
            //让拦截器向下走并且返回结果代码
            String result = invocation.invoke();
            System.out.println("后置拦截执行...");
            return result;
        }
    
    }

    要拦截的action类

    package com.rl.action;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    /**
     * 担当控制层的Action动作类
     */
    public class PersonAction2 extends ActionSupport{
    
        public String savePerson(){
            System.out.println("新增Person");
            return super.SUCCESS;
        }
        
        public String deletePerson(){
            System.out.println("删除Person");
            return super.SUCCESS;
        }
    }

    interceptor配置:牢记在interceptor标签中,action要放在其他标签的后面,不然会报错

    <package name="testInterceptor" extends="struts-default" namespace="/person">
            <interceptors>
                <!-- 配置我们自己的拦截器 -->
                <interceptor name="myInterceptor" class="com.rl.interceptor.MyInterceptor"></interceptor>
                <!-- 配置我们自己的拦截器栈 -->
                <interceptor-stack name="myStack">
                    <!-- 默认的拦截器栈 -->
                    <interceptor-ref name="defaultStack"></interceptor-ref>
                    <interceptor-ref name="myInterceptor"></interceptor-ref>
                </interceptor-stack>
            </interceptors>
            <!-- 包内默认拦截器栈设置为我们自己的myStack -->
            <default-interceptor-ref name="myStack"></default-interceptor-ref>
            <action name="*" class="com.rl.action.PersonAction2" method="{1}Person">
                <result name="success">/success.jsp</result>
            </action>
        </package>

    参考链接:

    过滤器,拦截器,监听器具体应用上的区别 - 阿里云  https://yq.aliyun.com/ziliao/365762

    session会话过期时间设置 https://blog.csdn.net/zqd_java/article/details/53687954

    web.xml的配置中<context-param>配置作用 https://www.cnblogs.com/jiaguozhilian/p/5819032.html

    struts.xml文件中package标签中的子标签顺序 https://blog.csdn.net/lc448986375/article/details/8027150

    servlet百度百科 https://baike.baidu.com/item/servlet/477555?fr=aladdin

  • 相关阅读:
    npm安装包时的几种模式
    git pull解决冲突
    mysql 连接数据库时时区报错
    idea设置自带的maven为国内镜像
    postgresql 判断字段的长度
    Git删除分支
    win10上安装mysql8(installer方式)并创建用户开启远程连接
    在spring boot中使用jasypt对配置文件中的敏感字符串加密
    spring boot中的底层配置文件application.yam(application.property)的装配原理初探
    CodeForces
  • 原文地址:https://www.cnblogs.com/Two-dimensionalSpace/p/9963012.html
Copyright © 2020-2023  润新知