Http Xml Servlet

发布时间 2023-03-26 17:54:06作者: 人工代码改变世界

Servlet

概述

访问网站时,我们都是基于Web Browser/Server这种模式,简称BS框架。

Servlet 是 Java Servlet的简称,称为小服务程序 或 服务连接器,用java编写的服务器端程序,具有独立于平台和协议的特性,是运行在web 服务器 或 应用于 服务器上的程序。

HTTP协议

基于TCP协议之上的请求-响应协议

2.1 HTTP 协议概述

​ 超文本传输协议(Hyper Text Transfer Protocol,HTTP)是一个简单的请求【Request】-响应【Response】协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。请求和响应消息的头以ASCII形式给出;而 消息内容则具有一个类似MIME的格式。这个简单模型是早期Web成功的有功之臣,因为它使开发和部署非常地直截了当。

MIME 邮箱支持文件形式协议,可以支持音频,视频,图片,各类文件。

2.2 浏览器请求服务器资源的简要概述信息

# 请求 URL 
Request URL: https://www.baidu.com/
# 请求方式
Request Method: GET
# 响应状态码
Status Code: 200 OK
# 请求服务器 IP 地址和端口号
Remote Address: 39.156.66.14:443
# 引用的协议【跨域支持】
Referrer Policy: strict-origin-when-cross-origin

2.2 HTTP 协议请求头 Request

# 浏览器提交数据的形式为 GET 请求方式,
# / 请求资源是当前服务器的根目录资源 
# HTTP/1.1 表示当前的请求的协议使用的 HTTP/1.1 协议
GET / HTTP/1.1
# 告知 服务器当前 浏览器支持的数据类型
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
# 当前浏览器支持的相关文件类型
Accept-Encoding: gzip, deflate, br
# 浏览器支持的语言
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,zh-TW;q=0.6
# 表示保持连接状态
Connection: keep-alive
# 【核心知识点】会话控制技术,对应 Cookie and Session 可以用于存储用户的相关数据,浏览信息,【令牌】
Cookie: PSTM=1649475867; BIDUPSID=9F672DC1210F6FE52BA93CE7B740D0C4; 
BAIDUID=FD51757FEC2FB00A454A8309BEB8C23D:SL=0:NR=10:FG=1; 
BD_UPN=12314753;

2.3 HTTP 协议响应头 Response

# 当前响应对应的协议包括状态码 当前表明使用的协议是 HTTP/1.1 协议,同时状态码是 200
HTTP/1.1 200 OK
Bdpagetype: 2
# baidu 根据业务所需,自行指定的响应头数据
Bdqid: 0xd1389d9f001ba7aa
# 表示保持连接状态
Connection: keep-alive
# Content 内容 Encoding 编码形式
Content-Encoding: gzip
# 页面内容类型和对应的编码集,当前页面内容为可视化文本 HTML 文件,同时编码集为 utf-8
Content-Type: text/html; charset=utf-8
# 格林尼治时间,如果需要展示为当前 北京时间 + 8 
Date: Thu, 23 Mar 2023 06:44:51 GMT
# 当前服务器的版本 BWS Baidu WebServer 服务器 1.1 版本
Server: BWS/1.1
# 【核心】会话控制技术,服务器发送给浏览器 Cookie 数据保存,Cookie 数据是一个【键值对数据】
Set-Cookie: BDSVRTM=382; path=/
Set-Cookie: BD_HOME=1; path=/

2.4 状态码

状态码是提供给浏览器端得知当前服务器运行状态的一种形式。

分类 分类描述
1** 信息,服务器收到请求,需要请求者继续执行操作
2** 成功,操作被成功接收并处理
3** 重定向,需要进一步的操作以完成请求
4** 客户端错误,请求包含语法错误或无法完成请求
5** 服务器错误,服务器在处理请求的过程中发生了错误
特殊关注状态码 信息描述
404 资源未找到异常,通常出现在资源名称错误,资源路径错误,资源尚未放行。
405 Method Not Allowed 项目代码中未满足方法必须重写的要求,例如 doGet 和 doPost (super.doGet() 应该删除。)
5XX 服务器错误,不要看浏览器,看 IDEA 的运行日志,运行日志有三个 Server,Tomcat Log, Cateline Log
200 成功

