#Filter、Listener#JavaWeb学习笔记(2020/3/5)

一、Filter

作用:

1、登录验证——不登录不让请求其他资源
2、关键字过滤
.....

使用方法:

  • 1、创建一个Filter接口的实现类,重写接口中的抽象方法
public class FilterDemo1 implements Filter {
    public void init(FilterConfig config) throws ServletException {

    }
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(req, resp);
    }
    public void destroy() {
    }
}

Filter接口中的方法说明:

  • ①.init方法:服务器启动时,会创建Filter对象,调用唯一的一次init方法。

  • ②.doFilter方法:每次有过滤路径的资源的请求,就调用一次。
    chain.doFilter(req, resp);作用是放行。

  • ③.destroy方法:服务器正常关闭前,调用一次,一般用于释放资源。

  • 2、用web.xml或者使用注解进行配置

        1. web.xml配置    
            <filter>
                <filter-name>demo1</filter-name>
                <filter-class>cn.itcast.web.filter.FilterDemo1</filter-class>
            </filter>
            <filter-mapping>
                <filter-name>demo1</filter-name>
                <!-- 拦截路径 -->
                <url-pattern>拦截路径 </url-pattern>
            </filter-mapping>
        2.注解配置:
            @WebFilter(value = "拦截路径" , dispatcherTypes={拦截方式,..} )

拦截路径的写法:

  1. 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
  2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
  3. 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
  4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

拦截方式的写法:

设置dispatcherTypes属性
DispatcherType. REQUEST:默认值。浏览器直接请求资源
DispatcherType. FORWARD:转发访问资源
DispatcherType. INCLUDE:包含访问资源
DispatcherType. ERROR:错误跳转资源
DispatcherType. ASYNC:异步访问资源

过滤器链:就好比几层的筛子。

过滤器的执行流程:
1. 过滤器1
2. 过滤器2
3. 资源执行
4. 过滤器2
5. 过滤器1


图片.png

过滤器先后顺序问题:

  1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
  • 如: AFilter 和 BFilter,AFilter就先执行了。
  1. web.xml配置: <filter-mapping>谁定义在上边,谁先执行

二、动态代理实现request对象增强

代理模式是一种设计模式
所谓代理就是第三方,去调用原来的方法并且在此之上进行一些功能的增强,何为动态代理,就是使用反射技术进行实现,不用依赖于具体的类文件。

关于代理的概念:

    1. 真实对象:被代理的对象
    1. 代理对象:真实对象增强之后的对象。
    1. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的。

动态代理的实现步骤:

    1. 代理对象和真实对象实现相同的接口
    1. 代理对象 = Proxy.newProxyInstance();
    1. 使用代理对象调用方法。
    1. 增强方法

newProxyInstance()方法的参数列表:

  真实对象.getClass().getClassLoader()——类加载器,把真实对象的Class对象加载进入内存。
  真实对象.getClass().getInterfaces()——获取所有的接口的Class对象
  new InvocationHandler(){
  代理对象调用所有的方法都会执行此方法,调用的方法对象会传给method参数。
  代理对象调用方法的参数会传递给args数组对象。
  匿名内部类实现 invoke(Object proxy, Method method, Object[] args) 方法
}

敏感字过滤器

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
//拦截资源路径为testSensitiveFilterServlet
@WebFilter("/testSensitiveFilterServlet")
public class SensitivewordsFilter implements Filter {
    List<String> sensitiveWordsList = new ArrayList<String>();
    public void init(FilterConfig config) throws ServletException {
        try{
            String realPath = config.getServletContext().getRealPath("/WEB-INF/classes/words.txt");
            System.out.println(realPath);
            BufferedReader br = new BufferedReader(new FileReader(realPath));
            String line = null;
            while((line = br.readLine())!=null){
                sensitiveWordsList.add(line);
            }
            System.out.println(sensitiveWordsList);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //使用动态代理来增强getParameter方法,完成过滤工作

        ServletRequest proxy_Requset = (ServletRequest)Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            //调用getParameter方法method就是getParameter方法对象
            //args是getParameter(String str)的str数据。
            //调用setAttribute方法method就是setAttribute方法对象
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                if ("getParameter".equals(method.getName())){
                    String msg = (String) method.invoke(req,args);
                    for (String s : sensitiveWordsList) {
                        if (msg.contains(s)){
                            msg = msg.replaceAll(s,"***");
                        }
                    }
                    return msg;
                }
                return method.invoke(req,args);
            }
        });
        chain.doFilter(proxy_Requset, resp);
    }


    public void destroy() {
    }


}

三、监听器Listener

Web三大技术:Servlet、Filter、Listener

事件监听机制

  • 事件 :一件事情
  • 事件源 :事件发生的地方
  • 监听器 :一个对象
  • 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码

ServletContextListener:web容器监听器
监听ServletContext对象的创建和销毁

  • 方法:
    • void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
    • void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法
  • 步骤:
      1. 定义一个ServletContextListener的实现类,重写接口的抽象方法。
      1. 配置
        1. web.xml
    <listener>
             <listener-class>监听器类的路径</listener-class>
    </listener>
   <!-- 指定初始化参数,一般用来加载默认配置 -->
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
   </context-param>

//使用servletContext.getInitParameter("contextConfigLocation");就能获取到param-value里的值。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容