[Java | Web] JavaWeb——Servlet 简介

目录

一、Servlet 概念

1、简介

2、简单实现一个 demo

3、url 地址如何访问到 servlet 程序

4、Servlet 生命周期

5、GET 和 POST 请求的分发处理

6、继承 HttpServlet 类实现 service 方法

二、Servlet 类

1、继承体系

2、ServletConfig 类

3、ServletContext 类

三、Http 协议

1、简介

2、请求的 HTTP 协议格式

3、常用请求头

4、如何区分 GET 和 POST 请求

5、响应的 HTTP 协议格式

6、常见的响应码说明

7、MIME 类型说明

四、HttpServletRequest 类

1、HttpServletRequest 常用方法

2、post 请求中文乱码

3、请求的转发

 4、<base> 标签的作用

5、路径复习

五、HttpServletResponse 类

1、HttpServletResponse 的作用

2、两个输出流

3、向客户端回传数据

4、浏览器显示响应中文乱码

5、请求重定向


一、Servlet 概念

1、简介

Servlet 是 JavaEE 规范之一。规范就是接口(Interface)。

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

Servlet 是运行在服务器上的一个 java 小程序,它可以通过 HTTP 接收客户端发送过来的请求,并响应数据给客户端

2、简单实现一个 demo

(1)编写一个类去实现 Servlet 接口;

(2)实现一个重要方法 service(),处理请求并响应数据;

(3)服务器上的数据都需要访问地址,到 web.xml 中去配置 servlet 程序的访问地址;

注意,该 web.xml 文件,必须是被部署的 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 标签给 tomcat 服务器配置servlet程序 -->
    <servlet>
        <!-- servlet-name标签 是 servlet 程序的一个别名(一般设置为 java 程序的类名) -->
        <servlet-name>servlet_demo</servlet-name>
        <!--  servlet-class标签 是 servlet 程序的完整类名-->
        <servlet-class>test.servlet_demo</servlet-class>
    </servlet>

    <!-- servlet-mapping标签 给 servlet 程序配置访问地址-->
    <servlet-mapping>
        <!-- servlet-name 标签的作用是,告诉服务器,当前配置的地址,是哪一个 servlet 程序使用的-->
        <servlet-name>servlet_demo</servlet-name>
        <!-- url-pattern 标签 配置访问地址
            / 斜杠,在服务器解析的时候,表示地址为:http://ip:port/工程路径
            则 /start 表示 http://ip:port/工程路径/start
        -->
        <url-pattern>/start</url-pattern>
    </servlet-mapping>

</web-app>

 其中,工程路径就是,部署在 tomcat 服务器上的 web 工程。

(4)启动 tomcat 服务器,访问 index.jsp;

 (5)补充访问地址 /start,启动 servlet 程序;

 IDEA 的控制台就会做相应的 service() 的操作:

3、url 地址如何访问到 servlet 程序

4、Servlet 生命周期

(1)执行 Servlet 构造方法;

(2)执行 init 初始化方法;

(3)执行 service 方法;

(4)执行 destroy 销毁方法;

前两步只会在第一次访问时执行一次,每次刷新只会重新执行 service 方法;第四步在 Web 工程停止的时候调用。

5、GET 和 POST 请求的分发处理

(1)编写一个包含表单提交的 html 页面:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action = "http://localhost:8080/JavaEnterprise_war_exploded/start" method = "get">
        <input type = "submit" value = "submit"/>
    </form>
</body>

 启动 tomcat 访问:

(2)修改 service 方法,分类处理请求:

@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    System.out.println("servlet 被访问了");
    // HttpServletRequests 是 ServletRequest 子接口,有获取请求类型的方法:getMethod()
    HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
    String method = httpServletRequest.getMethod();
    if (method.equalsIgnoreCase("get")) {
        System.out.println("这是 get 请求");
    } else if (method.equalsIgnoreCase("post")) {
        System.out.println("这是 post 请求");
    }
}

