一、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={拦截方式,..} )
拦截路径的写法:
- 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行
 - 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行
 - 后缀名拦截: *.jsp 访问所有后缀名为jsp资源时,过滤器都会被执行
 - 拦截所有资源:/* 访问所有资源时,过滤器都会被执行
 
拦截方式的写法:
设置dispatcherTypes属性
DispatcherType. REQUEST:默认值。浏览器直接请求资源
DispatcherType. FORWARD:转发访问资源
DispatcherType. INCLUDE:包含访问资源
DispatcherType. ERROR:错误跳转资源
DispatcherType. ASYNC:异步访问资源
过滤器链:就好比几层的筛子。
过滤器的执行流程:
1. 过滤器1
2. 过滤器2
3. 资源执行
4. 过滤器2
5. 过滤器1

图片.png
过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行
 
- 如: AFilter 和 BFilter,AFilter就先执行了。
 
- web.xml配置: <filter-mapping>谁定义在上边,谁先执行
 
二、动态代理实现request对象增强
代理模式是一种设计模式
所谓代理就是第三方,去调用原来的方法并且在此之上进行一些功能的增强,何为动态代理,就是使用反射技术进行实现,不用依赖于具体的类文件。
关于代理的概念:
- 真实对象:被代理的对象
 
- 代理对象:真实对象增强之后的对象。
 
- 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的。
 
动态代理的实现步骤:
- 代理对象和真实对象实现相同的接口
 
- 代理对象 = Proxy.newProxyInstance();
 
- 使用代理对象调用方法。
 
- 增强方法
 
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对象创建后会调用该方法
 
 - 步骤:
- 定义一个ServletContextListener的实现类,重写接口的抽象方法。
 
- 
- 配置
 
- 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里的值。