Servlet过滤器快速入门

不打扰是莪最后的温柔 提交于 2020-03-12 12:23:37

提前阅读:https://blog.csdn.net/Su_Levi_Wei/article/details/50665835

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■↓↓↓↓↓↓↓↓↓ Servlet过滤器 ↓↓↓↓↓↓↓↓↓↓↓■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
        
        
        Servlet过滤器;
                为什么要有?
                    如果有N多个Servlet要执行一样的操作的时候,
                        没有必须要在所有的Servlet都进行相同的代码操作,
                            那样会造成代码冗余性变大,也会使得开发效率低下。
                            
                            
                是什么?
                    是Servlet中的三大组件之一,是由SUN公司制定的标准/接口
                        过滤器的本质就是一个java应用中的一个对象而已。。。。。。
                    
                    
                作用;
                     过滤器可以在一个请求资源【动态或静态】的资源时,
                             或者是在响应资源时,执行过滤任务【代码逻辑】
                     
                    ◆ 因为是在Serlvet业务逻辑之前执行的,
                                   所以可以进行一些关键的操作,
                                 用于提高用户体验,以及提高开发效率
                                     因为没有必须都写在所有要使用
                                         这个业务逻辑代码的Servlet中写,
                                             只是需要把对应的Servlet和
                                                       服务器进行关联
                     
                     
                     如;1.在请求资源和响应资源的时候所有Servlet的编码集
                          2.用户统一登录的权限,就是只有用户登录了才可以进行访问某些资源。
                           
                           
                特点;
                     需要在web.xml文件中配置
                     运行在web服务器中
                   ◆在进行Servlet业务逻辑的之前执行的
                       
        
        
        
        


-----------------------------------↓↓↓↓↓↓↓Servlet过滤器 —— 开发步骤↓↓↓↓↓↓↓------------------------------------------------                                    
        
        
        Serlvet过滤器开发步骤;
                    1.编写一个自定义类,实现Filter接口
                    
                    2.重写doFilter()核心过滤器方法
                        
                        代码;
                            public void doFilter(ServletRequest request,
                                        ServletResponse response,
                                        FilterChain chain){
                                    
                                    
                                }
                        
                    3.在doFilter()方法写需要进行过滤的业务逻辑代码
                            
                            xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                            
                    4.使用FilterChain接口的doFilter方法放行 ---> (类似转发)
                            
                            public void doFilter(ServletRequest request,
                                        ServletResponse response,
                                        FilterChain chain){
                                    chain.doFilter(request,response);
                                    
                                }
                            
                            
                            
                            
                    5.在web.xml文件中配置过滤器
                        
            

--------------------------------↓↓↓↓↓↓↓Servlet过滤器 —— 运行过程↓↓↓↓↓↓↓------------------------------------------------                                    
        
        
        过滤器运行过程;
                1.在服务器启动加载所有的*.tld文件和web.xml文件的时候
                    就创建了一个过滤器的对象,而且只创建一次,所以是一个单例的
                    
                    方法;
                        会调用Filter接口的init()方法  --->  Filter接口
                            可以通过这个方法的FilterConfig对象获取到
                                    web.xml文件的<init-param>信息
                            
                        
                2.当用户访问与过滤器关联的Servlet的时候会先到过滤器,
                        的doFilter方法执行过滤器的业务逻辑代码,
                            在这时是否允许访问Servlet则是由过滤器代码决定的。
                    
                        a)过滤器逻辑代码通过了允许访问对应的Servlet,---> FiilterChain接口
                            那么则会调用FiilterChain接口的doFilter方法,
                                将用户访问的request和response请求带到对应的Servler中
                    
                    ◆◆    b)当访问了Servlet资源之后要将响应信息返回,
                                给用户不是直接返回的,而是通过过滤器返回的
                    
                    方法;
                         访问与过滤器关联的Servlet的时候都会调用doFilter方法  --->  Filter接口
                        
                        
                3.过滤器对象销毁,或者是服务器正常关闭
                    
                    方法;
                         destroy()
                
                
                
        ◆◆◆◆◆注;过滤器对象是一个单例的,
                    过滤器也是一个双向过滤,
                    ◆    因为请求和响应都需要经过过滤器。
        
        
            
        

