web服务端复习_day05_Filter&Listener

核能气质少年 提交于 2020-03-08 14:48:19

Filter

一. 概念

  • web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
  • 过滤器的作用:
    • 一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…

二. 使用步骤

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

2. 复写方法

  • init():在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
  • doFilter():每一次请求被拦截资源时,会执行。执行多次
  • destroy():在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源

3. 配置拦截路径

①. 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>

②. 注解

  • @WebFilter("/*")

③. 拦截路径配置:

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

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

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

4. 示例

@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
	    System.out.println("filterDemo1被执行了....");
	     //放行
	​	filterChain.doFilter(servletRequest,servletResponse);
	​			        
	​	System.out.println("filterDemo1回来了....");
	​			
	​}
	
	@Override
    public void destroy() {

    }
}

三. 过滤器链

1. 执行顺序

  • 如果有两个过滤器:过滤器1和过滤器2
  1. 过滤器1
  2. 过滤器2
  3. 资源执行
  4. 过滤器2
  5. 过滤器1

2. 过滤器先后顺序问题

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

四. 设计模式

1. 概念

  • 软件设计模式(Design pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

2. 代理模式

① 概念

  • 代理对象代理真实对象,达到增强真实对象功能的目的

② 实现方式

  • 静态代理:有一个类文件描述代理模式
  • 动态代理:在内存中形成代理类

③ 动态代理的实现步骤

  • 代理对象和真实对象实现相同的接口
  • 代理对象 = Proxy.newProxyInstance();
  • 使用代理对象调用方法。
  • 增强方法
    • 增强方式:
      1. 增强参数列表
      2. 增强返回值类型
      3. 增强方法体执行逻辑

五 . 案例

  • 敏感词汇过滤
  • 需求:
    1. 对day17_case案例录入的数据进行敏感词汇过滤
    2. 敏感词汇参考《敏感词汇.txt》
    3. 如果是敏感词汇,替换为 ***
@WebFilter("/*")
public class FilterDemo04 implements Filter {
    private List<String> list = new ArrayList<String>();

    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 {
                // 获取到调用的方法名
                String methodName = method.getName();
                if ("getParameter".equals(methodName)) {
                    // 如果是getParameter方法, 则增强
                    String res = (String) method.invoke(req, args);

                    for (String s : list) {
                        if (!res.contains(s)) continue;
                        res = res.replaceAll(s, "***");
                    }

                    return res;
                }

                if ("getParameterMap".equals(methodName)) {
                    Map<String, String[]> map = (Map<String, String[]>) method.invoke(req, args);
                    Set<String> keys = map.keySet();
                    for (String key : keys) {
                        String[] strings = map.get(key);
                        for (int i = 0; i < strings.length; i++) {
                            for (String s : list) {
                                if (!strings[i].contains(s)) continue;
                                strings[i] = strings[i].replaceAll(s, "***");
                            }
                        }
                    }
                    return map;
                }

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

        chain.doFilter(proxy_req, resp);
    }

    public void destroy() {
    }

    public void init(FilterConfig config) throws ServletException {
        // 读取敏感词汇表, 保存敏感词汇到List集合中
        BufferedReader br = null;
        try {
            ServletContext context = config.getServletContext();
            String realPath = context.getRealPath("/WEB-INF/classes/敏感词汇.txt");

            br = new BufferedReader(new FileReader(realPath));

            String line = null;

            while ((line = br.readLine()) != null) {
                list.add(line);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

Listener

一. 事件监听机制

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

二. ServletContextListener

1. 作用

  • 监听ServletContext对象的创建和销毁

2. 方法

  • void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
  • void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法

3. 步骤

  1. 定义一个类,实现ServletContextListener接口
  2. 复写方法
  3. 配置
  • web.xml
<listener>
	<listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class>
</listener>
* 指定初始化参数<context-param>
  • 注解:
    • @WebListener
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!