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的套路类似