目录:(点击红色方框展开子目录)
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 }
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 }
<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 }
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 }
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>
<body> <h1><center>这是用户主页,没有登陆的用户是不能直接访问该页的</center></h1> </body>
<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 }
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); } }
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 } }
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; } }
${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>
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 }
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 }
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; } }
关于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新特性中学习