context-param 监听器 过滤器 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

posted on 2018-11-15 13:31  二维空间  阅读(514)  评论(0编辑  收藏  举报

导航