《JavaWeb从入门到改行》过滤器学习笔记


 

Filter API 

 

 

@过滤器( filter)是JavaWeb三大组件之一 ,作用是拦截请求,在访问指定目标资源(如Servlet、JSP、css、html)之前先执行过滤器中的操作 。  

@过滤流程 是服务器启动后,自动创建Filter接口的实例对象,并进行初始化,我们编写一个filter类继承该实例对象,并且重写其doFilter方法,在此方法中添加过滤规则 。 当客户端每次要访问目标资源时,Servlet容器都会调用Filter接口的实例对象的doFilter方法,也就是会调用我们自己重写的doFilter方法,在此方法中,如果符合规则,则调用FilterChain对象的doFilter方法,表示这个过滤器对该请求进行放行,可以去执行下一个过滤器的生命周期方法中的doFilter方法。 如果下一个过滤器也放行的话,就再去执行下下个过滤器,知道通过了所有过滤器的考验,最终访问到目标资源

过滤器的详解

 @过滤器的配置在Servet2.5及以前版本都需要在web.xml中进行配置 ,一个目标资源可以添加多个过滤器,也就是多个过滤规则 ,只有全部通过了,请求才能到达目标资源

 1   <filter>
 2     <filter-name>第一个过滤器类名字</filter-name>
 3     <filter-class>包.类</filter-class>
 4   </filter>
 5   <filter-mapping>
 6     <filter-name>第一个过滤器类名字</filter-name>
 7     <url-pattern>要过滤的目标资源A</url-pattern>
 8   </filter-mapping>
 9   <filter>
10     <filter-name>第二个过滤器类名字</filter-name>
11     <filter-class>包.类</filter-class>
12   </filter>
13   <filter-mapping>
14     <filter-name>第二个过滤器类名字</filter-name>
15     <url-pattern>要过滤的目标资源A</url-pattern>
16   </filter-mapping>

@多个过滤器的执行顺序 是按照配置的先后顺序执行的

@四种拦截方式 ,假如: 我们编写一个过滤器用来过滤资源A,当我们直接访问该资源A时就会被过滤,但是当我们间接访问资源A(比如: 在其他页面用转发的形式间接访问资源A)时,过滤器不会执行。 所以有时候我们要定义我拦截方式。

拦截方式 说明
REQUEST 直接访问目标资源时执行过滤器 ,默认
FORWARD 转发访问执行过滤器
INCLUDE 包含访问执行过滤器
ERROR

当目标资源在web.xml中配置为<error-page>中时,并且真的出现了异常,转发到目标资源时,会执行过滤器。

 

 

 

 

 

 

 

 

在<filter-mapping>中添加0~n个<dispatcher>子元素,来说明当前访问的拦截方式。

<filter-mapping>
        <filter-name>过滤器名字</filter-name>
        <url-pattern>目标资源路径</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>              
</filter-mapping>

经典案例_分IP统计网站的访问次数

 @说明 网站的访问次数绝不可能随着浏览器的关闭而重置为0,因为和服务器的寿命是一样的,所以必须用Application域 。而访问次数与IP有关系,最好放在map中,即map<ip地址,访问次数>,而这个map又必须是在服务器启动时就需要创建并且要保存到Application域中以供使用,所以需要监听器

 @注意 类名包名等路径随自己的项目更改

 1 package cn.kmust.web.demo1.filter;
 2 
 3 import java.io.IOException;
 4 import java.util.LinkedHashMap;
 5 import java.util.Map;
 6 
 7 import javax.servlet.Filter;
 8 import javax.servlet.FilterChain;
 9 import javax.servlet.FilterConfig;
