Tomcat的使用及Servlet的实践

  • Tomcat的运行原理
  • Tomcat架构图
  • Tomcat处理请求过程
  • Select的生命周期
  • Select处理请求的原理
  • Select的作用
  • IDEA内如何添加tomcat,使用servlet
  • Idea 中的 web 项目部署
  • servlet的操作
    • 正常启动Tomcat显示index.jsp内的内容
    • servlet使用doget方式获取请求信息
    • Servlet使用doPost方式获取请求数据
    • servlet获取复选框数据
    • 获取所有提交数据的key
    • servlet使用Map结构获取提交的数据
    • servlet设置请求编码
    • servlet的资源访问方式
    • 获取请求头信息
      • 案例
    • HttpServletRequest对象的生命周期
    • 设置字符型响应
    • 设置字节型响应
    • 设置响应的编码方式
    • 在响应中添加附加信息
      • 重定向响应
      • 重定向响应案例
    • Servlet实现文件下载
    • 解决文件名中文乱码问题
    • ServletContext对象
      • 介绍
      • ServletContext 对象的作用
        • 相对路径转绝对路径
        • 获取容器得到附加信息
        • 获取 web.xml 文件中的信息
        • 全局容器
      • servletContext对象的生命周期
    • ServletConfig对象
      • 案例:
    • Cookie对象与HttpSession对象
      • Cookie对象
        • 特点:
        • 怎么用:
      • 状态cookie和持久化cookie
      • 通过 Cookie 实现客户端与服务端会话的维持
    • cookie小结
    • HttpSession对象
      • HttpSession创建的创建
      • 获取HttpSession内的数据
      • 通过session对象 判断运行的浏览器
      • 通过 HttpSession 实现客户端与服务端会话的维持
    • HttpSession的生命周期
    • HttpSession 与 Cookie 的区别:
  • 自启动Servlet
    • 什么是自启动Servlet
    • 如何创建
    • 通过自启动Servlet实现配置信息的获取
    • Servlet线程安全问题
    • Servlet的URL匹配规则
      • 精确匹配
      • 扩展名匹配
      • 路径匹配
      • 任意匹配
      • 优先顺序
    • URL映射方式
    • 基于注解式开发 Servlet
      • @WebInitParam属性
    • Servlet通过Part对象实现文件上传
    • Filter 过滤器
      • 作用
    • 使用filter
      • 创建filter对象
    • 在 Filter 中设置请求编码
    • FilterConfig 对象的使用
    • Filter执行顺序
    • 基于注解时开发Filter
    • 监听器
      • 监听器分类
    • ServletContext 监听器
      • ServletContext 对象的生命周期监听器
      • ServletContext 对象的属性操作监听器
    • HttpSession 对象的生命周期监听器
    • HttpSession 对象的属性操作监听器
    • HttpServletRequest 监听器
      • HttpServletRequest 对象的生命周期监听器
      • HttpServletRequest 对象的属性操作监听器
    • 基于注解式开发监听器

Tomcat的运行原理

Tomcat的使用及Servlet的实践_第1张图片

Tomcat架构图

Tomcat的使用及Servlet的实践_第2张图片

Tomcat处理请求过程

Tomcat的使用及Servlet的实践_第3张图片
处理过程:

1、用户访问 localhost:8080/test/index.jsp,请求被发送到 Tomcat,被监听 8080 端口并 处理 HTTP/1.1 协议的 Connector 获得。 

2、Connector 把该请求交给它所在的 Service 的 Engine 来处理,并等待 Engine 的回应。 

3、Engine 获得请求 localhost/test/index.jsp,匹配所有的虚拟主机 Host。
 
4、Engine 匹配到名为 localhost 的 Host 虚拟主机来处理/test/index.jsp 请求(即使匹配 不到会请求交给默认 Host 处理),Host 会根据/test 匹配它所拥有的所有的 Context。 
5、匹配到的 Context 获得请求/index.jsp。 

6、构造 HttpServletRequest 对象和 HttpServletResponse 对象,作为参数调用 JspServlet 的 doGet()或 doPost().执行业务逻辑、数据存储等程序。 

7、Context 把执行完之后的结果通过 HttpServletResponse 对象返回给 Host。 

8、Host 把 HttpServletResponse 返回给 Engine。 

9、Engine 把 HttpServletResponse 对象返回 Connector。 

10、Connector 把 HttpServletResponse 对象返回给客户 Browser。

Select的生命周期

Tomcat的使用及Servlet的实践_第4张图片

Select处理请求的原理

当浏览器基于 get 方式请求我们创建 Servlet 时,我们自定义的 Servlet 中的 doGet 方法 会被执行。doGet 方法能够被执行并处理 get 请求的原因是,容器在启动时会解析 web 工程 中 WEB-INF 目录中的 web.xml 文件,在该文件中我们配置了 Servlet 与 URI 的绑定,容器通 过对请求的解析可以获取请求资源的 URI,然后找到与该 URI 绑定的 Servlet 并做实例化处理 (注意:只实例化一次,如果在缓存中能够找到这个 Servlet 就不会再做次实例化处理)。在实 例化时会使用 Servlet 接口类型作为引用类型的定义,并调用一次 init 方法,由于 HttpServlet 中重写了该方法所以最终执行的是 HttpServlet 中 init 方法(HttpServlet 中的 Init 方法是一个空 的方法体),然后在新的线程中调用 service 方法。由于在 HttpServlet 中重写了 Service 方法 所以最终执行的是 HttpServlet 中的 service 方法。在 service 方法中通过 request.getMethod() 获取到请求方式进行判断如果是 Get 方式请求就执行 doGet 方法,如果是 POST 请求就执行 doPost 方法。如果是基于 GET 方式提交的,并且在我们自定义的 Servlet 中又重写了 HttpServlet 中的 doGet 方法,那么最终会根据 Java 的多态特性转而执行我们自定义的 Servlet 中的 doGet 方法。

Select的作用

Tomcat的使用及Servlet的实践_第5张图片

IDEA内如何添加tomcat,使用servlet

File->New Project,
Tomcat的使用及Servlet的实践_第6张图片
创建web工程,选择Project JDK为1.8
Tomcat的使用及Servlet的实践_第7张图片
在src内创建com.bjsxt.servlet文件
Tomcat的使用及Servlet的实践_第8张图片
为项目添加 servlet-api.jar
Tomcat的使用及Servlet的实践_第9张图片
Tomcat的使用及Servlet的实践_第10张图片
Tomcat的使用及Servlet的实践_第11张图片
点击apply,点击ok
Tomcat的使用及Servlet的实践_第12张图片
在idea内配置Tomcat
Tomcat的使用及Servlet的实践_第13张图片
Tomcat的使用及Servlet的实践_第14张图片
修改项目的访问路径,定位到tomcat文件下的
apache-tomcat-8.0.21\webapps\ROOT文件
Tomcat的使用及Servlet的实践_第15张图片
将 web 项目部署到 Tomcat 的 webapps 中
Tomcat的使用及Servlet的实践_第16张图片
在 tomcat 的 webapps 中创建一个目录demo,用于存放web项目

指定输出 artifacts 的目录为 Tomcat 的 webapps 中的 demo 目录
Tomcat的使用及Servlet的实践_第17张图片
启动 Tomcat,查看 demo 目录中的内容
Tomcat的使用及Servlet的实践_第18张图片

Idea 中的 web 项目部署

在 Idea 中默认的并不会把 web 项目真正的部署到 Tomcat 的 webapps 目录中,而是通过为每个 web 项目创建一个独立的 Tomcat 副本并在 Tomcat 副本中通过的 Tomcat 的 Context 组件完成项目的目录指定,在 Context 组件的 docBase 属性中会指定 Idea 对 web 项目编译后 的目录 out/artifacts/…。

servlet的操作

正常启动Tomcat显示index.jsp内的内容

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  输出
  </body>
</html>

Tomcat的使用及Servlet的实践_第19张图片

servlet使用doget方式获取请求信息

用到的文件
Tomcat的使用及Servlet的实践_第20张图片
在servlet.class内