2.5 服务器针对于 HTTP 协议相关对象

【重点关注两个对象】 Request 和 Response

服务器针对于用户的请求:
	Request 对象,当前对象中包含 HTTP 协议请求头的所有数据内容,包括用户请求参数内容。无论是 GET 请求还是 POST 请求,Request 都会存储对应的数据信息。

服务器针对于用户的响应:
	1. 服务器会根据用户的请求 【Request 对象】 针对性创建对应的【Response 对象】
	2. Response 对象通过 服务器发送给浏览器【解析】,针对于浏览器反馈的所有数据,都可以通过 Response 对象反
	馈

【网络编程】编写HTTP Server 服务器

HTTP Server的本质上是是一个TCP服务器。

public class Server {
    public static void main(String[] args) thorws IOException {
        ServerSocket ss = new ServerSocket(8080);
        System.out.println("server is running");
        for(;;) {
            Socket sock = ss.accept();
            System.out.println("connected from" + sock.getRemoteSocketAddress());
            Thread t = new Handler(sock);
            t.start();
        }
    }
}

class Handler extends Thread {
    Socket sock;
    public Handler(Socket sock) {
        this.sock = sock;
       
    }
    public void run() {
        try (InputStream input = this.sock.getInputStream()) {
            try (OutputStream output = this.sock.getOutputStream()) {
                handle(input, output);
            }
        } catch (Exception e) {
            try {
                this.sock.close();
            } catch (IOException e) {
                
            }
            System.out.println("client disconnected");
        }
        
    }
}

Servlet 程序的三种实现方式

源头都来自 Servlet 接口:

方式一:实现Servlet接口。

方式二:继承GenericServlet,其中 GenericServlet 实现 Servlet 接口,视为 核心类。

方式三:继承HttpServlet 类,其中HttpServlet类 ,继承GenericServlet类,对核心GenericServlet进行加工,加上Http约束,完成HttpServlet类 。

遵从 Servlet 接口

package com.qfedu.b_servletclass;

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

@WebServlet("/implServletInterface")
public class ImplementsServletInterface implements Servlet {
    /**
     * Servlet 初始化方法,所需参数是 ServletConfig 对象。ServletConfig 对象是 Tomcat 服务器在启动
     * Servlet 程序过程中,将注解或者 web.xml 对应的参数打包生成 ServletConfig 对象,作为初始化 Servlet
     * 程序必要参数
     * 【注意】当前方法是成员方法,需要对象调用执行,在【构造方法】之后执行。
     *
     * @param config ServletConfig 对象
     * @throws ServletException Servlet 异常
     */
    @Override
    public void init(ServletConfig config) throws ServletException {

    }

    /**
     * 获取 ServletConfig 对象
     * @return 返回是 ServletConfig 对象
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    /**
     * 【核心方法】
     *     Servlet 程序提供 JavaWEB 服务的核心方法,所需参数是 ServletRequest 和 ServletResponse 对象,请求和响应对象
     *     都是 Tomcat 服务器在处理用户请求过程中,提供给当前方法使用的,service 是完成当前 Servlet 程序对外 JavaWEB 服务
     *     的核心方法
     *
     * @param req ServletRequest 针对于用户请求的 Request 对象
     * @param res ServletResponse 针对于用户请求的 Request 对象绑定创建的 Response 对象
     * @throws ServletException Servlet 异常
     * @throws IOException IO 异常
     */
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        res.getWriter().append("<h1>Implements Servlet interface complete Servlet Program</h1>");
    }

    /**
     * 获取当前 Servlet 信息字符串
     * @return Servlet 信息字符串
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * Servlet 程序销毁方法,在 tomcat 关闭服务器 或者 Servlet 自行调用关闭。
     */
    @Override
    public void destroy() {

    }
}

继承 GenericServlet 类

package com.qfedu.b_servletclass;

import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;

/**
 * 继承 GenericServlet 有且只需要完成一个 service 核心方法,其他配套方法无需关注。
 *
 * interface Servlet 接口,制定的是【规范/规则】, GenericServlet 封装 Servlet 配套方法
 * 简化 Servlet 操作流程,同时将【核心方法】预留,依然交给用户来完成对应的操作。满足 Servlet
 * JavaWEB 服务相关内容。
 *
 * GenericServlet 【承上启下】
 */