(3)点击提交按钮,发起 GET 请求,再修改 html 页面,发送 POST 请求:

6、继承 HttpServlet 类实现 service 方法

在实际开发中,很少通过实现 servlet 接口这种方式实现 servlet 程序。一般是找 Servlet 的子类去继承,HttpServlet 用的比较多。

(1)编写一个类去继承 HttpServlet 类;

(2)根据需要重写 doGet() 或 doPost() 两个方法;

(3)到 web.xml 配置 Servlet 程序的访问地址;

package test;

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

public class servlet_demo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet方法");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost方法");
    }
}

7、IDEA 自动生成 Servlet 程序

(1)新建

(2)更改类名和全类名

(3)IDEA 会在 web.xml 生成代码,只需要配置 <serlvet_mapping> 即可

二、Servlet 类

1、继承体系

2、ServletConfig 类

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

(1)三大作用

  • 可以获取 Servlet 程序的别名,也就是 servlet-name 的值;
  • 获取初始化参数 init-param;
  • 获取 Servlet-Context 对象;

使用实现接口类,其中有 init() 方法,在 init() 中实现:

Java 代码:

package test;

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

public class servlet_demo_implements implements Servlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        // 可以获取 Servlet 程序的别名,也就是 servlet-name 的值;
        System.out.println("servlet 程序的别名(默认用类名)是:" + servletConfig.getServletName());
        // 获取初始化参数 init-param;
        System.out.println("初始化参数username的值是:" + servletConfig.getInitParameter("userName"));
        System.out.println("初始化参数url的值是:" + servletConfig.getInitParameter("url"));
        // 获取 Servlet-Context 对象;
        System.out.println("ServletContext对象:" + servletConfig.getServletContext());
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {

    }
}

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>servlet_demo_implements</servlet-name>
        <servlet-class>test.servlet_demo_implements</servlet-class>

        <init-param> <!-- 可以配置多个 -->
            <param-name>userName</param-name> <!-- 参数名 -->
            <param-value>name_1</param-value> <!-- 参数值 -->
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>http://114514:8080</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>servlet_demo_implements</servlet-name>
        <url-pattern>/begin</url-pattern>
    </servlet-mapping>

</web-app>

输出结果:

(2)补充

(2-1)getServletConfig()

Servlet 程序和 ServletConfig 对象都是由 Tomcat 负责创建,我们负责调用。

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

因此,如果在一个 Java 程序中使用 getServletConfig() 这个方法获取得到的 ServletConfig 对象,是不能访问到该 Java 程序之外的 config 信息的

(2-2)HttpServlet 重写 init()

因为默认情况下,继承 HttpServlet 是不需要实现 init() 的。

但是因为某些理由需要重写 init() 时,需要调用 super(config),否则调用 ServletConfig 对象会导致空指针:

package test;

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

public class servlet_demo extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println("重写了 init 方法");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet方法");
        ServletConfig config = getServletConfig();
        System.out.println("初始化参数 id 的值为:" + config.getInitParameter("id"));
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost方法");
    }
}

3、ServletContext 类

(1)什么是 ServletContext ?

  • ServletContext 是一个接口,他表示 Servlet 上下文对象;
  • 一个 Web 工程,只有一个 ServletContext 对象实例;
  • ServletContext 对象是一个域对象;

(2)什么是“域对象”?

域对象是指,可以像 Map 一样存取数据的对象。这里的域指的是,存取数据的操作范围,也就是整个 Web 工程。

若 Web 工程有多个 Servlet 程序,访问过的 Servlet 程序做出的操作是会保存到 context 中的。只要 Web 工程不停止,context 的内容就是实时的

举个例子:Servlet 程序 A,做了存数据操作,那么 Servlet 程序 B,就可以访问到这个数据。