package com.bjsxt;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class servlet extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        ServletContext servletContext = this.getServletContext();
        // req.getRequestURL() --- 返回客户端浏览器发出请求时的完整的URL
        StringBuffer requestURL = req.getRequestURL();
        // req.getRequestURI() --- 返回请求行中指定资源部分。
        String requestURI = req.getRequestURI();
        // req.getRemoteAddr() --- 返回发出请求的客户机的 IP 地址
        String remoteAddr = req.getRemoteAddr();
        // resp.getWriter() --- 返回 WEB 服务器的 IP 地址
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("URL:"+requestURL+"
"
); out.println("URI:"+requestURI+"
"
); out.println("RemoteAddr:"+remoteAddr+"
"
); String value1 = (String)servletContext.getAttribute("key1"); String value2 = (String)servletContext.getAttribute("key2"); out.println("Value1: "+value1+"
"
); out.println("Value2: "+value2+"
"
); out.println(""); out.println(""); out.flush(); out.close(); } }

配置web.xml文件

    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>com.bjsxt.servlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/demo.do</url-pattern>
    </servlet-mapping>

这样,我们在运行Tomcat之后,进入路径:
http://localhost:8080/demo/demo.do
即可获得请求信息
Tomcat的使用及Servlet的实践_第21张图片

Servlet使用doPost方式获取请求数据

创建一个GetRequestDataServlet.class

package com.bjsxt;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 获取请求数据
 */
public class GetRequestDataServlet extends HttpServlet {
     
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        /*req.setCharacterEncoding("utf-8");*/
        String username = req.getParameter("username");
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("UserName:"+username+"
"
); out.println(""); out.println(""); out.flush(); out.close(); } }

在web.xml内配置:

    <servlet>
        <servlet-name>GetRequestDataServlet</servlet-name>
        <servlet-class>com.bjsxt.GetRequestDataServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>GetRequestDataServlet</servlet-name>
        <url-pattern>/getInfo.do</url-pattern>
    </servlet-mapping>

在web下,创建一个文件夹html,存放addUser.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addUser</title>
</head>
<body>
    <form action="../getInfo.do" method="post">
       用户名: <input type="text" name="username"/><br/>
        <input type="submit" value="ok"/>
    </form>
</body>
</html>

启动tomcat,输入信息点击发送
Tomcat的使用及Servlet的实践_第22张图片
Tomcat的使用及Servlet的实践_第23张图片

servlet获取复选框数据

我们在获取请求数据的基础上进行改进

 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        /*req.setCharacterEncoding("utf-8");*/
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        //多选框的数据获取
        String[] userlikes = req.getParameterValues("userlike");
        List<String> strings =  Arrays.asList(userlikes);

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("UserName:"+username+"
"
); out.println("strings:"+strings+"
"
); out.println(""); out.println(""); out.flush(); out.close(); }

html页面:

    <form action="../getInfo.do" method="post">
       用户名: <input type="text" name="username"/><br/>
        用户爱好:<input type="checkbox" name="userlike" value="sport"/>体育
        <input type="checkbox" name="userlike" value="music"/>音乐
        <input type="submit" value="ok"/>
    </form>

Tomcat的使用及Servlet的实践_第24张图片
在这里插入图片描述

获取所有提交数据的key

   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        /*req.setCharacterEncoding("utf-8");*/
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        //多选框的数据获取 -- 获取复选框(checkbox 组件)中的值,返回一个 String[]
        String[] userlikes = req.getParameterValues("userlike");
        List<String> strings =  Arrays.asList(userlikes);

        //获取所有提交数据的key,这个方法会返回一个枚举类型
        Enumeration<String> parameterNames = req.getParameterNames();
        List<String> keys = new ArrayList<>();
        while(parameterNames.hasMoreElements()){
     
            keys.add(parameterNames.nextElement());
        }

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("UserName:"+username+"
"
); out.println("strings:"+strings+"
"
); out.println("Keys:"+keys+"
"
); out.println(""); out.println(""); out.flush(); out.close(); }

输出样式:
Tomcat的使用及Servlet的实践_第25张图片

servlet使用Map结构获取提交的数据

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        /*req.setCharacterEncoding("utf-8");*/
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        //多选框的数据获取 -- 获取复选框(checkbox 组件)中的值,返回一个 String[]
        String[] userlikes = req.getParameterValues("userlike");
        List<String> strings =  Arrays.asList(userlikes);

        //获取所有提交数据的key,这个方法会返回一个枚举类型
        Enumeration<String> parameterNames = req.getParameterNames();
        List<String> keys = new ArrayList<>();
        while(parameterNames.hasMoreElements()){
     
            keys.add(parameterNames.nextElement());
        }
        // 获取请求中所有的数据并存放到一个 Map 结构中,
        // 该方法返回一个 Map,其中 key 为 String 类型 value 为 String[]类型
        Map<String, String[]> parameterMap = req.getParameterMap();

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("UserName:"+username+"
"
); out.println("strings:"+strings+"
"
); out.println("Keys:"+keys+"
"
); //获取的是spring数组的key和spring数组的value Iterator<Map.Entry<String,String[]>> iterator = parameterMap.entrySet().iterator(); while(iterator.hasNext()){ Map.Entry<String,String[]> entry = iterator.next(); out.println("Keys:"+entry.getKey()+" Value:"+Arrays.asList(entry.getValue())+"
"
); } out.println(""); out.println(""); out.flush(); out.close(); }

返回的数据
Tomcat的使用及Servlet的实践_第26张图片

servlet设置请求编码

有中文内容时,。在 Tomcat 中使用的是 ISO-8859-1 的单字节编码完成字节与字符的转换就会出现乱码

可以通过 req.setCharacterEncoding(“utf-8”)方法来对提 交的数据根据指定的编码方式重新做编码处理
Tomcat的使用及Servlet的实践_第27张图片
我们开始设置请求编码

   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //对象代表客户端的请求,使用utf-8的格式 可以让传过来的汉字在页面上没有乱码的显示
        req.setCharacterEncoding("utf-8");
        //对跳转前的页面的乱码现象进行处理,规定使用utf-8格式
        resp.setContentType("text/html;charset=utf-8");
        String username = req.getParameter("username");
        //设定将发送的请求数据的编码方式从"iso-8859-1" 转为"utf-8"
        String name = new String(username.getBytes("iso-8859-1"),"utf-8");
        System.out.println(name);
        //多选框的数据获取 -- 获取复选框(checkbox 组件)中的值,返回一个 String[]
        String[] userlikes = req.getParameterValues("userlike");
        List<String> strings =  Arrays.asList(userlikes);

        //获取所有提交数据的key,这个方法会返回一个枚举类型
        Enumeration<String> parameterNames = req.getParameterNames();
        List<String> keys = new ArrayList<>();
        while(parameterNames.hasMoreElements()){
     
            keys.add(parameterNames.nextElement());
        }
        // 获取请求中所有的数据并存放到一个 Map 结构中,
        // 该方法返回一个 Map,其中 key 为 String 类型 value 为 String[]类型
        Map<String, String[]> parameterMap = req.getParameterMap();

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("UserName:"+username+"
"
); out.println("strings:"+strings+"
"
); out.println("Keys:"+keys+"
"
); //获取的是spring数组的key和spring数组的value Iterator<Map.Entry<String,String[]>> iterator = parameterMap.entrySet().iterator(); while(iterator.hasNext()){ Map.Entry<String,String[]> entry = iterator.next(); out.println("Keys:"+entry.getKey()+" Value:"+Arrays.asList(entry.getValue())+"
"
); } out.println(""); out.println(""); out.flush(); out.close(); }

注意:

req.setCharacterEncoding("utf-8");
和
String name = new String(username.getBytes("iso-8859-1"),"utf-8");

这两个必须同时出现才有效
转换前:
Tomcat的使用及Servlet的实践_第28张图片
转换后:
Tomcat的使用及Servlet的实践_第29张图片

servlet的资源访问方式

绝对路径
绝对路径访问资源表示直接以”/”作为项目的 Content Path。该方式适用于以”/”作为项目 的 Content Path。

相对路径
相对路径访问资源表示会相对于项目的 Content Path 作为相对路径。该方式适用于为项 目指定的具体的 Content Path。

获取请求头信息

package com.bjsxt;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

