但行好事
莫论前程❤

Javaweb基础(九)过滤器和监听器

过滤器(Filter):

能够完成筛选不需要数据的工具(东西).

1.什么是过滤器

生活中:净水器,香烟过滤嘴,滤纸,丈母娘,收费站等.——->单向的.
Web中:过滤器其实就是服务端的一个程序(程序的最小单元就是类).
在Web开发中,过滤器其实就是一个Web组件(Servlet/Filter/Listener),其实就是一个特殊的类.
一个类实现javax.servlet.Servlet接口:—>Servlet类.
一个类实现javax.servlet.Filter接口:—–>Filter类.

2.过滤器的作用:

过滤器可以对所有的请求或者响应做拦截操作.

  • 1:以常规的方式调用资源(Servlet/JSP);
  • 2:利用修改过的请求信息调用资源;
  • 3:调用资源之后,但在响应到客户端之前,对响应做出修改;
  • 4:阻止当前资源调用,代之转到其他资源.

img

Filter开发和使用

过滤器的开发和Servlet非常相似:(类比学习)

1.开发Servlet:

1):自定义一个类(XxxServlet),实现于javax.servlet.Servlet接口(继承于HttpServlet类).
2):在web.xml中做配置,告诉Tomcat来帮我管理这一个类(负责了该类的生命周期).:@WebServlet(“/xxx”)

    <servlet>
          <servlet-name>XxxServlet</servlet-name>
          <servlet-class>XxxServlet类的全限定名</servlet-class>
     </servlet>
     <servlet-mapping>
          <servlet-name>XxxServlet</servlet-name>
          <!--向外暴露一个资源名称,目的:让客户端通过该资源名称来访问服务端对应的一个Servlet-->
          <url-pattern>/xxx</url-pattern>
     </servlet-mapping>

2.开发Filter:

1):自定义一个类(XxxFilter,Xxx表示功能名),实现于javax.servlet.Filter接口.
2):在web.xml中做配置,告诉Tomcat来帮我管理这一个类(负责了该类的生命周期).:@WebFilter(“/hello.jsp”)

    <filter>
          <filter-name>XxxFilter</filter-name>
          <filter-class>XxxFilter类的全限定名</filter-class>
     </filter>
     <filter-mapping>
          <filter-name>XxxFilter</filter-name>
          <!--表示:当前Filter只对哪些资源做过滤/拦截操作,只对hello.jsp做拦截-->
          <url-pattern>/hello.jsp</url-pattern>
     </filter-mapping>

3.Filter的生命周期方法:

  • 1):void init(FilterConfig config): 初始化方法
  • 2):void doFilter(ServletRequest request, ServletResponse response, FilterChain chain):执行过滤的方法(每一次请求都会执行过滤)
  • 3):void destroy():销毁方法
    执行的流程:
    在启动Tomcat服务器的时候,就会执行构造器和init方法.
    构造器—>init方法 —–> ( doFilter方法 )N次——->destroy方法

chain:链,链条,多个链的节点组合而成.
FilterChain:过滤器链,多个过滤器按照一定的顺序排列在一起.

FilterChain.doFilter(req,resp):放行(放行给下一个Filter或资源)

img

4.Filter映射细节:

  • 1):多个Filter共存的时候,拦截的先后顺序由谁来决定?
    由<filter-mapping>的配置先后顺序来决定.
  • 2):Filter的对哪些资源做过滤.
    <url-pattern>被过滤的资源名称</url-pattern>
