JavaWeb——Filter过滤器
来源:互联网 发布:godaddy域名转到万网 编辑:程序博客网 时间:2024/06/04 18:25
1、Filter可以做什么
Filter(过滤器)对web服务器管理的web资源进行拦截,从而实现一些特殊功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些功能。
2、Filter如何实现拦截
web浏览器<————>web服务器<————>过滤器<————>web资源
Filter接口中有一个doFilter方法,web服务器在调用doFilter方法时,会传递一个filterChain对象,该对象有一个doFilter()方法,如果调用改方法,则服务器调用web资源,否则web资源不会被访问。
Filter接口的doFilter()方法:
- 前:对request,response做预处理
- 是否调用目标资源,是否执行filterChain对象的diFilter()方法。
- 后:捕获响应的web资源,实现一些新的功能。
3、Filter开发步骤
Filter开发分为两个步骤,首先要编写java类实现filter接口和doFilter方法,二是在web.xml中对编写的filter接口进行注册和映射,设置其拦截的资源。
3.1 XML配置
3.1.1 filter注册
注册Filter范例:
<filter> <description>FilterDemo02过滤器</description> <filter-name>FilterDemo02</filter-name> <filter-class>me.gacl.web.filter.FilterDemo02</filter-class> <!--配置FilterDemo02过滤器的初始化参数--> <init-param> <description>配置FilterDemo02过滤器的初始化参数</description> <param-name>name</param-name> <param-value>gacl</param-value> </init-param> <init-param> <description>配置FilterDemo02过滤器的初始化参数</description> <param-name>like</param-name> <param-value>java</param-value> </init-param></filter>
<filter>
标签用于内注册一个filter过滤器<description>
标签用于添加描述信息(可省略)<filter-name>
标签用于指定过滤器的名称<filter-class>
标签用于指定过滤器的类名<init-param>
标签用于设置filter的初始化参数,<param-name>
和<param-value>
制定了某属性的名称及该属性的值。
<init-param>
标签中的属性可以通过FilterConfig对象的方法获得。
3.1.2 filter映射
映射filter实例1:
<!--映射过滤器--> <filter-mapping> <filter-name>FilterDemo02</filter-name> <!--“/*”表示拦截所有的请求 --> <url-pattern>/*</url-pattern> </filter-mapping>
映射filter实例2:
<filter-mapping> <filter-name>testFilter</filter-name> <url-pattern>/index.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher></filter-mapping>
<dispatcher>
标签设置用户以什么方式访问时,过滤器工作。标签的属性值:
- REQUEST:用户直接访问页面,过滤器工作。
- INCLUDE:目标资源通过RequestDispatcher的include()方法访问,过滤器工作。
- FORWARD:目标资源通过RequestDispatcher的forward()方法访问,过滤器工作。
- ERROR:目标资源通过声明式异常处理机制调用时,过滤器工作。
3.2 实现Filter接口并实现doFilter方法
过滤器范例:
public class FilterDemo01 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("----过滤器初始化----"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //对request和response进行一些预处理 request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); System.out.println("FilterDemo01执行前!!!"); chain.doFilter(request, response); //让目标资源执行,放行 System.out.println("FilterDemo01执行后!!!"); } @Override public void destroy() { System.out.println("----过滤器销毁----"); }}
4、Filter的生命周期
Filter的创建和销毁都由WEB服务器负责。web应用程序启动,web服务器创建Filter的实例对象,调用init方法,这个过程只执行一次。
Filter的销毁由web容器调用destroy方法销毁Filter,释放过滤器使用的资源。在Filter的生命周期内执行一次。
5、Decorator设计模式
5.1 Decorator模式介绍
在某个对象不能满足业务需求时,通常有两种方式来对其进行增强:
- 编写子类,继承并重写需要增强的方法。
- 使用Decorator设计模式对方法进行增强。
一般情况下我们使用第一种方法,但在某个特殊情况下,我们只能使用第二种方法,即:被增强的对象,只能得到对象,不能得到class文件。
在filter中可以得到request,response对象,可以使用decorator模式对request和response对象进行包装, 在把包装对象传给目标资源。
5.2 Decorator模式实现
- 被增强对象集成了什么接口和父类,编写一个类,也继承这些接口和父类。
- 在类中定义变量,变量类型即被增强对象的类型。
- 在类中定义构造函数,接收被增强对象。
- 覆盖需增强的方法,编写增强的代码。
Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,(HttpServletRequestWrapper类实现了request接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的request对象的对应方法)以避免用户在对request对象进行增强时需要实现request接口中的所有方法。
所以当需要增强request对象时,只需要写一个类继承HttpServletRequestWrapper类,然后在重写需要增强的方法即可
当需要增强response对象时,继承HttpServletResponseWrapper类。
6、Filter的应用
6.1 统一全站字符编码
public class EncodingFilter implements Filter { String encoding = null; FilterConfig filterConfig = null; public void init(FilterConfig config ) throws ServletException{ this.filterConfig=config; this.encoding=filterConfig.getInitParameter("encoding"); } public void doFilter(ServletRequest request , ServletResponse response , FilterChain chain) throws IOException , ServletException{ if(encoding !=null){ request.setCharacterEncoding(encoding); } chain.doFilter(request, response); } public void destroy(){ this.encoding = null; this.filterConfig = null; }}
在init方法中获得XML注册时的encoding属性值,将它传递给该类的属性encoding,在doFilter方法中,使用erquest.setCharacterEncoding()方法,设置request的属性值。
6.2 禁止浏览器缓存动态页面
public class NoCacheFilter implements Filter{ public void init (){} public void doFilter(ServletRequest req , ServletResponse resp, FliterChain chain) throws IOException ,ServletException{ //强制转换 HttpServletRequest request = (HttpServletRequest )req; HttpServletResponse response = (HttpServletResponse ) resp; //三种方法设置禁止缓存 response.setDataHeader("Expires",-1); response.setHeader("Cache-control","no-cache"); response.setHeader("Pragma","no-cache"); chain.doFilter(request,response); } public void destroy(){}}
XML配置:
<filter> <filter-name>NoCacheFilter</filter-name> <filter-class>web.filter.NoCacheFilter</filter-class></filter><filter-mapping> <filter-name>NoCacheFilter</filter-name> <!--只拦截Jsp请求--> <servlet-name>*.jsp</servlet-name></filter-mapping>
HTTP响应头字段有三种禁止浏览器缓存的头字段:
- Expires:告诉浏览器把回送的资源缓存多长时间 -1或0则是不缓存
- Cache-Control:no-cache,控制浏览器不要缓存数据
- Pragma:no-cache,控制浏览器不要缓存数据
HTTP请求中的常用请求字段和HTTP的响应状态码及响应头
http://blog.csdn.net/qxs965266509/article/details/8082810
6.3 控制浏览器缓存静态页面
public class NoCacheFilter implements Filter{ public void init (){} public void doFilter(ServletRequest req , ServletResponse resp, FliterChain chain) throws IOException ,ServletException{ //强制转换 HttpServletRequest request = (HttpServletRequest )req; HttpServletResponse response = (HttpServletResponse ) resp; //得到请求资源的rul String url = request.getRequestURI(); //得到请求资源的后缀 String ext = uri.substring(uri.lastIndexOf(".")+1); //得到该后缀在xml设置中的缓存时间属性值 String time = filterConfig.getInitParameter(ext); if(time!=null){ long t = Long.parseLong(time)*3600*1000; //设置响应头字段Expires的缓存时间 response.setDataHeader("Expires",System.currentTimeMillis()+t); } } public void destroy(){}}
XML配置:
<!-- 配置缓存过滤器 --> <filter> <filter-name>CacheFilter</filter-name> <filter-class>me.gacl.web.filter.CacheFilter</filter-class> <!-- 配置要缓存的web资源以及缓存时间,以小时为单位 --> <init-param> <param-name>css</param-name> <param-value>4</param-value> </init-param> <init-param> <param-name>jpg</param-name> <param-value>1</param-value> </init-param> <init-param> <param-name>js</param-name> <param-value>4</param-value> </init-param> <init-param> <param-name>png</param-name> <param-value>4</param-value> </init-param> </filter> <!-- 配置要缓存的web资源的后缀--> <filter-mapping> <filter-name>CacheFilter</filter-name> <url-pattern>*.jpg</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CacheFilter</filter-name> <url-pattern>*.css</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CacheFilter</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CacheFilter</filter-name> <url-pattern>*.png</url-pattern> </filter-mapping>
6.4 用户自动登陆
引用redarmychen的部分代码
实现用户自动登陆的思路:
- 用户首次登陆成功后,发送一个名称为user的cookie给客户端,cookie的值为用户名和加密的密码,同时在session对象中存放一个用户登录记录的属性值。
- 编写一个LoginFilter,filter检查session的属性值是否匹配,或者检查用户是否带有名称为user的cookie,(如果有,则调用dao查询cookie的用户名和密码是否和数据库匹配)以实现程序完成自动登陆。
LoginServlet的部分代码
创建cookie:
long time = System.currentTimeMillis() + expires * 1000; //cookie拼接的value值,(可以根据自己的想法设计) String cookieValue = name + ":" + time + ":" + md5Value(name + ":" + pass + ":" + time); //创建cookie autoCookie = new Cookie("autologin", cookieValue);
添加cookie:
autoCookie.setMaxAge((int) expires); autoCookie.setPath("/day56"); // 添加cookie response.addCookie(autoCookie);
添加session对象:
request.getSession().setAttribute("admin", entity);
LoginFilter的部分代码
查看session中是否有标志:
// 1.首先判断sesion中有没有admin Object object = request.getSession().getAttribute("admin"); // 如果session中有用户 if (object != null) { // 跳转到成功登录的界面 request.getRequestDispatcher("./sc.jsp").forward(request, response); return; }
查看cookie中是否有用户登录记录:
// 2.判断cookie中是否存在 autologin标识符 的cookie对象 // 声明cookie Cookie autoCookie = null; // 获取所有的cookie Cookie cookies[] = request.getCookies(); // 如果没有cookie信息,就继续执行login.do,跳转到login.jsp页面 if (cookies != null) { // 如果有,就遍历cookie for (Cookie cookie : cookies) { // 判断cookie中是否有autologin标识符的cookie if ("autologin".equals(cookie.getName())) { autoCookie = cookie; // 如果有 就赋值给临时变量autoCookie } } // 3. 判断autoCookie是否等于null if (autoCookie == null) { // 如果等于null,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 3.如果autoCookie不等于null,就判断cookie的值 // 获取cookie值 String value = autoCookie.getValue(); // 拆分cookie的值 String temp[] = value.split(":"); System.out.println(temp.length); // 判断长度 是否等于自己拼接的长度 if (temp.length != 3) { // 如果不等于3,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 获取cookie拆分的各个值 String name = temp[0]; // 用户名 String time = temp[1];// 获取有效时间 String service_md5Value = temp[2];// 获取md5的加密后的字符 // 4.判断cookie是否失效 if (Long.valueOf(time) <= System.currentTimeMillis()) { // 如果失效,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 5.如果cookie没有失效,根据用户名,去查询用户信息 AdminService adminService = new AdminServiceImpl(); // 查询用户信息 Admin entity = adminService.checkLogin(name); System.out.println(entity+"0000"); // 判断用户是否为null if (entity == null) { // 如果没有查询的用户,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 按照服务器拼接的字符的方式,拼接md5加密的字符串 String md5Temp = entity.getName() + ":" + entity.getPass() + ":" + time; // 判断md5加密后和服务器端加密的字符是否相等 if (!(md5Value(md5Temp).equals(service_md5Value))) { // 在不相等的情况下,则继续执行login.jsp页面 chain.doFilter(request, response); return; } // 如果满足了cookie取值判断的所有结果,则跳转到成功登录的界面. request.getSession().setAttribute("admin", entity); request.getRequestDispatcher("./sc.jsp").forward(request, response); } else { // 在没有cookie信息的时候,则继续login.jsp页面 chain.doFilter(request, response); return; } }
- JavaWeb——Filter过滤器
- javaweb——Filter(过滤器)学习
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十六)——Filter(过滤器)常见应用
- javaweb学习总结(四十六)——Filter(过滤器)常见应用
- #笔记#圣思园 JavaWeb 第39讲——Filter过滤器
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十六)——Filter(过滤器)常见应用
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十六)——Filter(过滤器)常见应用
- javaweb学习总结(四十六)——Filter(过滤器)常见应用
- javaweb学习总结 ——Filter(过滤器)学习
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb学习总结(四十六)——Filter(过滤器)常见应用
- openssl动态库生成以及交叉编译
- android photoview 图片放大缩放功能 ImageView
- 排序算法
- ping-pong操作
- Android集成阿里云消息推送的方法步骤
- JavaWeb——Filter过滤器
- Android studio 过滤log中指定字符(不显示包含指定字符的log)
- 普通的 Web 应用数据安全
- JAVA 读取文件字符串乱码问题
- 微信公众号如何获得原创保护?
- test
- 区间dp-洛谷P1040 加分二叉树
- 80% 应聘者都不及格的 JS 面试题
- 使用moy快速开发后台管理系统(四)