public class GetRequestHeaderServlet extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        // req.getHeader("headerKey") --- 根据请求头中的 key 获取对应的 value。
        String header = req.getHeader("Accept-Language");
        // req.getHeaderNames() --- 获取请求头中所有的 key,该方法返回枚举类型
        Enumeration<String> headerNames = req.getHeaderNames();

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("Header:"+header+"
"
); out.println("======================================="+"
"
); while(headerNames.hasMoreElements()){ String key = headerNames.nextElement(); String value = req.getHeader(key); out.println("Key:"+key+" Value: "+value+"
"
); } out.println(""); out.println(""); out.flush(); out.close(); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { super.doPost(req, resp); } }

web.xml页面

<servlet>
<servlet-name>GetRequestHeaderServlet</servlet-name>
<servlet-class>com.bjsxt.GetRequestHeaderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetRequestHeaderServlet</servlet-name>
<url-pattern>/getHeader.do</url-pattern>
</servlet-mapping>

显示内容:
Tomcat的使用及Servlet的实践_第30张图片

案例

编写一个servlet,如果浏览器的语言是zh-CN,显示“你好,聪明的中国人!”,
如果浏览器的语言设置为en-US,就显示“hello,American!”

package com.bjsxt;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class LanguageServlet  extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取请求头内的浏览器的语言 accept-language
        //对跳转前的页面的乱码现象进行处理,规定使用utf-8格式
        resp.setContentType("text/html;charset=utf-8");
        String header = req.getHeader("accept-language");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("Header:"+header+"
"
); if(header.indexOf("zh-CN")!=-1){ //找到的情况下 out.println("你好,聪明的中国人"); }else if (header.indexOf("zh-US")!=-1){ out.println("hello,America"); }else{ out.println("抱歉。当前浏览器语言不支持"); } out.println(""); out.println(""); out.flush(); out.close(); } }

web.xml:

    <servlet>
        <servlet-name>LanguageServlet</servlet-name>
        <servlet-class>com.bjsxt.LanguageServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LanguageServlet</servlet-name>
        <url-pattern>/getlanguage.do</url-pattern>
    </servlet-mapping>
</web-app>

Tomcat的使用及Servlet的实践_第31张图片

HttpServletRequest对象的生命周期

当有请求到达 Tomcat 时,Tomcat 会创建 HttpServletRequest 对象,并将该对象通过参数的方式传递到我们 Servlet 的方法中,当处理请求处理完毕并产生响应后该对象生命周期结束。

设置字符型响应

常见的字符型响应类型:
resp.setContentType(“text/html”)
设置响应类型为文本型,内容含有 html 字符串,是默认的响应类型

resp.setContentType(“text/plain”)
设置响应类型为文本型,内容是普通文本。

resp.setContentType(“application/json”)
设置响应类型为 JSON 格式的字符串

例子:

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("hello");
        out.println("");
        out.println("");
        out.flush();
        out.close();
    }

使用resp.setContentType(“text/html”);时,页面内容:
Tomcat的使用及Servlet的实践_第32张图片
使用resp.setContentType(“text/plain”);,页面内容:
Tomcat的使用及Servlet的实践_第33张图片

设置字节型响应

什么时候设置
当你响应的文件是图片,影音时设置

常见的字节型响应:
resp.setContentType(“image/jpeg”)
设置响应类型为图片类型,图片类型为 jpeg 或 jpg 格式。

resp.setContentType(“image/gif”)
设置响应类型为图片类型,图片类型为 gif 格式。

读取jpg文件

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //读取图片文件
        File file = new File("D:/IDEA/demo/web/images/1.JPG");
        FileInputStream fis = new FileInputStream(file);
        byte[] buff = new byte[fis.available()];
        fis.read(buff);

        //设置响应类型
        resp.setContentType("image/jpeg");
        //从HttpServletResponse对象中获取字节输出流对象。
        OutputStream os = resp.getOutputStream();
        os.write(buff);
        os.flush();
        os.close();
    }

读取gif文件同理
导入gif文件的路径,同时设置响应类型为"images/gif"即可

设置响应的编码方式

response.setContentType(“text/html;charset=utf-8”);

设置服务端为浏览器产生响应的响应编码,服务端会根据此编码将响应内容的字符转换 为字节。同时客户端浏览器会根据此编码方式显示响应内容

在响应中添加附加信息

重定向响应

response.sendRedirect(URL 地址)
重定向响应会在响应头中添加一个 Location 的 key 对应的 value 是给定的 URL。客户端 浏览器在解析响应头后自动向 Location 中的 URL 发送请求。
重定向响应特点:
重定向会产生两次请求两次响应。
重定向的 URL 是有客户端浏览器发送的。

跳转到百度页面:

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        resp.sendRedirect("https://www.baidu.com");
    }

重定向响应案例

创建一个搜索页面,通过百度搜索引擎完成内容搜索

创建一个aearch.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="../redirset.do" method="post">
        搜索:<input type="text" name="search"/><br/>
        <input type="submit" value="Search"/>
    </form>
</body>
</html>
package com.bjsxt;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

public class RedirectServlet extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        req.setCharacterEncoding("utf-8");
        String search = req.getParameter("search");
        System.out.println(search);
        resp.sendRedirect("https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd="+URLEncoder.encode(search,"utf-8"));
    }
}

在web.xml内添加:

    <servlet>
        <servlet-name>RedirectServlet</servlet-name>
        <servlet-class>com.bjsxt.RedirectServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RedirectServlet</servlet-name>
        <url-pattern>/redirset.do</url-pattern>
    </servlet-mapping>
</web-app>

Tomcat的使用及Servlet的实践_第34张图片
Tomcat的使用及Servlet的实践_第35张图片

Servlet实现文件下载

在实现文件下载时,我们需要修改响应头,添加附加信息。

response.setHeader("Content-Disposition", "attachment; filename="+文件名); 

Content-Disposition:attachment
该附加信息表示作为对下载文件的一个标识字段。不会在浏览器中显示而是直接做下载 处理。

filename=文件名
表示指定下载文件的文件名。

通过在响应内添加附加信息的方式实现文件的下载

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //读文件
        File file = new File("D:/IDEA/demo/web/images/1.jpg");
        FileInputStream fis = new FileInputStream(file);
        byte[] buff = new byte[fis.available()];
        fis.read(buff);

        //在客户端浏览器下载文件之前产生响应,在响应内添加信息
        //获取文件名称
        resp.addHeader("Content-Disposition","attachment;filename="+file.getName());
        //获取字节输出流,向客户端做输出
        OutputStream os = resp.getOutputStream();
        os.write(buff);
        os.flush();
        os.close();
    }

但该方法无法识别下载文件内的中文内容:
在这里插入图片描述

Tomcat的使用及Servlet的实践_第36张图片

解决文件名中文乱码问题

//获取文件名称
resp.addHeader("Content-Disposition","attachment;filename="+new String(file.getName().getBytes("gbk"),"iso-8859-1"));

这样,就可以解决中文乱码

在这里插入图片描述

ServletContext对象

介绍

ServletContext 官 方 叫 Servlet 上 下 文 。 服 务 器 会 为 每 一 个 Web 应 用 创 建 一 个 ServletContext 对象。这个对象全局唯一,而且 Web 应用中的所有 Servlet 都共享这个对象。 所以叫全局应用程序共享对象

ServletContext 对象的作用

相对路径转绝对路径

context.getRealPath(“path”)

该方法可以将一个相对路径转换为绝对路径,在文件上传与下载时需要用到该方法做路径的转换
用该方法修改文件的下载,使得图片可以下载项目内的图片

   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //路径转换
        String realPath = servletContext.getRealPath("/images/1-副本.JPG");
        System.out.println(realPath);
        //读文件
        File file = new File(realPath);
        System.out.println(file.getName());
        FileInputStream fis = new FileInputStream(file);
        byte[] buff = new byte[fis.available()];
        fis.read(buff);
        //在响应中添加附加信息
        resp.addHeader("Content-Disposition","attachment;filename="+new String(file.getName().getBytes("gbk"),"iso-8859-1"));
        OutputStream os = resp.getOutputStream();
        os.write(buff);
        os.flush();
        os.close();
    }

