26、过滤器

来源:互联网 发布:全局搜索算法 编辑:程序博客网 时间:2024/06/03 14:24

过滤器

项目开发中,经常会涉及到重复代码的实现!

注册 ---- 提交Servlet 【1. 设置编码格式】 ----转到JSP修改 ---- 提交Servlet 【1. 设置编码格式】 --- 转到JSP

其他:

如判断用户是否登陆,只有登陆才能有操作权限!涉及到重复判断: 获取session,取出session数据,判断是否为空,为空说明没有登陆,不能操作只有登陆后,才能操作!

如何解决:

  1. 抽取重复代码,封装
  2. 每个用到重复代码的地方,手动的调用!

过滤器,设计执行流程:

  1. 用户访问服务器
  2. 过滤器: 对Servlet请求进行拦截
  3. 先进入过滤器, 过滤器处理
  4. 过滤器处理完后, 在放行, 此时,请求到达Servlet/JSP
  5. Servlet处理
  6. 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
原创粉丝点击