因此 Web 和 Servlet 的关系可以这么理解:Web 工程的许多信息,比如 ServletContext,可以使用 Servlet 程序进行操作。 

(3)ServletContext 类的四个作用

  • 获取 web.xml 中配置的上下文参数 context-param;
  • 获取当前的工程路径,格式:/工程路径;
  • 获取工程部署后,在服务器硬盘上的绝对路径;
  • 像 Map 一样存取数据;
package test;

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

public class ServletContext_test extends HttpServlet {

    private ServletContext context;

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        context = getServletConfig().getServletContext(); // 也可以写 context = getServletContext();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
        // 1.获取 web.xml 中配置的上下文参数 context-param;
        System.out.println("context-param 参数 userName 的值是:" + context.getInitParameter("userName"));
        System.out.println("context-param 参数 url 的值是:" + context.getInitParameter("url"));
        // 2.获取当前的工程路径,格式:/工程路径;
        System.out.println("当前工程路径:" + context.getContextPath());
        // 3/获取工程部署后,在服务器硬盘上的绝对路径;
        System.out.println("工程部署的服务器硬盘绝对路径:" + context.getRealPath("/"));
        System.out.println("工程下 html 目录的绝对路径是:" + context.getRealPath("/html"));
        /*
            / 斜杠代表:http://ip:port/工程名/,因此写一个 / 即可
            其意义为:映射到 IDEA 的 webapp 目录,可以直接在磁盘上访问该绝对路径
        */
        // 4.像 Map 一样存取数据;
        System.out.println("设置之前:context 获取到 key1 的值为:" + context.getAttribute("key1"));
        context.setAttribute("key1", "value1");
        System.out.println("context 中获取域数据 key1 的值是:" + context.getAttribute("key1"));
    }

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

    }
}

三、Http 协议

1、简介

HTTP 协议是指,客户端与服务器通信时,需要遵守的规则,叫做 HTTP 协议。HTTP 协议中的数据又叫报文。

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

2、请求的 HTTP 协议格式

请求分为 GET 和 POST 请求。

(1)GET 请求

(1-1)GET 请求的 HTTP 协议格式:

1、请求行
    (1)请求的方式:默认 GET 字符串
    (2)请求的资源路径 + [? + 请求参数]
    (3)请求的协议的版本号:默认 HTTP/1.1
2、请求头
    由 key:value 组成,不同的键值对表示不同的含义

(1-2)抓包:

(1-3)分析:

(2)POST 请求

(2-1)POST 请求的 HTTP 协议格式:

1、请求行
    (1)请求的方式:默认 GET 字符串
    (2)请求的资源路径 + [? + 请求参数]
    (3)请求的协议的版本号:默认 HTTP/1.1
2、请求头
    由 key:value 组成,不同的键值对表示不同的含义
3、空行
4、请求体
    就是发送给服务器的数据

(2-2)抓包:

(2-3)分析:

(3)测试代码

HTML:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action = "http://localhost:8080/JavaEnterprise_war_exploded/start" method = "POST">
        <!-- 将表单发送给 tomcat 服务器,并执行相应的 servlet 程序 -->
        <input type = "hidden" name = "action" value = "login"/>
        <input type = "hidden" name = "username" value = "root"/>
        <input type = "submit" value = "submit"/>
    </form>
</body>

Java(Servlet 程序):

package test;

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

public class servlet_demo extends HttpServlet {
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println("重写了 init 方法");
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet方法");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost方法");
    }
}

3、常用请求头

  • Accept:表示客户端可以接收的数据类型;
  • Accept-Languege:表示客户端可以接收的语言类型;
  • User-Agent:表示客户端浏览器信息;
  • Host:表示请求的服务器 ip 和 port;

4、如何区分 GET 和 POST 请求

(1)GET 请求有:

  • form 标签 method = get;
  • a 标签;
  • link 标签引入 css 文件;
  • script 标签引入 js 文件;
  • img 标签引入 图片;
  • iframe 标签引入 html 页面;
  • 在浏览器地址栏输入地址进行访问;

