JavaWeb(实训六)--第九章Servlet的高级特性

目录

1.Filter

1.1什么是Filter

[1.2Filter 相关API](#1.2Filter 相关API)

[1. 2.1Filter 接口](#1. 2.1Filter 接口)

[1.2.2 FilterConfig 接口](#1.2.2 FilterConfig 接口)

[1.2.3 FilterChain 接口](#1.2.3 FilterChain 接口)

[1.3Filter 的生命周期](#1.3Filter 的生命周期)

1.4实现Filter

[1.5Filter 映射](#1.5Filter 映射)

[1.5.1 使用通配符"*"拦截用户所有请求](#1.5.1 使用通配符“*”拦截用户所有请求)

[1.5.2 拦截不同访问方式的请求](#1.5.2 拦截不同访问方式的请求)

[1.6Filter 链](#1.6Filter 链)

[​编辑1.7任务:Filter 在Cookie自动登录中的使用](#编辑1.7任务:Filter 在Cookie自动登录中的使用)

[1. 编写User类](#1. 编写User类)

[2. 实现登录页面和首页](#2. 实现登录页面和首页)

[3. 创建Servlet](#3. 创建Servlet)

[4. 创建过滤器](#4. 创建过滤器)

[5. 运行项目,查看结果](#5. 运行项目,查看结果)

2.Listener

[2.1 Listener 概述](#2.1 Listener 概述)

[2.2 Listener 的API](#2.2 Listener 的API)

2.3任务:监听域对象的生命周期

[1. 创建监听器](#1. 创建监听器)

[package cn.itcast.chapter09.listener;import javax.servlet.*;import javax.servlet.annotation.WebListener;import javax.servlet.http.*;@WebListenerpublic 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对象被销毁了"); }}](#package cn.itcast.chapter09.listener;import javax.servlet.;import javax.servlet.annotation.WebListener;import javax.servlet.http.;@WebListenerpublic 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对象被销毁了"); }})

[2. 启动项目,查看ServletContext对象创建信息](#2. 启动项目,查看ServletContext对象创建信息)

[3. 关闭项目,查看ServletContext对象销毁信息](#3. 关闭项目,查看ServletContext对象销毁信息)

[4. 创建测试页面](#4. 创建测试页面)

[5. 设置监听超时信息](#5. 设置监听超时信息)

[6. 重启项目,查看结果](#6. 重启项目,查看结果)

动手实践:实现文件上传

[1. 创建项目,导入JAR包](#1. 创建项目,导入JAR包)

[2. 创建上传页面](#2. 创建上传页面)

[3. 创建Servlet](#3. 创建Servlet)

[4. 启动项目,查看运行结果](#4. 启动项目,查看运行结果)

动手实践:实现文件下载

[1. 创建下载页面](#1. 创建下载页面)

[2. 创建Servlet](#2. 创建Servlet)

[3. 创建下载目录及文件](#3. 创建下载目录及文件)

[4. 启动项目,查看结果](#4. 启动项目,查看结果)


1.Filter

1.1什么是Filter

在Servlet 高级特性中,Filter 被称为过滤器,它位于客户端和处理程序之间,能够对请求和响应进行检 查和修改,通常将请求拦截后进行一些通用的操作,例如,过滤敏感词汇、统一字符编码和实施安全控制等。 Filter 好比现实中的污水净化设备,专门用于过滤污水杂质。

当客户端对服务器资源发送请求时,服务器会根据过滤 规则进行检查,如果客户的请求满足过滤规则,则对客户请求进行拦截,对请求头和请求数据进行检查或修 改,并依次通过Filter 链,最后把过滤之后的请求交给处理程序。请求信息在过滤器链中可以被修改,也可 以根据客户端的请求条件不将请求发往处理程序。

Filter 除了可以实现拦截功能外,还可以提高程序的性能,在Web开发时,不同的Web资源中的过滤操 作可以放在同一个Filter中完成,这样可以不用多次编写重复的代码,从而提高了程序的性能。

1.2Filter 相关API

1. 2.1Filter 接口

1.2.2 FilterConfig 接口

1.2.3 FilterChain 接口

1.3Filter 的生命周期

  1. 创建阶段

2.执行阶段

3.销毁阶段

1.4实现Filter

(1)首先在IDEA中创建一个名为chapter09的Web项目,然后在该项目的src目录下创建一个名为 cn.itcast.chapter09.filter的包,最后在该包下创建一个名为MyServlet的Servlet类,用于在浏览器中输出"Hello MyServlet"。

复制代码
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,可以看 到浏览器成功访问到了MyServlet程序,运行效果如图:

(2)在cn.itcast.chapter09.filter包中创建一个名为MyFilter 的Filter类,用于拦截MyServlet程序。

复制代码
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.println("Hello MyFilter");
    }
    public void destroy() {
        // 过滤器对象在销毁时自动调用,释放资源
    }
}

第6行代码使用@WebFilter注解配置需要拦截的资源,@WebFilter注解的属性filterName 用于设置Filter 的名称,urlPatterns 属性用于匹配用户请求的 URL。例如"/MyServlet"表示过滤器 MyFilter 会拦截发送到"/MyServlet"资源的请求。这个URL还可 以使用通配符"*"表示。例如,"*.do"匹配所有以".do" 结尾的Servlet 路径。 在IDEA 中重新启动Tomcat 服务器,在浏览器的地 址栏中访问http://localhost:8080/chapter09/MyServlet,浏览 器窗口显示的结果如图所示:

1.5Filter 映射

1.5.1 使用通配符"*"拦截用户所有请求

如果想让过滤器拦截用户所有请求,可以使用通配符"*"实现。下面修改文件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.println("Hello MyFilter");
    }
    public void destroy() {
        // 过滤器对象在销毁时自动调用,释放资源
    }
}

1.5.2 拦截不同访问方式的请求

(1)在chapter09 项目的cn.itcast.chapter09.filter 包中,创建一个名为 ForwardServlet 的 Servlet 类,用于将 请求转发给first.jsp 页面。

复制代码
package cn.itcast.chapter09.filter;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;

@WebServlet(name = "ForwardServlet",urlPatterns = "/ForwardServlet")
public class ForwardServlet extends HttpServlet {
    public void doGet(HttpServletRequest request,
                      HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/first.jsp").forward(request, response);
    }

    public void doPost(HttpServletRequest request,
                       HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

(2)在chapter09 项目的 web目录下创建名称为first的JSP 页面,用于输出内容。

复制代码
<html>
<head></head>
<body>
first.jsp
</body>
</html>

(3)在cn.itcast.chapter09.filter 包中,创建一个过滤器 ForwardFilter.java,专门用于对 first.jsp 页面的请求 进行拦截。

复制代码
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() {
        // 过滤器对象在销毁时自动调用,释放资源
    }
}

(4)在IDEA中启动Tomcat服务器,在浏览器中输入地址http://localhost:8080/chapter09/ForwardServlet 访 问ForwardServlet,浏览器显示的结果如图9-4 所示:

(5)如果要拦截ForwardServlet 类通过forward( )方法转发到first.jsp 页面的请求,可以在@WebFilter 注解 中设置 dispatcherTypes 属性值为 FORWARD。修改文件 9-6 中第 5 行代码,在@WebFilter 注解中设置 dispatcherTypes 属性值为 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() {
        // 过滤器对象在销毁时自动调用,释放资源
    }
}

(6)在 IDEA 中重新启动 Tomcat 服务器,在浏览器的地址栏中再次输入地址 http://localhost:8080/ chapter09/ForwardServlet 访问 ForwardServlet,浏览器显示的结果如图 9-5 所示:


1.6Filter 链

(1)在chapter09项目的cn.itcast.chapter09.filter包中新建两个过滤器MyFilter01和MyFilter02,这两个过 滤器的实现分别如文件9-7和文件9-8所示:

MyFilter01.java

复制代码
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() {
        // 过滤器对象在销毁时自动调用,释放资源
    }
}

MyFilter02.java

复制代码
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() {
        // 过滤器对象在销毁时自动调用,释放资源
    }
}

(2)在IDEA中重新启动Tomcat服务器,在浏览器地址栏 中输入 http://localhost:8080/chapter09/MyServlet 访问 MyServlet 类,浏览器窗口中显示的结果如图所示:

1.7任务:Filter 在Cookie自动登录中的使用

1. 编写User类

在chapter09 项目的src 目录下创建cn.itcast.chapter09.entity 包,在该包中新建 User 类,用于封装用户的 信息。User类的实现如文件9-9所示:

User.java

复制代码
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;
    }
}

2. 实现登录页面和首页

(1)在chapter09项目的web目录中创建名称为login的JSP文件,在该文件中编写一个用户登录表单。 用户登录表单需要填写用户名和密码,以及用户自动登录的时间。login.jsp页面的实现如文件9-10所示:

login.jsp

复制代码
<%@ 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>&nbsp;&nbsp;
                <input type="text" name="username" />${errerMsg }</td>
        </tr>
        <tr>
            <td height="30" align="center">密&nbsp; 码:</td>
            <td>&nbsp;&nbsp;
                <input type="password" name="password">
        </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="登录" />
                &nbsp;&nbsp;&nbsp;&nbsp;
                <input type="reset" value="重置" />
            </td>
        </tr>
    </table>
</form>
</body>
<html>

(2)在chapter09项目的web根目录中创建名称为index的JSP文件用于显示登录的用户信息,如果没有 用户登录,在index.jsp页面中显示一个用户登录的超链接,如果用户已经登录,在index.jsp页面中显示登录 的用户名,以及一个注销的超链接。index.jsp页面的实现如文件9-11所示:

index.jsp

复制代码
<%@ 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>

3. 创建Servlet

(1)编写LoginServlet类

在chapter09项目的cn.itcast.chapter09.filter包中,编写LoginServlet类,用于处理用户的登录请求,如果 输入的用户名和密码正确,则发送一个用户自动登录的Cookie,并跳转到首页,否则提示输入的用户名或密 码错误,并跳转至登录页面(login.jsp),让用户重新登录。LoginServlet类的实现如文件9-12所示:

LoginServlet.java

复制代码
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);
    }
}

(2)编写LogoutServlet类

LogoutServlet.java

复制代码
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.setMaxAge(0);
        response.addCookie(cookie);
        response.sendRedirect(request.getContextPath()+"/index.jsp");
    }
    public void doPost(HttpServletRequest request,
                       HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

4. 创建过滤器

AutoLoginFilter.java

复制代码
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;
        // 获得一个名为 autologin 的cookie
        Cookie[] cookies=request.getCookies();
        String autologin = null;
        for (int i = 0;cookies != null && i < cookies.length; i++) {
            if ("autologin".equals(cookies[i].getName())) {
                // 找到了指定的cookie
                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() {
    }
}

5. 运行项目,查看结果

(1)访问login.jsp页面 重启服务器,打开浏览器,在地址栏中输入http://localhost:8080/chapter09/login.jsp,浏览器窗口中会显示 一个用户登录的表单,如图所示:

(2)实现用户登录 在图9-8所示的登录表单中输入用户名"itcast"、密码"123456",并选择用户自动登录的时间,单击"登 录"按钮,便可完成用户自动登录。单击"登录"按钮之后,浏览器窗口会显示登录的用户名,如图所示:

(3)注销用户

单击图中的"注销"超链接,就可以注销当前的用户,注销之后浏览器显示的页面如图所示。

2.Listener

2.1 Listener 概述

在 Web 程序开发中,经常需要对某些事件进行监听,以便及时做出处理,例如监听鼠标单击事件、监 听键盘按下事件等。为此,Servlet 提供了监听器(Listener),专门用于监听 Servlet 事件。Listener 在监听过 程中会涉及几个重要的组成部分,具体如下:

(1)事件:用户的一个操作,例如单击一个按钮、调用一个方法、创建一个对象等。

(2)事件源:产生事件的对象。

(3)事件监听器:负责监听发生在事件源上的事件。

(4)事件处理器:监听器的成员方法,当事件发生的时候会触发对应的处理器(成员方法)

当用户执行一个操作触发事件源上的事件时,该事件会被事件监听器监听到,当监听器监听到事件发生 时,相应的事件处理器就会对发生的事件进行处理。

事件监听器的工作过程可分为以下几个步骤:

(1)将监听器绑定到事件源,也就是注册监听器。

(2)监听器监听到事件发生时,会调用监听器的成员方法,将事件对象传递给事件处理器,即触发事件 处理器。

(3)事件处理器通过事件对象获得事件源,并对事件源进行处理。

2.2 Listener 的API

2.3任务:监听域对象的生命周期

1. 创建监听器

在chapter09 项目的src 目录下创建一个cn.itcast.chapter09.listener 包,在该包中新建一个 MyListener 类, 用于实现ServletContextListener、HttpSessionListener和ServletRequestListener 三个监听器接口,并实现这些接 口中的所有方法:

MyListener.java

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对象被销毁了");
}
}

2. 启动项目,查看ServletContext对象创建信息

3. 关闭项目,查看ServletContext对象销毁信息

4. 创建测试页面

为了查看HttpSessionListener 和 ServletRequestListener 的运行效果,在 chapter09 项目的 web 目录中编写 一个名称为myjsp的JSP文件,具体代码如文件所示:

myjsp.jsp

复制代码
<%@ 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>

5. 设置监听超时信息

6. 重启项目,查看结果

重新启动项目chapter09,再打开浏览器,在地址栏中输入 http://localhost:8080/chapter09/myjsp.jsp,访问 myjsp.jsp 页面,控制台窗口中显示的结果如图所示:

关闭访问myjsp.jsp 页面的浏览器窗口或保持浏览器窗口不刷新,与之对应的HttpSession 对象将在2 分 钟之后被销毁,控制台窗口显示的结果如图所示:

动手实践:实现文件上传

1. 创建项目,导入JAR包

2. 创建上传页面

form.jsp

复制代码
<%@ 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>
<form action="UploadServlet" method="post"
      enctype="multipart/form-data">
    <table width="600px">
        <tr>
            <td>上传者</td>
            <td><input type="text" name="name" /></td>
        </tr>
        <tr>
            <td>上传文件</td>
            <td><input type="file" name="myfile" /></td>
        </tr>
        <tr>
            <td colspan="2"><input type="submit" value="上传" /></td>
        </tr>
    </table>
</form>
</body>
</html>

3. 创建Servlet

UploadServlet.java

复制代码
package cn.itcast.fileupload;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
//上传文件的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("D:\\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);
    }
}

4. 启动项目,查看运行结果

在IDEA中启动Tomcat服务器,通过浏览器访问地址http://localhost:8080/chapter09/form.jsp,浏览器显示 的结果如图所示:

填写上传者信息"itcast",并选择需要上传的文件,如图所示:

单击"上传"按钮上传文件,文件成功上传后,浏览器的界面如图所示:

至此,将文件上传到服务器的功能已经实现。进入项目发布目录,可以看到刚才上传的文件,如图所示:

动手实践:实现文件下载

1. 创建下载页面

download.jsp

复制代码
<%@ 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>

2. 创建Servlet

DownloadServlet.java

复制代码
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);
    }
}

3. 创建下载目录及文件

在chapter09项目的web目录下创建一个名称为download的文件夹,在该文件夹中放置一个名称为"1.png" 的图片文件。

4. 启动项目,查看结果

在IDEA中启动Tomcat服务器,通过浏览器访问地址http://localhost:8080/chapter09/download.jsp,浏览器 显示的界面如图所示:

在图中单击"文件下载"链接,浏览器显示的结果如图所示:

相关推荐
武子康2 分钟前
大数据-230 离线数仓 - ODS层的构建 Hive处理 UDF 与 SerDe 处理 与 当前总结
java·大数据·数据仓库·hive·hadoop·sql·hdfs
武子康4 分钟前
大数据-231 离线数仓 - DWS 层、ADS 层的创建 Hive 执行脚本
java·大数据·数据仓库·hive·hadoop·mysql
极客代码5 分钟前
【Python TensorFlow】进阶指南(续篇三)
开发语言·人工智能·python·深度学习·tensorflow
苏-言10 分钟前
Spring IOC实战指南:从零到一的构建过程
java·数据库·spring
土豆湿10 分钟前
拥抱极简主义前端开发:NoCss.js 引领无 CSS 编程潮流
开发语言·javascript·css
界面开发小八哥17 分钟前
更高效的Java 23开发,IntelliJ IDEA助力全面升级
java·开发语言·ide·intellij-idea·开发工具
草莓base31 分钟前
【手写一个spring】spring源码的简单实现--容器启动
java·后端·spring
Allen Bright44 分钟前
maven概述
java·maven
qystca1 小时前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
编程重生之路1 小时前
Springboot启动异常 错误: 找不到或无法加载主类 xxx.Application异常
java·spring boot·后端