获取容器得到附加信息

 servletContext.getServerInfo()
 返回 Servlet 容器的名称和版本号 
 servletContext.getMajorVersion()
 返回 Servlet 容器所支持 Servlet 的主版本号。
 servletContext.getMinorVersion() 
 返回 Servlet 容器所支持 Servlet 的副版本号。
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        resp.setContentType("text/html;charset=utf-8");
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        String serverInfo = servletContext.getServerInfo();
        int majorVersion = servletContext.getMajorVersion();
        int minorVersion = servletContext.getMinorVersion();
        //做字符输出流
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("Servlet容器的名称以及版本:"+serverInfo+"
"
); out.println("容器所支持的Servlet的版本号:"+majorVersion+"."+minorVersion); out.println(""); out.println(""); out.flush(); out.close(); }

Tomcat的使用及Servlet的实践_第37张图片

获取 web.xml 文件中的信息

<context-param>
  	<param-name>key</param-name>
  	<param-value>value</param-value> 
 </context-param>
servletContext.getInitParameter("key")
 该方法可以读取 web.xml 文件中<context-param>标签中的配置信息。

 servletContext.getInitParameterNames()
  该方法可以读取 web.xml 文件中所有 param-name 标签中的值。

代码:

/**
 * ServletContext对象读取web.xml文件中的信息
 */
   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取ServletContext
        ServletContext servletContext = this.getServletContext();
        Enumeration<String> initParameterNames = servletContext.getInitParameterNames();
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        while(initParameterNames.hasMoreElements()){
     
            String name = initParameterNames.nextElement();
            out.println("Name:"+name+" Value: "+servletContext.getInitParameter(name)+"
"
); } out.println(""); out.println(""); out.flush(); out.close(); }

我们在xml文件内的web-app标签下设置子标签:

    <context-param>
        <param-name>key</param-name>
        <param-value>value</param-value>
    </context-param>
    <context-param>
        <param-name>name</param-name>
        <param-value>BJSXT</param-value>
    </context-param>

Tomcat的使用及Servlet的实践_第38张图片

全局容器

 servletContext.setAttribute("key",ObjectValue)
 向全局容器中存放数据。 
 servletContext.getAttribute("key") 
 从全局容器中获取数据。 
 servletContext.removeAttribute("key") 
 根据 key 删除全局容器中的 value。
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("key1","Oldlu");
        servletContext.setAttribute("key2","Kevin");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        String value1 = (String)servletContext.getAttribute("key1");
        String value2 = (String)servletContext.getAttribute("key2");
        out.println("Value1: "+value1+"
"
); out.println("Value2: "+value2+"
"
); out.println(""); out.println(""); out.flush(); out.close(); }

Tomcat的使用及Servlet的实践_第39张图片

servletContext对象的生命周期

当容器启动时会创建 ServletContext 对象并一直缓存该对象,直到容器关闭后该对象生 命周期结束。ServletContext 对象的生命周期非常长,所以在使用全局容器时不建议存放业务数据。

ServletConfig对象

ServletConfig 对象对应 web.xml 文件中的节点。当 Tomcat 初始化一个 Servlet 时,会将该 Servlet 的配置信息,封装到一个 ServletConfig 对象中。我们可以通过该对象读 取节点中的配置信息

案例:

取节点中的配置信息:

<servlet> 
 <servlet-name>servletName</servlet-name>
  	<servlet-class>servletClass</servlet-class>
  	<init-param>
   		<param-name>key</param-name>
   		<param-value>value</param-value>
  	</init-param>
 </servlet>
servletConfig.getInitParameter("key")
该方法可以读取 web.xml 文件中标签中标签中的配置信息。

 servletConfig.getInitParameterNames() 
 该方法可以读取 web.xml 文件中当前标签中所有标签中的值。
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取ServletConfig对象
        ServletConfig servletConfig = this.getServletConfig();
        //servletConfig.getInitParameterNames(): 该方法可以读取 web.xml 文件中当前标签中所有标签中的值。
        Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        while(initParameterNames.hasMoreElements()){
     
            String key = initParameterNames.nextElement();
            //servletConfig.getInitParameter(key): 该方法可以读取 web.xml 文件中标签中标签中的配置信息
            out.println("Key: "+key+" Value: "+servletConfig.getInitParameter(key)+"
"
); } out.println(""); out.println(""); out.flush(); out.close(); }

web.xml配置:

    <servlet>
        <servlet-name>GetConfigInfoServlet</servlet-name>
        <servlet-class>com.bjsxt.GetConfigInfoServlet</servlet-class>

        <init-param>
            <param-name>key1</param-name>
            <param-value>BJSXT</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>GetConfigInfoServlet</servlet-name>
        <url-pattern>/getconfig.do</url-pattern>
    </servlet-mapping>

Cookie对象与HttpSession对象

Cookie 对象与 HttpSession 对象的作用是维护客户端浏览器与服务端的会话状态的两个 对象。由于 HTTP 协议是一个无状态的协议,所以服务端并不会记录当前客户端浏览器的访 问状态,但是在有些时候我们是需要服务端能够记录客户端浏览器的访问状态的,如获取当 前客户端浏览器的访问服务端的次数时就需要会话状态的维持。在 Servlet 中提供了 Cookie 对象与 HttpSession 对象用于维护客户端与服务端的会话状态的维持。二者不同的是 Cookie 是通过客户端浏览器实现会话的维持,而 HttpSession 是通过服务端来实现会话状态的维持。

Cookie对象

特点:

   Cookie 使用字符串存储数据
   Cookie 使用 Key 与 Value 结构存储数据
   单个 Cookie 存储数据大小限制在 4097 个字节
   Cookie 存储的数据中不支持中文,Servlet4.0 中支持
   Cookie 是与域名绑定所以不支持跨一级域名访问
   Cookie 对象保存在客户端浏览器或系统磁盘中 
   Cookie 分为持久化 Cooke 与状态 Cookie 
   浏览器在保存同一域名所返回 Cookie 的数量是有限的。不同浏览器支持的数量不同,Chrome 浏览器为 50 个 
   浏览器每次请求时都会把与当前访问的域名相关的 Cookie 在请求中提交到服务端。

怎么用:

  1. Cookie 对象的创建
    Cookie cookie = new Cookie(“key”,“value”)
    通过 new 关键字创建 Cookie 对象

    response.addCookie(cookie) 通过 HttpServletResponse 对象将 Cookie 写回给客户端浏览器。
    代码:

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //创建Cookie对象
        Cookie cookie = new Cookie("name", URLEncoder.encode("北京尚学堂","utf-8"));
        //设置Cookie的失效时间,一旦设置了失效时间,该Cookie为持久化Cookie
        cookie.setMaxAge(60);
        resp.addCookie(cookie);
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("Create Cookie 
"
); out.println(""); out.println(""); out.flush(); out.close(); }
  1. 获取 Cookie 中的数据
    通过 HttpServletRequest 对象获取 Cookie,返回 Cookie 数组。 Cookie[] cookies = request.getCookies()
  2. 解决 Cookie 不支持中文
    代码:
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //在请求中获取Cookie对象
        Cookie[] cookies = req.getCookies();
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        for(int i=0;i<cookies.length;i++){
     
            Cookie cookie = cookies[i];
            out.println("Name: "+cookie.getName()+" Value: "+ URLDecoder.decode(cookie.getValue(),"utf-8") +"
"
); } out.println(""); out.println(""); out.flush(); out.close(); }

状态cookie和持久化cookie

上方的cookie对象的使用,是状态cookie的实例使用,也就是说,当浏览器被关闭后,再次进入浏览器访问路径,设置的內容就会消失

介绍:


状态 Cookie:浏览器会缓存 Cookie 对象。浏览器关闭后 Cookie 对象销毁。

 持久化 Cookie:浏览器会对 Cookie 做持久化处理,基于文件形式保存在系统的指定目 录中。在 Windows10 系统中为了安全问题不会显示 Cookie 中的内容。 

当 Cookie 对象创建后默认为状态 Cookie。可以使用 Cookie 对象下的 cookie.setMaxAge(60) 方法设置失效时间,单位为秒。一旦设置了失效时间,那么该 Cookie 为持久化 Cookie,浏 览器会将 Cookie 对象持久化到磁盘中。当失效时间到达后文件删除。

