Filter 和Listener

Filter 和Listener

Filter : 过滤器

1.概念

浏览器发出请求访问服务器的资源,过滤器将请求拦截,完成一些特殊的功能。 作用:一般用于完成通过的操作。如:登陆验证、统一编码处理、敏感字符过滤等等。

2.入门

1.定义一个类,实现接口Filter

2.复写方法

3.配置拦截路径

3.1 注解

@WebFilter("/*") //访问所有资源之前,都会执行该过滤器

/user/ * 访问user目录下所有资源,执行

*.jsp 访问jsp后缀,执行

filterChain.doFilter(servletRequest,servletResponse);//放行
每一次请求被拦截资源时,都会执行。执行多次

3.2web.xml    

4. 执行周期

1.放行前对request增强
2. 放行
3.回来时对response增强

5.拦截方式配置:资源被访问的方式

1. 注解配置:设置dispatcherTypes属性  

  1.request:默认值,浏览器直接请求资源 
  2.forward:转发访问资源
  3.include:包含访问资源 
  4.error:错误跳转资源 
  5.async:异步访问资源  .

  例:@WebFilter(value = "/index.jsp",dispatcherTypes = DispatcherType.REQUEST)
      @WebFilter(value = "/index.jsp",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})

2. web.xml配置

6.过滤器链(配置多个过滤器)

*执行顺序:如果有2个过滤器:过滤器1和过滤器2
         1.过滤器1
         2.过滤器2 
         3.资源执行
         4.过滤器2
         5.过滤器1
*过滤器先后问题:
        1.注解配置:按照类名字符串比较规则,小的先执行
            *如:AFilter 和 BFilter, 第一个先执行
        2.web.xml配置:<filter-mapping>谁定义在上边,谁先执行

7.案例

1.登录校验

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    //强转
HttpServletRequest request = (HttpServletRequest) req;

String uri = request.getRequestURI();

//1判断

if (uri.contains("/login.jsp")||uri.contains("/loginServlet")||uri.contains("/css/")||uri.contains("/js/")
||uri.contains("/fonts/")||uri.contains("/checkCodeServlet")){
chain.doFilter(req, resp);
}else {
Object user = request.getSession().getAttribute("user");
if (user!=null){
chain.doFilter(req, resp);
}else {
request.setAttribute("loginmsg","您尚未登录,请登录");
request.getRequestDispatcher("/login.jsp").forward(request,resp);
    }
}

}

2.敏感词汇过滤

    *分析:
        对request对象进行增强

    *增强对象的功能:
        *设计模式:一些通用的解决固定问题的方式
        1.装饰模式
        2.代理模式
            *概念:
                1.真实对象:被代理的对象
                2.代理对象:
                3.代理模式:代理对象代理真实对象,增强对象功能
            *实现方式:
                1.静态代理:有一个类文件描述代理模式
                2.动态代理:在内存中形成代理类
                    *实现步骤:
                        1.代理对象和恶真实对象实现相同接口
                        2.代理对象 = Proxy.newProxyInstance();
                        3.使用代理对象调用方法。
                        4.增强方法
        代码如下:
package cn.zzz.web.filter;

@WebFilter("/sensitiveFilter")
public class SensitiveFilter implements Filter {
public void destroy() {
}

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
    //创建代理对象,增强getParameter
    ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //增强getParameter
            if (method.getName().equals("getParameter")) {
                //增强返回值
                String value = (String) method.invoke(req, args);
                if (value != null) {
                    for (String str : list) {
                        if (value.contains(str)) {
                            value = value.replace(str, "***");
                        }
                    }
                }
                return value;
            }

            if (method.getName().equals("getParameterMap")) {
                Map<String, String[]> map = (Map<String, String[]>) method.invoke(req, args);
                if (map != null) {
                    for (int i = 0; i < list.size(); i++) {
                        String str = list.get(i);
                        for (String s : map.keySet()) {
                            if (map.get(s)[0].contains(str)) {
                                map.get(s)[0] = map.get(s)[0].replace(str, "***");
                            }
                        }
                    }
                }
                return map;
            }
            if (method.getName().equals("getParameterValues")) {
                String[] value = (String[]) method.invoke(req, args);

                //需要把敏感词汇txt每一行的字符都搞到一个字符串数组中
                if (value != null) {
                    for (String str : list) {
                        for (int i = 0; i < value.length; i++) {
                            if (value[i].contains(str)) {
                                value[i].replaceAll(str, "***");

                            }
                        }
                    }
                }
                return value;
            }

            return method.invoke(req, args);
        }
    });


    chain.doFilter(proxy_req, resp);
}

private List<String> list = new ArrayList<String>();

public void init(FilterConfig config) throws ServletException {

    try {
        //加载文件
        ServletContext servletContext = config.getServletContext();
        String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");

        //读取文件
        FileInputStream fis = new FileInputStream(realPath);
        BufferedReader br = new BufferedReader(new InputStreamReader(fis, "UTF-8"));
        //将文件的每一行添加到list中
        String line = null;
        while ((line = br.readLine()) != null) {
            list.add(line);
        }
        br.close();
    } catch (Exception e) {
        e.printStackTrace();
    }

}
}

Listener:监听器

*概念:web的三大组件之一
    *事件监听机制
        *事件
        *事件源
        *监听器
        *注册监听
    
    *ServletContextListener:监听ServletContext对象的创建和销毁
        *方法:
            1.contextInitialized
            2.contextDestroyed
        *步骤:
            1.定义类,实现接口
            2.复写方法
            3.配置
                3.1web.xml
                3.2注解
posted @ 2019-12-07 14:31  lopzzzzzzzzzzzzzz  阅读(169)  评论(0编辑  收藏  举报