10 import javax.servlet.ServletContext;
11 import javax.servlet.ServletException;
12 import javax.servlet.ServletRequest;
13 import javax.servlet.ServletResponse;
14 
15 /**
16  * 过滤器  [分IP统计访问次数案例]
17  * @功能 在访问a.jsp和b.jsp资源之前,进行分ip统计访问次数
18  *    统计功能不需要拦截,所以放行,web.xml中为了不与其他demo项目冲突,
19  *         所以拦截对象只是本例的demo1_show.jsp
20  * @author ZHAOYUQIANG
21  *
22  */
23 public class CountFilter implements Filter {
24     private FilterConfig config ;
25     
26     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
27         /*
28          * 1. 得到application对象
29          * 2. 获取application域中的Map
30          * 3. 从request中获取当前客户端的IP地址
31          * 4. 查看Map中是否存在这个IP对应的访问次数,
32          *     如果存在,获取访问次数,+1
33          * 5. 如果不存在ip,说明第一次访问,设置访问次数为1
34          * 6. 操作完成后,再把map放回到application中
35          * 7. 这个过滤器不需要拦截,所以放行
36          */
37         ServletContext app = config.getServletContext();
38         Map<String,Integer> map = (Map<String , Integer>)app.getAttribute("map");
39         String ip  = request.getRemoteAddr();
40         if(map.containsKey(ip)){
41             int cnt = map.get(ip);
42             map.put(ip, cnt+1);
43         }else{
44             map.put(ip, 1);
45         }
46         app.setAttribute("map", map);
47         chain.doFilter(request, response);
48     }
49 
50     /**
51      * 在服务器启动时执行
52      *   保存config对象
53      */
54     public void init(FilterConfig fConfig) throws ServletException {
55         this.config = fConfig ;
56         
57     }
58     public void destroy() {
59         // TODO Auto-generated method stub
60     }
61 
62 }
CountFilter
 1 package cn.kmust.web.demo1.listerner;
 2 
 3 import java.util.LinkedHashMap;
 4 import java.util.Map;
 5 
 6 import javax.servlet.ServletContext;
 7 import javax.servlet.ServletContextEvent;
 8 import javax.servlet.ServletContextListener;
 9 
10 /**
11  * 监听器   [项目统计按IP分类为统计访问人数的辅助类] 
12  * @功能 创建Map,保存到application域中
13  *     分IP查询,Map的类型为Map<IP地址,访问次数> ; 因为访问次数是项目整体范围,所以保存到application域中
14  * @author ZHAOYUQIANG
15  *
16  */
17 public class CountListerner implements ServletContextListener {
18     /**
19      * 在服务器启动时创建Map,保存到ServletContext中
20      */
21     public void contextInitialized(ServletContextEvent sce) {
22         /*
23          * 1. 创建Map<IP地址,访问次数>
24          * 2. 通过ServletContextEvent对象获取ServletContext
25          * 3. 把Map保存到application中
26          */
27         Map<String,Integer> map = new LinkedHashMap<String, Integer>();
28         ServletContext application = sce.getServletContext();
29         application.setAttribute("map", map);
30     }
31 
32     public void contextDestroyed(ServletContextEvent arg0) {
33         // TODO Auto-generated method stub
34     }
35     
36 }
CountListerner
<body>
    <h1><center>显示结果</center></h1>
    <table align="center" width="60%" border="1">
        <tr>
           <th>IP</th>
           <th>次数</th>
        </tr>
<c:forEach items="${applicationScope.map }" var="entry">
        <tr>
           <td>${entry.key }</td>
           <td>${entry.value }</td>
        </tr>
</c:forEach>
         
    </table>
  </body>
测试页面
<filter>
    <display-name>CountFilter</display-name>
    <filter-name>CountFilter</filter-name>
    <filter-class>cn.kmust.web.demo1.filter.CountFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>CountFilter</filter-name>
    <url-pattern>/demo1_show.jsp</url-pattern>
  </filter-mapping>
  <listener>
    <listener-class>cn.kmust.web.demo1.listerner.CountListerner</listener-class>
  </listener>
配置

经典案例_粗粒度权限控制

 @说明 防止为登陆的用户访问主页, /user/userindex.jsp是目标资源 ,如果为登陆的用户直接访问该资源,则打回到登陆页面

 @注意 类名包名等路径随自己的项目更改

 1 package cn.kmust.webfilter.web.filter;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.Filter;
 6 import javax.servlet.FilterChain;
 7 import javax.servlet.FilterConfig;
 8 import javax.servlet.ServletException;
 9 import javax.servlet.ServletRequest;
