学习内容:
了解Filter及其相关API。熟悉Filter的生命周期。掌握Filter的实现。掌握Filter的映射与过滤器链的使用。熟悉Listener及相关API。熟悉Servlet 3.0新特性。掌握文件上传和下载。
- 学习重点:掌握Filter的实现。
- 学习难点:掌握Filter的映射与过滤器链的使用
Filter包含三个接口:Filter接口、FilterConfig接口和FilterChain接口。
- Filter接口:是编写过滤器必须要实现的接口,该接口定义了init()、doFilter()、destory()三个方法。
- FilterConfig接口:用于封装Filter的配置信息,在Filter初始化时,服务器将FilterConfig对象作为参数传递给Filter对象的初始化方法。
- FilterChain接口:doFilter()方法用于调用Filter链中的下一个过滤器,如果这个过滤器就是链上的最后一个过滤器,则将请求提交给处理程序或将响应发送给客户端。
Filter的生命周期:指一个Filter对象从创建到执行再到销毁的过程。
实训任务:
实现Filter
在IDEA 中创建一个名为chapter09 的Web 项目,在该项目的src 目录下创建一个名为cn.itcast.chapter09.filter 的包,在该包下创建一个名为MyServlet 的Servlet 类如文件9-1(p186)。
package cn.itcast.chapter09.filter; import java.io.*; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; @WebServlet(name="MyServlet",urlPatterns = "/MyServlet") public class MyServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("Hello MyServlet"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
在IDEA 中使用Tomcat 启动chapter09 项目,在浏览器的地址栏中访问http://localhost:8080/chapter09 /MyServlet,在浏览器显示如图9-2 所示(p186)。
在cn.itcast.chapter09.filter 包中创建一个名为MyFilter的Filter 类如文件9-2(p186)。
在IDEA 中重新启动Tomcat 服务器,在浏览器的地址栏中访问
package cn.itcast.chapter09.filter; import java.io.*; import javax.servlet.Filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; @WebFilter(filterName = "MyFilter",urlPatterns = "/MyServlet") //@WebFilter(filterName = "MyFilter",urlPatterns = "/*")//拦截用户所以请求 public class MyFilter implements Filter { public void init(FilterConfig fConfig) throws ServletException { // 过滤器对象在初始化时调用,可以配置一些初始化参数 } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用 PrintWriter out = response.getWriter(); out.write("Hello MyFilter"); } public void destroy() { // 过滤器对象在销毁时自动调用,释放资源 } }
http://localhost:8080/chapter09/MyServlet,浏览器窗口显示的结果如图9-3 所示(p187)。
Filter映射
下面修改文件9-2,如文件9-3 所示。@WebFilter 注解的urlPatterns 属性值为“/*”,表示用户访问chapter09 项目的任何路径都会被MyFilter 类拦截。
package cn.itcast.chapter09.filter; import java.io.*; import javax.servlet.Filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; //@WebFilter(filterName = "MyFilter",urlPatterns = "/MyServlet") @WebFilter(filterName = "MyFilter",urlPatterns = "/*")//拦截用户所以请求 public class MyFilter implements Filter { public void init(FilterConfig fConfig) throws ServletException { // 过滤器对象在初始化时调用,可以配置一些初始化参数 } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用 PrintWriter out = response.getWriter(); out.write("Hello MyFilter"); } public void destroy() { // 过滤器对象在销毁时自动调用,释放资源 } }
在IDEA 中重新启动Tomcat 服务器,在浏览器的地址栏中访问http://localhost:8080/chapter09/My,浏览器窗口显示的结果如图9-3 所示(p187)。
在chapter09 项目的cn.itcast.chapter09.filter 包中,创建一个名为ForwardServlet 的Servlet 类,如文件9-4 所示。在chapter09 项目的web 目录下创建名称为first 的JSP 页面,如文件9-5 所示。在cn.itcast.chapter09.filter 包中,创建一个过滤器ForwardFilter.java,如文件9-6 所示。
package cn.itcast.chapter09.filter; import java.io.*; import javax.servlet.*; import javax.servlet.annotation.WebFilter; /*@WebFilter(filterName = "ForwardFilter",urlPatterns = "/first.jsp")*/ @WebFilter(filterName = "ForwardFilter",urlPatterns = "/first.jsp") public class ForwardFilter implements Filter { public void init(FilterConfig fConfig) throws ServletException { // 过滤器对象在初始化时调用,可以配置一些初始化参数 } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用 PrintWriter out = response.getWriter(); out.write("Hello FilterTest"); } public void destroy() { // 过滤器对象在销毁时自动调用,释放资源 } }
运行前,需要将MyFilter文件代码改回
@WebFilter(filterName = "MyFilter",urlPatterns = "/MyServlet") //@WebFilter(filterName = "MyFilter",urlPatterns = "/*")//拦截用户所以请求
在IDEA 中启动Tomcat 服务器,在浏览器中输入地址http://localhost:8080/chapter09/ForwardServlet,浏览器显示的结果如图9-4 所示(p189)。
修改文件9-6 中第5 行代码,在@WebFilter 注解中设置
dispatcherTypes 属性值为FORWARD,具体代码如下。@WebFilter(filterName = "ForwardFilter",urlPatterns = "/first.jsp",dispatcherTypes = DispatcherType.FORWARD)
package cn.itcast.chapter09.filter; import java.io.*; import javax.servlet.*; import javax.servlet.annotation.WebFilter; /*@WebFilter(filterName = "ForwardFilter",urlPatterns = "/first.jsp")*/ @WebFilter(filterName = "ForwardFilter",urlPatterns = "/first.jsp", dispatcherTypes = DispatcherType.FORWARD) public class ForwardFilter implements Filter { public void init(FilterConfig fConfig) throws ServletException { // 过滤器对象在初始化时调用,可以配置一些初始化参数 } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用 PrintWriter out = response.getWriter(); out.write("Hello FilterTest"); } public void destroy() { // 过滤器对象在销毁时自动调用,释放资源 } }
在IDEA 中重新启动Tomcat 服务器,在浏览器的地址栏中再次输入地址http://localhost:8080/chapter09/ForwardServlet 访问ForwardServlet,浏览器显示的结果如图9-5 所示(p189)。
Filter 链
在chapter09 项目的cn.itcast.chapter09.filter 包中新建两个过滤器MyFilter01 和MyFilter02,这两个过滤器的实现分别如文件9-7 和文件9-8 所示(p190)。
package cn.itcast.chapter09.filter; import java.io.*; import javax.servlet.*; import javax.servlet.annotation.WebFilter; @WebFilter(filterName = "MyFilter01",urlPatterns = "/MyServlet") public class MyFilter01 implements Filter { public void init(FilterConfig fConfig) throws ServletException { // 过滤器对象在初始化时调用,可以配置一些初始化参数 } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用 PrintWriter out = response.getWriter(); out.println("Hello MyFilter01"); chain.doFilter(request, response); } public void destroy() { // 过滤器对象在销毁时自动调用,释放资源 } }
package cn.itcast.chapter09.filter; import java.io.*; import javax.servlet.Filter; import javax.servlet.*; import javax.servlet.annotation.WebFilter; @WebFilter(filterName = "MyFilter02",urlPatterns = "/MyServlet") public class MyFilter02 implements Filter { public void init(FilterConfig fConfig) throws ServletException { // 过滤器对象在初始化时调用,可以配置一些初始化参数 } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 用于拦截用户的请求,如果和当前过滤器的拦截路径匹配,该方法会被调用 PrintWriter out = response.getWriter(); out.println("MyFilter02 Before"); chain.doFilter(request, response); out.println("MyFilter02 After"); } public void destroy() { // 过滤器对象在销毁时自动调用,释放资源 } }
在IDEA 中重新启动Tomcat 服务器,在浏览器地址栏中输入http://localhost:8080/chapter09/MyServlet,浏览器窗口中显示的结果如图9-7 所示(p191)。
Filter 在Cookie 自动登录中的使用
在chapter09 项目的src 目录下创建cn.itcast.chapter09.entity 包,在该包中新建User 类,用于封装用户的信息。User 类的实现如文件9-9 所示(p191)。
package cn.itcast.chapter09.entity; public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
在chapter09 项目的web 目录中创建名称为login 的JSP 文件,login.jsp 页面的实现如文件9-10(p192)。
<%@ page language="java" contentType="text/html; charset=utf-8" import="java.util.*"%> <html> <head></head> <center><h3>用户登录</h3></center> <body style="text-align: center;"> <form action="${pageContext.request.contextPath }/LoginServlet" method="post"> <table border="1" width="600px" cellpadding="0" cellspacing="0" align="center" > <tr> <td height="30" align="center">用户名:</td> <td> <input type="text" name="username" />${errerMsg }</td> </tr> <tr> <td height="30" align="center">密 码:</td> <td> <input type="password" name="password" /></td> </tr> <tr> <td height="35" align="center">自动登录时间</td> <td><input type="radio" name="autologin" value="${60*60*24*31}"/>一个月 <input type="radio" name="autologin" value="${60*60*24*31*3}"/>三个月 <input type="radio" name="autologin" value="${60*60*24*31*6}"/>半年 <input type="radio" name="autologin" value="${60*60*24*31*12}"/>一年 </td> </tr> <tr> <td height="30" colspan="2" align="center"> <input type="submit" value="登录" /> <input type="reset" value="重置" /> </td> </tr> </table> </form> </body> <html>
在chapter09 项目的web 根目录中创建名称为index 的JSP 文件,如9-11所示(p193)。
<%@ page language="java" contentType="text/html; charset=utf-8" import="java.util.*" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <html> <head> <title>显示登录的用户信息</title> </head> <body> <br /> <center> <h3>欢迎光临</h3> </center> <br /> <br /> <c:choose> <c:when test="${sessionScope.user==null }"> <a href="${pageContext.request.contextPath }/login.jsp">用户登录</a> </c:when> <c:otherwise> 欢迎你,${sessionScope.user.username }! <a href="${pageContext.request.contextPath }/LogoutServlet">注销</a> </c:otherwise> </c:choose> <hr /> </body> </html>
在chapter09 项目的cn.itcast.chapter09.filter 包中,编写LoginServlet 类, 如文件9-12 所示(p193)。
package cn.itcast.chapter09.filter; import java.io.IOException; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; import cn.itcast.chapter09.entity.User; @WebServlet(name = "LoginServlet",urlPatterns = "/LoginServlet") public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 获得用户名和密码 String username = request.getParameter("username"); String password = request.getParameter("password"); // 检查用户名和密码 if ("itcast".equals(username) && "123456".equals(password)) { // 登录成功 // 将用户状态 user 对象存入 session域 User user = new User(); user.setUsername(username); user.setPassword(password); request.getSession().setAttribute("user", user); // 发送自动登录的cookie String autoLogin = request.getParameter("autologin"); if (autoLogin != null) { // 注意 cookie 中的密码要加密 Cookie cookie = new Cookie("autologin", username + "-" + password); cookie.setMaxAge(Integer.parseInt(autoLogin)); cookie.setPath(request.getContextPath()); response.addCookie(cookie); } // 跳转至首页 response.sendRedirect(request.getContextPath()+"/index.jsp"); } else { request.setAttribute("errerMsg", "用户名或密码错误"); request.getRequestDispatcher("/login.jsp") .forward(request,response); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
在chapter09 项目的cn.itcast.chapter09.filter 包中,编写LogoutServlet 类,如文件9-13 所示(p194)
package cn.itcast.chapter09.filter; import java.io.IOException; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; @WebServlet(name = "LogoutServlet",urlPatterns = "/LogoutServlet") public class LogoutServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 用户注销 request.getSession().removeAttribute("user"); // 从客户端删除自动登录的cookie Cookie cookie = new Cookie("autologin", "msg"); cookie.setPath(request.getContextPath()); cookie.setMaxAge(0); response.addCookie(cookie); response.sendRedirect(request.getContextPath()+"/index.jsp"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
在chapter09 项目的cn.itcast.chapter09.filter 包中,编写AutoLoginFilter 类,如文件9-14 所示(p194)。
package cn.itcast.chapter09.filter; import java.io.IOException; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.*; import cn.itcast.chapter09.entity.User; @WebFilter(filterName = "AutoLoginFilter",urlPatterns = "/*") public class AutoLoginFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest req, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; Cookie[] cookies = request.getCookies(); String autologin = null; for(int i = 0; cookies != null && i < cookies.length; ++i) { if ("autologin".equals(cookies[i].getName())) { autologin = cookies[i].getValue(); break; } } if (autologin != null) { // 做自动登录 String[] parts = autologin.split("-"); String username = parts[0]; String password = parts[1]; // 检查用户名和密码 if ("itcast".equals(username)&& ("123456").equals(password)) { // 登录成功,将用户状态 user 对象存入 session域 User user = new User(); user.setUsername(username); user.setPassword(password); request.getSession().setAttribute("user", user); } } // 放行 chain.doFilter(request, response); } public void destroy() { } }
重启服务器,打开浏览器,在地址栏中输入http://localhost:8080/chapter09/login.jsp,浏览器窗口显示如图9-8 、9-9、9-10(p195-196)
Listener
在chapter09 项目的src 目录下创建一个cn.itcast.chapter09.listener 包,在该包中新建一个MyListener 类,如文件9-15 所示。
package cn.itcast.chapter09.listener; import javax.servlet.*; import javax.servlet.annotation.WebListener; import javax.servlet.http.*; @WebListener public class MyListener implements ServletContextListener, HttpSessionListener,ServletRequestListener { public void contextInitialized(ServletContextEvent arg0) { System.out.println("ServletContext对象被创建了"); } public void contextDestroyed(ServletContextEvent arg0) { System.out.println("ServletContext对象被销毁了"); } public void requestInitialized(ServletRequestEvent arg0) { System.out.println("ServletRequest对象被创建了"); } public void requestDestroyed(ServletRequestEvent arg0) { System.out.println("ServletRequest对象被销毁了"); } public void sessionCreated(HttpSessionEvent arg0) { System.out.println("HttpSession对象被创建了"); } public void sessionDestroyed(HttpSessionEvent arg0) { System.out.println("HttpSession对象被销毁了"); } }
在IDEA 中启动Tomcat 服务器,控制台窗口显示的结果如图9-11 所示(p198)。
关闭Web 服务器之后,控制台窗口显示的结果如图9-12 所示(p198)。
在chapter09 项目的web 目录中编写一个名称为myjsp 的JSP 文件,如文件9-16 所示(p198)。
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <html> <head> <title>this is MyJsp.jsp page</title> </head> <body> 这是一个测试监听器的页面 </body> </html>
在chapter09 项目的web.xml 文件中设置session的超时时间为2分钟,具体代码如下。
<session-config> <session-timeout>2</session-timeout> </session-config>
重新启动项目chapter09,再打开浏览器,在地址栏中输入http://localhost:8080/chapter09/myjsp.jsp,控制台窗口中显示的结果如图9-13、9-14所示(p199)。
实现文件上传
在项目chapter09 的WEB-INF 下新建lib 目录,在lib 目录下导入JAR 包commons-fileupload-1.3.3.jar 和commons-io-2.7.jar。
在chapter09 项目的web 目录下创建一个名称为form 的JSP文件,如文件9-17 所示(p204)。
在chapter09 项目的src 目录下创建一个名称为cn.itcast.fileupload 的包,在该包中新建一个名称为UploadServlet 的类,如文件9-18 所示(p205)。
//上传文件的Servlet类 @WebServlet(name = "UploadServlet",urlPatterns = "/UploadServlet") //该注解用于标注文件上传的Servlet @MultipartConfig public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { try { //设置ContentType字段值 response.setContentType("text/html;charset=utf-8"); // 创建DiskFileItemFactory工厂对象 DiskFileItemFactory factory = new DiskFileItemFactory(); //设置文件缓存目录,如果该目录不存在则新创建一个 File f = new File("E:\\TempFolder"); if (!f.exists()) { f.mkdirs(); } // 设置文件的缓存路径 factory.setRepository(f); // 创建 ServletFileUpload对象 ServletFileUpload fileupload = new ServletFileUpload(factory); //设置字符编码 fileupload.setHeaderEncoding("utf-8"); // 解析 request,得到上传文件的FileItem对象 List<FileItem> fileitems = fileupload.parseRequest(request); //获取字符流 PrintWriter writer = response.getWriter(); // 遍历集合 for (FileItem fileitem : fileitems) { // 判断是否为普通字段 if (fileitem.isFormField()) { // 获得字段名和字段值 String name = fileitem.getFieldName(); if(name.equals("name")){ //如果文件不为空,将其保存在value中 if(!fileitem.getString().equals("")){ String value = fileitem.getString("utf-8"); writer.print("上传者:" + value + "<br />"); } } } else { // 获取上传的文件名 String filename = fileitem.getName(); //处理上传文件 if(filename != null && !filename.equals("")){ writer.print("上传的文件名称是:" + filename + "<br />"); // 截取出文件名 filename = filename.substring(filename.lastIndexOf("\\") + 1); // 文件名需要唯一 filename = UUID.randomUUID().toString() + "_" + filename; // 在服务器创建同名文件 String webPath = "/upload/"; //将服务器中文件夹路径与文件名组合成完整的服务器端路径 String filepath = getServletContext() .getRealPath(webPath + filename); // 创建文件 File file = new File(filepath); file.getParentFile().mkdirs(); file.createNewFile(); // 获得上传文件流 InputStream in = fileitem.getInputStream(); // 使用FileOutputStream打开服务器端的上传文件 FileOutputStream out = new FileOutputStream(file); // 流的拷贝 byte[] buffer = new byte[1024];//每次读取1个字节 int len; //开始读取上传文件的字节,并将其输出到服务端的上传文件输出流中 while ((len = in.read(buffer)) > 0) out.write(buffer, 0, len); // 关闭流 in.close(); out.close(); // 删除临时文件 fileitem.delete(); writer.print("上传文件成功!<br />"); } } } } catch (Exception e) { throw new RuntimeException(e); } } public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { doGet(request, response); } }
在IDEA 中启动Tomcat 服务器,通过浏览器访问地址http://localhost:8080/chapter09/form.jsp,浏览器显示的结果如图9-22、9-23、9-24、9-25 所示(p206-207)。
实现文件下载
在chapter09 项目的web 目录下创建名称为download 的JSP 文件,如文件9-19 所示(p207)。
<%@ page language="java" contentType="text/html; charset=UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>文件下载</title> </head> <body> <a href= "http://localhost:8080/chapter09/DownloadServlet?filename=1.png"> 文件下载</a> </body> </html>
在chapter09 项目的src 目录下新建cn.itcast.fileupload 包,在cn.itcast.fileupload 包中创建DownloadServlet类,如文件9-20 所示(p208)。
package cn.itcast.fileupload; import java.io.*; import javax.servlet.*; import javax.servlet.annotation.WebServlet; import javax.servlet.http.*; @WebServlet(name = "DownloadServlet",urlPatterns = "/DownloadServlet") public class DownloadServlet extends HttpServlet { private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //设置ContentType字段值 response.setContentType("text/html;charset=utf-8"); //获取所要下载的文件名称 String filename = request.getParameter("filename"); //下载文件所在目录 String folder = "/download/"; // 通知浏览器以下载的方式打开 response.addHeader("Content-Type", "application/octet-stream"); response.addHeader("Content-Disposition", "attachment;filename="+filename); folder=folder+filename; // 通过文件流读取文件 InputStream in = getServletContext().getResourceAsStream(folder); // 获取response对象的输出流 OutputStream out = response.getOutputStream(); byte[] buffer = new byte[1024]; int len; //循环取出流中的数据 while ((len = in.read(buffer)) != -1) { out.write(buffer, 0, len); } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
在chapter09项目的web目录下创建一个名称为download的文件夹,在该文件夹中放置一个名称为“1.png”的图片文件。
在IDEA 中启动Tomcat 服务器,通过浏览器访问地址http://localhost:8080/chapter09/download.jsp,浏览器显示的界面如图9-26 所示(p209)。
在图9-26 中单击“文件下载”链接,浏览器显示的结果如图9-27 所示(p209)。
版权归原作者 玉茗685 所有, 如有侵权,请联系我们删除。