@WebServlet("/extendsGenericServlet")
public class ExtendsGenericServlet extends GenericServlet {
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        res.getWriter().append("<h1>Extends GenericServlet to Complete Servlet Program</h1>");
    }
}

继承HttpServlet类

package com.qfedu.b_servletclass;

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;

/**
 * HttpServlet 继承 GenericServlet ,完成了 Servlet 接口规定的
 *      public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
 * 同时引入 HTTP 协议规范,在源码中加入
 *      protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
 *      通过不同的请求方式,将 service 方法请求和响应,分发给不同的处理方式
 *          GET ==> doGet(HttpServletRequest, HttpServletResponse)
 *          POST ==> doPost(HttpServletRequest, HttpServletResponse)
 *          DELETE ==> doDelete(HttpServletRequest, HttpServletResponse)
 *          OPTION ==> doOption(HttpServletRequest, HttpServletResponse)
 *          .....
 *      并且 对应的 doXXX 方法并没有完成对应的业务逻辑,要求用户根据所需请求方式
 *      完成对应的方法重写,如果直接使用提示警告【405 Method Not Allowed】
 *
 */
@WebServlet("/extendsServlet")
public class ExtendsHttpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().append("<h1>Extends HttpServlet</h1>");
    }

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

Servlet 配置【注册】方式

两种 Servlet 配置方式:

  1. 通过XML文件配置
  2. 通过注解的方式配置文件

通过 XML 文件配置【注册】

配置详情

【优点】支持 Servlet 任意版本

并且在配置多个 servlet 程序 是,可以根据 xml 文件配置规则,很容易检查出错误

web.xml 配置内容 (web.xml 放在 WEB-INF 文件夹中才行)

<?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 在 Web Application 名称和对应的class -->
    <servlet>
        <!-- 当前 Servlet 程序在服务器上的名称,或者可以认为是web.xml文件中的唯一名称 -->
        <servlet-name></servlet-name>
        <!-- 当前 Servlet 程序对应的【完整的包名.类名】 用于 Tomcat 服务器启动对应的 Servlet 程序 -->
        <servlet-class></servlet-class>



    <!--
 		配置 this这个Servlet程序参数,放在其 注册 Servlet 标签中
		通过 XML 文件为 Servlet 配置参数 
        以下参数会在 Servlet 启动阶段提供给对应的 Servlet 程序使用
        在 Servlet 程序中,可以使用 ServletConfig 获取对应的参数数据
        在 Servlet 程序中,通过 this.getServletConfig() 获取 ServletConfig 对象
        通过 servletConfig 对象 就是一个【键值对数据】。
        sevletConfig.getInitParameter(param-name) 获取 XML 中的 init-param 初始化参数。
    -->
    <init-param>
        <param-name></param-name>
        <param-value></param-value>
    </init-param>

    <!-- 
        Servlet 程序 Tomcat 启动项目过程中【自动启动】 
    -->
    <load-on-startup>1</load-on-startup>

    </servlet>
    <!-- Servlet 映射配置,配置Servlet 对应的名称和【注册资源名】-->
    <servlet-mapping>
        <!-- Servlet 名称,当前 Servlet-mapping 映射配置对应的那一个Servlet 标签 对应上述 -->
        <servlet-name></servlet-name>
         <!-- 【重点】 Servlet 在服务器的【注册资源名】,【唯一】用于路径访问 -->
        <url-pattern></url-pattern>
    </servlet-mapping>
    <!-- 一个 Servlet程序对应一组 <servlet> 和 <servlet-mapping> 标签  -->
    <servlet></servlet>
    <servlet-mapping></servlet-mapping>
    <!-- 在web-app可以定义多个 servlet and servlet-mapping -->
</web-app>

建立 Servlet 程序,即 Servlet 类

// 通过继承 HttpServlet 声明 我的Servlet 类,即 XML 配置文件中的 Servlet-class 

public class MyServletApp extends HttpServlet {
    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        resp.getWriter().append("<h1>XML Config Servlet Program...</h1>");
    }
    
    @Override 
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
         doGet(req, resp);
    }
}

XML 文件详解

XML 概述

XML ==> Extensible Markup Language。是一种自定义的文本格式。
	常用于:配置文件,数据传递,小型数据库。