修改为持久化Cookie:

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
       //创建Cookie对象
        Cookie cookie = new Cookie("name", URLEncoder.encode("北京尚学堂","utf-8"));
        //设置Cookie的失效时间,一旦设置了失效时间,该Cookie为持久化Cookie
        cookie.setMaxAge(60);
        resp.addCookie(cookie);
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("Create Cookie 
"
); out.println(""); out.println(""); out.flush(); out.close(); }

在这里,我们做出的改动为

    //设置Cookie的失效时间,一旦设置了失效时间,该Cookie为持久化Cookie
    cookie.setMaxAge(60);

单位是秒

通过 Cookie 实现客户端与服务端会话的维持

实现
当客户端浏览器第一次访问 Servlet 时返回“您好,欢迎您第一次访问!”,第 二次访问时返回“欢迎您回来!”

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取Cookie
        Cookie[] cookies = req.getCookies();
        boolean flag = false;
        if(cookies != null){
     
            for(Cookie cookie:cookies){
     
                if("first".equals(cookie.getName())){
     
                    flag = true;
                }
            }
        }
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        if(flag){
     
            out.println("欢迎您回来!");
        }else{
     
            out.println("您好,欢迎您第一次访问!");
            Cookie cookie = new Cookie("first","first");
            //设置cookie的失效时间
            cookie.setMaxAge(60);
            resp.addCookie(cookie);
        }

        out.println("");
        out.println("");
        out.flush();
        out.close();
    }

第一次访问 :
Tomcat的使用及Servlet的实践_第40张图片
第二次访问:
Tomcat的使用及Servlet的实践_第41张图片

cookie小结

Cookie 对于存储内容是基于明文的方式存储的,所以安全性很低。

不要在 Cookie 中存 放敏感数据。

在数据存储时,虽然在 Servlet4.0 中 Cookie 支持中文,但是建议对 Cookie 中 存放的内容做编码处理,也可提高安全性。

HttpSession对象

HttpSession创建的创建

HttpSession 对象的创建是通过 request.getSession()方法来创建的。

getSession()方法还有一个重载方法getSession(true|false)。
当参数为true时与getSession() 方法作用相同。

当参数为 false 时则只去根据 SessionID 查找是否有与这个客户端浏览器对应
45 的 HttpSession,如果有则返回,如果没有 SessionID 则不会创建新的 HttpSession 对象。
 //获取session
 HttpSession session = req.getSession();

获取HttpSession内的数据

session.setAttribute("key",value) 
将数据存储到 HttpSession 对象中 

Object value = session.getAttribute("key") 
根据 key 获取 HttpSession 中的数据,返回 Object 

Enumeration<String> attributeNames = session.getAttributeNames() 
获取 HttpSession 中所有的 key,返回枚举类型 

session.removeAttribute("key") 
根据 key 删除 HttpSession 中的数据 

String id = session.getId() 
根据获取当前 HttpSession 的 SessionID,返回字符串类型

先将数据存储到HttpSession对象内

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取session
        HttpSession session = req.getSession();
        session.setAttribute("key","bjsxt");
        String Id = session.getId();
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("id:"+Id);
        out.println("");
        out.println("");
        out.flush();
        out.close();
    }

我们查看获取到的session对象的id
Tomcat的使用及Servlet的实践_第42张图片
根据 key 获取 HttpSession 中的数据,返回 Object

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        HttpSession session =  req.getSession();
        String value =  (String)session.getAttribute("key");

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("value:"+value);
        out.println("");
        out.println("");
        out.flush();
        out.close();
    }

输出查看结果:
Tomcat的使用及Servlet的实践_第43张图片

通过session对象 判断运行的浏览器

先将数据存储到HttpSession对象内,同时进行判断

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        String header = req.getHeader("User-Agent");
        //获取session
        HttpSession session = req.getSession();
        if (header.indexOf("Chrome") != -1){
     
            session.setAttribute("key","BJSXT-Chrome");
        }else{
     
            session.setAttribute("key","IE");
        }
        String Id = session.getId();
        System.out.println(session+" "+Id);
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("id:"+Id);
        out.println("");
        out.println("");
        out.flush();
        out.close();
    }

根据 key 获取 HttpSession 中的数据,返回 Object

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        HttpSession session =  req.getSession();
        String value =  (String)session.getAttribute("key");

        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("value:"+value);
        out.println("");
        out.println("");
        out.flush();
        out.close();
    }

谷歌浏览器:
Tomcat的使用及Servlet的实践_第44张图片
IE浏览器
Tomcat的使用及Servlet的实践_第45张图片
我们可以在 web.xml 文件中指定 HttpSession 的超时时间,当到达指定的超时时间后,容 器就会销该 HttpSession 对象,单位为分钟。该时间对整个 web 项目中的所有 HttpSession 对 象有效。
web.xml

    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>

一分钟到后,自动销毁对象
Tomcat的使用及Servlet的实践_第46张图片

invalidate()方法是 HttpSession 对象中所提供的用于销毁当前 HttpSession 的方法。我们 通过调用该方法可以销毁当前 HttpSession 对象。

        HttpSession session = req.getSession();
        if (header.indexOf("Chrome") != -1){
     
            session.setAttribute("key","BJSXT-Chrome");
            //销毁当前HttpSession的方法
            session.invalidate();
        }else{
     
            session.setAttribute("key","IE");
        }

Tomcat的使用及Servlet的实践_第47张图片
这样做,就直接销毁httpSession方法

通过 HttpSession 实现客户端与服务端会话的维持

要求:当客户端浏览器第一次访问 Servlet 时返回“您好,欢迎您第一次访问!”,第 二次访问时返回“欢迎您回来!”

我们之前实现过 “ 通过 Cookie 实现客户端与服务端会话的维持 ”,在这里,我们通过HttpSession实现客户端和服务端回话的维持

   protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     

        HttpSession session = req.getSession(false);
        boolean flag = true;
        if (session == null){
     
            flag = false;
            //将req的session值设置为ture
            req.getSession(true);
        }
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        if(flag){
     
            out.println("欢迎您回来!");
        }else{
     
            out.println("您好,欢迎您第一次访问!");
        }

        out.println("");
        out.println("");
        out.flush();
        out.close();
    }

Tomcat的使用及Servlet的实践_第48张图片
刷新后:
Tomcat的使用及Servlet的实践_第49张图片

HttpSession的生命周期

在 HttpSession 对象生命周期中没有固定的创建时间与销毁时间。

何时创建取决于我们 什么时候第一次调用了 getSession()或 getSession(true)的方法。

HttpSession 对象的销毁时间 取决于超时时间的到达以及调用了 invalidate()方法。

如果没有超时或者没有调用 invalidate() 方法,那么 HttpSession 会一直存储。

默认超时时间为 30 分钟(Tomcat 的 web.xml 文件配置 的时间就是默认超时时间)。

HttpSession 与 Cookie 的区别:

  • cookie 数据存放在客户的浏览器或系统的文件中,而 HttpSession 中的数据存放在服务 器中。
  • cookie 不安全,而 HttSession 是安全的。
  • 单个 cookie 保存的数据不能超过 4K,很多浏览器都限制一个域名保存 cookie 的数量。 而 HttpSession 没有容量以及数量的限制。

因为HttpSession对象的生命周期不固定,我们一般只用HttpSession对象存放用户登录信息

自启动Servlet

什么是自启动Servlet

自启动Servlet在Tomcat启动时就会实例化这个Servlet,他的实例化过程不依赖于请求,而是依赖于容器的启动。
可以通过在web.xml中的标签中通过1配置自启动Servlet。

如何创建

web.xml

    <servlet>
        <servlet-name>AutoStartServlet</servlet-name>
        <servlet-class>com.bjsxt.AutoStartServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AutoStartServlet</servlet-name>
        <url-pattern>/autostart.do</url-pattern>
    </servlet-mapping>
/**
 * 自启动Servlet
 */
public class AutoStartServlet extends HttpServlet {
     
    @Override
    public void init() throws ServletException {
     
       System.out.println("Servlet  Init...");
    }
}

通过自启动Servlet实现配置信息的获取

案例:
修改文件下载案例,通过自启动 Servlet 读取配置信息
配置web.xml文件:

    <servlet>
        <servlet-name>AutoStartServlet</servlet-name>
        <servlet-class>com.bjsxt.AutoStartServlet</servlet-class>
        <init-param>
            <param-name>path</param-name>
            <param-value>/images</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>AutoStartServlet</servlet-name>
        <url-pattern>/autostart.do</url-pattern>
    </servlet-mapping>

