Java Web 从入门到退坑 第七章 Servlet


Java Web 从入门到退坑 —— 第七章 Servlet


By -gregPerlinLi-


1. Servlet 技术

1.1. 什么是 Servlet

​ 1. Servlet 是 JavaEE 规范之一,规范就是接口

​ 2. Servlet 是 JavaWeb 三大组件之一,分别是:Servlet 程序、Filter 过滤器、Listener 监听器

​ 3. Servlet 是运行在服务器上的 Java 小程序,它可以接受客户端发送过来的请求,并响应数据给客户端。

1.2. 动手实现 Servlet 程序

​ 1. 编写一个类去实现 Servlet 接口

​ 2. 实现 service 方法,处理请求并响应数据

​ 3. 到 web.xml 去配置 Servlet 程序的访问地址

<!-- Servlet tag is configuring Servlet program for Tomcat -->
    <servlet>
        <!-- servlet-name tag is give an alias to the servlet program (It's usually a class name) -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- servlet-class is full class name of the Servlet program -->
        <servlet-class>com.gregperlinli.Servlet.HelloServlet</servlet-class>
    </servlet>

    <!-- servlet-mapping tag is configure access address for servlet program -->
    <servlet-mapping>
        <!-- servlet-name tag is to tell the server the current server address to which servlet program to use-->
        <servlet-name>HelloServlet</servlet-name>
        <!-- url-pattern tag is configure access address
                /             When the slash is parsed by the server, it means that the address is: http://ip:port/projectPath
                /hello        The address is: http://ip:port/projectPath/hello
        -->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

​ 常见错误:

​ 1. url-pattern 中配置的路径没有以斜杠 / 打头

Invaid <url-pattern> hello in servlet mapping

​ 2. servlet-name 配置的值不存在

Servlet mapping specifies an unknown servlet name HelloServlet1

​ 3. servlet-class 标签的全类名配置错误

java.lang.ClassNotFoundException: ...

1.3. URL 地址到 Servlet 程序的访问

UrlToServlet

1.4. Servlet 程序的生命周期

​ 1. 执行 Servlet 的构造器方法

​ 2. 执行 init 初始化方法

​ 3. 执行 service 方法

​ 4. 执行 destory 销毁方法

​ 注意⚠️:第一、二步,是在第一次访问创建 Servlet 程序会调用,第三步每次访问都会调用,第四部在 Web 工程停止的时候调用

1.5. GET 和 POST 请求的分发处理

​ 示例代码:

public class HelloServlet implements Servlet &#123;
      /**
     * Service method is dedicated to handling requests and responses
     *
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException e
     * @throws IOException e
     */
        @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException &#123;
        System.out.println("Hello Servlet is visited");
        // Type transformation
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        // Access request mode
        String method = httpServletRequest.getMethod();
        System.out.println(method);

        if ( "GET".equals(method) ) &#123;
            doGet();
        &#125;
        if ( "POST".equals(method) ) &#123;
            doPost();
        &#125;
    &#125;

    /**
     * get request operate
     */
    public void doGet() &#123;
        System.out.println("GET request");
    &#125;

    /**
     * post request operate
     */
    public void doPost() &#123;
        System.out.println("POST request");
    &#125;
&#125;

1.6. 通过继承 HttpServlet 实现 Servlet 程序

​ 一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序

​ 1. 编写一个类去继承 HttpServlet 类

​ 2. 根据业务需要重写 doGet 或 doPost 方法

​ 3. 到 web.xml 中配置 Servlet 程序的访问地址

​ 示例代码:

​ Servlet 类的代码

/**
 * @author gregperlinli
 */
public class HelloHttpServlet extends HttpServlet &#123;
    /**
     * doGet() wil be called on GET request
     *
     * @param req
     * @param resp
     * @throws ServletException e
     * @throws IOException e
     */
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        System.out.println("Hello HttpServlet by doGet()");
    &#125;
    /**
     * doPost() wil be called on POST request
     *
     * @param req
     * @param resp
     * @throws ServletException e
     * @throws IOException e
     */
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        System.out.println("Hello HttpServlet by doPost()");
    &#125;
&#125;

​ web.xml 的代码

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
        <servlet>
        <servlet-name>HelloHttpServlet</servlet-name>
        <servlet-class>com.gregperlinli.Servlet.HelloHttpServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloHttpServlet</servlet-name>
        <url-pattern>/hello2</url-pattern>
    </servlet-mapping>
</web-app>

1.7. 使用 IDEA 创建 Servlet 程序

​ 1. 选择 src 下的包名,右键,然后点击 New > Create New Servlet

​ 2. 配置 Servlet 项(不要勾选创建 Java EE 6+ 注解类)

​ NewServlet

1.8. Servlet 类的继承体系

ServletImplementFamily

2. ServletConfig 类

​ ServletConfig 类从类名上看,就知道是 Servlet 程序的配置信息类

​ Servlet 程序和 ServletConfig 对象都是由 Tomcat 服务器负责创建,我们负责使用

​ Servlet 程序默认是第一次访问的时候创建,ServletConfig 是每个 Servlet 程序创建时,就创建一个对应的 ServletConfig 对象。

2.1. ServletConfig 类的三大作用

​ 1. 可以获取 Servlet 程序的别名 servlet-name 的值

​ 2. 获取初始化参数 init-parm

​ 3. 获取 ServletContext 对象

​ 示例代码:

​ Servlet 类的代码

/**
 * @author gregperlinli
 */
public class HelloServlet implements Servlet &#123;
    @Override
    public void init(ServletConfig servletConfig) throws ServletException &#123;
        System.out.println("init initialization method");
        // 1. You can get the value of the alias servlet-name of the servlet program
        System.out.println("The alias of HelloServlet is: " + servletConfig.getServletName());
        // 2. Get initialization parameters init-parm
        System.out.println("The value of initialization parameter username is: " + servletConfig.getInitParameter("username"));
        System.out.println("The value of initialization parameter url is: " + servletConfig.getInitParameter("url"));
        // 3. Get the ServletContext object
        System.out.println("The ServletContext object is: " + servletConfig.getServletContext());
    &#125;
&#125;

​ web.xml 中的配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!-- Servlet tag is configuring Servlet program for Tomcat -->
    <servlet>
        <!-- servlet-name tag is give an alias to the servlet program (It's usually a class name) -->
        <servlet-name>HelloServlet</servlet-name>
        <!-- servlet-class is full class name of the Servlet program -->
        <servlet-class>com.gregperlinli.Servlet.HelloServlet</servlet-class>
        <!-- init-param is the initialization parameters of the servlet program -->
        <init-param>
            <!-- Parameter name -->
            <param-name>username</param-name>
            <!-- Parameter value -->
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/test</param-value>
        </init-param>
    </servlet>
</web-app>

​ 注意⚠️:

​ 重写 init 方法时一定要调用父类

@Override
public void init(ServletConfig config) throws ServletException &#123;
    // If you want to override the init method, please enter the following sentence!
    super.init(config);
    System.out.println("Override the init initialization method and do some updated");
&#125;

3. ServletContext 类

3.1. 什么是 ServletContext ?

​ 1. ServletContext 是一个接口,它表示 Servlet 上下文对象

​ 2. 一个 Web 工程只有一个 ServletContext 对象实例

​ 3. ServletContext 对象是一个域对象

​ 4. ServletContext 是在 Web 工程创建的时候创建,在 Web 工程结束的时候销毁

​ 什么是域对象:

​ 域对象是可以像 Map 一样存储数据的对象,这里的域指的是存储数据的操作范围。

存数据 取数据 删除数据
Map put() get() remove()
域对象 setAttribute() getAttribute() removeAttribute()

3.2. ServletContext 类的四个作用

​ 1. 获取 web.xml 中配置的上下文参数 context-parm

​ 2. 获取当前的工程路径,格式:/projectPath

​ 3. 获取工程部署后在服务器磁盘上的绝对路径

​ 4. 像 Map 一样存取数据

​ 示例代码:

​ Servlet 类的代码

public class ContextServlet extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException &#123;
        // 1. Obtain web.xml context parameters configured in context-parm
        ServletContext context = getServletConfig().getServletContext();
        String username = context.getInitParameter("username");
        String password = context.getInitParameter("password");
        System.out.println("The context-parm parameter username is: " + username);
        System.out.println("The context-parm parameter password is: " + password);
        // 2. Get the current project path in the format of /projectPath
        System.out.println("The current project path is: " + context.getContextPath());
        // 3. Get the absolute path of the project on the server disk after deployment
        /**
         * / The slash is parsed by the server as: http://ip:port/projectName/      Web directory mapped to IDEA code
         */
        System.out.println("The absolute path of the project on the server disk is: " + context.getRealPath("/"));
        System.out.println("The absolute path of css directory under the project is: " + context.getRealPath("/css"));
        System.out.println("The absolute path of 1.jpg in img directory under the project is: " + context.getRealPath("/img/1.jpg"));
      ServletContext context = getServletContext();
        // 4. Access data like a Map
        context.setAttribute("key1", "value1");
        System.out.println("The value of domain data key1 in context is: " + context.getAttribute("key1"));
    &#125;

​ web.xml 中的配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <!-- context-parm is context parameters (It belongs to the whole web project) -->
    <context-param>
        <param-name>username</param-name>
        <param-value>context</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>root</param-value>
    </context-param>
      <servlet>
        <servlet-name>ContextServlet</servlet-name>
        <servlet-class>com.gregperlinli.Servlet.ContextServlet</servlet-class>
    </servlet>
      <servlet-mapping>
        <servlet-name>ContextServlet</servlet-name>
        <url-pattern>/contextServlet</url-pattern>
    </servlet-mapping>
</web-app>

4. HTTP 协议

4.1. 什么是 HTTP 协议

​ 什么是协议: 协议是指双方或多方相互约定好需要遵守的相关规定的规则。

​ 什么是 HTTP 协议: 就是指客户端与服务器之间通信时,发送的数据需要准遵守的规则。

​ HTTP 协议中的数据又叫报文。

4.2. 请求的 HTTP 协议格式

​ 客户端给服务器发送数据叫请求,服务器给客户回传数据叫响应。

​ 请求又分为 GET 请求和 POST 请求

​ 1. GET 请求

​ 请求行

​ (1)请求的方式 GET

​ (2)请求的资源路径[+?+请求参数]

​ (3)请求的协议版本号 HTML/1.1

​ 请求头

​ key:value 组成 不同的键值对表示不同的含义。

GetRequestData

​ 2. POST 请求

​ 请求行

​ (1)请求的方式 POST

​ (2)请求的资源路径[+?+请求参数]

​ (3)请求的协议版本号 HTML/1.1

​ 请求头

​ key:value 组成 不同的键值表示识不同的含义。

​ 空行

​ 请求体

​ 就是发送给服务器的数据

PostRequestData

​ 3. 常用请求头的说明

​ Accept:表示客户端可以接收的数据类型

​ Accept-Language:表示客户端可以接受的语言类型

​ User-Agnet:表示客户端浏览器的信息

​ Host:表示请求时服务器的 `IP 和端口号

​ 4. 哪些是 GET 请求,哪些是 POST 请求

​ GET 请求有哪些:

​ 1. from 标签 method=get

​ 2. a 标签

​ 3. link 标签引用 CSS

​ 4. script 标签引用 JavaScript

​ 5. img 标签引入图片

​ 6. iframe 引入 HTML 页面

​ 7. 在浏览器地址栏中输入地址后回车

​ POST 请求有哪些:

​ 1. from 标签 method=post

4.3. 响应的 HTTP 格式请求

​ 1. 响应行

​ (1)响应的协议和版本号 HTTP/1.1

​ (2)响应状态码 200

​ (3)响应状态描述符(不一定有) OK

​ 2. 响应头

​ (1) key:value 不同的响应头,有其不同的含义

​ 3. 空行

  1. 响应体

    ​ 回传给客户端的数据

4.4. 常见的响应码说明

​ 200 表示请求成功

​ 302 表示请求重定向

​ 404 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)

​ 500 表示服务器已经收到请求,但是服务器代码错误(内部错误)

​ 502 请求未完成。服务器充当网关或者代理的角色时,从上游服务器收到一个无效的响应。

4.5. MIME 类型说明

​ MIME 是 HTTP 协议中的数据类型

​ MIME 英文全称是 Multipurpose Internet Mall Extensions 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小类型”,并与某一文件的扩展名相对应

​ 常见的 MIME 类型

文件 MIME 类型
超文本标记语言文本 .html, .html text/html
普通文本 .txt txt/plain
RTF 文本 .rtf application/rtf
GIF 图形 .gif image/gif
JPEG 图形 .jpeg, .jpg image/jpeg
AU 声音文件 .au audio/basic
MIDI 音乐文件 .mid, .midi audio/midi, audio/x-midi
RealAudio 音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG 文件 .mpg, .mpeg video/mpeg
AVI 文件 .avi video/x-msvideo
GZIP 文件 .gz application/x-gzip
TAR 文件 .tar application/x-tar

5. HttpServletRequest 类

5.1. HttpServletRequest 类的作用

​ 每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会把请求过来的 HTTP 协议信息解析好并封装到 Request 对象中,然后传到 service 方法(doGet 和 doPost)中使用。我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。

5.2. HttpServletRequest 类的常用方法

​ getRequestURI() 获取请求的资源路径

​ getRequestURL() 获取请求的统一资源定位符(绝对路径)

​ getRemoteHost() 获取客户端的 IP 地址

​ getHeader() 获取请求头

​ getParameter() 获取请求的参数

​ getParameterValues() 获取请求的参数(多个值的时候使用)

​ getMethod() 获取请求的方式 GET 或 POST

​ setAttribute(key, value) 设置域数据

​ getAttribute(key) 获取域数据

​ getRequestDispatcher() 获取请求转发对象

​ 示例代码

/**
 * @author gregperlinli
 */
public class RequestAPIServlet extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        // 1. getRequestURI()
        System.out.println("URI ==>> " + req.getRequestURI());
        // 2. getRequestURL()
        System.out.println("URL ==>> " + req.getRequestURL());
        // 3. getRemoteHost()
        System.out.println("Remote host ==>> " + req.getRemoteHost());
        /**
         * When using localhost to access in idea, the IP address is ===> 127.0.0.1
         * When using 127.0.0.1 to access in idea, the IP address is ===> 127.0.0.1
         * When using the real IP address to access in idea, the IP address is ===> Real IP address
         */
        // 4. getHeader()
        System.out.println("Header User-Agent ==>> " + req.getHeader("User-Agent"));
        // 7. getMethod()
        System.out.println("Method ==>> " + req.getMethod());
    &#125;
&#125;

5.3. 如何获取请求参数

​ 示例代码

/**
 * @author gregperlinli
 */
public class ParameterServlet extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        System.out.println("-------------------- Do get --------------------");
        // Gets the parameters of the request
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobby");

        System.out.println("Username: " + username);
        System.out.println("Password: " + password);
        System.out.print("Hobby: ");
        if ( hobbies != null ) &#123;
            for ( String hobby : hobbies ) &#123;
                System.out.print(hobby + ", ");
            &#125;
        &#125;
        System.out.println();
    &#125;
  @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        // Set the character set of the request to UTF-8, so as to solve the problem of text garbled in the post request
        // The call is valid until the request parameter is obtained
        req.setCharacterEncoding("UTF-8");
        System.out.println("-------------------- Do post --------------------");
        // Gets the parameters of the request
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("Username: " + username);
        System.out.println("Password: " + password);
        System.out.print("Hobby: ");
        if ( hobbies != null ) &#123;
            for ( String hobby : hobbies ) &#123;
                System.out.print(hobby + ", ");
            &#125;
        &#125;
        System.out.println();
    &#125;
&#125;

​ 注意⚠️: 在用 POST 方法提交的时候,一定要在调用请求参数之前先使用 req.setCharacterEncoding("UTF-8"); 来设置请求体字符集为 UTF-8 格式,否则会出现 POST 请求的中文乱码问题

5.4. 请求转发

​ 什么是请求的转发:

​ 请求转发是指服务器收到请求后从一个资源跳转到另一个服务器资源的操作。

RequestDispatcher

​ 请求转发的特点

​ 1. 浏览器地址栏没有变化

​ 2. 它们是一次请求

​ 3. 它们共享 Request 域中的数据

​ 4. 可以转发到 WEB-INF 目录下(在客户端无法访问)

​ 5. 只能在工程以内转发

​ 示例代码

​ Servlet1.java

/**
 * @author gregperlinli
 */
public class Servlet1 extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        // Gets the parameters of the request (Materials for handling affairs) to check
        String username = req.getParameter("username");
        System.out.println("Check the parameter username in Servlet1 (counter 1): " + username);
        // Seal the material and pass it to Servlet2 (counter2) to check
        req.setAttribute("key", "Seal1");
        // Ask for directions: Servlet2 (counter2)
        /**
         * Request forwarding must start with a slash.
         * The address indicated by the slash is: http://ip:port/ProjectName/,
         * mapped to the web directory of idea code
         */
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
        // Towards Servlet2 (counter2)
        requestDispatcher.forward(req, resp);
    &#125;
&#125;

​ Servlet2.java

/**
 * @author gregperlinli
 */
public class Servlet2 extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        // Gets the parameters of the request (Materials for handling affairs) to check
        String username = req.getParameter("username");
        System.out.println("Check the parameter username in Servlet2 (counter 2): " + username);
        // Check whether servlet1 (counter1) has a seal
        Object key = req.getAttribute("key");
        System.out.println("Does Servlet1 (counter1) have a seal: " + key);
        // Handle the own business
        System.out.println("Servlet 2 is handling the own business");

    &#125;
&#125;

5.5. base 标签的作用

​ 所有相对路径在工作时候都会参照当前浏览器地址栏中的地址来进行查询;而当使用请求转发的时候,浏览器的地址是不变的,所以参照的地址也会发生变化,这就需要靠 base 标签来保证和原来的地址一致

​ base 标签可以设置当前页面中所有相对路径工作时,参照哪个路径来进行跳转

​ base 标签中最后的资源名是可以省略的,但是斜杠 / 不能省略

​ 示例代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>C</title>
    <!-- base tag sets the address to be referenced when the page works relative to the path
         href attribute is the address value of the parameter
    -->
    <base href="http://localhost:8080/ServletRequest/a/b/"/>
    <style type="text/css">
        body &#123;
            font-family: Futura, "PingFang SC", Helvetica, Arial, sans-serif;
        &#125;
    </style>
</head>
<body>
    <h1>
        This is the C.html page under a and b
    </h1>
    <br/>
    <a href="../../index.jsp">Back to index</a>
</body>
</html>

5.6. Web 中的相对路径和绝对路径

​ 在 JavaWeb 中,路径分为相对路径和绝对路径两种

​ 相对路径:

​ . 表示当前目录

​ .. 表示上一级目录

​ 资源名 表示当前目录下的资源名

​ 绝对路径:

​ http://ip:port/projectName/resourceName

5.7. Web 中 /斜杠的不同意义

​ 在 Web 中, / 斜杠是一种绝对路径

​ / 斜杠如果被浏览器解析,得到的地址是: http://ip:port/

​ / 斜杠如果被服务器解析,得到的地址是:http://ip:port/projectName

​ 1. <url-pattern>/servlet1</url-pattern>

​ 2. servletContext.getRealPath("/");

​ 3. request.getRequestDispatcher("/")

​ 特殊情况:

​ response.sendRedirect("/"); 把斜杠发送给浏览器解析,得到 http://ip:port/(请求重定向)

6. HttpServletResponse 类

6.1. HttpServletResponse 类的作用

​ HttpServletResponse 类和 HttpServletRequest 类一样,每次请求进来,Tomcat 服务器都会创建一个 Response 对象传递给 Servlet 程序去使用,HttpServletRequest 表示请求过来的信息,HttpServletResponse 表示所有响应的信息。

​ 如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置。

6.2. 两个输出流的说明

​ 字节流 getOutputStream(); 常用于下载(传递二进制代码)

​ 字符流 getWriter(); 常用于回传字符串(常用)

​ 注意⚠️: 两个流同时只能使用一个,即使用了字节流,就不能使用字符流,反之亦然,否则就会报错。

6.3. 如何往客户端回传数据

​ 要求:往客户端回传字符串数据

​ 示例代码:

/**
 * @author gregperlinli
 */
public class ResponseIOServlet extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        // Request: return data to client
        PrintWriter writer = resp.getWriter();
        writer.write("response's content!!!");
    &#125;
&#125;

6.4. 响应的乱码解决

​ 示例代码:

​ 第一种方法

/**
 * @author gregperlinli
 */
public class ResponseIOServlet extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        // System.out.println(resp.getCharacterEncoding());    // ISO-8859-1 default
        // Set the server character set to UTF-8
        resp.setCharacterEncoding("UTF-8");
        // Through the response header, set the browser to also use UTF-8 character set
        resp.setHeader("Content-Type", "text/html; charset=UTF-8");
        // Request: return data to client
        PrintWriter writer = resp.getWriter();
        writer.println("response's content!!!");
        writer.println("返回数据!!!");
    &#125;
&#125;

​ 第二种方法(推荐)

/**
 * @author gregperlinli
 */
public class ResponseIOServlet extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        // System.out.println(resp.getCharacterEncoding());    // ISO-8859-1 default
        // It sets both the server and the client to use the UTF-8 character set, and also sets the response header
        // ATTENTION: This method must be invoked before obtaining the stream object.
        resp.setContentType("text/html; charset=UTF-8");
        // Request: return data to client
        PrintWriter writer = resp.getWriter();
        writer.println("response's content!!!");
        writer.println("返回数据!!!");
    &#125;
&#125;

​ 注意⚠️: 此方法一定要在获取流对象之前调用才有效!

6.5. 请求重定向

​ 请求重定向是指客户端给服务器发请求,服务器返回给客户端一个新地址,并让服务端去访问新地址(因为之前的地址可能已经被废弃)。

RequestRedirect

​ 请求重定向的特点:

​ 1. 浏览器地址栏回发生变化

​ 2. 两次请求

​ 3. 不共享 Request 域中的数据

​ 4. 不能访问 WEB-INF 下的资源

​ 5. 可以访问工程以外的资源

​ 示例代码:

​ 方案一

​ Response1.java

/**
 * @author gregperlinli
 */
public class Response1 extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        System.out.println("Goodbye Response1!");
        // Set response status code 302 to indicate redirection (relocated)
        resp.setStatus(302);
        // Set the response header to indicate where the new address is
        resp.setHeader("Location", "http://localhost:8080/ServletRequest/response2");
    &#125;
&#125;

​ Response2.java

/**
 * @author gregperlinli
 */
public class Response2 extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        System.out.println("Hello Response2!");
        resp.getWriter().println("Response2 result");
    &#125;
&#125;

​ 方案二(推荐)

​ Response1.java

/**
 * @author gregperlinli
 */
public class Response1 extends HttpServlet &#123;
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException &#123;
        System.out.println("Goodbye Response1!");    
        resp.sendRedirect("http://localhost:8080/ServletRequest/response2");
    &#125;
&#125;

​ Response2.java 与方案一的一致



文章作者: gregPerlinLi
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 gregPerlinLi !
  目录