XML 在 Java 框架中常用于配置文件,

XML语法基本要求

  1. XML 文件标签可以自定义
  2. XML 文件标签的属性可以自定义
  3. XML文件标签严格区分大小写
  4. XML文件只能有一个【根结点】
  5. XML文件支持的标签有【属性标签】【文本标签】
<?xml version="1.0" encoding="utf-8"?>
<students>
    <student id="001">
    	<name></name>
        <id></id>
        <gender></gender>
        <address>
        	<province></province>
            <city></city>
            <area></area>
        </address>
    </student>
</students>

XML 文件两种解析方式

将XML看作 树的结构

DOM 解析

把整个XML文件完整的读取到内存中,进行数据解析,可以针对于XML文件进行【增删改查】 操作。会导致文件内存占用过大。 常用于服务器配置,项目配置【Spring 】 内置DOM解析范式,使用:DOM4j。

maven依赖导入

<dependency>
    <groupId>dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>1.1</version>
</dependency>
/*
<?xml version="1.0" encoding="utf-8"?>
<students>
    <student id="000">
    	<name></name>
        <id></id>
        <gender></gender>
        <address>
        	<province></province>
            <city></city>
            <area></area>
        </address>
    </student>
</students>
*/

// 1. 获取对应的文件的输入流对象
InputStream inputStream = Demo1.class.getClassLoader().getResourceAsStream("student.xml");

// 2. 创建 DOM 解析核心类 【核心】
SAXReader reader = new SAXReader();

// 3. 通过 SAXReader 实例化对象,根据输入流对象,获取对应 XML 文件的 Document 对象
Document document = reader.read(inputStream);

// 4. 【核心步骤】获取根结点对象
Element rootElement = document.getRootElement();

/*
        1. 获取第一个子结点
        2. 获取所有的子结点
         */

// 5. 获取结点名称为 student 的第一个子结点
Element student = rootElement.element("student");
System.out.println(student);

// 6. 可以获取当前结点的【属性结点】--> 属性值
String id = student.attributeValue("id");
System.out.println("id:" + id);

/*
         7. 获取 Student 结点的所有子节点
                List elements();
                当前方法没有明确声明泛型,可以自行指定为 List<Element>
                同时为了解决代码中的警告,可以使用警告压制 @SuppressWarnings("all")
         */
List<Element> elements = student.elements();

for (Element element : elements) {
    List<Element> elements1 = element.elements();
    if (elements1.isEmpty()) {
        // 8. 获取 XML 文件结点的名称和对应的文件数据内容
        System.out.println(element.getName() + ":" + element.getText());
    } else {
        for (Element element1 : elements1) {
            System.out.println(element1.getName() +  ":" + element1.getText());
        }
    }
}

inputStream.close();
SAX 解析

通过逐行读取进行解析,节约内存,但是有且只能完成针对于XML 文件的【读取解析操作】,可以用于手机端的配置。

 // 获取指定 XML 文件输入流对象,同时创建 SAXReader 核心对象,获取 Document 对象
InputStream input = Demo2.class.getClassLoader().getResourceAsStream("student.xml");
SAXReader reader = new SAXReader();
Document document = reader.read(input);

// 【核心代码】获取根结点元素对象
Element rootElement = document.getRootElement();

/*
XPath 语法
*/

/*
    1. 获取所有的 name 标签值
    //name ==>
    // 表示忽略层级关系
    name 表示要求获取的 XML 结点名称为 name
*/
List<Node> nodes = rootElement.selectNodes("//name");
nodes.forEach(n -> System.out.println(n.getName() + ":" + n.getText()));

System.out.println();

// 2. 忽略层级关系,获取 address 结点下的所有子结点
List<Node> nodes1 = rootElement.selectNodes("//address/*");
nodes1.forEach(n -> System.out.println(n.getName() + ":" + n.getText()));

// 3. 忽略层级关系,找到 student 结点,要求 student 结点 有 id 属性,并且 属性值 为 001
List<Node> nodes2 = rootElement.selectNodes("//student[@id='001']");
for (Node node : nodes2) {
    Element e = (Element) node;
    System.out.println("id:" + e.attributeValue("id"));
}