配置自启动文件,获取xml文件内的指定内容:

/**
 * 自启动Servlet
 */
public class AutoStartServlet extends HttpServlet {
     
    @Override
    public void init() throws ServletException {
     
       System.out.println("Servlet  Init...");
        ServletConfig servletConfig = this.getServletConfig();
        String value = servletConfig.getInitParameter("path");
        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("path",value);
    }
}

修改文件下载代码:

   @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();

        String path = (String) servletContext.getAttribute("path");
        System.out.println(path);
        //路径转换
        String realPath = servletContext.getRealPath(path+"/1-副本.JPG");
        System.out.println(realPath);
        //读文件
        File file = new File(realPath);
        System.out.println(file.getName());
        FileInputStream fis = new FileInputStream(file);
        byte[] buff = new byte[fis.available()];
        fis.read(buff);
        //在响应中添加附加信息
        resp.addHeader("Content-Disposition","attachment;filename="+new String(file.getName().getBytes("gbk"),"iso-8859-1"));
        OutputStream os = resp.getOutputStream();
        os.write(buff);
        os.flush();
        os.close();
    }

Servlet线程安全问题

在 Servlet 中使用的是多线程方式来执行 service()方法处理请求,所以我们在使用 Servlet 时需要考虑到线程安全问题,在多线程中对于对象中的成员变量是最不安全的,所以不要在 Servlet 中通过成员变量的方式来存放数据,如果一定要使用成员变量存储数据,在对数据 进行操作时需要使用线程同步的方式来解决线程安全问题,避免出现数据张冠李戴现象。

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        String name = req.getParameter("name");
        //线程同步
       synchronized (this){
     

           pw = resp.getWriter();
           try{
     
               //让线程做一个休眠
               Thread.sleep(5000);
               pw.println(name);
               pw.flush();
               pw.close();
           }catch(Exception e){
     
               e.printStackTrace();
           }
       }
    }

Tomcat的使用及Servlet的实践_第50张图片

这样,在非要使用成员变量去存储数据时,对数据进行操作时使用线程的同步,在加载页面时保证线程的安全

Servlet的URL匹配规则

精确匹配

精确匹配是指中配置的值必须与 url 完全精确匹配

<servlet-mapping>
  <servlet-name>demoServlet</servlet-name>
  <url-pattern>/demo.do</url-pattern> 
 </servlet-mapping>

http://localhost:8888/demo/demo.do 匹配 http://localhost:8888/demo/suibian/demo.do 不匹配

扩展名匹配

在允许使用统配符“”作为匹配规则,“”表示匹配任意字符。在扩展 名匹配中只要扩展名相同都会被匹配和路径无关。注意,在使用扩展名匹配时在 中不能使用“/”,否则容器启动就会抛出异常。

<servlet-mapping>
  <servlet-name>demoServlet</servlet-name>
  <url-pattern>*.do</url-pattern> 
</servlet-mapping>

http://localhost:8888/demo/abc.do 匹配
http://localhost:8888/demo/suibian/haha.do 匹配 http://localhost:8888/demo/abc 不匹配

路径匹配

根据请求路径进行匹配,在请求中只要包含该路径都匹配。“*”表示任意路径以及子 路径。

<servlet-mapping>
  <servlet-name>demoServlet</servlet-name>
  <url-pattern>/suibian/* 

http://localhost:8888/demo/suibian/haha.do 匹配 http://localhost:8888/demo/suibian/hehe/haha.do 匹配 http://localhost:8888/demo/hehe/heihei.do 不匹配

任意匹配

匹配“/”。匹配所有但不包含 JSP 页面

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

http://localhost:8888/demo/suibian.do 匹配 http://localhost:8888/demo/addUser.html 匹配 http://localhost:8888/demo/css/view.css 匹配 http://localhost:8888/demo/addUser.jsp 不匹配 http://localhost:8888/demo/user/addUser.jsp 不匹配
匹配所有

<url-pattern>/*

http://localhost:8888/demo/suibian.do 匹配 http://localhost:8888/demo/addUser.html 匹配 http://localhost:8888/demo/suibian/suibian.do 匹配

优先顺序

当一个 url 与多个 Servlet 的匹配规则可以匹配时,则按照 “ 精确路径 > 最长路径 > 扩展名”这样的优先级匹配到对应的 Servlet。

URL映射方式

在 web.xml 文件中支持将多个 URL 映射到一个 Servlet 中,但是相同的 URL 不能同时映 射到两个 Servlet 中。
方式一:


	 demoServlet
	 /suibian/*
	 *.do 
 

方式二:


	 demoServlet
 	 /suibian/*
  
 
 	 demoServlet
  	 *.do 
   

基于注解式开发 Servlet

在 Servlet3.0 以及之后的版本中支持注解式开发 Servlet。对于 Servlet 的配置不在依赖于 web.xml 配置文件,而是使用@WebServlet 注解完成 Servlet 的配置。
Tomcat的使用及Servlet的实践_第51张图片

/**
 * 使用注解去开发Servlet
 */
//urlPatterns  Servlet的访问URL,支持多个
@WebServlet(urlPatterns = "/ann.do")
public class AnnotationServlet extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
       this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("Annotation Servlet!");
        out.println("");
        out.println("");
        out.flush();
        out.close();
    }
}

@WebInitParam属性

    <servlet>
        <servlet-name>GetConfigInfoServlet</servlet-name>
        <servlet-class>com.bjsxt.GetConfigInfoServlet</servlet-class>

        <init-param>
            <param-name>key1</param-name>
            <param-value>BJSXT</param-value>
        </init-param>
    </servlet>

我们使用 @WebInitParam属性去取代web.xml的init-param

/**
 * 通过注解方式读取Servlet的初始化配置信息
 */
@WebServlet(urlPatterns = "/initParam.do",initParams = {
     @WebInitParam(name="key1",value = "value1"),@WebInitParam(name="key2",value = "value2")},loadOnStartup = 1)
public class InitParamServlet extends HttpServlet {
     
    @Override
    public void init() throws ServletException {
     
        super.init();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     

        ServletConfig servletConfig = this.getServletConfig();
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("Value1: "+servletConfig.getInitParameter("key1")+"
"
); out.println("Value2: "+servletConfig.getInitParameter("key2")+"
"
); out.println(""); out.println(""); out.flush(); out.close(); } }

Tomcat的使用及Servlet的实践_第52张图片

Servlet通过Part对象实现文件上传

文件的上传
Part 对象中常用的方法 :
Tomcat的使用及Servlet的实践_第53张图片

String getContentType()
获取上传文件的文件的 MIME 类型
long getSize()
上传文件的大小
String getSubmittedFileName()
上传文件的原始文件名
我们创建一个html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
    <body>
        <form action="/fileupload" method="post" enctype="multipart/form-data">
            文件描述:<input type="text" name="desc"/>
            上传文件:<input type="file" name="file"/>
            <input type="submit" value="OK"/>
        </form>
    </body>
</html>

Tomcat的使用及Servlet的实践_第54张图片


import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.UUID;

/**
 * 使用注解完成文件的上传
 */
@WebServlet("/fileupload")
//上传的注解
@MultipartConfig
public class FileUploadServlet extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        this.doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        System.out.println("进入fileupload");
        req.setCharacterEncoding("utf-8");
        String desc = req.getParameter("desc");
        Part part = req.getPart("file");
        /*
        //获取文件上传的字节流
        InputStream inputStream = part.getInputStream();*/
        System.out.println("输出原名称:"+part.getSubmittedFileName());
        //给文件改名
        String fileName = UUID.randomUUID().toString()+part.getSubmittedFileName().substring(part.getSubmittedFileName().lastIndexOf("."));

        //获取ServletContext对象
        ServletContext servletContext = this.getServletContext();
        //获取一个绝对路径
        String realPath = servletContext.getRealPath("/images/"+fileName);
        //路径转换 -- 将相对路径转为绝对路径