方式作用域
<url-pattern>/hello.jsp</url-pattern>只对/hello.jsp做过滤.
<url-pattern>/*</url-pattern>对所有的资源做过滤操作.
<url-pattern>/system/*</url-pattern>只对以/system/打头的资源做过滤.
<url-pattern>*.do</url-pattern>只对以.do结尾的资源做过滤
  • 3):可以通过<init-param>元素来给当前Filter配置初始化参数.
    通过FilterConifg对象.getInitParameter(String name)来获取初始化参数.
  • 4):Servlet,Filter,Listener都属于Web组件.
    一般的,先配置监听器,再配置过滤器,最后配置Servlet.
  • 5):<filter-mapping>中的子元素<dispatcher>表示对哪些操作执行过滤.
<!-- 缺省情况:REQUEST -->
<dispatcher>REQUEST</dispatcher>

<!-- 对请求转发做拦截 -->
<dispatcher>FORWARD</dispatcher>

<!-- 对请求包含做拦截 -->
<dispatcher>INCLUDE</dispatcher>

<!-- 出错之后再跳转到全局的结果视图之前做拦截 -->
<dispatcher>ERROR</dispatcher>

请求编码过滤器:CharacterEncodingFilter

img

img

img

img

上述编码过滤器,没问题.但是却把字符编码写死了.

解决方案:把字符编码作为Filter的初始化参数来配置.

img

img

登录验证过滤器:CheckLoginFilter

img

img

img

img

img

屏蔽敏感字过滤器:ContentFilter

img

img

上图在Servlet类中调用了FilterUtil的filter方法,完成对参数
字符串的敏感字过滤功能.

从正确与否上分析,没问题.但是,违背了责任分类的原则.
解决方案:使用过滤器来解决.

img

上述方式,可以完成敏感字过滤,但是改变了获取请求参数的机制.放弃.

img

img

我们需要解决的问题是啥:敏感字过滤.
为什么需要做这件事情:在原生的HttpServletRequest中的getParameter方法不支持敏感字过滤.
所以,得出结论,我们需要完成的: 让请求对象中的getParameter方法拥有敏感字过滤的功能.
目标:在不改变原有类的基础之上,对某一个方法做增强.
解决方案:
1):继承方式,覆盖需要增强的方法.——->子类出现爆炸式增强.
2):组合方式.—>包装设计模式(装饰设计模式:decorator)

装饰设计模式的作用:在不改变原有类的基础之上,对某一个对象做增强.

IServletRequerst接口: 模拟 ServletRequest接口.
DefaultServletRequestImpl类: 模拟 ServletRequest接口的实现类.
提供String getParameter(String name):并返回一个固定的值.

img

监听器

1.事件驱动编程:

简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数)。

事件驱动编程中核心对象:

1):事件源:谁发出事件通知,发出消息;也就是事件主体,比如按钮;

2):事件名称:发出什么样的通知的名称,比如鼠标到我头上了,我被别人点了一下;

3):事件响应函数:谁对这个这个事件感兴趣,当这个事件发生时要执行什么样的操作;

4):事件对象:一般来说,当事件发生时,会产生一个描述该事件的具体对象,包含事件相关信息。

调戏事件: 某一天,在大街上,张三看到一个美女,很美,很美,在美女的脸上点击了一下,美女给了张三一巴掌.

2.Web常见监听器:

监听request,session,ServletContext对象.

1):监听作用域对的创建和销毁.
ServletRequestListener:
HttpSessionListener:
ServletContextListener:监听服务器的启动和关闭.
2):监听作用域对象的属性的添加/删除/替换操作.(attributeAdded/attributeRemoved/attributeReplaced)
ServletRequestAttributeListener:
HttpSessionAttributeListener:
ServletContextAttributeListener:

开发监听器:对哪一种事件感兴趣,就实现哪一个事件对应的接口.
监听器没有自己的初始化参数,只能使用全局的初始化参数.

 <context-param>
        <param-name></param-name>
        <param-value></param-value>
 </context-param>

perftrace项目相关代码展示:

 <!-- Web容器加载顺序ServletContext-context-param-listener-filter-servlet -->

    <context-param>
        <param-name>log4jConfigLocation</param-name>
        <param-value>classpath:log4j.xml</param-value>
    </context-param>

    <!-- root application context configuration and shiro xml load-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:applicationContext-web.xml,
            classpath:applicationContext-shiro.xml,
            classpath:applicationContext-jedis.xml
        </param-value>
    </context-param>

    <!-- 防止发生java.beans.Introspector内存泄露,应将它配置在ContextLoaderListener的前面 -->
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>

    <!-- root application context -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

自定义监听器

  • web.xml
<!--自定义的listener-->
    <listener>
        <listener-class>
            com.feinno.perftrace.web.listener.PtListener
        </listener-class>
    </listener>
  • 代码实现ServletContextListener
public class PtListener implements ServletContextListener {

    public PtListener(){

    }

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //通过WebApplicationContextUtils工具类解决容器管理无法注入spring管理对象的问题
        applicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContextEvent.getServletContext());
        //获取各对象 HbaseTemplate2
        applicationIndexDao = (HbaseApplicationIndexDao) applicationContext.getBean("hbaseApplicationIndexDao");
        hbaseTemplate = (HbaseTemplate2) applicationContext.getBean("hbaseTemplate");
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
        long oneDay = 24 * 60 * 60 * 1000;
        long initDelay  = getTimeMillis("00:00:00") - System.currentTimeMillis();
        initDelay = initDelay > 0 ? initDelay : oneDay + initDelay;
        logger.info("applicationContext'value : " + applicationContext + ", applicationIndexDao'value : " + applicationIndexDao + ",hbaseTemplate'value" + hbaseTemplate);
        executor.scheduleAtFixedRate(
                new Runnable() {
                    @Override
                    public void run() {
                        logger.info("enter the timer thread!!!");
                        //查询0点拓扑
                        List<Application> apps = applicationIndexDao.selectAllApplicationNames();
                        logger.info("apps'value is  {}" + apps);
                        //写入新表中TopologicalGraph
                        for (Application application:apps) {
                            //rowKey为0点时间戳
                            Put put = new Put(Bytes.toBytes(getTimeMillis("00:00:00")));
                            //qualifier为appname
                            byte[] qualifier = Bytes.toBytes(application.getName());
                            byte[] value = Bytes.toBytes(application.getServiceTypeCode());

                            put.addColumn(HBaseTables.TOPOLOGICAL_GRAPH_CF_NAMES, qualifier, value);

                            logger.info("Start writing to the database!!!");

                            hbaseTemplate.put(HBaseTables.TOPOLOGICAL_GRAPH, put);

                            logger.info("Writing to the database ends!!!");

                            logger.debug("Insert application. {}", application);
                        }
                    }
                },
                initDelay,
                oneDay,
                TimeUnit.MILLISECONDS);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}
  • ServletContextListener 接口源码
public interface ServletContextListener extends EventListener {
    void contextInitialized(ServletContextEvent var1);

    void contextDestroyed(ServletContextEvent var1);
}
赞(1) 打赏
未经允许不得转载:刘鹏博客 » Javaweb基础(九)过滤器和监听器
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