System.out.println();
// 4. 忽略层级关系,找到 student 结点 要求当前 Student 结点下标为 1【注意】 XML 文件下标为 1 开始
List<Node> nodes3 = rootElement.selectNodes("//student[1]");
nodes3.forEach(n -> {
    Element e = (Element) n;
    System.out.println(e.attributeValue("id"));
});

// 4. 忽略层级关系,找到 student 结点 要求当前 Student 结点为最后一个结点
List<Node> nodes4 = rootElement.selectNodes("//student[last()]");

nodes4.forEach(n -> {
    Element e = (Element) n;
    System.out.println(e.attributeValue("id"));
});
input.close();

XML Scheme 约束 【定义XML文件】

scheme 约束文件,用于约束XML文件 【深造】

<?xml version="1.0"?>
<!--
schema申明
xmlns namespace 命名空间声明
xmlns:xsd 使用XMLSchema规范URL
targetNamespace 目标命名空间
elementFormDefault 元素规则默认要求
 -->
<xsd:schema xmlns="http://www.qfedu.com/xml"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="http://www.qfedu.com/xml" elementFormDefault="qualified">
    <!-- 根节点名字和包含的内容,内容是自定义studentType -->
    <xsd:element name="students" type="studentsType"/>
    <!-- studentsType 根节点对应类型声明   -->
    <xsd:complexType name="studentsType">
        <xsd:sequence>
            <!-- students根节点中存放的是student类型  type="studentType" 要求student的个数从0开始 个数不限制 -->
            <xsd:element name="student" type="studentType" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>
    <!-- studentType声明 -->
    <xsd:complexType name="studentType">
        <xsd:sequence>
            <!-- 要求student标签内有name,age,sex子标签,并且要求对一个对应保存的数据类型是type指定 -->
            <xsd:element name="name" type="xsd:string"/>
            <!-- ageType 和 sexType 是自定义数据约束 -->
            <xsd:element name="age" type="ageType" />
            <xsd:element name="sex" type="sexType" />
        </xsd:sequence>
        <!-- 给予Student标签属性 属性为id,要声明idType, use="required"不可缺少的 -->
        <xsd:attribute name="id" type="idType" use="required"/>
    </xsd:complexType>
    <!-- sexType性别类型声明 -->
    <xsd:simpleType name="sexType">
        <xsd:restriction base="xsd:string">
            <!-- 有且只有两个数据 male female -->
            <xsd:enumeration value="male"/>
            <xsd:enumeration value="female"/>
        </xsd:restriction>
    </xsd:simpleType>
    <!-- ageType年龄类型声明 -->
    <xsd:simpleType name="ageType">
        <xsd:restriction base="xsd:integer">
            <!-- 0 ~ 256 要求范围,是一个integer类型 -->
            <xsd:minInclusive value="0"/>
            <xsd:maxInclusive value="128"/>
        </xsd:restriction>
    </xsd:simpleType>
    <!-- idType id类型声明 -->
    <xsd:simpleType name="idType">
        <xsd:restriction base="xsd:string">
            <!-- ID类型,要求ZZ2011_xxxx(四位数字) -->
            <xsd:pattern value="ZZ2218_\d{4}"/>
        </xsd:restriction>
    </xsd:simpleType>
</xsd:schema>

通过【注解】配置

@WebServlet 注解方式

多个注解配置Servlet类,容易访问路径重名出错,不容易察觉。

注解配置 Servlet 有版本限制,要求Servlet 版本必须是Servlet 3.0 以上,同时要求JDK是 1.5 以上:

/**
* 通过注解配置
*/
@WebServlet("/annoConfig")
public class AnnotationConfigServlet extends HttpServlet {
    @Override 
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         /*
        HttpServletResponse
            getWriter() 获取 响应对外输出流对象。
         */
        resp.getWriter().append("<h1>Annotation Config Servlet Program...</h1>");
    }

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

注解配置常见错误

配置时出现,@WebServlet(资源定位字符),资源定位重复问题

Caused by: java.lang.IllegalArgumentException: The servlets named [com.qfedu.b_servlet.AnnotationConfigServlet] and [com.qfedu.b_servlet.AnnotationConfigServlet2] are both mapped to the url-pattern [/annoConfig] which is not permitted

@WebServlet 详解