//        String realPath = "D:/IDEA/ServletDemo/web/images/"+fileName;
        System.out.println("路径:"+realPath);
        //将上传的文件存放到获取到的路径
        part.write(realPath);
        resp.setContentType("text/html;charset=utf-8");
        PrintWriter out = resp.getWriter();
        out.println("");
        out.println("");
        out.println(" ITBZ ");
        out.println("");
        out.println("上传成功!"+desc);
        out.println("");
        out.println("");
        out.flush();
        out.close();
    }
}

我们上传一个图片
Tomcat的使用及Servlet的实践_第55张图片
Tomcat的使用及Servlet的实践_第56张图片
在这里插入图片描述
这样,我们完成一个图片上传到指定文件夹下
文件目录:Tomcat的使用及Servlet的实践_第57张图片

正确的创建servlet以及导入项目的流程
跳转链接

Filter 过滤器

Filter 过滤器是 Servlet 中的一个组件。

作用

对从客户端向服务器端发送的请求进行过滤,也可以对服务器端返回的响应进行处理。
Tomcat的使用及Servlet的实践_第58张图片

使用filter

创建filter对象

创建一个 Class 实现 Filter 接口,并实现接口中三个抽象方法。
init()方法:初始化方法,在创建 Filter 后立即调用。可用于完成初始化动作。
doFilter()方法:拦截请求与响应方法,可用于对请求和响应实现预处理。
destroy()方法:销毁方法,在销毁 Filter 之前自动调用。可用于完成资源释放等动作。


import javax.servlet.*;
import java.io.IOException;

/**
 * 第一个Filter案例
 */
public class FirstFilter implements Filter {
     
    /**
     * init方法在这里是一个初始化方法
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
     
        System.out.println("初始化方法");
    }

    /**
     * 处理请求和响应的方法
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
     

        System.out.println("预处理请求");

        //对请求作放行处理
        filterChain.doFilter(servletRequest,servletResponse);

        System.out.println("预处理响应");
    }

    /**
     * 销毁方法,当filter被销毁之前会调用一次这个方法
     */
    @Override
    public void destroy() {
     

    }
}

xml:

    <filter>
        <filter-name>FirstFilter</filter-name>
        <filter-class>filter.FirstFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FirstFilter</filter-name>
        <url-pattern>/suibian/*
    

Tomcat的使用及Servlet的实践_第59张图片

在 Filter 中设置请求编码

我们要实现一个可以对所有页面进行编码处理的效果

在原来的上传页面内,我们使用req.setCharacterEncoding(“utf-8”);对数据进行编码处理
如果去除,且不对文件进行改名处理,汉字文件名就会出现乱码
在这里插入图片描述
这样,我们进行一个当出现请求时进行编码处理的效果

import javax.servlet.*;
import java.io.IOException;

/**
 * 处理请求编码Filter
 */
public class EncodingFilter implements Filter {
     
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
     

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
     
        //设置处理请求的编码
        servletRequest.setCharacterEncoding("utf-8");
        //对请求产生响应
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
     

    }
}

web.xml:

   <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>filter.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*
    

这样,当我们进行运行时,就会对请求的数据(/*)进行编码处理
在这里插入图片描述

FilterConfig 对象的使用

FilterConfig 对象是用来读取中初始化参数的对象。该对象通过参数 传递到 init 方法中,用于读取初始化参数。

filterConfig.getInitParameter(“name”)
通过 name 获取对应的 value。
filterConfig.getInitParameterNames()
返回该 Filter 中所有中的值。
实例:
我们对上面的全局编码进行改造,因为编码格式不一定是utf-8
先在xml文件内添加init-name:


    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>filter.EncodingFilter</filter-class>
        <init-param>
            <param-name>code</param-name>
            <param-value>utf-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*
    

在filter文件内,进行编码方式的获取与判断:

package filter;

import javax.servlet.*;
import java.io.IOException;

/**
 * 处理请求编码Filter
 */
public class EncodingFilter implements Filter {
     
    private String encoding;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
     
        String code = filterConfig.getInitParameter("code");
        this.encoding = code;
        System.out.println("encoding:"+encoding);

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
     
        if (this.encoding==null){
        //说明在xml文件内没有给定编码,需要给定

            //设置处理请求的编码
            servletRequest.setCharacterEncoding("utf-8");
        }else {
          //说明在xml文件内有给定的编码,调用即可

            servletRequest.setCharacterEncoding(this.encoding);
        }

        //对请求产生响应
        filterChain.doFilter(servletRequest,servletResponse);
    }

    @Override
    public void destroy() {
     

    }
}

这样,编码方式的选择就更加灵活

Filter执行顺序

按照在 web.xml 文件中配置的上下顺序来决定先后。在上的先执行,在下的后执行。

基于注解时开发Filter

Tomcat的使用及Servlet的实践_第60张图片

注意:
当web.xml和注解同时存在,且都是对全部加载时进行操作,优先使用web.xml内的Filter,因为系统启动时,先去查看的是web.xml文件

 
import javax.servlet.annotation.WebFilter; 

/**
 * 注解Filter案例
 */
@WebFilter("/*")
public class FirstFilter2 implements Filter {
     
//代码区域
}

当使用注解式开发 Filter 时,执行顺序会根据 Filter 的名称进行排序的结果决定调用的顺序 在这里插入图片描述

监听器

监听器用于监听 web 应用中某些对象的创建、销毁、增加,修改,删除等动作的发 生,然后作出相应的响应处理。

监听器分类

按监听的对象划分,可以分为:

  • ServletContext 对象生命周期监听器与属性操作监听器
  • HttpSession 对象生命周期监听器与属性操作监听器
  • ServletRequest 对象生命周期监听器与属性操作监听器

ServletContext 监听器

ServletContext 对象的生命周期监听器

ServletContextListener 接口定义了 ServletContext 对象生命周期的监听行为。

package listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

/**
 * ServletCOntext对象生命周期监听器
 */
public class ServletContextLifeCycleListener implements ServletContextListener {
     
    /**
     * 当服务器被启动后就会调用这个方法
     * ServletContext 对象创建后会触发该监听方法,并将 ServletContext 对象传递到该方法中。
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
     
        //获取已经创建好的ServletContext对象
        ServletContext servletContext = sce.getServletContext();
        System.out.println("输出servletContext:"+servletContext);
        System.out.println("ServletContext Init.....");
    }

    /** 
     * ServletContext 对象在销毁之前会触发该监听方法,并将 ServletContext 对象传递到该方 法中
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
     
        ServletContext servletContext = sce.getServletContext();
        System.out.println("销毁时再次输出servletContext:"+servletContext);
        System.out.println("ServletContext Destory.....");
    }
}

web.xml


    <listener>
        <listener-class>listener.ServletContextLifeCycleListener</listener-class>
    </listener>

这样,一个监听器就设置完毕
在这里插入图片描述
我们关闭tomcat
Tomcat的使用及Servlet的实践_第61张图片
Tomcat的使用及Servlet的实践_第62张图片
这样,创建和销毁的是同一个对象

ServletContext 对象的属性操作监听器

package listener;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

/**
 * ServletContext对象属性操作监听器
 */
public class ServletContextAttr implements  ServletContextAttributeListener {
     

    /**
     * 向 ServletContext 对象中添加属性时会触发该监听方法,
     * 并将 ServletContext 对象传递到 该方法中。
     * 触发事件的方法 servletContext.setAttribute("key","value")。
     *
     */
    @Override
    public void attributeAdded(ServletContextAttributeEvent scae) {
     
        System.out.println("-----------Added Start---------------");
        System.out.println(scae.getName()+"-----"+scae.getValue());
        System.out.println(scae.getServletContext());
        System.out.println("------------Added End--------------");
    }

    /**
     * 当从 ServletContext 对象中删除属性时会触发该监听方法,
     * 并将 ServletContext 对象传递 到该方法中。
     * 触发事件方法 servletContext.removeAttribute("key")。
     *
     */
    @Override
    public void attributeRemoved(ServletContextAttributeEvent scae) {
     
        System.out.println("-----------Removed Start---------------");
        System.out.println(scae.getName()+"-----"+scae.getValue());
        System.out.println(scae.getServletContext());
        System.out.println("------------Removed End--------------");

    }