10 import javax.servlet.ServletResponse;
11 import javax.servlet.http.HttpServletRequest;
12 /**
13  * 过滤器 用来 ,对/user/userindex.jsp进行过滤
14  * @功能 当有请求访问userindex.jsp时,先检查session域中有没有用户名,如果有则放行,如果没有,则拦截,并且打回
15  * @author ZHAOYUQIANG
16  *
17  */
18 public class LoginFilter implements Filter {
19     public void destroy() {        
20     }
21     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
22         //因为用的是Http协议的请求,所以需要把过滤器中的ServletRequest转换成Http协议的
23         HttpServletRequest req = (HttpServletRequest) request;
24         //从session域中获取用户名
25         String name  = (String) req.getSession().getAttribute("session_user");
26         if(name != null ){
27             chain.doFilter(request, response);
28         }else{
29             req.getRequestDispatcher("/user/userlogin.jsp").forward(request, response);
30         }
31         chain.doFilter(request, response);
32     }
33     public void init(FilterConfig fConfig) throws ServletException {
34     
35     }
36 }
filter
 1 package cn.kmust.webfilter.web.filter;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.Filter;
 6 import javax.servlet.FilterChain;
 7 import javax.servlet.FilterConfig;
 8 import javax.servlet.ServletException;
 9 import javax.servlet.ServletRequest;
10 import javax.servlet.ServletResponse;
11 import javax.servlet.http.HttpServletRequest;
12 /**
13  * 过滤器 用来 ,对/user/userindex.jsp进行过滤
14  * @功能 当有请求访问userindex.jsp时,先检查session域中有没有用户名,如果有则放行,如果没有,则拦截,并且打回
15  * @author ZHAOYUQIANG
16  *
17  */
18 public class LoginFilter implements Filter {
19     public void destroy() {        
20     }
21     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
22         //因为用的是Http协议的请求,所以需要把过滤器中的ServletRequest转换成Http协议的
23         HttpServletRequest req = (HttpServletRequest) request;
24         //从session域中获取用户名
25         String name  = (String) req.getSession().getAttribute("session_user");
26         if(name != null ){
27             chain.doFilter(request, response);
28         }else{
29             req.getRequestDispatcher("/user/userlogin.jsp").forward(request, response);
30         }
31         chain.doFilter(request, response);
32     }
33     public void init(FilterConfig fConfig) throws ServletException {
34     
35     }
36 }
servlet
1 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2 <body>
3   <h2>用户名字是user,密码是123</h2>
4     <form action ="<c:url value="/LoginServlet"/>" method="post">
5       <input type="text" name="username"/><br>
6       <input type="password" name="password"/><br>
7       <input type="submit" name="登陆"/>
8     </form>
9   </body>
login
<body>
   <h1><center>这是用户主页,没有登陆的用户是不能直接访问该页的</center></h1>
  </body>
userindex
<filter>
    <display-name>LoginFilter</display-name>
    <filter-name>LoginFilter</filter-name>
    <filter-class>cn.kmust.webfilter.web.filter.LoginFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/LoginFilter</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>LoginFilter</filter-name>
    <url-pattern>/user/userindex.jsp</url-pattern>
  </filter-mapping>
配置

经典案例_解决全站字符乱码

@说明 servlet处理post和get请求编码可以写在过滤器中,但是post和get编码的处理方式不是一样的,所以需要对request进行装饰,所以编写了EncodingRequest类来对request进行装饰,来帮助过滤器完成对get请求的编码 。  

<%--get请求,传递过去method参数,指明调用TestServlet的fun2方法,并且传递一个参数param--%>
<a href="<c:url value='/GetServlet?param=哈哈'/>"> 这是get请求</a>
<%--post请求--%>
<form action="<c:url value='/PostServlet'/>" method="post">
   <input type="text" name="param" value="我是表单参数" />
   <input type="submit" name="提交"/>
</form>
提交页面
 1 package cn.kmust.webfilter.web.servlet;
 2 import java.io.IOException;
 3 
 4 import javax.servlet.ServletException;
 5 import javax.servlet.http.HttpServlet;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 /**
 9  *  post请求访问的Servlet,在过滤器中会进行编码的处理 
10  *  获取参数,转发到显示页面
11  * @author ZHAOYUQIANG
12  *
13  */
14 public class PostServlet extends HttpServlet {
15 
16     public void doPost(HttpServletRequest request, HttpServletResponse response)
17             throws ServletException, IOException {
18          request.setAttribute("param", request.getParameter("param"));
19          request.getRequestDispatcher("/show.jsp").forward(request, response);
20     }
21 }
PostServlet
package cn.kmust.webfilter.web.servlet;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 *  get请求访问的Servlet,在过滤器中会进行编码的处理 
 *  获取参数,转发到显示页面
 * @author ZHAOYUQIANG
 *
 */
public class GetServlet extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String  param = request.getParameter("param");
        request.setAttribute("param", param);
        request.getRequestDispatcher("/show.jsp").forward(request, response);
    }
}
GetServlet
package cn.kmust.webfilter.web.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import cn.kmust.webfilter.utils.EncodingRequest;