(2)POST  请求有:

  • form 标签 method = post;

5、响应的 HTTP 协议格式

(1)格式

1、响应行
    (1)响应的协议和版本号    HTTP/1.1
    (2)响应状态码    200(200表示响应成功)
    (3)响应状态描述符    ok
2、响应头
    (1)key :value    不同的响应头,有不同的含义
3、空行
4、响应体
    回传给客户端的数据

(2)抓包

(2-1)响应行 + 响应头:

(2-2)响应体:

(3)分析:

6、常见的响应码说明

  • 200:表示请求成功;
  • 302:表示请求重定向;
  • 404:表示请求已经被服务器接收,但是目标数据不存在(一般是请求地址错误);
  • 500:表示服务器已经收到请求,但是服务器内部错误(代码错误);

7、MIME 类型说明

MIME 是 HTTP 协议中的数据类型。“Multipurpose Internet Mail Extensions”:多功能 Internet 邮件扩充服务。

MIME 的格式是“大类型/小类型”,并与某一种文件的拓展名相对应。

四、HttpServletRequest 类

我们可以通过 HttpServletRequest 对象,获取到所有请求的信息。

每次只要有请求进入 Tomcat 服务器,Tomcat 服务器就会创建 HttpServletRequest 对象,把请求的 HTTP 协议信息解析后封装到 HttpServletRequest 对象中。(每次请求都会创建一个,请求完成就会销毁

1、HttpServletRequest 常用方法

(1)测试一

  • getRequestURI():获取请求的资源路径
  • getRequestURL():获取请求的统一资源定位符(绝对路径)
  • getRemoteHost():获取客户端 ip 地址
  • getHeader():获取请求头
  • getMethod():获取请求的方式(GET 或 POST)
package test;

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

public class RequestAPIServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // super.doGet(req, resp); 这个不需要,这是调用父类 HttpServlet 的 doget
        // getRequestURI():获取请求的资源路径
        System.out.println("URI ==> " + req.getRequestURI());
        // getRequestURL():获取请求的统一资源定位符(绝对路径)
        System.out.println("URL ==> " + req.getRequestURL());
        // getRemoteHost():获取客户端 ip 地址
        /*
            使用 localhost / 127.0.0.1 访问,得到的都是 127.0.0.1;
            使用真实 ip 访问,得到的就是真实 ip。
         */
        System.out.println("客户端 ip 地址 ==> " + req.getRemoteHost());
        // getHeader():获取请求头
        System.out.println("请求头 User-Agent ==> " + req.getHeader("User-Agent"));
        // getMethod():请求的方式
        System.out.println("请求的方式 ==> " + req.getMethod());
    }
}

(2)测试二

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

访问 HTML 页面,完成表单的提交,提交给 servlet 程序

(2-1)HTML 代码:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action = "http://localhost:8080/JavaEnterprise_war_exploded/start_ParameterServlet" method = "GET">
        用户名:<input type = "text" name = "username" value = "default"/> <br/>
        密码:<input type = "password" name = "password" value = "default"/> <br/>
        兴趣爱好:
        <input type = "checkbox" name = "hobby" value = "C++"/> C++
        <input type = "checkbox" name = "hobby" value = "Python"/> Python
        <input type = "checkbox" name = "hobby" value = "Java"/> Java
        <br/>
        <input type = "submit" value = "submit"/>
    </form>
</body>

(2-2)Java 代码:

package test;

import javax.servlet.ServletException;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.Arrays;

public class ParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取 一个 请求参数
        System.out.println("用户名:" + req.getParameter("username"));
        System.out.println("密码:" + req.getParameter("password"));
        // 获取 多个个 请求参数
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("兴趣爱好:" + Arrays.asList(hobbies));

    }
}

(2-3)效果:

