JavaEE学习之过滤器 Filter
2017-04-28 16:29
399 查看
过滤器 Filter
概念 :
Filter也称之为过滤器,可以对web服务器管理的所有web资源: 例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截, 从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
作用 :
1:实现动态资源不缓存 2:静态资源缓存 3:中文乱码集中处理 4: 特殊字符过滤 5:自动登录实现
写法
第一步: 写一个类实现 Filter public class MyFirstFilter implements Filter { public void destroy() { System.out.println("filter被销毁了"); } public void doFilter(ServletRequest servletRequeset, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("开始过滤"); // 放行 如果不放行,就不能到达目标资源 filterChain.doFilter(servletRequeset, servletResponse); System.out.println("放行了---"); } public void init(FilterConfig arg0) throws ServletException { System.out.println("filter初始化了"); } } 第二步: 在web.xml中进行配置 <filter> <filter-name>MyFirstFilter</filter-name> <filter-class>com.example.filterdemo.MyFirstFilter</filter-class> </filter> <filter-mapping> <filter-name>MyFirstFilter</filter-name> <url-pattern>/servlet/FirstServlet</url-pattern> </filter-mapping>
生命周期
1.在应用被加载或容器启动时,过滤器就进行实例化,初始化 2.对比请求的资源及web.xml,以后每调拦截时,直接执行doFilter() 3.容器停止或应用卸载时,destory()执行销毁
配置详解
1.一个Filter 可以有多个 filter-mapping 可以拦截多个资源2.可以使用通配符 /* 或者 *.扩展名进行配置
3.filter-mapping靠前的先拦截
4.filter默认只拦截拦截浏览器发送的请求,对转发不进行拦截
<dispatcher>FORWARD</dispatcher> <dispatcher>REQUEST</dispatcher>
5.errorPage 可以根据错误类型或者错误码配置对应的错误界面
<error-page> <error-code>404</error-code> <location>/404error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/500error.jsp</location> </error-page>
过滤器链
过滤器1------->过滤器2---------->目标资源------->过滤器2------->过滤器1
FilterConfig接口
对于过滤器,可以配置一些初始化的参数,这些参数可以直接放置到filter中,在初始化的时候,可以将参数读取出来<filter> <filter-name>MyFirstFilter</filter-name> <filter-class>com.example.filterdemo.MyFirstFilter</filter-class> <init-param> <param-name>encode</param-name> <param-value>utf-8</param-value> </init-param> </filter> String getInitParameter(String name):
案例一:乱码问题解决
对于乱码问题,每个Servlet界面都需要进行处理,太耗时费力了,可以统一在过滤器中进行解决对Post请求方式进行乱码统一处理
对于post方式,解决乱码非常简单,只需要在过滤器中设置两行代码即可
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding("UTF-8"); resp.setContentType("text/html;charset=UTF-8"); chain.doFilter(req, resp); }
统一修改Get和Post乱码
对于get方式,由于浏览器编码采用的是ISO-8859-1,需要对每个参数进行编解码
在这里使用一种装饰者模式,修改getParameter方法
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) req; resp.setContentType("text/html;charset=UTF-8"); chain.doFilter(new MyServletRequest(httpServletRequest), resp); } class MyServletRequest extends HttpServletRequestWrapper { private HttpServletRequest request; public MyServletRequest(HttpServletRequest request) { super(request); this.request = request; } @Override public String getParameter(String name) { String method = request.getMethod(); //判断请求方式--如果是get方式请求,先对参数使用ISO-8859-1解码成字节,再使用UTF-8进行编码 if ("get".equalsIgnoreCase(method)) { try { String value = request.getParameter(name); return new String(value.getBytes("ISO-8859-1"), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } else if ("post".equalsIgnoreCase(method)) { try { request.setCharacterEncoding("utf-8"); } catch (UnsupportedEncodingException e) { } } return super.getParameter(name); } }
案例二:设置动态web资源全部不缓存
对于动态Web资源,要求实时更新,可以在过滤器中统一将其配置为不缓存,只需要设置响应中的三个响应头即可public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; //三个头 response.setHeader("Expires", "-1"); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache"); chain.doFilter(request, response); }
案例三:设置静态Web资源全部缓存
对于静态Web资源,为了加载时间,可以在过滤器中统一将其配置为缓存,只需要设置缓存的响应头,指定过期时间就好response.setDateHeader("Expires",System.currentTimeMillis()+60*60*1000);//单位:毫秒
案例四:自动登录
自动登录的场景分析:当用户在登录表单中勾选了自动登录按钮的时候,意味着用户下次再进入到程序的某个需要用户名的界面时,可以直接将用户名取出,而不需要再次进行登录步骤分析: 1.使用集合模拟数据库 private static List<User> users = new ArrayList<User>(); static { users.add(new User("zhangsan", "123")); users.add(new User("lisi", "123")); users.add(new User("wangwu", "123")); } public static User findUser(String username, String password) { for (User u : users) { if (username.equals(u.getUsername()) && password.equals(u.getPassword())) { return u; } } return null; } public static User findUser(String username) { for (User u : users) { if (username.equals(u.getUsername())) { return u; } } return null; }
LoginServlet
// 1--- 获取请求参数 String username = req.getParameter("username"); String password = req.getParameter("password"); // 2--- 进行用户验证 User user = UserDB.findUser(username, password); if (user == null) { // 2.1 提醒 resp.getWriter().write("please login first"); resp.setHeader("Refresh", "2;url=/Day17_AutoLogin/login.jsp"); } else { // 2.2 登录成功 --存储到session中,因为登录成功要访问其他界面 req.getSession().setAttribute("user", user); // 3-判断是否勾选了记住用户名 String rememberName = req.getParameter("rememberName"); String autoLogin = req.getParameter("autoLogin"); if ("on".equals(rememberName)) { Cookie cookie = new Cookie("savename", user.getUsername()); cookie.setMaxAge(60 * 60 * 24); cookie.setPath(req.getContextPath() + "/"); resp.addCookie(cookie); } // 3--- 判断是否勾选自动登录 // 4-- 如果勾选,往客户端设置cookie,存储用户名和密码 if ("on".equals(autoLogin)) { Cookie cookie = new Cookie("autoLogin", user.getUsername() + "_" + user.getPassword()); cookie.setMaxAge(60 * 60 * 24); cookie.setPath(req.getContextPath() + "/"); System.out.println("勾选了自动登录,路径为" + cookie.getPath()); resp.addCookie(cookie); } resp.sendRedirect(req.getContextPath() + "/index.jsp");
AutoLoginFilter
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { // 1---强转 HttpServletRequest requeset = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; String resource = requeset.getRequestURI();// 得到资源名 boolean isLogin = resource.endsWith("login.jsp");// 判断是否想进行登录操作 System.out.println(resource + "----"); if (!isLogin) { // 2--判断session域中有无user User user = (User) requeset.getSession().getAttribute("user"); // 3--如果user不为空,说明已经登录了,直接放行,不做操作 System.out.println(user); if (user == null) { System.out.println("用户为空"); // 4 user 为空,判断之前是否有勾选自动登录 Cookie[] cookies = requeset.getCookies(); if (cookies == null || cookies.length == 0) { // 说明根本没有cookie-- System.out.println("没有cookie"); } else { System.out.println("遍历cookie"); for (Cookie cookie : cookies) { String name = cookie.getName(); System.out.println(name + "------"); if ("autoLogin".equals(name)) { // 找到了autologin的cookie zhangsan_123 String value = cookie.getValue(); System.out.println(value + "00000"); String[] split = value.split("_"); String username = split[0]; String password = split[1]; // 去查询一下这个用户名和密码的人是否存在 User user2 = UserDB.findUser(username, password); if (user2 != null) { System.out.println("cookie中用户不为空"); // 封装成user,放到session域中 requeset.getSession().setAttribute("user", user2); } break; } } } } } chain.doFilter(requeset, response); }
相关文章推荐
- JavaEE学习14--过滤器filter
- Apidemo学习之ColorFilter(颜色过滤器)
- ZendFramework学习第三章(核心组件—过滤器之 Zend_Filter_Input过滤器)
- javaweb学习总结(四十二)——Filter(过滤器)学习
- javaweb——Filter(过滤器)学习
- 过滤器Filter学习的一些体会
- Filter(过滤器)学习
- Servlet3.0学习总结(二)——使用注解标注过滤器(Filter)
- javaWeb学习总结(10)- Filter(过滤器)学习(2)
- 学习笔记_Filter小结(过滤器JavaWeb三大组件之一)
- ZendFramework学习第三章(核心组件—过滤器之 Zend_Filter_Input过滤器)
- AngularJS学习--- 过滤器(filter),格式化要显示的数据 step 9
- javaWeb之在例子中学习(过滤器Filter)
- Filter--过滤器学习笔记
- 过滤器 filter-----入门学习
- ⑧javaWeb之在例子中学习(过滤器Filter)
- angularjs学习笔记之三(变量及过滤器Filter的使用)
- Filter(过滤器)学习