/**
 * 解决乱码的过滤器,servlet处理post和get乱码的操作,全都在这儿处理
 * @author ZHAOYUQIANG
 *
 */
public class EncodingFilter implements Filter {

    public void destroy() {
    }
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        /*
         * 处理post请求乱码问题
         */
        request.setCharacterEncoding("utf-8");
        /*
         * 处理GET请求编码问题
         *   String name1 =  request.getParameter("name");
         *   name2 = new String(name.getBytes("ISO-8859-1"),"utf-8");
         *    GET不一样,设置编码后,servlet中获取name,获取应该是name2,都是如果如上写的话,
         *     getParameter("name")获取的是name1 .
         * 掉包request
         *    1. 写一个request的装饰类
         *    2. 放行时,使用我们自己的request
         *    3. 但是POST方式依然使用request
         */
        HttpServletRequest req = (HttpServletRequest) request ;
        if(req.getMethod().equals("GET")){
            EncodingRequest er = new EncodingRequest(req);     
            chain.doFilter(er, response);
        }else if(req.getMethod().equals("POST")){
            chain.doFilter(request, response);
        }
//        response.setContentType("text/html;charset=UTF-8");
    }

    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
    }
}
EncodingFilter
package cn.kmust.webfilter.utils;

import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
 * 辅助过滤器来处理GET编码问题
 * @author ZHAOYUQIANG
 *
 */
public class EncodingRequest extends HttpServletRequestWrapper{
private HttpServletRequest request ;
    
    public EncodingRequest(HttpServletRequest request) {
        super(request);
        this.request = request ;
    }
    /**
     * 处理编码问题
     */
    public String getParameter(String name) {
        String value = request.getParameter(name);
        /*
         * 处理编码问题
         */
        try {
            value = new String (value.getBytes("ISO-8859-1"),"utf-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            throw new RuntimeException(e);
        }        
        return value;
    }

}
EncodingRequest
 ${requestScope.param }
显示页面
<filter>
    <display-name>EncodingFilter</display-name>
    <filter-name>EncodingFilter</filter-name>
    <filter-class>cn.kmust.webfilter.web.filter.EncodingFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/EncodingFilter</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/GetServlet</url-pattern>
  </filter-mapping>
  <filter-mapping>
    <filter-name>EncodingFilter</filter-name>
    <url-pattern>/PostServlet</url-pattern>
  </filter-mapping>
过滤器配置

经典案例_页面静态化