(3)其他方法

  • setAttribute(key, value):设置域数据
  • getAttribute(key):获取域数据
  • getRequestDispatcher():获取请求转发对象

2、post 请求中文乱码

使用 setCharacterEncoding("UTF-8") 设置字符集。

protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    // 设置请求字符集为 UTF-8,解决 post 请求中文乱码问题,注意,必须在获取请求参数之前调用
    req.setCharacterEncoding("UTF-8");
    System.out.println("用户名:" + req.getParameter("username"));
}

3、请求的转发

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

(1)编写代码

(1-1)Java 代码1:

package test;

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

public class Servlet1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求的参数
        String username = req.getParameter("username");
        System.out.println("在 Servlet1(柜台1) 中查看参数(材料):" + username);

        // 给材料盖章,并传递到 Servlet2(柜台2)
        req.setAttribute("key", "Servlet1 的章");

        // 问路,如何去 Servlet2
        /*
            请求转发必须以 / 开头,表示:http://ip:port/工程名/,与之前的 / 的意义相同
            映射到 IDEA 代码的 web 工程目录,也就是与 web.xml 中配置的 url 相同。
         */
        RequestDispatcher requestDispatcher =req.getRequestDispatcher("/start_Servlet2");
        // 访问 WEB-INF 目录内的资源可以写 "/WEB-INF/xxx.xxx"

        // 走向 Servlet2
        requestDispatcher.forward(req, resp);
    }
}

(1-2)Java 代码2:

package test;

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

public class Servlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求的参数
        /*
            Servlet2 的 req 与 Servlet1 的 req 是同一个,是通过 forword 将请求转发到 Servlet2。
            可以理解为,Servlet1 是登录页面,Servlet2 是登陆后进入的主页面
         */
        String username = req.getParameter("username");
        System.out.println("在 Servlet2(柜台2) 中查看参数(材料):" + username);

        // 检查是否有 Servlet1 的盖章
        Object key = req.getAttribute("key");
        System.out.println("Servlet1 是否盖章:" + key);

        // 处理自己的业务
        System.out.println("Servlet2 处理自身业务。。。。。");
    }
}

(2)向 Servlet1 发送请求,并添加参数

(3)访问 Servlet1 成功,请求转发给 Servlet2 成功

(4)请求转发的特点

  • 访问的地址不会发生改变:都是对 Servlet1 的访问,但由 Servlet1 将请求转发至 Servlet2
  • 是同一次请求
  • 共享 Request 域中的数据
  • 可以访问 WEB-INF 目录:直接对 WEB-INF 的访问是做不到的,但是可以通过转发间接访问
  • 不能访问 Web 工程以外的资源:因为根地址就是 Web 工程目录

 4、<base> 标签的作用

浏览器解析时会在路径前加上 <base> 给的目标,而页面中的相对路径也都转换成了绝对路径(也就是说,在 base 标签引入后的所有 url,都是绝对路径,只是写法与相对路径一致)。

需要注意的是,如果使用 base 标签,则必须出现在所有 url 之前

(1)首先定义两个 html 页面:

web/index.html:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href = "html/b/c.html">跳转至html/b/c.html页面</a>
</body>

web/html/b/c.html:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href = "../../index.html">跳转至index.html</a>
</body>

效果:这两个页面可以通过点击 a 标签实现相互跳转

(2)使用请求转发跳转

给 index.html 添加 Servlet 程序的链接,使用该链接,观察是否还能实现这两个 html 页面的相互跳转。

web/index.html:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href = "html/b/c.html">跳转至html/b/c.html页面</a> <br/>
    <a href = "http://localhost:8080/JavaEnterprise_war_exploded/start_ForwardChtml">请求转发</a>
</body>

Java 代码:

public class ForwardChtml extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("经过了 ForwordChtml 程序");
        req.getRequestDispatcher("/html/b/c.html").forward(req, resp);
    }
}

