Filter 过滤器

Filter过滤器 是什么

java web 中的过滤器可以拦截所有访问web资源的请求或响应操作。

Filter过滤器 有什么用

  • 拦截
  • 数据处理
  • 统一控制

Filter过滤器 如何用

使用步骤

  • 创建一个类实现Filter接口
  • 重写接口中方法 doFilter 方法是真正过滤的。
  • 在web.xml文件中配置
注意
在Filter的doFilter方法如果没有执行chain.doFilter(request,response)
那么资源是不会被访问到的。
示例
public class Myfilter2 implements Filter {

    public void destroy() {
    }
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("Myfilter2 执行了");
        //放行
        chain.doFilter(request, response);
        System.out.println("Myfilter2 拦截结束了");
    }

    public void init(FilterConfig fConfig) throws ServletException {
    }

}

  <filter>
      <filter-name>MyFilter3</filter-name>
      <filter-class>cn.leyue.filter.MyFilter3</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>MyFilter3</filter-name>
      <url-pattern>/servlet/indexServlet</url-pattern>
  </filter-mapping>

FilterChain

FilterChain是servlet 容器为开发人员提供的对象,他提供了对某一个资源的已过滤请求调用链的视图。
过滤器使用FilterChain调用链中的下一个过滤器。
如果调用的过滤器是链中的最后一个过滤器 则调用链末尾的资源。

怎样可以形成一个Filter链?
    只要多个Filter 对同一个资源进行拦截可以形成Filter链
怎样确定Filter的执行顺序
    由<filter-mapping>来确定
filter过滤器.png

Filter 生命周期

  • 当服务器启动,会创建Filter对象,并调用init方法,只调用一次
  • 当访问资源时,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,这个方法
    是真正拦截操作的方法。
  • 当服务器关闭时,会调用Filter的destroy 方法来进行销毁操作。

FilterConfig

在Filter的init 方法上有一个参数,类型就是FilterConfig,
FilterConfig它是Filter的配置对象,它可以完成以下功能:
* 获取Filter名称
* 获取Filter初始化参数
* 获取ServletContext 对象
getFilterName()  getInitParameter(String name) 
getInitParameterNames() getServletContext();

* 怎样在Filter中获取一个FilterConfig对象?
    private FilterConfig fConfig;
    public void init(FilterConfig fConfig) throws ServletException {
        this.fConfig = fConfig;
    }

Filter 配置

基本配置
<filter>
    <filter-name>filter</filter-name>
    <filter-class>filter类的包名.类名</filter-class>

</filter>   
<filter-mapping>
    <filter-name>filter 名称</filter-name>    
    <filter-pattern>路径</filter-pattern>
</filter-mapping>   

<url-pattern>

完全匹配 以“/demo”开始,不包含通配符
目录匹配 以“/”开始,以*结束
扩展名匹配 *.xxx 不能写成 /*.xxx

<servlet-name>

<filter>
  <filter-name>MyFilter3</filter-name>
  <filter-class>cn.leyue.filter.MyFilter3</filter-class>
</filter>
   
<filter-mapping>
    <filter-name>MyFilter3</filter-name>
    <url-pattern>/servlet/indexServlet</url-pattern>
</filter-mapping>

<dispatcher>

<filter-mapping>
  <filter-name>MyFilter3</filter-name>
  <url-pattern>/servlet/*</url-pattern>
  <dispatcher>REQUEST</dispatcher>
  <dispatcher>FORWARD</dispatcher>
  
</filter-mapping>

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

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;
}

全局的编码过滤器

public class EncodingFilter implements Filter {

/**
 * Default constructor.
 */
public EncodingFilter() {
    // TODO Auto-generated constructor stub
}

/**
 * @see Filter#destroy()
 */
public void destroy() {
    // TODO Auto-generated method stub
}

/**
 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
 */
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    req.setCharacterEncoding("utf-8");
    
    
    MyRequest myRequst = new MyRequest(req);

    chain.doFilter(myRequst, response);
}

/**
 * @see Filter#init(FilterConfig)
 */
public void init(FilterConfig fConfig) throws ServletException {
    // TODO Auto-generated method stub
}

/**
 * 实现与被包装对象相同的接口
 *  定义一个与包装类相同对象的引用 
 *  定义一个构造方法,把被包装对象传过来 
 *  对于不需要改写方法,直接调用
 * 对于无需要改写方法,写自己的方法体
 */
class MyRequest extends HttpServletRequestWrapper {
    HttpServletRequest request;

    public MyRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    @Override
    public String getParameter(String name) {
        if(getParameterMap().get(name)==null) {
            return null;
        }
        return getParameterMap().get(name)[0];
    }

    @Override
    public String[] getParameterValues(String name) {
        return getParameterMap().get(name);
    }

    private boolean flag = true;

    @Override
    public Map<String, String[]> getParameterMap() {
        //获取请求方式
        String method = request.getMethod();
        if(method.equalsIgnoreCase("post")) {
            //处理乱码
            try {
                request.setCharacterEncoding("utf-8");
                return request.getParameterMap();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            
        } else if(method.equalsIgnoreCase("get")) {
            Map<String, String[]> map = this.request.getParameterMap();
            if (!flag) {
                for (Map.Entry<String, String[]> m : map.entrySet()) {
                    String[] values = m.getValue();
                    for (int i = 0; i < values.length; i++) {
                        try {
                            //get方式处理乱码
                            values[i] = new String(values[i].getBytes("ISO-8859-1"), "utf-8");
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                    }
                }
                flag =true;
            }
            return map;
            
        }
        return super.getParameterMap();
        
    }
}

}


2016.11.6

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容

  • 创建 编写一个过滤器的类,实现Filter接口 实现接口尚未实现的方法,着重实现doFilter方法 在web.x...
    蕊er阅读 433评论 0 0
  • Filter可以视作是servlet的加强版,主要用作对用户的请求进行预处理,或者对返回给客户端的结果进行再次加工...
    Single_YAM阅读 2,676评论 1 7
  • 本文包括:1、Filter简介2、Filter是如何实现拦截的?3、Filter开发入门4、Filter的生命周期...
    廖少少阅读 7,248评论 3 56
  • Filter的使用和经典案例 一、什么是Filter Filter也称之为过滤器。 通过Filter可以拦截所有对...
    明天你好向前奔跑阅读 1,154评论 0 5
  • Filter简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,Web开发人员通过Filter...
    java部落阅读 285评论 0 1