 @说明 (页面静态化是什么请自行百度,这儿不做累述),我们做一个过滤器,让其访问servlet时判断是否符合静态化页面的要求 。如果是,则让其直接访问静态化的页面,如果不是,则继续访问资源。 

CREATE TABLE `t_book` (
  `bid` char(32) NOT NULL,
  `bname` varchar(100) DEFAULT NULL,
  `price` decimal(10,2) DEFAULT NULL,
  `category` int(11) DEFAULT NULL,
  PRIMARY KEY (`bid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



insert  into `t_book`(`bid`,`bname`,`price`,`category`) values ('b1','JavaSE_1','10.00',1),('b2','JavaSE_2','15.00',1),('b3','JavaSE_3','20.00',1),('b4','JavaSE_4','25.00',1),('b5','JavaEE_1','30.00',2),('b6','JavaEE_2','35.00',2),('b7','JavaEE_3','40.00',2),('b8','Java_framework_1','45.00',3),('b9','Java_framework_2','50.00',3);
数据库
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config><!-- 这是默认的配置信息 -->
        <!-- 连接四大参数配置 -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/filtertest</property>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <!-- 池本身的参数配置 -->
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </default-config>
    
    <!-- 专门为oracle准备的配置信息 -->
    <!-- 这也是命名配置信息,在JDBC中创建连接池对象的时候要加 oracle-config这个参数-->
    <named-config name="oracle-config">
        <property name="jdbcUrl">  oracle的url   </property>
        <property name="driverClass">  oracle的驱动   </property>
        <property name="user">    oracle的用户 </property>
        <property name="password">    密码</property>
        <property name="acquireIncrement">3</property>
        <property name="initialPoolSize">10</property>
        <property name="minPoolSize">2</property>
        <property name="maxPoolSize">10</property>
    </named-config>
    
</c3p0-config>
c3p0配置
1 <h1>链接页面</h1> 
2 <%--Get方式,向页面传递method参数和方法中的参数 --%>  
3 <a href="<c:url value='/BookServlet?method=findAll'/>">查询所有</a><br/>
4 <a href="<c:url value='/BookServlet?method=findByCategory&category=1'/>">查询SE</a><br/>
5 <a href="<c:url value='/BookServlet?method=findByCategory&category=2'/>">查询EE</a><br/>
6 <a href="<c:url value='/BookServlet?method=findByCategory&category=3'/>">查询Framework</a><br/>
提交页面
 1  <h1 align="center">图书列表</h1>
 2   <table border="1" align="center" width="50%">
 3     <tr>
 4         <th>书名</th>
 5         <th>单价</th>
 6         <th>分类</th>
 7     </tr>
 8 <c:forEach items="${bookList }" var="book">    
 9     <tr>
10         <td>${book.bname }</td>
11         <td>${book.price }</td>
12         <%--每个分类都是不同的颜色 --%>
13         <c:choose>
14           <c:when test="${book.category eq 1 }"><td style="color:red">JavaSE</td></c:when>
15           <c:when test="${book.category eq 2 }"><td style="color:blue">JavaEE</td></c:when>
16           <c:when test="${book.category eq 3 }"><td style="color:green">JaveFrameWork</td></c:when>
17         </c:choose>
18         <td>${book.category }</td>
19     </tr>
20 </c:forEach>    
21   </table>
显示页面
 1 package cn.kmust.book.web.servlet;
 2 
 3 import java.io.IOException;
 4 
 5 import javax.servlet.ServletException;
 6 import javax.servlet.http.HttpServletRequest;
 7 import javax.servlet.http.HttpServletResponse;
 8 
 9 import cn.itcast.servlet.BaseServlet;
10 import cn.kmust.book.dao.BookDao;
11 /**
12  * servlet层 
13  * @功能 把查询到的图书放到request域中,转发到list.jsp中显示
14  * @author ZHAOYUQIANG
15  *
16  */
17 public class BookServlet extends BaseServlet {
18     private BookDao bookDao = new BookDao();
19     /**
20      * 查询所有图书
21      * @param request
22      * @param response
23      * @return
24      * @throws ServletException
25      * @throws IOException
26      */
27     public String findAll(HttpServletRequest request,HttpServletResponse response)
28              throws ServletException,IOException{
29         request.setAttribute("bookList", bookDao.findAll());
30         return "/list.jsp" ;
31     }
32     /**
33      * 按分类条件查询图书
34      * @param request
35      * @param response
36      * @return
37      * @throws ServletException
38      * @throws IOException
39      */
40     public String findByCategory(HttpServletRequest request,HttpServletResponse response)
41              throws ServletException,IOException{
42         String value = request.getParameter("category");
43         int category = Integer.parseInt(value);
44         request.setAttribute("bookList", bookDao.findByCategorys(category));
45         return "/list.jsp" ;
46     }
47 
48 }
servlet
 1 package cn.kmust.book.web.filter;
 2 
 3 import java.io.File;
 4 import java.io.IOException;
 5 import javax.servlet.Filter;
 6 import javax.servlet.FilterChain;
 7 import javax.servlet.FilterConfig;
 8 import javax.servlet.ServletContext;
 9 import javax.servlet.ServletException;
10 import javax.servlet.ServletRequest;
11 import javax.servlet.ServletResponse;
12 import javax.servlet.http.HttpServletRequest;
13 import javax.servlet.http.HttpServletResponse;
14 
15 import cn.kmust.book.utils.StaticResponse;
16 /**
17  * 过滤器
18  * @功能 /BookServlet, 访问Servlet之前,进行判断,如果静态化页面存在,过滤器直接拦截下来,直接让它访问该静态化页面,避免继续往下访问serlvet去查询数据库。
19  *      如果静态化页面不存在(第一次访问),此时,生成新的静态化页面 ,过滤器放行, 放行之后,servlet会通过访问dao层查询数据库得到查询的数据,这个时候servlet会向list.jsp页面输出数据,但是
20  *        我们不能让list.jsp输出,而是想办法让新的静态化页面做输出。
21  * @解决问题 如何不能让list.jsp输出,而是让新的静态化页面做输出 ? 
22  *           jsp的输出实际上是out.write("<html>"),而这个out流底层就是response的getWriter()(注意,区分开Out内置对象)。
23  *             就是因为这个out流,jsp中的out.write()才会输出在jsp页面中 。假如我们改变了out流,让这个流与我们指定静态页面绑定,那么
24  *                jsp中的out流就会向定的静态页面中输出,这个过程就做调包response 。
25  *                   毕竟response在一个请求中是不变的,用的同一个,所以我们用调包后的response来操作就完成了解决了这个问题 
26  * @解决问题  新的html页面会产生乱码问题 。 所以需要jsp页面中添加<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">                
27  *                  
28  * @author ZHAOYUQIANG
29  *
30  */
31 public class StaticFilter implements Filter {
32     private FilterConfig config ;
33     public void destroy() {}    
34     public void init(FilterConfig fConfig) throws ServletException {
35         this.config = fConfig ;
36     }    
37     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
38         /*
39          * 把request和response转换成HttpServlet类型的
40          */
41         HttpServletRequest req = (HttpServletRequest) request ;
42         HttpServletResponse res = (HttpServletResponse) response;
43         /*
44          * 1. 获取category参数,变成对应的文件名称
45          *     category有四种值,分别对应四个静态化的页面
46          *       null--> null.html
47          *       1--> 1.html
48          *       2--> 2.html
49          *       3--> 3.html
50          * 2. 获取文件所在目录路径
51          *       FilterConfig对象的getServletContext()能够获取ServletContext对象
52          * 3. 用路径和文件名称 创建一个新的文件
53          * 4. 判断该新文件是否存在,如果文件存在,重定向到这个文件
54          *
55          */
56         String category = request.getParameter("category");
57         String htmlPage = category+".html" ;
58         String htmlPath = config.getServletContext().getRealPath("/htmls");
59         File destFile = new File(htmlPath,htmlPage);
60         if(destFile.exists()){
61             res.sendRedirect(req.getContextPath()+"/htmls/"+htmlPage);
62             return ;
63         }
64         /*
65          * 5. 如果该新文件不存在,调包response
66          *      把新文件的路径传递过去,让out流与其路径绑定
67          * 6. 放行
68          *     在放行后,程序访问servlet,查询到数据,因为sr是调包后的response(response的getWriter()方法产生的out流与指定html绑定的),
69          *        那么,数据都输出到指定的静态页面中了。这个时候浏览器是不显示这个页面的,用户也是看不到的
70          * 7. 来一个重定向,让浏览器去显示这个静态页面
71          */
72         StaticResponse sr = new StaticResponse(res, destFile.getAbsolutePath());
73         chain.doFilter(request, sr);
74         res.sendRedirect(req.getContextPath()+"/htmls/"+htmlPage);
75         
76     }
77 
78 }
filter
package cn.kmust.book.utils;

import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
/**
 * 调包response 
 *    让getWriter()与传递过来的路径绑定
 * @author ZHAOYUQIANG
 *
 */
public class StaticResponse extends HttpServletResponseWrapper {
    private PrintWriter pw ;
    /**
     * 创建一个与html文件路径在一起的流对象
     * String path表示的是html文件路径
     * 
     * @param response
     * @param path
     * @throws UnsupportedEncodingException 
     * @throws FileNotFoundException 
     */
    public StaticResponse(HttpServletResponse response,String path) 
            throws FileNotFoundException, UnsupportedEncodingException {
        super(response);
        
        pw = new PrintWriter(path,"utf-8");
    }

    /**
     * 返回一个与html绑定在一起的printWriter对象
     *  jsp会使用它进行输出,这样数据都输出到了静态html页面中了
     */
    public PrintWriter getWriter(){
        
        return pw;
    }

}
调包response,辅助过滤器

关于dao层和servic层页面不再给出源码,大家可以直接下载完整项目源码:

@本项目源码使用说明 本代码第一次访问,查看各种分类 时,会访问数据库,获取资源,并且在htmls文件下建立静态化页面,可以去tomcat目录下的htmls下查看。 当再次访问该页面时候,直接重定向到该静态页面,不需要再去访问数据库了 。 

@全部项目源码下载地址  https://files.cnblogs.com/files/zyuqiang/%E9%A1%B9%E7%9B%AE.zip

Servlet3.0新特性 之 使用@WebFilter注解取代web.xml进行对filter的配置

 点击这里   请去Servlet3.0新特性中学习 

 

posted @ 2017-08-22 15:45  阿斯兰。līōń  阅读(333)  评论(0编辑  收藏  举报