当点击返回 index.html 时,就会出现以下情况:

(3)原因

显然是因为点击返回 index.html 时,参照的相对路径有问题。

当通过请求转发访问 c.html 时,路径为:

http://localhost:8080/JavaEnterprise_war_exploded/start_ForwardChtml

那么以此为基础,../../index.html 会使得访问路径变为:

http://localhost:8080/index.html

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

(4)最后的修改

web/html/b/c.html:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- base 标签设置页面相对路径工作时参照的地址
            href属性就是参照的地址值,c.html 可以省略
    -->
    <base href = "http://localhost:8080/JavaEnterprise_war_exploded/html/b/c.html"/>
</head>
<body>
    <a href = "../../index.html">跳转至index.html</a>
</body>

这样就完成了 base 标签的作用。

5、路径复习

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

(1)相对路径:

  • .        表示当前目录
  • ..        表示上一级目录
  • 资源名        表示当前目录/资源名

(2)绝对路径:

http://ip:port/工程名/资源路径

(3)/ 斜杠意义:

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

(3-1)/ 斜杠如果被浏览器解析,得到的路径是:http://ip:port/

<a href = "/">斜杠</a>

(3-2)/ 斜杠如果被服务器解析,得到的地址是:http://ip:port/工程路径

<url-pattern>/start_servlet</url-pattern>
servletContext.getRealPath("/");
request.getRequestDispatcher("/");

(3-3)特殊情况

response.sendRedirect("/");

把斜杠发给浏览器解析,得到:http://ip:port/

五、HttpServletResponse 类

1、HttpServletResponse 的作用

  • HttpServletResponse 类和 HttpServletRequest 类一样,Tomcat 服务器会为每次请求创建一个 Response 对象,将其传递给 Servlet 程序去使用。
  • HttpServletRequest 表示请求的信息,HttpServletResponse 表示所有响应的信息。
  • 如果需要设置返回给客户端的信息,都可以通过 HttpServletResponse 对象进行设置。

2、两个输出流

HttpServletResponse 返回给客户端的数据是怎么传输的呢?是通过“流”来传输的。

两个流在同一时间只能使用一种,否则会错误。

(1)字节流

使用 response.getOutputStream() 获取。常用于下载(传递二进制数据)。

(2)字符流

使用 response.getWriter() 获取。常用于回传字符串(常用)。

3、向客户端回传数据

(1)发送字符串数据

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.write("there is response's content.");
    }
}

4、浏览器显示响应中文乱码

(1)第一种方法:服务器和客户端浏览器的编码设置要一样,且需要支持中文。

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置服务器字符集为 UTF-8
        resp.setCharacterEncoding("UTF-8");

        // 通过响应头,设置浏览器也要使用 UTF-8
        resp.setHeader("Content-Type", "text/html; charset=UTF-8");

        PrintWriter writer = resp.getWriter();
        writer.write("there is response's content.");
        writer.write("这是响应内容。");
    }
}

(2)第二种方法:setContentType()

public class ResponseIOServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=UTF-8");
        // 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置响应头。
        // 此方法一定要在获取 流对象 之前调用。
        PrintWriter writer = resp.getWriter();
        writer.write("there is response's content.");
        writer.write("这是响应内容。");
    }
}

5、请求重定向

请求重定向是指,客户端给服务器发送请求,然后服务器给客户端一个新的地址,要求客户端访问新地址。(通常因为旧地址已经被废弃,这个旧地址包括但不限于一些 Servlet 程序或资源)

(1)请求重定向第一种方法:

(1-1)编写两个 Servlet 程序,分别代表两个 Response

