JavaWeb-Filter
来源:互联网 发布:java高级工程师技能 编辑:程序博客网 时间:2024/05/22 18:42
话说:
Servlet之后,我们客串了一下数据连接池,这会总结一下过滤器——Filter。
What?
Flilter即过滤器,就是javax.servlet包下面的一个接口。实现这个接口可以帮我们做很多事情。它是向Web应用程序的请求和响应添加功能的Web服务组件;可以统一的集中处理请求和响应;实现对数据的过滤。
可是还是抽象,到底有什么卵用?
应用场合:
1、对请求和响应进行统一处理
2、对请求日志进行日志记录和审核
3、对数据进行屏蔽和替换
笔者猜测,屏蔽色情、论坛屏蔽敏感字段可能会用到这个
4、对数据进行加密和解密
近代的电报,和这个类似吧
Why?
貌似跟我们有毛线关系啊?有的。还记得前面,我们写了很多个Servlet,后来简化成了BaseServlet,在BaseServlet里面,写多个方法。方法里面实现调用。本质还是一个Servlet处理一个请求。然鹅,Filter就可以实现一个Filter处理按照正则表达式匹配后满足条件的所有请求。这里我们来3个案例,实践出真知嘛!
案例一:MyFilter(Filter的实现及生命周期)
案例二:Filter实现权限过滤
案例三:Filter字符编码过滤
案例一:MyFilter(Filter的实现及生命周期)
Filter是什么东东?如何用呢?建立一个Filter步骤:
1)建立实现Filter接口的类(javax.servlet.Filter)也就是Tomcat自带的lib
2)实现过滤行为
3)在web.xml中配置过滤器
1)建立实现Filter接口的类(javax.servlet.Filter)也就是Tomcat自带的lib
整体工程架构图如下:
MyFilter
package com.hmc.filter;import javax.servlet.*;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 java.io.IOException;/** * User:Meice * 2017/10/6 */public class MyFilter implements Filter{ @Override public void init(FilterConfig config) throws ServletException { System.out.println("Filter初始化...."); } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { System.out.println("请求来了..."); //执行过滤 chain.doFilter(req,resp); System.out.println("处理响应..."); } @Override public void destroy() { System.out.println("Filter销毁啦...."); }}
需要注意的是,一定要调用doFilter(request,response)方法,且在这个方法之前是过滤请求,此方法之后,过滤响应。那么以后如果写关于请求的操作,就要在该方法之后。
配置web.xml
<!--配置MyFilter过滤器--> <filter> <filter-name>myFilter</filter-name> <filter-class>com.hmc.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <!-- <url-pattern>/*</url-pattern>--><!--对所有请求过滤;一般我们不同时写多个过滤条件--> <!-- <url-pattern>/admin/*</url-pattern>--><!-- 对admin目录下的所有请求进行过滤--> <url-pattern>*.do</url-pattern><!--对所有以.do结尾的请求过滤--> </filter-mapping>
这里,我们开启猫,然后做各种测试即可。
总结:
1、Filter根据你的条件,对所有符合条件的请求进行过滤;如果是目录的话,目录下的任何请求也照样过滤;
2、对比Servlet,当年我们写Servlet的时候,每写一个Servlet都要处理编码,每一个请求最开始也要写对应的Servlet,好在后面我们用BaseServlet进行了优化。
4、Filter的生命周期和Servlet一模一样,不过Filter在一开始启动猫的时候就初始化了,然后执行请求,最后销毁。从此,我们又可以掌控Filter的生命啦,有木有感觉很有权力感?
*案例二:Filter实现权限过滤*
我们在web根目录下创建一个admin的目录,该目录下新建一个manager.jsp;代表后台管理界面。
按照案例一的过滤方法,如果我们知道这个目录,就可以直接访问的admin下的任何一个页面,这有点可怕。后台页面只允许管理员才能访问的,这就是案例二要解决的问题:如何通过过滤器来管理权限?
思路是这样的,我们把问题简化一下,如果在登录界面,用户没有输入用户名和密码,我们直接提示用户“未登录”,并且页面跳转到login.jsp;如果用户输入了用户名和密码,判断用户名是否等于admin,如果相等,ok,才允许跳转到admin目录下的manager.jsp页面(执行管理员操作);如果用户名不等于admin,跳转到noaccess.jsp页面,并给出权限不足提示。
页面整体架构图见案例一那张图。
1)用户在登录界面一旦登录,我们通过LoginSerlvet在后台获取用户名和密码,存到session里面,这里不做页面跳转。
登陆页面代码login.jsp
<%-- User: Meice Date: 2017/10/6 Time: 18:41 --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>用户登陆</title> </head> <body> <form action="login.do" method="post"> 用户名:<input type="text" name="uname"><br/> 密码:<input type="password" name="pwd"><br/> <input type="submit" value="登陆"> </form> </body> </html>
编写LoginServlet
package com.hmc.servlet;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * User:Meice * 2017/10/6 */public class LoginServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //接受参数 String uname = req.getParameter("uname"); String pwd = req.getParameter("pwd"); //存储session req.getSession().setAttribute("curUser",uname); }}
在web.xml中配置LoginServlet
<!--Login Servlet 配置--> <servlet> <servlet-name>login</servlet-name> <servlet-class>com.hmc.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login.do</url-pattern> </servlet-mapping>
这样,一旦用户登陆,我们就把页面的参数存在了session里,便于下一步的权限判断。
2)用户一旦你在地址栏输入localhost://8080/JavaWeb_Filter/admin/manager.jsp;也就是用户企图访问后台管理员界面的时候,我们设置一个过滤器AuthFilter来做权限判断。
编写AuthFilter
package com.hmc.filter;import javax.servlet.*;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.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * User:Meice * 2017/10/6 */public class AuthFilter implements Filter { @Override public void init(FilterConfig config) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { chain.doFilter(req,resp); //转换一下请求 HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)resp; //设置编码;奇怪的是,未设置编码也没出现乱码啊!server.xml也没有改 // request.setCharacterEncoding("utf-8"); // response.setCharacterEncoding("utf-8"); //判断sessiion是否为空 String uname =(String) request.getSession().getAttribute("curUser"); System.out.println("uname:"+uname); //如果不输入用户名,默认是"",而不是null值,以下是验证 /* System.out.println("uname == null?"+uname==null); System.out.println("uname== \"\" "+"".equals(uname));*/ //以下验证路径问题(相对路径、绝对路径) System.out.println("====================================="); System.out.println("我是Scheme: "+request.getScheme()); System.out.println("我是ServerName :"+request.getServerName()); System.out.println("我是ServerPort:"+request.getServerPort()); System.out.println("我是ContextPath: "+request.getContextPath()); //所以把我们拼接在一起就是这样 System.out.println(request.getScheme()+"://"+request.getServerName()+":"+ request.getServerPort()+request.getContextPath()+"/" ); //需要注意ContextPath自动带上半边/;为避免路径过长,一般我们这么写: String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; /** * 页面获取路径用 * <%>=basePath</%>或者${basePath}即可;ContextPath就是项目路径 */ //获取上下文路径 String root = request.getContextPath(); if(uname !=null && !"".equals(uname)){ //判断session用户是否是管理员 if("admin".equals(uname)){ }else{ response.getWriter().write("<script>alert('权限不足');location.href='"+root+"/noaccess.jsp'</script>"); } }else{ response.getWriter().write("<script>alert('尚未登录');location.href='"+root+"/login.jsp'</script> "); } chain.doFilter(request,response); } @Override public void destroy() { }}
这里需要注意一下路径的问题,上面root的作用就在此。为此,上面代码中间加入了以下这部分,仅仅作为路径的验证,读者可以忽略。
//以下验证路径问题(相对路径、绝对路径) System.out.println("====================================="); System.out.println("我是Scheme: "+request.getScheme()); System.out.println("我是ServerName :"+request.getServerName()); System.out.println("我是ServerPort:"+request.getServerPort()); System.out.println("我是ContextPath: "+request.getContextPath()); //所以把我们拼接在一起就是这样 System.out.println(request.getScheme()+"://"+request.getServerName()+":"+ request.getServerPort()+request.getContextPath()+"/" ); //需要注意ContextPath自动带上半边/;为避免路径过长,一般我们这么写: String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; /** * 页面获取路径用 * <%>=basePath</%>或者${basePath}即可;ContextPath就是项目路径 */
同样,配置Web.xml中的过滤器
<!--配置权限过滤器--> <filter> <filter-name>authFilter</filter-name> <filter-class>com.hmc.filter.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>authFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping>
这样用户访问的时候,如果没有填写用户名或者密码,就跳转到login.jsp;如果已经填写,不是admin,那么就会跳转到noaccess.jsp
noaccess.jsp代码如下:
<%-- User: Meice Date: 2017/10/7 Time: 8:03--%><%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>管理权限</title></head><body> <h2>您没有访问权限,请联系管理员授权!</h2></body></html>
好了,到此为止,我们就实现了对后台权限页面的全面掌控!
案例三:Filter字符编码过滤
目的:我们希望,对web根目录下的所有请求在初始化的时候就处理掉编码,而不用每次在对应的Filter的doFilter()里面重复类似的代码
request.setCharacterEncoding(“utf-8”);
response.setCharacterEncoding(“utf-8”);
那么如何设置初始化参数呢?
跟Servlet一模一样,我们新建一个Filter叫做EncodingFilter专门处理字符编码,具体结构请参考上一张架构图。
EncodingFilter代码如下:
package com.hmc.filter;import javax.servlet.*;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 javax.servlet.http.HttpServletResponse;import java.io.IOException;/** * User:Meice * 2017/10/7 */public class EncodingFilter implements Filter { String encoding = null; @Override public void init(FilterConfig config) throws ServletException { //初始化的时候就获取编码 encoding = config.getInitParameter("encoding"); //验证是否得到参数 System.out.println("初始化编码:"+encoding); //判断字符编码值是否为空 if(encoding == null || "".equals(encoding)){ encoding="UTF-8"; } System.out.println("初始化编码:"+encoding); } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { //这里用到了向下转型,主要还是方便session的获取,因为session属于HttpSession HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)resp; request.setCharacterEncoding(encoding); response.setCharacterEncoding(encoding); //上面转换过来了,过滤当然也要过滤转化后的request,response chain.doFilter(request,response); } @Override public void destroy() { }}
web.xml配置如下:
<!--配置字符编码过滤器--> <filter> <filter-name>encoding</filter-name> <filter-class>com.hmc.filter.EncodingFilter</filter-class> <!--配置初始化参数encoding--> <init-param> <param-name>encoding</param-name> <param-value></param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern><!--字符编码,当然要对所有请求处理啦--> </filter-mapping>
配置Filter的初始化参数和Servlet一模一样奥。如果读者对于Servlet不熟悉,请回看笔者关于Servlet相关的所有博客。哈哈。
到这里,我们的字符编码处理好啦!不论你是否给了字符编码的初始化参数,我们都设置为了再也亲切不过的UTF-8了。web目录下的所有请求都会经过这个字符编码过滤器!宝宝再也不用担心中文乱码的的问题啦!
还需要注意一下,我们到此为止,3个案例全部结束,整体的web.xml配置是这样的:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!--配置MyFilter过滤器--> <filter> <filter-name>myFilter</filter-name> <filter-class>com.hmc.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <!-- <url-pattern>/*</url-pattern>--><!--对所有请求过滤;一般我们不同时写多个过滤条件--> <!-- <url-pattern>/admin/*</url-pattern>--><!-- 对admin目录下的所有请求进行过滤--> <url-pattern>*.do</url-pattern><!--对所有以.do结尾的请求过滤--> </filter-mapping> <!--Login Servlet 配置--> <servlet> <servlet-name>login</servlet-name> <servlet-class>com.hmc.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>login</servlet-name> <url-pattern>/login.do</url-pattern> </servlet-mapping> <!--配置权限过滤器--> <filter> <filter-name>authFilter</filter-name> <filter-class>com.hmc.filter.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>authFilter</filter-name> <url-pattern>/admin/*</url-pattern> </filter-mapping> <!--配置字符编码过滤器--> <filter> <filter-name>encoding</filter-name> <filter-class>com.hmc.filter.EncodingFilter</filter-class> <!--配置初始化参数encoding--> <init-param> <param-name>encoding</param-name> <param-value></param-value> </init-param> </filter> <filter-mapping> <filter-name>encoding</filter-name> <url-pattern>/*</url-pattern><!--字符编码,当然要对所有请求处理啦--> </filter-mapping></web-app>
以上总共有有3个过滤器:形成了一个过滤器链;这么多过滤器,那么执行顺序呢?所以,过滤器链按找注册先后顺序执行,也就是配置位置的先后顺序。
所以,字符编码应该放在权限配置之前奥。
Ok!睡个午觉吧。
- javaWeb-filter
- JavaWeb-Filter
- javaweb之Filter详解
- javaweb之Filter详解
- javaweb之Filter详解
- javaweb之Filter详解
- JavaWeb开发过滤器Filter
- javaweb之Filter详解
- javaweb之Filter详解
- JavaWeb -- Servlet Filter 过滤器
- javaweb之Filter详解
- javaweb之Filter详解
- javaWeb开发之filter
- javaweb之Filter详解
- javaweb之Filter详解
- javaweb之Filter详解
- javaweb之Filter详解
- javaweb---过滤器(Filter)
- 禁止浏览器自动填充密码
- 菜鸟前端日记4(原生JS--基本数据类型)
- 背包九讲——完全背包
- settings选项
- 51nod 1258 序列求和 V4 拉格朗日插值法求自然数幂和
- JavaWeb-Filter
- 从零基础到具备前端基本技能的道路、学习方法、资料
- Cassandra key说明
- Danware.NetOp.Remote
- 计蒜客-内部收益率
- android发彩信
- 第7周实践项目1.1 环形队列中用队尾和队的元素个数来实现队列的算法库
- POJ 3255 Roadblocks 笔记
- 日期对话框