Filter过滤器
一、Filter过滤器是什么?
- 概念:处于客户端与服务器目标资源之间的一道过滤技术。
- 作用:在访问目标资源文件之前,通过一系列的过滤器对请求进行修改、判断等,把不符合规则的请求在中途拦截或修改。也可以对响应进行过滤,拦截或修改响应。
- 创建:
- 实现Filter接口,重写方法,通过web.xml进行配置
- 注解配置:@WebFilter(value=“/过滤目标资源”)
- 和Servlet的区别:
- Filter的value中设置的是过滤(拦截)路径
- 过滤路径不能单独使用/
- 过滤器链:chain
doFilter: 执行过滤,核心方法
放行(如果有下一个过滤器,则执行下一个过滤器,没有则执行目标资源)
chain.doFilter(request, response);
- 优先级:
- web.xml高于注解
- web.xml中的优先级由先后顺序决定
- 注解的先后顺序由全类名的字符串顺序决定。(Windows按字母的先后顺序,MAC、LINUX是按字母的倒序)
二、Filter过滤器的应用
1.禁止浏览器缓存动态页面(老问题,只有老浏览器会有这种问题,现在一般不会发生),比如验证码
- 解决办法1:在JSP页面中添加
```jsp
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
```
解决办法2:在过滤器中设置响应头
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
//放行
HttpServletResponse response= (HttpServletResponse) resp;
//不让浏览器走缓存
response.setHeader("pragma", "no-cache");
response.setHeader("cache-control", "no-cache");
response.setDateHeader("expires", 0);
chain.doFilter(req, resp);
}
2.设置浏览器缓存一些数据,比如图片等等一些资源
@WebFilter("*.jpg")
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletResponse response = (HttpServletResponse)resp;
response.setHeader("cache-control","max-age=600");
response.setDateHeader("expires",System.currentTimeMillis()+600000);
chain.doFilter(req, resp);
}
- 为什么会出现缓存的问题?
- 刷新走的是服务器,不会出现缓存问题。
- 返回和回车都有可能会走缓存,也可能走服务器。
- 相同的请求内容IE会直接走缓存,Chrome会走304(重定向缓存)既走服务器,又走缓存。
3.自动登录。简单demo,还有很多功能没实现
-
首页
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head> <body> <h2>欢迎:${username}</h2> </body> </html>
登录页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>用户登陆</title> </head> <body> <form action="${pageContext.request.contextPath}/loginServlet" method="post" enctype="application/x-www-form-urlencoded"> <input type="text" name="username" placeholder="请输入用户名"><br> <input type="password" name="password" placeholder="请输入密码"><br> <input type="checkbox" name="auto">记住我<br> <input type="submit" value="登陆"> </form> </body> </html>
登录Servlet
package com.hs.controller; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Base64; @WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); String auto = request.getParameter("auto"); if ("admin".equals(username)&&"888".equals(password)){ request.getSession().setAttribute("username",username); //判断是否勾选记住用户 if (auto!=null){ //勾选了,将用户信息保存在cookie中,有效期七天 //用户信息,用户名和密码 String userInfo = username + "#" +password; //给用户信息加密 //加盐操作 char[] chars = userInfo.toCharArray(); for (int i = 0; i < chars.length; i++) { chars[i]--; } userInfo = new String(chars); //Base64编码 userInfo = Base64.getEncoder().encodeToString(userInfo.getBytes()); //创建cookie对象,将加密后的信息存入 Cookie cookie = new Cookie("userInfo",userInfo); cookie.setPath(request.getContextPath()); cookie.setMaxAge(7*24*60*60); //将cookie添加到响应报文 response.addCookie(cookie); } response.sendRedirect(request.getContextPath()+"/index.jsp"); }else { request.setAttribute("msg","用户名或密码错误"); request.getRequestDispatcher("/message.jsp").forward(request,response); } } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } }
Index.jsp的拦截过滤器
-
package com.hs.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Base64; @WebFilter(filterName = "AutoLoginFilter",value = "/index.jsp") public class AutoLoginFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String username = (String) request.getSession().getAttribute("username"); //判断用户是否已经登陆 if(username!=null){ //已经登陆就直接放行,结束方法 chain.doFilter(req, resp); return; } //没登录从cookie中查看缓存的信息是否正确 Cookie[] cookies = request.getCookies(); //遍历cookie查看用户信息是否存在 for (Cookie cookie : cookies) { if ("userInfo".equals(cookie.getName())){ String userInfo = cookie.getValue(); //解码 byte[] decode = Base64.getDecoder().decode(userInfo.getBytes()); userInfo = new String(decode); //减盐 char[] chars = userInfo.toCharArray(); for (int i = 0; i < chars.length; i++) { chars[i]++; } userInfo = new String(chars); //切割 String[] split = userInfo.split("#"); String name = split[0]; String pwd = split[1]; //判断cookie中存储的信息是否正确 if ("admin".equals(name)&&"888".equals(pwd)){ request.getSession().setAttribute("username",name); }else { //不正确,删除cookie Cookie delCookie = new Cookie("userInfo",""); delCookie.setPath(request.getContextPath()); delCookie.setMaxAge(0); response.addCookie(delCookie); } } } chain.doFilter(req, resp); } @Override public void init(FilterConfig config) throws ServletException { } }
4.过滤文明词汇(简单实现)
-
提交过滤信息的页面comment.jsp
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>过滤内容</title> </head> <body> <form action="commentServlet" method="post"> <textarea name="comment"> </textarea> <input type="submit" value="骂人"> </form> </body> </html>
获取过滤数据的CommentServlet
package com.hs.controller; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/commentServlet") public class CommentServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置编码 request.setCharacterEncoding("utf-8"); //获取数据 String comment = request.getParameter("comment"); System.out.println(comment); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }
过滤文明词汇的拦截器DirtyFilter,关键:增强request的getParameter(),利用到装饰类
package com.hs.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.IOException; import java.util.ArrayList; import java.util.List; @WebFilter("/commentServlet") public class DirtyFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //获取请求数据后,对数据的、内容的不文明词语进行替换 // HttpServletRequest request = (HttpServletRequest) req; MyRequest myRequest = new MyRequest(request); //将增强功能后的request作为参数返回 chain.doFilter(myRequest, resp); } //静态内部类,需要增强request.getParameter()的功能,利用到装饰类HttpServletRequestWrapper static class MyRequest extends HttpServletRequestWrapper{ //文明词汇集合 private List<String> dirties; public MyRequest(HttpServletRequest request) { super(request); dirties = new ArrayList<>(); dirties.add("猪"); dirties.add("傻"); dirties.add("逼"); dirties.add("废物"); dirties.add("SB"); } //重写getParameter(),增强功能 @Override public String getParameter(String name) { String value = super.getParameter(name); //对文明词汇进行替换 for (String dirty : dirties) { value = value.replace(dirty,"🐷"); } return value; } } @Override public void init(FilterConfig config) throws ServletException { } }
5.内容压缩(简单实现,JSP页面,不同文本)
-
被压缩的页面
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>新闻页面</title> </head> <body> <h2>建党100年!走向深蓝的人民海军,正如您所愿</h2> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> <h2>建党100年!走向深蓝的人民海军,正如您所愿</h2> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> <p> “潜航大洋,他们是捍卫国家主权的杀手锏;翱翔海天,他们是维护祖国安宁的急先锋;蛟龙突击,他们是攻无不克的夺命刃……”在人民海军成立72周年之际,海军向全社会公开发布主题宣传片《大海向党旗报告》,庆祝党的百年华诞。通过展现海军一线部队忠诚使命、英勇善战、建功海洋的精神追求,让你领略新时代海军官兵的家国情怀,让你感悟人民海军向海图强的豪情壮志。(视频:海军政治工作部宣传局、新华社解放军分社 联合摄制 /文字: 李珂嘉贺 孙飞 /编辑:高泽明) </p> </body> </html>
-
拦截要被压缩页面的GZIPFilter。关键:增强response的getWriter(),也利用到装饰类
-
package com.hs.filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.*; import java.util.zip.GZIPOutputStream; @WebFilter("/news.jsp") public class GZIPFilter implements Filter { @Override public void destroy() { } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { //使用增强功能的myResponse HttpServletResponse response = (HttpServletResponse) resp; MyResponse myResponse = new MyResponse(response); chain.doFilter(req, myResponse); //将压缩后的内容打印到页面上 System.out.println("原始大小:"+myResponse.getByteArrayOutputStream().size()); //响应 //保存压缩后的内容,gzip压缩数据后的内容会存放在zipContent ByteArrayOutputStream zipContent = new ByteArrayOutputStream(); //压缩流 GZIPOutputStream gzip = new GZIPOutputStream(zipContent); //获取保存数据的内存流,利用压缩流进行压缩写入 gzip.write(myResponse.getByteArrayOutputStream().toByteArray()); gzip.flush(); gzip.close(); System.out.println("压缩后的大小:"+zipContent.size()); //把压缩后的数据发给浏览器 //先设置响应头告诉浏览器是压缩后的数据 response.setHeader("Content-Encoding","gzip"); response.getOutputStream().write(zipContent.toByteArray()); } @Override public void init(FilterConfig config) throws ServletException { } //静态内部类,需要增强response.getWrite()的功能,利用到装饰类HttpServletResponseWrapper static class MyResponse extends HttpServletResponseWrapper { private PrintWriter printWriter; private ByteArrayOutputStream byteArrayOutputStream; public MyResponse(HttpServletResponse response) { super(response); byteArrayOutputStream = new ByteArrayOutputStream(); try { printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream,"utf-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } @Override public PrintWriter getWriter() throws IOException { return printWriter; } public ByteArrayOutputStream getByteArrayOutputStream() { if (printWriter!=null){ printWriter.flush(); } return byteArrayOutputStream; } } }