过滤器filter,监听器listener

1. filter过滤器

  • 作用:
  • 过滤servlet,jsp,js,css,图片对象,以及一切在服务器,客户端想访问的对象
  • 用来设置编码,过滤掉脏话等…
  • 过滤器链:你有多个过滤器,你如果多个filter过滤一个servlet,配置一个servlet,那么这个多个过滤器会形成过滤器链。

1.1 原理

  • 不多bb,请看下面的图

  • 就像学校的图书馆,你进学校有保安守着校门,这是一次过滤,进学校图书馆,你得刷卡,才可自习。只是过滤器可以配置多个,对不同得对象…

1.2 配置

  • 比如我想创建一个过滤掉脏话的过滤器叫FilterDirtyTalk
  • 对DirtyMsg servlet进行过滤
  <filter>
  	<filter-name>FilterDirtyTalk</filter-name>
  	<filter-class>filter.FilterDirtyTalk</filter-class>

	<!-- 与servlet配置相似 -->
  </filter>
  
  <filter-mapping>
  	<filter-name>FilterDirtyTalk</filter-name>
  	<url-pattern>/DirtyMsg</url-pattern> <!-- 想进入dirtymsg servlet 得先经过filter -->
  </filter-mapping>
  • 但是上面的servlet只能过滤从jsp进来的 !假如,你有业务,从一个servlet转发到jsp后台页面,但是这个页面要登录才行。你没登录,按上面的配置,过滤器过滤不到,所以来了解过滤器的规则。

  • 过滤器过滤规则

FORWARD:转发时进行过滤
REQUEST:浏览器直接请求时进行过滤(默认:没有配置dispatcher节点的时候)
INCLUDE:动态包含的时候执行过滤器
<%@ include %>:静态包含,把被包含的页面的源代码拷贝过来与包含页面一起转译编译运行;包含的过程中不能传参
jsp:include动态包含:包含页面和被包含页面分开转译编译运行,然后将结果合并到一起;包含的过程中可以传参
ERROR:在出错的时候进入过滤器

  • 在web.xml <filter-mapping>加上
  	<dispatcher>REQUEST</dispatcher> <!-- 默认对请求进行过滤 -->
  	<dispatcher>FORWARD</dispatcher> <!-- 会检查请求转发-->

1.3 过滤掉脏话demo

  • 过滤掉脏话filter_config.txt 文本文件
你妹=妹妹
你弟=弟弟
你妈=妈妈
  • 拿到request对象中的用户请求数据,继承HttpServletRequestWrapper
package servlet;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class MyRequest extends HttpServletRequestWrapper {

	private Map<String, String[]> map;
	
	public MyRequest(HttpServletRequest request) {
		super(request);
		map = request.getParameterMap();	
	}
	
	@Override
	public String getParameter(String name) {
		// 返回第一个值
		String[] str = map.get(name);
		if (str.length > 0 && str != null)
			return str[0];
		return null;
	}
	
	@Override
	public Map<String, String[]> getParameterMap() {
		// 返回map
		return map;
	}
	
	@Override
	public String[] getParameterValues(String name) {
		// string数组值
		
		return map.get(name);
	}

}

  • 把脏话转成civilized word
package filter;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import servlet.MyRequest;

public class FilterDirtyTalk implements Filter {

	@Override
	public void destroy() {
		// 过滤掉 你妹,你妈,你弟等 -> 你妹=妹妹 
	
		// tomcat8.0 给你的版本map是副本, 重写HttpServletRequestWrapper 重新拿到map的值 ... 

	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest hreq = (HttpServletRequest) req;
		
		// 把请求改变为我的请求类,里面正真的改变了map集合
		req = new MyRequest(hreq);
		
		if (hreq.getMethod().equalsIgnoreCase("get")) { // get方式
			// tomcat 8.0 已经设置好了get编码
		} else if (hreq.getMethod().equalsIgnoreCase("post")) {
			req.setCharacterEncoding("utf-8");
		}
		resp.setContentType("text/html;charset=utf-8");
		
		File file = new File("E:\\servletStudy\\Servlet3\\filter_config.txt");
		
		// 读取脏话
		FileReader fr = new FileReader(file);
		BufferedReader br = new BufferedReader(fr);
		
		HashMap<String, String> dirtyMap = new HashMap<String, String>();
		// 改变value的值 如果是dirty-talk
		// 读取filter-config
		String str = br.readLine();
		
		while (str != null) {
			dirtyMap.put(str.split("=")[0], str.split("=")[1]);
			str = br.readLine();
		}	
		// 把脏话放入集合。。。
		Set<Entry<String, String>> dirtySet = dirtyMap.entrySet();
		
		// 请求对象键值对
		Map<String, String[]> map = req.getParameterMap();
		
		Set<Entry<String,String[]>> entrySet = map.entrySet();
		for (Entry<String, String[]> entry : entrySet) {
			
			String key = entry.getKey(); // 请求对象参数
			String[] value = entry.getValue(); // 请求对象值
			
			System.out.println(key + "\t" + Arrays.toString(value));
				
			for (int i = 0; i < value.length; i++) {
				for(Entry<String, String>  set : dirtySet) {
					String dirty = set.getKey();
					if (dirty.equals(value[i]))
						value[i] = set.getValue();
				}
			}
			System.out.println("转换后");
			System.out.println(key + "\t" + Arrays.toString(value));
		}
		
		br.close();
		fr.close();
	
		
		// 放行 jsp才可访问servlet...
		chain.doFilter(req, resp);
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
	
	}

}

  • DirtyMsg 拿到jsp页面过滤的值
package servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class DirtyMsg extends HttpServlet {

	/**
	 * dirty msg
	 */
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse arg1)
			throws ServletException, IOException {
		String name1 = req.getParameter("name1");
		String name2 = req.getParameter("name2");
		String name3 = req.getParameter("name3");
		
		System.out.println(name1 + name2 + name3);
	}
}

  • jsp页面

  • 正确过滤后:

2. listener监听器

2.1 作用

  • 用来监听request/session/application的创建/销毁/数据操作
  • 讲一个ServletContextListener, 用来监听application的创建和销毁(监听tomcat的开启和关闭)

2.2 ServletContextListener demo

  • 配置
  <listener>
  	<listener-class>test.MyServletContextListener</listener-class>
  </listener>
  • 实现
package test;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("服务器开启啦。。。 可以初始配置文件啦...");
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		System.out.println("服务器销毁啦。。。");
	}

}

  • ServletContextAttributeListener,元素的移除,可得到移除信息,rbr
  • request,session的套路类似

猜你喜欢

转载自blog.csdn.net/qq_44783283/article/details/106971163