Filter过滤器

来源:互联网 发布:淘宝千牛客服怎么设置 编辑:程序博客网 时间:2024/06/07 11:47
A:
    Filter过滤器:Javaweb中的过滤器,可以拦截所有访问web资源的请求或响应操作
        1:创建自己的过滤器Filter的步骤:
            (1)创建一个类实现Filter接口
            (2)重写接口中的方法,doFilter方法是真正执行过滤方法
            (3)在web.xml文件中配置
        注:在Filter的doFilter方法内如果没有执行chain.doFilter(request,response),那么过滤器后的资源不能被访问到


        2:代码如下:
          
       public class MyFilter implements Filter{

                public void init(FilterConfig filterCongfig)throws ServletException{

                }

                public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,ServletException{
                    //显示运行了doFilter方法
                    System.out.println("开始拦截了");
                    //允许放行,访问其后面的资源
                    chain.doFilter(request,response);
                    //再次过滤返回来的资源,之后结束放行
                    System.out.println("结束了过滤拦截");
                }

                public void destroy(){

                }
            }


        3:在web.xml中的配置:
            <filter>
                <filter-name>MyFilter</filter-name>
                <filter-class>com.qianfeng.web.MyFilter<filter-class>
            </filter>

            <filter-mapping>
                <filter-name>MyFilter<filter-name>
                <url-pattern>/demo1</url-pattern>//代表能过滤的资源的路径
            </filter-mapping>


B:
    FilterChain:(1)过滤链,当多个过滤器对同一资源进行过滤拦截的时候,会形成过滤链;
                (2)servlet 容器为开发人员提供的对象,它提供了对某一资源的已过滤请求调用链的视图。
                (3)过滤器使用 FilterChain 调用链中的下一个过滤器,如果调用的过滤器是链中的最后一个过滤器,则调用链末尾的资源。
        问题:怎样可以形成一个Filter链?
            只要多个Filter对同一个资源进行拦截就可以形成Filter链
        问题:怎样确定Filter的执行顺序?
            由<filter-mapping>来确定


C:
    Filter生命周期:
        (1)当服务器启动,会创建Filter对象,并调用init方法,只调用一次.
        (2)当访问资源时,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,这个方法是真正拦截操作的方法.
        (3)当服务器关闭时,会调用Filter的destroy方法来进行销毁操作.        

D:
    FilterConfig接口:用户在配置filter时,可以使用<init-param>为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。
        1:因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得:
          String getFilterName():得到filter的名称。
          String getInitParameter(String name): 返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
          Enumeration getInitParameterNames():返回过滤器的所有初始化参数的名字的枚举集合。
          public ServletContext getServletContext():返回Servlet上下文对象的引用。


        2:利用FilterConfig得到filter配置信息,代码如下:
            
public class FilterDemo02 implements Filter {
                private FileterConfig filterConfig;
                public void init(FilterConfig filterConfig) throws ServletException {
                    //在Filter中获取一个FilterConfig对象
                    this.filterconfig=filterConfig;
                    System.out.println("----过滤器初始化----");

         /**
          * <filter>
                   <filter-name>FilterDemo02</filter-name>
                   <filter-class>me.gacl.web.filter.FilterDemo02</filter-class>

                   <!--配置FilterDemo02过滤器的初始化参数-->
                   <init-param>
                       <description>配置FilterDemo02过滤器的初始化参数</description>
                      <param-name>name</param-name>
                       <param-value>gacl</param-value>
                   </init-param>

                  <init-param>
                       <description>配置FilterDemo02过滤器的初始化参数</description>
                       <param-name>like</param-name>
                       <param-value>java</param-value>
                   </init-param>
            </filter>

            <filter-mapping>
                   <filter-name>FilterDemo02</filter-name>
                   <!--“/*”表示拦截所有的请求 -->
                   <url-pattern>/*</url-pattern>
            </filter-mapping>
          */
                  //得到过滤器的名字
                 String filterName = filterConfig.getFilterName();
                   //得到在web.xml文件中配置的初始化参数
                 String initParam1 = filterConfig.getInitParameter("name");
                 String initParam2 = filterConfig.getInitParameter("like");
                  //返回过滤器的所有初始化参数的名字的枚举集合。
                 Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();

                 System.out.println(filterName);
                 System.out.println(initParam1);
                 System.out.println(initParam2);
                 while (initParameterNames.hasMoreElements()) {
                     String paramName = (String) initParameterNames.nextElement();
                     System.out.println(paramName);
                }
             }