源码查看

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
    
    /**
     * The name of the servlet
     *
     * @return the name of the servlet
     */
    String name() default "";
    
    /**
     * The URL patterns of the servlet
     * default assign to value property
     * @return the URL patterns of the servlet
     */
    String[] value() default {};

    /**
     * The URL patterns of the servlet
     *
     * @return the URL patterns of the servlet
     */
    String[] urlPatterns() default {};
    
    /**
     * The load-on-startup order of the servlet 
     * trun on the load-on-startup when value is 1
     * @return the load-on-startup order of the servlet
     */
    int loadOnStartup() default -1;
   
    /**
     * The init parameters of the servlet
     *
     * @return the init parameters of the servlet
     */
    WebInitParam [] initParams() default {};

    boolean asyncSupported() default false;

    String smallIcon() default "";

    String largeIcon() default "";
    
    String description() default "";

    String displayName() default "";

}

【重点】注解核心数据

  1. String[] value() 和 String[] urlPatterns();

    注册当前 Servlet 对应的资源名称,属性数据类型为 String[] 数组形式。

    Servlet 支持多个资源名称,所以是数组形式。

    value 和 urlPatterns 互斥,只能存在一个,如果没有明确提供属性的描述,默认赋值 value。

  2. int loadOnStartup() default -1;

    用于控制当前 servlet 程序是否 Tomcat 自动加载。

  3. WebInitParam[] initParam() default {};

    // 注解类型

    @WebInitParam {

    ​ String name(); // 参数名称

    ​ String value(); // 参数值

    }

// 栗子
@WebServlet(
        value = {"/annoConfig", "/anno"},
        loadOnStartup = 1,
        initParams = {
                @WebInitParam(name = "country", value = "中国"),
                @WebInitParam(name = "city", value = "安阳"),
        }
)

注解Servlet 注册资源名称

精准匹配 【最常用】
@WebServlet("/urlPattern1")
@WebServlet("/user/test")
@WebServlet("/student/info")

// 要求在请求资源过程中,资源名称必须严格遵守 url-pattern 配置内容,不可以错误,否则会导致 404
模糊匹配
@WebServlet("*.action")
@WebServlet("*.do")

// 用户请求 URL 结尾限制 .action 或者 .do,路径关系,名称无所谓!!!
路径匹配
@WebServlet("/user/*")
// 要求 URL 请求路径为 /user/ 开头,之后的内容不限制。

@WebServlet("/user/*.option")
// Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> [/user/*.option] in servlet mapping
// Tomcat 启动失败,不支持当前方法的 Url-Pattern

两种配置方式在实际中的解析流程

web.xml XML 文件方式

1. 用户通过浏览器请求URL http://localhost:8080/xmlConfig
2. 浏览器操作:
	1. 根据用户请求URL明确请求协议
		HTTP协议
	2. 明确用户请求对应的服务器【IP:端口号】
		localhost:8080
	3. 明确用户请求的资源名称
		xmlConfig
	4. 判断是否需要提交其他数据内容,例如:Cookie
3. 服务器操作:
	1. 收到浏览器发送的请求
		http:// localhost:8080/xmlConfig
	2. 服务器所在电脑判断当前请求针对的软件是哪一个
		8080端口 ==> Tomcat服务器
	3. Tomcat 服务器收到请求之后
		1. 根据用户请求数据创建对应的HttpServiceRequest对象
		2. 根据 HttpServletRequest 对象绑定创建对应的 HttpServletResponse
	4. Tomcat 服务器根据资源名称
		xmlConfig开始进行解析操作,执行目标Servlet程序
        解析过程 --> 从 web.xml 配置文件中开始进行解析,从Servlet-mapping 中找到 url-pattern 标签进行匹配,匹配到通过servlet-name 标签 进行查找--servlet 注册配置中的标签,通过注册部分的 servlet-name 找到 servlet-class 交给 Tomcat 服务器,服务器根据完整包名.类名,加载执行对应的 Servlet 程序,提供 web 服务。

