Servlet之Filter过滤器1

本文深入探讨了Servlet中的Filter过滤器接口及其在Web应用中的应用,详细介绍了如何使用Filter实现URL级别的权限访问控制、过滤敏感词汇、自动登录、压缩响应信息等功能,并通过实例展示了如何在web.xml文件中配置Filter过滤器以及执行顺序。此外,文章还阐述了Filter的生命周期、过滤器链的概念,以及如何利用Filter提取公共代码来简化开发过程。
摘要由CSDN通过智能技术生成

Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、自动登录、压缩响应信息等一些高级功能。

Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:

自定义filter

public class FilterDemo1 implements Filter{

       //销毁方法

       publicvoid destroy() {

              //TODO Auto-generated method stub

             

       }

       //执行方法

       publicvoid doFilter(ServletRequest request, ServletResponse response,

                     FilterChainchain) throws IOException, ServletException {

              //TODO Auto-generated method stub

              System.out.println("doFilter");           

       }

       //初始方法

       publicvoid init(FilterConfig arg0) throws ServletException {

              //TODO Auto-generated method stub

             

       }

 

}

ShowServlet

protectedvoid doGet(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {

       // TODO Auto-generatedmethod stub    

       //设置编码

       response.setContentType("text/html;charset=UTF-8");

       response.getWriter().write("欢迎学习servlet下篇!");

    }

在web.xml中配置filter

<!-- filter放在servlet的上面 -->

    <filter>

       <filter-name>FilterDemo1</filter-name>

       <filter-class>cn.itcast.web.filter.FilterDemo1</filter-class>

    </filter>

    <filter-mapping>

       <filter-name>FilterDemo1</filter-name>

       <!-- /*表示拦截所有,/表示项目名称,*代表所有 -->

       <!-- 不是用户访问的,指的是filter拦截所有资源 -->

       <url-pattern>/*</url-pattern>

    </filter-mapping>

    <servlet>

       <servlet-name>ShowServlet</servlet-name>

       <servlet-class>cn.itcast.web.servlet.ShowServlet</servlet-class>

    </servlet>

    <servlet-mapping>

       <servlet-name>ShowServlet</servlet-name>

       <url-pattern>/ShowServlet</url-pattern>

    </servlet-mapping>

访问网站会先转到过滤器

过滤器工作原理:

放行请求:

    //放行请求

       chain.doFilter(request,response);

chain.doFilter(request,response)具有二义性:

       >>如果有下一个Filter时,将请求转发给下一个Filter

        >>如果无下一个Filter时,将请求转发给Web资源(serlvet/jsp/html)

filter执行顺序:

//执行方法

    publicvoid doFilter(ServletRequest request, ServletResponseresponse,

           FilterChain chain) throws IOException, ServletException{

       // TODO Auto-generatedmethod stub

       System.out.println("A");

       //放行请求,类似于函数调用

       chain.doFilter(request, response);

       System.out.println("B");

    }

Filter2

    publicvoid doFilter(ServletRequest request, ServletResponseresponse,

           FilterChain chain) throws IOException, ServletException{

       // TODO Auto-generatedmethod stub

       System.out.println("C");

       chain.doFilter(request, response);

       System.out.println("D");

    }

在web.xml中配置(filter配置应在sevlet配置的上面,配置在前面的filter会先执行)

    <filter-mapping>

       <filter-name>FilterDemo1</filter-name>

       <!-- /*表示拦截所有,/表示项目名称,*代表所有 -->

       <!-- 不是用户访问的,指的是filter拦截所有资源 -->

       <url-pattern>/*</url-pattern>

    </filter-mapping>

    <filter>

       <filter-name>FilterDemo2</filter-name>

       <filter-class>cn.itcast.web.filter.FilterDemo2</filter-class>

    </filter>

    <filter-mapping>

       <filter-name>FilterDemo2</filter-name>

       <!-- /*表示拦截所有,/表示项目名称,*代表所有 -->

       <!-- 不是用户访问的,指的是filter拦截所有资源 -->

       <url-pattern>/*</url-pattern>

    </filter-mapping>


filter提取公共代码:

publicvoid doFilter(ServletRequest request, ServletResponseresponse,

           FilterChain chain) throws IOException, ServletException{

       // TODO Auto-generatedmethod stub

       chain.doFilter(request, response);

      

    }

filter2

publicvoid doFilter(ServletRequest request, ServletResponseresponse,

           FilterChain chain) throws IOException, ServletException{

       // TODO Auto-generatedmethod stub

       //设置编码,公共代码

       response.setContentType("text/html;charset=UTF-8");

    }

ShowServlet,这里就不用再设置编码了,因为在过滤器中已经设置

protectedvoid doGet(HttpServletRequest request, HttpServletResponseresponse) throws ServletException, IOException {

       // TODO Auto-generatedmethod stub    

       response.getWriter().write("欢迎学习servlet下篇!");

    }

showServlet不用再过滤中文乱码问题

2 过滤器简介(过滤器的配置要写在servlet的前面)

  a)FilterSUN公司提供的一个资源过滤器接口,不同的Web容器有着不同的实现

  b)Filter位于Web服务器和Web资源(Servlet/Jsp/Html)之间

  c)过滤请求和响应二者

  d)Filter可以进行简单判段,是否将请求放行给Web资源

  e)Filter的开发过程:

       >> implements javax.servlet.Filter接口

        >>web.xml文件配置Filter过滤器,告之Web服务器有过滤器的存在

              web.xml中的配置信息如下:

       <filter>

        <filter-name>FilterDemo1</filter-name>(过滤器,可以随意,但要和filter-mapping中的name一致)

        <filter-class>cn.itcast.web.filter.FilterDemo1</filter-class>(过滤器全路径)

        </filter>

       <filter-mapping>

        <filter-name>FilterDemo1</filter-name>(过滤器名,同上)

        <url-pattern>/*</url-pattern>(过滤器能够过滤的资源路径,不是用户在URL中访问的路径)

       </filter-mapping>

 

3 过滤器链

  a)一个Web应用可以有0个或多个Filter,多个Filter的组合就是过滤器链

  b)多个Filter的执行先后顺序,与web.xml文件中配置的顺序有关

 c)chain.doFilter(request,response)具有二义性:

       >>如果有下一个Filter时,将请求转发给下一个Filter

        >>如果无下一个Filter时,将请求转发给Web资源(serlvet/jsp/html)

  d)可以将web资源中的一些公共代码,提取出来,放入Filter

 

4 过滤器生命周期

  空参构造() 1

  init() 1

  doFilter(请求,响应,过滤器链) N次,与请求次数有关

  destory() 1

  Filter是一个单例

//单例

publicclass FilterDemo3 implements Filter{

    private FilterConfig  filterConfig;

    //构造函数:执行一次

    public FilterDemo3() {

       System.out.println("构造:"+this.hashCode());

    }

    //销毁方法:执行一次

    publicvoid destroy() {

       // TODO Auto-generatedmethod stub

       System.out.println("destroy:"+this.hashCode());

    }

    //N次,与请求有关,web容器调用

    publicvoid doFilter(ServletRequest request, ServletResponseresponse,

           FilterChain chain) throws IOException, ServletException{

       // TODO Auto-generatedmethod stub

       Enumeration<String>enums=filterConfig.getInitParameterNames();

       while(enums.hasMoreElements()){

           String key=enums.nextElement();       

           String value=filterConfig.getInitParameter(key);

           System.out.println(key+":"+value);

       }

       System.out.println("doFilter:"+this.hashCode());

       String encoding=filterConfig.getInitParameter("encoding");

       System.out.println(encoding);

       response.setContentType("text/html;charset="+encoding);

       chain.doFilter(request, response);

    }

    //初始化filter,执行一次

    publicvoid init(FilterConfig filterConfig) throws ServletException {

       // TODO Auto-generatedmethod stub

       System.out.println("init:"+this.hashCode());

       this.filterConfig=filterConfig;

      

    }

web.xml中配置


<filter>

       <filter-name>FilterDemo3</filter-name>

       <filter-class>cn.itcast.web.filter.FilterDemo3</filter-class>

       <init-param>

           <param-name>encoding</param-name>

           <param-value>UTF-8</param-value>

       </init-param>

       <init-param>

           <param-name>email</param-name>

           <param-value>jack@163.com</param-value>

       </init-param>

    </filter>

    <filter-mapping>

       <filter-name>FilterDemo3</filter-name>

       <!-- /*表示拦截所有/表示项目名称,*代表所有 -->

       <!-- 不是用户访问的,指的是filter拦截所有资源 -->

       <url-pattern>/*</url-pattern>

    </filter-mapping>

当访问一个web资源时,没有得到对应的结果,有可能是Filter没有放行资源

  b)静态资源和动态资源进行不同的缓存处理,代码如下:

              if(uri!=null&& uri.endsWith("jsp")){

                     //NO3如果是动态资源,设置三个响应头通知浏览器不缓存

                     response.setHeader("expires","-1");

                     response.setHeader("cache-control","no-cache");

                     response.setHeader("pragma","no-cache");

              }else if(uri!=null &&uri.endsWith("html")){

                     //NO4如果是静态资源,缓存一定的时间

                     StringstrHtml = filterConfig.getInitParameter("html");

                     longtime = System.currentTimeMillis()+Integer.parseInt(strHtml)*1000;

                     //time为毫秒值

                     response.setDateHeader("expires",time);

                     response.setHeader("cache-control",time/1000+"");

                     response.setHeader("pragma",time/1000+"");

              }

   c)总结:写Filter一定要知道该Filter过滤哪个或哪些资源,不是所有的Filter都过滤/*的资源。

动态资源缓存,静态资源缓存

静止缓存动态资源如jsp

//禁止浏览器缓存动态资源,例如JSP资源

public class FilterDemo5 implements Filter {

       privateFilterConfig filterConfig;

       public voidinit(FilterConfig filterConfig) throws ServletException {

              this.filterConfig= filterConfig;

       }

       public voiddoFilter(ServletRequest req, ServletResponse res,FilterChain chain) throwsIOException, ServletException {

 

              //NO将父子接口强转

              HttpServletRequestrequest = (HttpServletRequest) req;

              HttpServletResponseresponse = (HttpServletResponse) res;

             

              //NO1取得客户端访问的资源的URI,形式/day19/login.jsp

              Stringuri = request.getRequestURI();

             

              //NO2判段是否以jsp结尾,即动态资源

              if(uri!=null&& uri.endsWith("jsp")){

                     //NO3如果是动态资源,设置三个响应头通知浏览器不缓存

                     response.setHeader("expires","-1");

                     response.setHeader("cache-control","no-cache");

                     response.setHeader("pragma","no-cache");

              }elseif(uri!=null && uri.endsWith("html")){

                     //NO4如果是静态资源,缓存一定的时间,有助于减轻服务器压力

                     StringstrHtml = filterConfig.getInitParameter("html");

                     longtime = System.currentTimeMillis()+Integer.parseInt(strHtml)*1000;

                     //time为毫秒值

                     response.setDateHeader("expires",time);

                     response.setHeader("cache-control",time/1000+"");

                     response.setHeader("pragma",time/1000+"");

              }

             

              //NO5放行资源

              chain.doFilter(request,response);

       }

       public voiddestroy() {

       }

}

web.xml中配置

<filter>

       <filter-name>FilterDemo5</filter-name>

       <filter-class>cn.itcast.web.filter.FilterDemo5</filter-class>

       <init-param>

           <param-name>html</param-name>

           <param-value>86400</param-value>

       </init-param>

      

    </filter>

    <filter-mapping>

       <filter-name>FilterDemo5</filter-name>

       <!-- /*表示拦截所有,/表示项目名称,*代表所有 -->

       <!-- 不是用户访问的,指的是filter拦截所有资源 -->

       <url-pattern>/*</url-pattern>

    </filter-mapping>

 loign.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <body>
     <form action="${pageContext.request.contextPath}/LoginServlet" method="post">
         <table border="1" align="center">
             <caption>用户登录</caption>
             <tr>
                 <th>用户名</th>
                 <td><input type="text" name="username"/></td>
             </tr>
             <tr>
                 <th>密码</th>
                 <td><input type="password" name="password"/></td>
             </tr>
             <tr>
                 <td colspan="2" align="center">
                     <input type="submit" value="提交"/>
                 </td>
             </tr>
         </table>
     </form>
  </body>
</html>

login.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  </head>
  <body>
     <form action="/day19/LoginServlet" method="post">
         <table border="1" align="center">
             <caption><br>用户自动登录</caption>
             <tr>
                 <th>用户名</th>
                 <td><input type="text" name="username"/></td>
             </tr>
             <tr>
                 <th>密码</th>
                 <td><input type="password" name="password"/></td>
             </tr>
             <tr>
                 <th>时间</th>
                 <td>
                     <input checked name="time" type="radio" value="60"/>1分钟
                     <input name="time" type="radio" value="180"/>3分钟
                     <input name="time" type="radio" value="300"/>5分钟
                 </td>
             </tr>
             <tr>
                 <td colspan="2" align="center">
                     <input type="submit" value="提交"/>
                 </td>
             </tr>
         </table>
     </form>
  </body>
</html>


查看缓存:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值