public class Response1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置请求域数据
        req.setAttribute("key", "value");

        System.out.println("访问 Response1");
        // 设置响应状态码 302,表示已搬迁
        resp.setStatus(302);
        // 设置响应头,说明新的地址在哪里
        /*
            注意这里是浏览器请求,地址需要写完整
            不同于 Servlet 的请求转发,可以使用相对路径
         */
        resp.setHeader("Location", "http://localhost:8080/JavaEnterprise_war_exploded/start_Response2");
    }
}
public class Response2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取请求域数据
        resp.setContentType("text/html; charset=UTF-8");

        System.out.println("请求域数据:" + req.getAttribute("key"));
        resp.getWriter().write("这是 Response2 的响应数据");
    }
}

(1-2)访问结果

(1-3)请求重定向的特点

  • 浏览器地址会发生变化(请求转发的地址就不会改变)
  • 有两次请求
  • 不共享 Request域 中的数据(因为第二次产生的是一个新的 request 对象)
  • 不能访问 WEB-INF 下的资源(因为第二次还是浏览器进行请求,而 WEB-INF 是不会被浏览器访问的)
  • 可以访问 Web 工程外的资源

(2)请求重定向的第二种方法(推荐使用):

public class Response1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("访问 Response1");

        resp.sendRedirect("http://localhost:8080/JavaEnterprise_war_exploded/start_Response2");
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ServletJavaEE 规范中的一部分,是处理 Web 请求的组件。Servlet 运行在服务器端,能够接收客户端发来的请求,并给客户端响应结果。下面我们来看看 Servlet 的基本概念和使用方法。 ## 一、Servlet 的基本概念 ### 1.1 Servlet 的生命周期 Servlet 的生命周期包含以下三个阶段: - 初始化阶段(init):当 Servlet 实例化后,Web 容器会调用其 init() 方法进行初始化操作。在此阶段,Servlet 可以执行一些初始化操作,例如读取配置信息、建立数据库连接等。 - 请求处理阶段(service):当客户端发来请求时,Web 容器会创建一个线程调用 Servlet 的 service() 方法处理请求。在此阶段,Servlet 可以获取请求参数、处理请求并生成响应数据。 - 销毁阶段(destroy):当 Web 应用停止或 Servlet 被卸载时,Web 容器会调用 Servlet 的 destroy() 方法进行清理工作。在此阶段,Servlet 可以释放资源、关闭数据库连接等。 ### 1.2 Servlet 的配置 在使用 Servlet 时,需要在 web.xml 文件中进行配置。以下是一个 Servlet 的基本配置: ```xml <servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.example.MyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>MyServlet</servlet-name> <url-pattern>/myservlet</url-pattern> </servlet-mapping> ``` 其中,servlet-name 表示 Servlet 的名称,servlet-class 表示 Servlet 的类名,url-pattern 表示请求的 URL 匹配规则。 ## 二、Servlet 的使用方法 ### 2.1 编写 Servlet 编写 Servlet 有两种方法:一种是继承 HttpServlet 类,另一种是实现 Servlet 接口。这里以继承 HttpServlet 类为例: ```java public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 处理 GET 请求 PrintWriter out = resp.getWriter(); out.println("Hello, world!"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 处理 POST 请求 PrintWriter out = resp.getWriter(); out.println("Hello, world!"); } } ``` 在 Servlet 中,doGet() 方法用于处理 GET 请求,doPost() 方法用于处理 POST 请求。通过调用 HttpServletResponse 对象的 getWriter() 方法可以向客户端返回响应数据。 ### 2.2 部署 Servlet 将编写好的 Servlet 部署到 Web 容器中,有两种方法:一种是将 Servlet 类打成 war 包放到 Web 容器的 webapps 目录下,另一种是通过 Eclipse 等开发工具将 Servlet 部署到 Web 容器中。部署完成后,可以通过访问 Servlet 的 URL 来测试 Servlet 是否正常工作。 ## 三、总结 本文介绍了 Servlet 的基本概念和使用方法。ServletJava Web 开发中非常重要的组件,掌握 Servlet 的使用方法对于 Java Web 开发人员来说是必不可少的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值