@WebServlt 注解方式

  1. 用户通过浏览器请求URL http://localhost:8080/annoConfigServlet

  2. 浏览器操作

    1. 根据用户请求URL明确请求协议

      HTTP 协议

    2. 明确用户请求对应的服务器IP:端口号

      localhost:8080

    3. 明确用户请求的资源名称

      annoConfigServlet

    4. 判断是否需要提交其他数据内容,例如:Cookie

  3. 服务器操作

    1. 收到浏览器发送的请求

      http://localhost:8080/annoConfigServlet

    2. 服务器所在电脑判断请求针对的软件是哪一个

      8080端口 ==> Tomcat 服务器

    3. Tomcat 服务器收到请求之后

      1. 根据用户请求数据创建对应的HttpServletRequest 对象
      2. 根据HttpServletRequest 对象绑定创建对应的HttpServletResponse
    4. Tomcat 服务器根据资源名进行解析

      annoConfigServlet --> 从WebServlet注解内容中找到相应的类,获取类,实例化,提供相应的服务。

      此时,可以将Tomcat服务器,视为一个简单地Map容器,Map<String, Class<? extends Servlet>>,

      通过字符串 对应 Servlet 实现类。(Servlet -> GenericServlet -> HttpServlet)

Servlet 的生命周期

创建对象 (构造方法)
初始化 (init 初始化方法)
处理请求 (service 方法)
销毁 (destory 方法)

创建Servlet对象后(构造方法):初始化(init方法)--> 处理请求(service doGet doPost等方法) --> 销毁(destroy方法)

/**
	构造方法
	初始化方法
	核心方法
	销毁方法
	
    1. 构造方法首先执行,有且只执行一次
    2. init 初始化方法执行,有且只执行一次
    3. service 用户要求请求几次,执行几次
    4. Tomcat 服务器关闭时,销毁对应的 Servlet 程序
*/
@WebServlet("/life")
public class LifeServlet extends HttpServlet {
    /**
     * 当前 Servlet 程序构造方法,用于提供给 Tomcat 服务器实例化 Servlet 对象使用,
     */
    public LifeServlet() {
        System.out.println("LifeServlet Constructor running...");
    }

    /**
     * Servlet 初始化方法,所需参数是 ServletConfig 对象,Servlet 程序启动运行之前
     * 都需要 init 方法进行基本的初始化操作
     *
     * @param config ServletConfig 对象
     * @throws ServletException Servlet 异常
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        // 保留 super.init(config); 操作,保证 Servlet 程序完整性
        super.init(config);
        System.out.println("LifeServlet init method running...");
    }

    /**
     * Servlet 核心方法,提供对外的 WEB 相关服务
     *
     * @param req HttpServletRequest
     * @param resp HttpServletResponse
     * @throws ServletException Servlet 异常
     * @throws IOException IO 异常
     */
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("LifeServlet service method running...");
        resp.getWriter().append("<h1>LifeServlet....</h1>");
    }

    /**
     * Servlet 销毁方法
     */
    @Override
    public void destroy() {
        // 保留 super.destroy(); 操作,保证 Servlet 程序完整性
        super.destroy();
        System.out.println("LifeServlet destroy method running...");
    }
}

doGet,doPost 参数【重点】

HttpServletRequest

包含用户所有数据,针对于HTTP请求头,请求参数。

通过request对象可以获取用户提交的数据内容

/* 
	1. String getParameter(String parameterName); --> 获取用户提交表单中 标签name属性值为 parameterName 的 value 值。
	2. Map<String, String[]> getParameterMap(); --> 获取 用户提交表单所有的参数 使用Map双边队列存放,通过Map.get(String parameterName) 进行获取数据内容。
	3. String[] getParameterValues(String parameterName) --> 获取指定名称参数所有的值,对应String类型数组。
	4. Enumeration<String> getParameterNames(); --> 获取所有的参数名称。
*/

HttpServletResponse

针对于用户响应的所有数据内容都在Response对象中。

/*
	1. setContentType(String Type) --> 设置当前响应返回的数据类型
	2. PrintWriter getWriter() --> 获取响应返回的字符对象
	3. setHeader(String name, String value) --> 设置响应头信息
	4. setStatus(int status) --> 设置当前页面的状态码
	5. OutputStream getOutputStream() --> 输出字节流对象
*/
public class ResponseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置当前响应返回的数据类型是 文本/html类型,字符集为utf-8
        resp.setContextType("text/html;charset=utf-8");
        
		PrintWriter writer = resp.getWriter();
        
        wirter.append("<a>xxx</a>");
    }
}