--------------------------------↓↓↓↓↓↓↓Servlet过滤器 —— 过滤器链↓↓↓↓↓↓↓------------------------------------------------                                    
        
            
        过滤器链;
             某一个Servlet资源被多个过滤器进行过滤叫做过滤器链。
             
        
         FilterChain;是一个过滤器类的主要对象
                         使用执行下一个过滤器
                             如果当前的过滤器是最后一个过滤器则执行目标资源
                   
                   也是通过这个接口的doFilter()方法把用户的请求信息和响应信息返回给用户端


--------------------------------↓↓↓↓↓↓↓Servlet过滤器 —— Web文件配置↓↓↓↓↓↓↓------------------------------------------------                                    
        
    
        过滤器web.xml文件配置;
                    <filter>
                        <filter-name>自定义标识唯一名</filter-name>
                        <filter-class>过滤器绝对路径【包名+类名】</filter-class>
                        
                        <〓
                            <init-param>是设置过滤器的初始化过滤参数的
                        〓>
                        
                        <init-param>
                            <param-name>参数名</param-name>
                            <param-value>参数值</param-value>
                        </init-param>
                    </filter>
                    
                    <filter-mapping>
                        <filter-name>对应的唯一标识名</filter-name>
                        
                        <〓-- 
                            1、url-pattern;是指定需要过滤的serlvet路径
                                
                                精确过滤;/x ---> http://localhost:8080/xx/xx
                                
                                模糊过滤;/* ---> http://localhost:8080/xx/yy
                                      /包名/* --->       http://localhost:8080/包名/xx
                                  
                                  *      --->       http://localhost:8080/xx/xx 
                                  *.do   --->       http://localhost:8080/xx/xx.do 
                                  *.html
                                  。。。    
                                    
                                    
                          ◆◆◆注;在进行模糊过滤查询的时候,
                                   需要是符合url-pattern的语法的时候,
                                       则会执行过滤器,无论是否存在的Servlet
                                
                           【个人看法】建议不使用模糊过滤,即便写100个url-pattern,
                                        因为耗费服务器资源,过滤器是在服务器执行的
                        
                              
                              
                              2、servlet-name;是可以根据对应的Servlet在web.xml配置
                                                      的name属性值进行关联
                           
                        
                              
                              3、dispatcher;是设置要进行过滤的请求类型
                                      
                                      a_)request是设置过滤请求信息 ---> 默认
                                      b_)include是设置过滤包含信息
                                      c_)forword是设置过滤转发信息
                                      d_)error是设置过滤错误信息  ---> 触发<error-page>标签
                              
                        --〓>
                        
                        
                        <url-pattern>/过滤的Servlet</url-pattern>
                        
                        <servlet-name>对应的servlet配置名</servlet-name>
                        
                        <dispatcher>REQUEST</dispatcher>
                        <dispatcher>INCLUDE</dispatcher>
                        <dispatcher>FORWOED</dispatcher>
                        <dispatcher>ERROR</dispatcher>
                    </filter-mapping>
            
                    <〓-- 
                        这个是发生错误的时候,触发的
                    
                    --〓>
                    <error-page>
                        <error-code>500</error-code>  ---> 设置发生错误的码号
                        <location>/地址</location>     ---> 发生错误要进行跳转的地址
                    </error-page>


■■■■■■■■■■■■■■■■■■■--------------------------↓↓↓↓↓↓↓ 装饰者模式 ↓↓↓↓↓↓↓-------------------------■■■■■■■■■■■■■■■■■■■■
        
                
        装饰者模式;
               是用于对一个类的特定方法进行增强的,
                       而这个类只会是实体类,基本不会是抽象类,
                           因为如果是抽象类则需要实现所有的抽象方法,
                               也违反了装饰者模式的概念,是对特定的方法增强。
               
               
        反射和装饰者模式的区别;
                    反射是用于获取到一个类的方法的访问权,
                        从而操作这个类的方法,甚至改变这个方法的输出内容,
                                          而反射可以是抽象类等。
                              
                    装饰者模式只是做一个在原有的基础上进行的增强。
                    
                
          开发所需;
                 1.被装饰者,需被增强的类
                 2.装饰者,增强这个方法的类
                 3.装饰方法,需被增强的方法
                 
                             
          开发步骤;
                 1.编写一个装饰类继承被装饰类【非find】
               2.在装饰类中声明一个被装饰类的变量
               3.在装饰类的构造方法的形参要求传入一个被装饰类的对象
               4.对需要被装饰的方法进行重写
               


-----------------------------------↓↓↓↓↓↓↓装饰者模式 —— 案例 —— 过滤器链↓↓↓↓↓↓↓------------------------------------------------                                    
        
                
        编写一个请求统一编码集的方法。。。。。。
        
                                                                                
//继承HttpServletRequestWrapper类
public class MyTrimmer extends HttpServletRequestWrapper {

    //声明一个这个被装饰类的成员变量
    private HttpServletRequest request;
    
    public MyTrimmer(HttpServletRequest request) {
        super(request);
        //获取到这传进来的对象
        this.request = request;
    }
            
            
    /**
     * 重写被装饰类需要增强功能的getParameter方法
     */
    @Override
    public String getParameter(String name) {
        try {
            //判断这个提交是否是GET提交
            if("GET".equals(request.getMethod())){
            
                //获取到这个参数的值,进行转码操作,因为Get提交默认都是ISO-8859-1
                String temp = new String(request.getParameter(name).getBytes("ISO-8859-1"),"UTF-8");

                //返回这个转了码的参数值
                return temp;
            }
            
            //否则则是Post提交则设置编码集为UTF-8
            request.setCharacterEncoding("UTF-8");
            
            //返回这个参数值
            return request.getParameter(name);
            
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
    
    /**
     * 重写这个被装饰类需要增强功能的getParameterValues方法
     */
    @Override
    public String[] getParameterValues(String name) {
        try{
            //判断是否是Get提交的
            if("GET".equals(request.getMethod())){
                //获取到这参数名的所有值
                String[] arr = request.getParameterValues(name);
                
                //遍历这个数组
                for (int i = 0; i < arr.length; i++) {
                    //转换这个数组的每一个元素的编码集
                    arr[i] = new String(arr[i].getBytes("ISO-8859-1"),"UTF-8");
                }
                //返回这个转换好编码集元素的数组
                return arr;
            }
            
            //否则是Post提交则直接设置编码集
            request.setCharacterEncoding("UTF-8");
            
            //返回这个原有的数据
            return request.getParameterValues(name);
            
        }catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
    
    /**
     * 重写这个被装饰类需要增强功能的getParameterMap方法
     */
    @Override
    public Map getParameterMap() {
        try{
            //判断是否是Get提交方法
            if("GET".equals(request.getMethod())){
                //获取到这个参数的Map集合
                Map<String,String[]> map = request.getParameterMap();
                
                //遍历这个集合
                for (Entry<String,String[]> en : map.entrySet()) {
                    //遍历这个Entry的Value数组
                    for (int i = 0; i < en.getValue().length; i++) {
                        //设置转换编码集
                        en.getValue()[i] = new String(en.getValue()[i].getBytes("ISO-8859-1"),"UTF-8");
                    }
                }
                //返回这个集合
                return map;
            }
            
            //否则则是Post提交则直接设置编码集
            request.setCharacterEncoding("UTF-8");
            
            //返回这个集合
            return request.getParameterMap();
            
        }catch(Exception e ){
            e.printStackTrace();
            throw new RuntimeException();
        }
    }
    }    

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!