            public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
                     System.out.println("FilterDemo02执行前!!!");
                     chain.doFilter(request, response);  //让目标资源执行,放行
                     System.out.println("FilterDemo02执行后!!!");
             }

            public void destroy() {
                 System.out.println("----过滤器销毁----");
            }
 }




E:
    关于Filter在web.xml中的配置信息:
        1:基本配置:
            <filter>
                <filter-name>filter名称</filter-name>
                <filter-class>Filter类的包名.类名</filter-class>
            </filter>
            <filter-mapping>
                <filter-name>filter名称</filter-name>
                <url-pattern>路径</url-pattern>
            </filter-mapping>

        2:其他配置:
            (1).<url-pattern>
                完全匹配   以”/demo1”开始,不包含通配符*
                目录匹配   以”/”开始  以*结束
                扩展名匹配" *.xxx "不能写成" /*.xxx "

            (2).<servlet-name>
                它是对指定的servlet名称的servlet进行拦截的。

            (3).<dispatcher>
            可以取的值有  REQUEST  FORWARD  ERROR  INCLUDE   
            它的作用是:当以什么方式去访问web资源时,进行拦截操作.   
                1.REQUEST 当是从浏览器直接访问资源,或是重定向到某个资源时进行拦截方式配置的 它也是默认值
                2.FORWARD 它描述的是请求转发的拦截方式配置
                3.ERROR 如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
                4.INCLUDE 如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用


F:
    关于MD5算法加密:
        (1)在mysql中可以对数据进行MD5加密:UPDATE USER SET PASSWORD=MD5(PASSWORD);

        (2)在java中也提供了MD5加密,代码如下:
          
       public static String md5(String plainText) {
                byte[] secretBytes = null;
                try {
                    secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());
                } catch (NoSuchAlgorithmException e) {
                    throw new RuntimeException("没有md5这个算法!");
                }
                String md5code = new BigInteger(1, secretBytes).toString(16);
                for (int i = 0; i < 32 - md5code.length(); i++) {
                    md5code = "0" + md5code;
                }
                return md5code;
            }


G:
    关于全局的编码过滤器:
        (1)在java中怎样可以对一个方法进行功能增强?
            1.继承
            2.装饰设计模式
                1.    创建一个类让它与被装饰类实现同一个接口或继承同一个父类
                2.    在装饰类中持有一个被装饰类的引用
                3.    重写要增强的方法


        (2)做一个通用的,可以处理post,get所有请求方式的,处理请求方式就是处理参数问题:
            我们获取请求参数有以下方法
                1.    getParameter
                2.    getPrameterValues
                3.    getParameterMap
                这三个方法都可以获取请求参数。
                分析后,我们知道getParameter与getParameterValue方法可以依赖于getParamterMap方法来实现。

        (3)处理请求方式,那么就要重写request中的处理编码问题的方法,这时就要对request进行装饰
        因为请求会经过过滤器,所以把装饰request的代码下载了过滤器中,代码如下:
           
public class EncodeFilter implements Filter{

                public void init(FilterConfig filterConfig)throws ServletException{

                }

                public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws IOException,SerletException{
                    //处理post方式的乱码
                    //request.setCharacterEncoding("utf-8");

                    HttpServletRequest req=(HttpServletRequest)request;
                    MyRequest myReq=new MyRequest(req);

                    chain.doFilter(myReq,response);
                }

                public void destroy(){

                }

            }
            //装饰request的类
            class MyRequest extends HttpServletRequestWrapper{

                private HttpServletRequest req;
                MyRequest(HttpServletRequest req){

                    super(req);//因为继承的父类中没有空参的构造方法
                    this.req=req;
                }

                public String getParameter(String name){
                    Map<String,String[]> map=getParameterMap();
                    return map.get(name)[0];
                }

                public String[] getParameterValues(String name){
                    Map<String,String[]> map=getParameterMap();
                    return map.get(name);
                }

                private boolean flag=true;
                public Map<String,String[]> getParameterMap(){
                    Map<String,String[]> map=req.getParameterMap();
                    if(flag){
                        for(Map.Entry<String,String[]> en:map.entrySet()){
                            String arr[]=en.getValue();
                            for(int i=0;i<arr.length;;i++){
                                try{
                                    arr[i]=new String(arr[i].getBytes("ISO-8859-1"),"utf-8");
                                }catch(UnsupportedEncodingException){
                                    e.printStackTrace();
                                }
                            }

                        }
                    }
                    flag=false;
                }
                return map;
            }




























0 0
原创粉丝点击