26、过滤器
来源:互联网 发布:全局搜索算法 编辑:程序博客网 时间:2024/06/03 14:24
过滤器
项目开发中,经常会涉及到重复代码的实现!
注册 ---- 提交Servlet 【1. 设置编码格式】 ----转到JSP修改 ---- 提交Servlet 【1. 设置编码格式】 --- 转到JSP
其他:
如判断用户是否登陆,只有登陆才能有操作权限!涉及到重复判断: 获取session,取出session数据,判断是否为空,为空说明没有登陆,不能操作只有登陆后,才能操作!
如何解决:
- 抽取重复代码,封装
- 每个用到重复代码的地方,手动的调用!
过滤器,设计执行流程:
- 用户访问服务器
- 过滤器: 对Servlet请求进行拦截
- 先进入过滤器, 过滤器处理
- 过滤器处理完后, 在放行, 此时,请求到达Servlet/JSP
- Servlet处理
- Servlet处理完后,再回到过滤器, 最后在由tomcat服务器相应用户;
(过滤器就像回家的门!)
基本知识
过滤器: * 概述: * Filter的作用:起到过滤的作用. * Filter执行的时机: * 在执行对应的Servlet之前.(过滤Request对象中的内容) * 在执行对应的Servlet之后.(过滤Respons对象中的内容) * 发展: * Filter最早在Servlet 2.3版本提供. * Filter在Servlet 2.5版本完善. * 如何使用Filter: * Filter是JavaEE提供的一个接口.(自定义Filter需要实现该接口,并重写所有方法) * Filter提供的方法: * init() * doFilter() * destroy() * 实现步骤: * 创建Java类,实现Filter接口,并且重写所有方法. * 在web.xml文件中进行配置. <filter> <filter-name>MyFilter1</filter-name> <filter-class>app.java.filter.MyFilter1</filter-class> </filter> <filter-mapping> <filter-name>MyFilter1</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> * Filter的生命周期: * 出生:Hello World * init()方法 * 活着:Love World * doFilter()方法 * 死去:GoodBye World * destroy()方法 * 过滤器链: * 问题: * 如何定义过滤器被执行的先后顺序? * Filter的doFilter()方法具有一个参数FilterChain,通过调用chain.doFilter()方法可以放行. * 在过滤器链中,执行chain.doFilter()方法,是否还是放行的作用? * 如果是,应该被放行到哪里去了?(单个Filter时,直接被放行到对应的Web资源[Servlet、JSP]) * 解决以上问题: * chain.doFilter()方法依旧是放行方法. * 如果执行的不是过滤器链中最后一个过滤器的话,执行chain.doFilter()方法,会被放行到下一个过滤器里. * 如果执行的是过滤器链中最后一个过滤器的话,chain.doFilter()方法,才会被放行到对应Web资源中. * 过滤器链中的过滤器执行的先后顺序由web.xml文件中的<filter-mapping>标签定义的先后顺序决定. * 实际开发的意义: * 单个Filter完成单个任务. * FilterConfig * 读取web.xml文件中的初始化参数. * 在web.xml文件中是如何配置的: <filter> <filter-name>MyFilter2</filter-name> <filter-class>app.java.filter.MyFilter2</filter-class> <init-param> <param-name>mingjiao</param-name> <param-value>zhangwuji</param-value> </init-param> </filter> * FilterConfig的用法与ServletConfig一致. * 在web.xml文件中配置全局初始化参数<context-param>,通过ServletContext对象读取. * Filter的映射配置:<url-pattern> * 完全匹配:/xxxx * 目录匹配:/aaaa/ * 扩展名匹配:*.do * 优先级别:完全匹配 -> 目录匹配 -> 扩展名匹配 * 如果当前Filter拦截对应Servlet的话: * 还可以使用<servlet-name>标签 * Filter拦截Servlet默认情况是拦截直接请求. * 在web.xml文件中配置<filter-mapping>标签中具有<dispatcher> * <dispatcher>标签在同一个Filter的配置中,可以配置多个. * <dispatcher>标签的值: * REQUEST:是默认值,表示一次请求. * FORWARD:表示请求转发到. * INCLUDE:表示包含(例如JSP包含另一个JSP等) * ERROR:表示JSP的<%@ page errorPage=""%> * Filter的案例: * 全站乱码案例: * 利用Servlet的doGet()和doPost()方法中,可以解决中文乱码: * doGet() String value = request.getParameter(""); value = new String(value.getBytes("ISO8859-1"),"utf-8"); response.setContentType("text/html;charset=utf-8"); * doPost() request.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); * 以上问题: * 实际开发时,Web应用程序的逻辑比较复杂(多个Servlet). * 上述的解决方案,仅能解决当前Servlet的中文乱码问题. * 如果使用上述方案,解决中文乱码问题:代码重复性太多.
过滤器案例:
接口:
|-- interface Filter 过滤器核心接口 Void init(filterConfig); 初始化方法,在服务器启动时候执行 Void doFilter(request,response,filterChain); 过滤器拦截的业务处理方法 Void destroy(); 销毁过滤器实例时候调用|-- interface FilterConfig 获取初始化参数信息 String getInitParameter(java.lang.String name) Enumeration getInitParameterNames() |-- interface FilterChain 过滤器链参数;一个个过滤器形成一个执行链; void doFilter(ServletRequest request, ServletResponse response); //执行下一个过滤器或放行
public class HelloFilter implements Filter{ // 创建实例 public HelloFilter(){ System.out.println("1. 创建过滤器实例"); } @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("2. 执行过滤器初始化方法"); // 获取过滤器在web.xml中配置的初始化参数 String encoding = filterConfig.getInitParameter("encoding"); System.out.println(encoding); // 获取过滤器在web.xml中配置的初始化参数 的名称 Enumeration<String> enums = filterConfig.getInitParameterNames(); while (enums.hasMoreElements()){ // 获取所有参数名称:encoding、path String name = enums.nextElement(); // 获取名称对应的值 String value = filterConfig.getInitParameter(name); System.out.println(name + "\t" + value); } } // 过滤器业务处理方法: 在请求到达servlet之前先进入此方法处理公用的业务逻辑操作 @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("3. 执行过滤器业务处理方法"); // 放行 (去到Servlet) // 如果有下一个过滤器,进入下一个过滤器,否则就执行访问servlet chain.doFilter(request, response); System.out.println("5. Servlet处理完成,又回到过滤器"); } @Override public void destroy() { System.out.println("6. 销毁过滤器实例"); }}
public class HelloFilter2 implements Filter{ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("第二个过滤器"); // 放心 chain.doFilter(request, response); System.out.println("第二个过滤器执行结束"); } @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } @Override public void destroy() { // TODO Auto-generated method stub }}
xml配置:
<!-- 过滤器配置 <filter> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>path</param-name> <param-value>c:/...</param-value> </init-param> <filter-name>hello_filter</filter-name> <filter-class>cn.itcast.a_filter_hello.HelloFilter</filter-class> </filter> <filter-mapping> <filter-name>hello_filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> --> <!-- 配置第二个过滤器 --> <!-- 演示: 拦截指定的请求 --> <filter> <filter-name>hello_filter2</filter-name> <filter-class>cn.itcast.a_filter_hello.HelloFilter2</filter-class> </filter> <filter-mapping> <filter-name>hello_filter2</filter-name> <!-- 1. 拦截所有 <url-pattern>/*</url-pattern> --> <!-- 2. 拦截指定的jsp <url-pattern>/index.jsp</url-pattern> <url-pattern>/list.jsp</url-pattern> --> <!-- 拦截所有的jsp <url-pattern>*.jsp</url-pattern> --> <!-- 3. 根据servlet的内部名称拦截 <servlet-name>IndexServlet</servlet-name> --> <!-- 拦截指定的servlet <url-pattern>/index</url-pattern> --> <!-- 4. 指定拦截指定的类型 --> <url-pattern>/*</url-pattern> <!-- 拦截直接访问的请求或者重定向的资源 --> <dispatcher>REQUEST</dispatcher> <!--<dispatcher>FORWARD</dispatcher>--> </filter-mapping>
编码处理过滤器
public class EncodingFilter implements Filter { // 过滤器业务处理方法:处理的公用的业务逻辑操作 @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { // 转型 final HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // 一、处理公用业务 request.setCharacterEncoding("UTF-8"); // POST提交有效 response.setContentType("text/html;charset=UTF-8"); /* * 出现GET中文乱码,是因为在request.getParameter方法内部没有进行提交方式判断并处理。 * String name = request.getParameter("userName"); * * 解决:对指定接口的某一个方法进行功能扩展,可以使用代理! * 对request对象(目标对象),创建代理对象! */ HttpServletRequest proxy = (HttpServletRequest) Proxy.newProxyInstance( request.getClass().getClassLoader(), // 指定当前使用的累加载器 new Class[]{HttpServletRequest.class}, // 对目标对象实现的接口类型 new InvocationHandler() { // 事件处理器 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 定义方法返回值 Object returnValue = null; // 获取方法名 String methodName = method.getName(); // 判断:对getParameter方法进行GET提交中文处理 if ("getParameter".equals(methodName)) { // 获取请求数据值【 <input type="text" name="userName">】 String value = request.getParameter(args[0].toString()); // 调用目标对象的方法 // 获取提交方式 String methodSubmit = request.getMethod(); // 直接调用目标对象的方法 // 判断如果是GET提交,需要对数据进行处理 (POST提交已经处理过了) if ("GET".equals(methodSubmit)) { if (value != null && !"".equals(value.trim())){ // 处理GET中文 value = new String(value.getBytes("ISO8859-1"),"UTF-8"); } } return value; } else { // 执行request对象的其他方法 returnValue = method.invoke(request, args); } return returnValue; } }); // 二、放行 (执行下一个过滤器或者servlet) chain.doFilter(proxy, response); // 传入代理对象 } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void destroy() { }}
数据过滤器
/** * 无效数据过滤 * @author Jie.Yuan * */public class DateFilter implements Filter { // 初始化无效数据 private List<String> dirtyData; @Override public void init(FilterConfig filterConfig) throws ServletException { // 模拟几个数据 dirtyData = new ArrayList<String>(); dirtyData.add("NND"); dirtyData.add("炸使馆"); } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { // 转型 final HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; // 一、处理公用业务 request.setCharacterEncoding("UTF-8"); // POST提交有效 response.setContentType("text/html;charset=UTF-8"); HttpServletRequest proxy = (HttpServletRequest) Proxy.newProxyInstance( request.getClass().getClassLoader(), // 指定当前使用的累加载器 new Class[]{HttpServletRequest.class}, // 对目标对象实现的接口类型 new InvocationHandler() { // 事件处理器 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 定义方法返回值 Object returnValue = null; // 获取方法名 String methodName = method.getName(); // 判断:对getParameter方法进行GET提交中文处理 if ("getParameter".equals(methodName)) { // 获取请求数据值【 <input type="text" name="userName">】 String value = request.getParameter(args[0].toString()); // 调用目标对象的方法 // 获取提交方式 String methodSubmit = request.getMethod(); // 直接调用目标对象的方法 // 判断如果是GET提交,需要对数据进行处理 (POST提交已经处理过了) if ("GET".equals(methodSubmit)) { if (value != null && !"".equals(value.trim())){ // 处理GET中文 value = new String(value.getBytes("ISO8859-1"),"UTF-8"); } } // 中文数据已经处理完: 下面进行无效数据过滤 //【如何value中出现dirtyData中数据,用****替换】 for (String data : dirtyData) { // 判断当前输入数据(value), 是否包含无效数据 if (value.contains(data)){ value = value.replace(data, "*****"); } } // 处理完编码、无效数据后的正确数据 return value; } else { // 执行request对象的其他方法 returnValue = method.invoke(request, args); } return returnValue; } }); // 二、放行 (执行下一个过滤器或者servlet) chain.doFilter(proxy, response); // 传入代理对象 } @Override public void destroy() { }}
拦截过滤器
/** * 登陆验证过滤器 * * http://localhost:8080/emp_sys/login.jsp 可以直接访问 http://localhost:8080/emp_sys/login 可以直接访问 http://localhost:8080/emp_sys/index 不能直接访问 http://localhost:8080/emp_sys/list.jsp 不能直接访问 * @author Jie.Yuan * */public class LoginFilter implements Filter { private String uri; /** * 分析: * 1. 先指定放行的资源,哪些资源不需要拦截: login.jsp + /login (request对象可以获取) 2. 获取session,从session中获取登陆用户 3. 判断是否为空: 为空, 说明没有登陆, 跳转到登陆 不为空, 已经登陆,放行! */ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { //0. 转换 HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; //1. 获取请求资源,截取 String uri = request.getRequestURI(); // /emp_sys/login.jsp // 截取 【login.jsp或login】 String requestPath = uri.substring(uri.lastIndexOf("/") + 1, uri.length()); //2. 判断: 先放行一些资源:/login.jsp、/login if ("login".equals(requestPath) || "login.jsp".equals(requestPath)) { // 放行 chain.doFilter(request, response); } else { //3. 对其他资源进行拦截 //3.1 先获取Session、获取session中的登陆用户(loginInfo) HttpSession session = request.getSession(false); // 判断 if (session != null) { Object obj = session.getAttribute("loginInfo"); //3.2如果获取的内容不为空,说明已经登陆,放行 if (obj != null) { // 放行 chain.doFilter(request, response); } else { //3.3如果获取的内容为空,说明没有登陆; 跳转到登陆 uri = "/login.jsp"; } } else { // 肯定没有登陆 uri = "/login.jsp"; } request.getRequestDispatcher(uri).forward(request, response); } } public void init(FilterConfig filterConfig) throws ServletException { } public void destroy() { }}
0 0
- 26、过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 过滤器
- 我就试试代码
- okhttp源码解析(3)
- c++实践参考:圆
- HTML5:Canvas
- 找工作 操作系统
- 26、过滤器
- 6. datasource - mysql【从零开始学Spring Boot】
- 互斥锁的实现
- Spring定时任务的几种实现
- 总结
- Codeforces Round #356 (Div. 2)
- ubuntu 14.04下 下载Android源码
- 7. JPA - Hibernate【从零开始学Spring Boot】
- <LeetCode OJ> 200 / 130 Number of Islands / Surrounded Regions