过滤器学习笔记
2016-07-13 18:31
225 查看
1. 过滤器概念和原理
1.1 定义
过滤器是一个服务器端的组件,它可以截取客户端的请求与响应信息,并对这些信息过滤。1.2 工作原理
2. 过滤器声命周期
2.1 生命周期
2.2 三个方法的作用
请求index.jsp页面,触发过滤器,执行doFilter方法,输出“start…doFilter”,filter放行,执行index.jsp,再执行dofilter余下的代码。
2.3 过滤器配置
先创建过滤器类,然后实现Filter接口,在配置Web.xml文件过滤器能改变用户请求的Web资源,也就是能改变用户请求的路径,但是,过滤器不能处理用户的请求
2.4 过滤器链
3. 过滤器类型
REQUEST,FORWARD,INCLUDE过滤器
@Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("start.....doFilter----FirstFilter"); arg2.doFilter(arg0, arg1);//放行?? HttpServletRequest req = (HttpServletRequest) arg0; HttpServletResponse response2 = (HttpServletResponse) arg1; //重定向(相当于一个新的请求,所以在main界面继续出发FirstFilter) 陷入死循环 response2.sendRedirect(req.getContextPath()+"/main.jsp"); //请求转发,没有进入死循环,但是如果把main页面的过滤器改为forward则同样出现死循环 // req.getRequestDispatcher("main.jsp").forward(arg0, arg1); //与上面几乎一样 // req.getRequestDispatcher("main.jsp").include(arg0, arg1); System.out.println("end.....doFilter----FirstFilter"); }
ERROR过滤器:
<!--当输入路径不对,引发404错误,请求error.jsp;触发errorFilter --> <filter> <filter-name>ErrorFilter</filter-name> <filter-class>com.imooc.filter.ErrorFilter</filter-class> </filter> <filter-mapping> <filter-name>ErrorFilter</filter-name> <url-pattern>/error.jsp</url-pattern> <dispatcher>ERROR</dispatcher> </filter-mapping> <error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page>
AsynFilter(@WebFilter)(servlet3.0新增)
@WebFilter用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。
创建过滤器类实现Filter接口,配置@WebFilter即完成了过滤器的配置,无需手动去配置Web.xml
怎么体现异步过滤器的异步特性呢?
新建一个servlet,在内部类里设计一个线程,在里面执行一些复杂业务,模拟异步操作(servlet和filter都要设置支持异步)
从结果可以看出,过滤器并没有等待模拟的复杂业务执行(线程),而是直接执行完了过滤器。
4. 登录认证及编码转换实战案例
login.jsp<body> <form action="<%=request.getContextPath() %>/servlet/LoginServlet" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit" value="提交"> </form> </body>
LoginServlet.java
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String uesrname = request.getParameter("username"); String password = request.getParameter("password"); //手动解决乱码 //System.out.println(new String(uesrname.getBytes("ISO-8859-1"),"UTF-8")); //过滤器解决乱码 System.out.println(uesrname); if ("admin".equals(uesrname)&&"admin".equals(password)) { //校验通过 HttpSession session = request.getSession(); session.setAttribute("username", uesrname); response.sendRedirect(request.getContextPath()+"/success.jsp"); }else { //校验失败 response.sendRedirect(request.getContextPath()+"/fail.jsp"); } }
到这里,已经可以实现登录,但是完全没有过滤
Login_Filter.java
public class Login_Filter implements Filter { private FilterConfig config; @Override public void destroy() { } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) arg0; HttpServletResponse response = (HttpServletResponse) arg1; HttpSession session = request.getSession(); //在过滤器内直接设置编码 //request.setCharacterEncoding("utf-8"); //过滤器设置初始化参数解决乱码 String charset = config.getInitParameter("charset"); //未指定编码时默认utf-8 if (charset==null) { charset="utf-8"; } request.setCharacterEncoding(charset); String noLonginPaths = config.getInitParameter("noLonginPaths"); //通过设置初始化参数,解决多个不过滤界面问题 if (noLonginPaths != null) { String[] strArray = noLonginPaths.split(";"); for (int i = 0; i < strArray.length; i++) { //参数为空和null时不放行 if (strArray[i] == null || "".equals(strArray[i])) continue; //url.indexif(str):如果url包含str,则返回str在url中的位置,如果不包含则返回-1 if (request.getRequestURI().indexOf(strArray[i]) != -1) { arg2.doFilter(arg0, arg1); return; } } } //如果请求地址就是登录界面的话,或者loginServlet就放行,否则会进入死循环 //后来发现,fail.jsp也需要放行,这样一来,这里代码会变得很繁琐,以后增加新的页面还需要修改代码,不符合java设计原则 // if (request.getRequestURI().indexOf("login.jsp")!=-1 // ||request.getRequestURI().indexOf("LoginServlet")!=-1) { // arg2.doFilter(arg0, arg1); //返回,否则还会执行下面的代码 // return; // } //通过session获取用户名,如果有登录信息。就放行;否则,别人只需输入成功页面地址就可以显示登陆成功界面 //如果没有登录信息就跳转到登录界面 if (session.getAttribute("username") != null) { arg2.doFilter(arg0, arg1); } else { response.sendRedirect("login.jsp"); } } @Override public void init(FilterConfig arg0) throws ServletException { //通过设置初始化参数,解决多个不过滤界面问题 config = arg0; } }
web.xml
<filter> <filter-name>LoginFilter</filter-name> <filter-class>com.imooc.filter.Login_Filter</filter-class> <init-param> <param-name>noLonginPaths</param-name> <param-value>login.jsp;fail.jsp;LoginServlet</param-value> </init-param> <init-param> <param-name>charset</param-name> <param-value>utf-8</param-value> </init-param> </filter> <!-- 不允许未登录用户访问界面不止success.jsp一个,所以要对所有界面进行过滤 --> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.imooc.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/servlet/LoginServlet</url-pattern> </servlet-mapping>
要注意这里两个主要问题(设置多个不过滤的页面和解决编码)都是通过设置初始化参数完成的!
相关文章推荐
- Android4.2中应用接收开机广播(android.intent.action.BOOT_COMPLETED)失败的原因
- 大数据技术之Sqoop配置示例
- YARN
- 编译Win32动态库工程的两个链接错误的解决
- discuz 登录代码流程
- 为什么mysql 连接url中useUnicode=true&characterEncoding=UTF-8?
- 分布式与集群的区别
- Chrome开发者工具不完全指南(一、基础功能篇)
- mac下adb命令大全
- 编译Win32动态库工程的两个链接错误的解决
- Android.mk中引用第3方动态库
- jsp基础
- 网站header头信息中Cache-Control max-age=0是什么意思?
- Python爬虫抓取代理IP并检验可用性
- UE4学习笔记(五): 基于物理光照的材质
- C++中的对齐方式及sizeof小结
- 【Android】MediaRecorder/MediaPlayer实现录音与播放录音
- 如何对MySQL数据库中的数据进行实时同步
- android ndk开发爬坑之无法解析的符号
- UE4学习笔记(四): 开发体验