    /**
     * 当从 ServletContext 对象中属性的值发生替换时会触发该监听方法,
     * 并将 ServletContext 对象传递到该方法中。
     * 触发事件的方法 servletContext.setAttribute("key","value")。
     *
     */
    @Override
    public void attributeReplaced(ServletContextAttributeEvent scae) {
     
        System.out.println("-----------Replaced Start---------------");
        System.out.println(scae.getName()+"-----"+scae.getValue());
        System.out.println(scae.getServletContext());
        System.out.println("------------Replaced End--------------");

    }
}

在web.xml内 :

 
    <listener>
        <listener-class>listener.ServletContextAttr</listener-class>
    </listener>

我们创建一个servlet,给Servlet对象赋值:

package servlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/attr.do")
public class ServletContextAttrServlet  extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        ServletContext servletContext = this.getServletContext();
        servletContext.setAttribute("key","bjsxt");
        servletContext.setAttribute("key","ITBZ");
        servletContext.removeAttribute("key");
    }
}

运行结果:
Tomcat的使用及Servlet的实践_第63张图片

HttpSession 对象的生命周期监听器


    <listener>
        <listener-class>listener.HttpSessionLifeCycleListener</listener-class>
    </listener>
package listener;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * HttpSession对象的生命周期监听器
 */
public class HttpSessionLifeCycleListener implements HttpSessionListener {
     
    @Override
    /**
     * HttpSession 对象创建后会触发该监听方法,并将已创建 HttpSession 对象传递到该方法中
     */
    public void sessionCreated(HttpSessionEvent se) {
     
        System.out.println(se.getSession());
        System.out.println("Http Session Created....");
    }

    @Override
    /**
     * HttpSession 对象在销毁之前会触发该监听方法,并将要销毁的 HttpSession 对象传递到该方法中
     * 关闭客户端浏览器不会触发这个方法
     * 当计时器时间到时会触发,或者被调用才会被触发
     */
    public void sessionDestroyed(HttpSessionEvent se) {
     
        System.out.println(se.getSession());
        System.out.println("Http Session Destroyed....");
    }
}

运行结果:
Tomcat的使用及Servlet的实践_第64张图片

HttpSession 对象的属性操作监听器

将数据存放到HttpSession对象内:

package servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/sessionAttr.do")
public class HttpSessionAttrServlet extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        HttpSession session = req.getSession();
        session.setAttribute("key","bjsxt");
        session.setAttribute("key","BJSXT");
        session.removeAttribute("key");
    }
}


在 监听器内进行监听

package listener;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

/**
 * HttpSession对象属性监听器
 */
public class HttpSessionAttrListener implements HttpSessionAttributeListener {
     
    @Override
    /**
     * 向 HttpSession 对象中添加属性时会触发该监听方法,
     * 并将 HttpSession 对象传递到该方 法中。
     * 触发事件的方法 HttpSession.setAttribute("key","value")。
     *
     */
    public void attributeAdded(HttpSessionBindingEvent se) {
     
        System.out.println("---HttpSessionAttr--------Added Start---------------");
        System.out.println(se.getName()+"-----"+se.getValue());
        System.out.println(se.getSession());
        System.out.println("----HttpSessionAttr--------Added End--------------");
    }

    @Override
    /**
     *当从 HttpSession 对象中删除属性时会触发该监听方法,
     * 并将 HttpSession 对象传递到该 方法中。
     * 触发事件方法 HttpSession.removeAttribute("key")。
     *
     */
    public void attributeRemoved(HttpSessionBindingEvent se) {
     
        System.out.println("---HttpSessionAttr--------Removed Start---------------");
        System.out.println(se.getName()+"-----"+se.getValue());
        System.out.println(se.getSession());
        System.out.println("----HttpSessionAttr--------Removed End--------------");
    }

    @Override
    /**
     * 当从 HttpSession 对象中属性的值发生替换时会触发该监听方法,
     * 并将 HttpSession 对象 传递到该方法中。
     * 触发事件的方法 HttpSession.setAttribute("key","value")。
     *
     */
    public void attributeReplaced(HttpSessionBindingEvent se) {
     
        System.out.println("---HttpSessionAttr--------Replaced Start---------------");
        System.out.println(se.getName()+"-----"+se.getValue());
        System.out.println(se.getSession());
        System.out.println("----HttpSessionAttr--------Replaced End--------------");
    }
}

配置xml文件:


    <listener>
        <listener-class>listener.HttpSessionAttrListener</listener-class>
    </listener>

运行结果:
Tomcat的使用及Servlet的实践_第65张图片

HttpServletRequest 监听器

HttpServletRequest 对象的生命周期监听器

ServletRequestListener 接口定义了 ServletReqest(是 HttpServletRequest 接口的父接口类 型)对象生命周期的监听行为。

package listener;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;

/**
 * 监听HttpServletRequest对象生命周期监听器
 */
public class HttpServletRequestLifeCycleListener implements ServletRequestListener {
     
    @Override
    /**
     * HttpServletRequest 对象创建后会触发该监听方法,并将已创建 ServletRequest 对象传递 到该方法中
     */
    public void requestInitialized(ServletRequestEvent sre) {
     
        System.out.println((HttpServletRequest)sre.getServletRequest());
        System.out.println("HttpServletRequest....Initialized");
    }
    @Override
    /**
     * HttpServletRequest 对象在销毁之前会触发该监听方法,并将要销毁的 ServletRequest 对 象传递到该方法中
     */
    public void requestDestroyed(ServletRequestEvent sre) {
     
        System.out.println((HttpServletRequest)sre.getServletRequest());
        System.out.println("HttpServletRequest....Destroyed");
    }

}

在这里插入图片描述
Tomcat的使用及Servlet的实践_第66张图片

HttpServletRequest 对象的属性操作监听器

ServletRequestAttributeListener 接口定义了对于 HttpServletRequest 对象属性操作的监听 行为
配置xml文件:


    <listener>
        <listener-class>listener.HttpServletRequestAttrListener</listener-class>
    </listener>
package listener;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.http.HttpServletRequest;

/**
 * HttpServletRequest属性操作监听器
 */
public class HttpServletRequestAttrListener implements ServletRequestAttributeListener {
     
    @Override
    /**
     * 向 HttpServletRequest 对象中添加属性时会触发该监听方法,
     * 并将 ServletRequest 对象传 递到该方法中。
     * 触发事件的方法 HttpServletRequest.setAttribute("key","value")。
     */
    public void attributeAdded(ServletRequestAttributeEvent srae) {
     
        System.out.println("---HttpServletRequestAttr--------Added Start---------------");
        System.out.println(srae.getName()+"-----"+srae.getValue());
        System.out.println((HttpServletRequest)srae.getServletRequest());
        System.out.println("----HttpServletRequestAttr--------Added End--------------");
    }

    @Override
    /**
     * 当从 HttpServletRequest 对象中删除属性时会触发该监听方法,
     * 并将 ServletRequest 对象 传递到该方法中。
     * 触发事件方法 HttpServletRequest.removeAttribute("key")
     */
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
     
        System.out.println("---HttpServletRequestAttr--------Removed Start---------------");
        System.out.println(srae.getName()+"-----"+srae.getValue());
        System.out.println((HttpServletRequest)srae.getServletRequest());
        System.out.println("----HttpServletRequestAttr--------Removed End--------------");
    }

    @Override
    /**
     * 当从HttpServletRequest对象中属性的值发生替换时会触发该监听方法,并将ServletRequest 对象传递到该方法中
     * 触发事件的方法 HttpServletRequest.setAttribute("key","value")。
     */
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
     
        System.out.println("---HttpServletRequestAttr--------Replaced Start---------------");
        System.out.println(srae.getName()+"-----"+srae.getValue());
        System.out.println((HttpServletRequest)srae.getServletRequest());
        System.out.println("----HttpServletRequestAttr--------Replaced End--------------");
    }
}

package servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestAttr.do")
public class HttpServletRequestAttrServlet extends HttpServlet {
     
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
     
        req.setAttribute("key","bjsxt");
        req.setAttribute("key","BJSXT");
        req.removeAttribute("key");
    }
}

我们运行http://localhost:8080/requestAttr.do:
Tomcat的使用及Servlet的实践_第67张图片

基于注解式开发监听器

通过@WebListener注解去代替web.xml内的Listener的配置

你可能感兴趣的:(tomcat,servlet,java)