JavaWeb 速通Servlet(Servlet和HttpServlet)

简介: JavaWeb——Servlet,HttpServlet及其底层原理 内容分享。

目录

一、Servlet快速入门

       1.为什么需要Servlet?

       2.什么是Servlet?

       3.Servlet开发说明 :

       4.入门案例 :

二、 Servlet生命周期

       1.浏览器请求Servlet的流程分析(重要) :

       2.生命周期 :

           1° 初始化阶段

           2° 处理请求阶段

           3° 终止阶段

三、Servlet基本使用

       1.Get请求和Post请求的处理 :

       2.开发Servlet的正确姿势(HttpServlet) :

       3.注解方式开发Servlet :

       4.URL匹配的4种方式:

           1° 精确匹配

           2° 目录匹配

           3° 扩展名匹配

           4° 任意匹配

           5° Δ注意事项Δ

四、Servlet(上)总结


一、Servlet快速入门

       1.为什么需要Servlet?

       当浏览器向Web服务器请求静态web资源(HTML,CSS,JS,图片等)时,Tomcat可以对请求进行解析后,拿到资源,以响应的方式直接返回给浏览器,不与数据库发生关系。此时Tomcat只提供普通的web服务

       但是,当浏览器发出动态地与用户进行交互的请求时,比如用户留言,用户评论等直接与数据库挂钩的需求,就需要Servlet去调用其他Java程序来实现,Java程序通常会分层(Service,DAO等)。此时Tomcat作为了Servlet的容器(也称作引擎),因为Tomcat支持Servlet,能够完成对Servlet的解析

       2.什么是Servlet?

       Servlet在开发动态WEB工程中,得到广泛的应用,Servlet是SpringMVC,SpringBoot的底层基础。

       Servlet本义是java服务器小程序,特点如下——

       由服务器端调用和执行(eg : 由Tomcat解析和执行)。

       java语言编写,本质就是Java类,供其他Java程序(Servlet引擎)调用,不能独立运行。

       按照Servlet规范开发(类似于JDBC接口的规范,符合规范的Web服务器例如Tomcat, WebLogic都可以支持Servlet)。

       Servlet功能强大,可以完成几乎所有的网站功能,但对于技术栈的要求很高。

       3.Servlet开发说明 :

       servlet3.0前使用 web.xml;servlet3.0 版本以后 ( 包括 3.0) 支持注解(实际使用更多) ,同时支持 web.xml配置
       PS : 原生的
Servlet 在项目中使用很少。

       4.入门案例 :

               首先,新建一个项目,引入Web Application框架支持后,在WEB-INF目录下新建lib目录。如下图所示 :

image.gif编辑

               然后,导入Servlet所需的jar包"servlet-api.jar",在Tomcat的lib目录下,如下图所示 :

image.gif编辑

               导入后要部署到当前项目,如下图所示 :

image.gif编辑

               接着配置Tomcat

               然后,新建一个类,实现Servlet接口并重写Servlet接口的五个方法。

               TryServlet类代码如下 : (注意看注释

package intro;
import jakarta.servlet.*;
import java.io.IOException;
/**
 * @author : Cyan_RA9
 * @version : 21.0
 */
/** 一个类只有实现了Servlet接口,才能被当作Servlet使用。 */
public class TryServlet implements Servlet {
    //创建TryServlet实例时会调用init方法,该方法只会被调用一次。
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init方法被调用");
    }
    //返回ServletConfig对象,即返回Servlet的配置信息
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    /*
        (1)service方法用于处理浏览器的请求(包括get/post)
        (2)每当浏览器请求一次Servlet时,都会调用一次service方法。
        (3)当Tomcat调用该方法时,会将请求的数据封装成实现了ServletRequest接口的servletRequest对象,
            通过servletRequest对象,可以得到用户提交的数据。
        (4)servletResponse对象可以用于返回数据给Tomcat,Tomcat解析得到对应的数据后,
            会再把数据封装成HTTP响应的方式,发送给浏览器,浏览器再解析并显示。
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("This is the first Servlet try~");
    }
    //返回servlet信息,使用较少
    @Override
    public String getServletInfo() {
        return null;
    }
    //该方法是在servlet被销毁时被Tomcat调用,只调用一次
    @Override
    public void destroy() {
        System.out.println("destroy方法被调用。");
    }
}

image.gif

               在web.xml中配置TryServlet:TryServlet提供对外访问地址。web.xml主要用于配置该web应用使用到的Servlet。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>TryServlet</servlet-name>
        <servlet-class>intro.TryServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>TryServlet</servlet-name>
        <url-pattern>/tryServlet</url-pattern>
    </servlet-mapping>
</web-app>
<!--
1.<servlet>:
    (1)<servlet-name>指给当前Servlet取名(由程序员手动指定,但一般取类名),该名字唯一。
    (2)<servlet-class>此处为Servlet类的全路径(全类名);Tomcat在反射生成该Servlet时需要使用。
2.<servlet-mapping>:
    (1)<servlet-name>同上
    (2)<url-pattern>是该servlet访问URL的配置(路径)
        当前访问形式:http://localhost:8080/Servlet_Demo/tryServlet
-->

image.gif

               运行效果(如下GIF图):

image.gif编辑


二、 Servlet生命周期

       1.浏览器请求Servlet的流程分析(重要) :

                浏览器会先从URL中解析出主机名,eg : www.baidu.com。

               浏览器到本机C:\Windows\System32\drivers\etc目录下的hosts文件中,去查询有无主机名对应的IP。如下图所示 :

image.gif编辑

               若本机的hosts文件中没有找到域名对应的IP,就会转向外网的DNS(域名系统)继续查找,如果仍然没有找到,就会提示网站找不到,如下图所示 :

image.gif编辑

               若浏览器在hosts文件中或者在DNS服务器中成功查找到了主机名对应的IP;则会根据获取到的IP,向Tomcat发出HTTP请求

               Tomcat收到HTTP请求后会进行判断——如果是第一次请求,Tomcat会去查询web.xml配置文件,查看请求的资源(eg : /tryServlet) 是否在<servlet-mapping>的url-pattern配置中(即web.xml文件中是否已经配置了该Servlet)。如果找到了对应的url-pattern,就会得到<servlet-name>(eg : TryServlet);如果没有,Tomcat会返回给浏览器一个404页面(找不到资源)。

              Tomcat维护了至少两个牛逼的大的HashMap容器,其中一个是HashMap<id,Servlet>,id以<servlet-name>(不可重复)来存放,Servlet则存放Servlet的实例。Tomcat会通过id查询该HashMap, 确认该Servlet实例(反射创)是否存在

               另一个HashMap容器中, key用来存放web.xml配置文件中的<servlet-mapping>中的<url-pattern>;value则存放<servlet-name>。(所以说,先得到url-pattern才会得到对应的<servlet-name>。

               如果没有查找到<servlet-name>对应的id,即没有该Servlet实例。Tomcat就会根据<servlet-name>来拿到<servlet-class>中的全类名,然后通过反射技术,实例化该Servlet(调用init方法),然后将Servlet实例放入到维护的HashMap集合中。

                接着,Tomcat调用service方法,由对应的Servlet实例来处理service.对于每次访问请求,Servlet 引擎都会创建一个新的 HttpServletRequest 请求对象和一个新的HttpServletResponse 响应对象,然后将这两个对象作为参数传递给它调用的Servlet的service()方法,service 方法会根据请求方式,调用doGet | dePost | 其他方法

               6° 如果在HashMap集合中查到了该Servlet实例,就直接调用该Servlet的service方法;可见,Servlet常驻内存,是单例的(仅一个实例)

              servlet实例处理完毕service方法后,会以HttpServletResponse对象的形式将数据返回给Tomcat

               8°Tomcat会对HttpServletResponse对象进行解析,得到数据后再把数据打包到HTTP响应中,以HTTP响应的方式返回给浏览器

               浏览器解析返回的结果并显示。

               PS :

               浏览器对静态Web资源(html,css,js,图片等)的请求实际是由TomcatDefaultServlet来完成的当其他的utl-pattern都匹配不上时,Tomcat就通过DefaultServlet来拦截到其它静态资源。

       2.生命周期 :

           1° 初始化阶段

       向Tomcat这样的Servlet 容器,加载 Servlet完成后,Servlet 容器会创建一个 Servlet 实例并调用 init()方法,init()方法只会调用一次(因为Servlet是单例的,一个类只会被加载一次)对每次请求都导致 Servlet 擎调用一次 servlet service 方法

       Servlet 容器在下面的情况装载 Servlet:

       (1)Servlet 容器(Tomcat)启动时自动装载某些 servlet,需要在 web.xml 文件中添加<load-on-startup>1</load-on-startup>,其中1 表示该Servlet装载的顺序

       (2)在 Servlet 容器启动后,浏览器首次发送Servlet 的请求

       (3)Servlet 重新装载后(eg: Tomcat进行 redeploy操作时 [redeploy操作会销毁当前Tomcat维护的HashMap集合中——所有的 Servlet 实例] ),浏览器再次向 Servlet 发送请求的第 1 次,也会导致Servlet的装载。

           2° 处理请求阶段

       1. 处理请求阶段,就是Servlet对service方法的调用。

       2. 每收到一个 HTTP 请求,服务器就会产生一个新的线程去处理该HTTP请求。

       3. 创建一个用于封装 HTTP 请求消息的 ServletRequest 对象和一个代表 HTTP 响应消息的 ServletResponse 对象。

       4. 然后调用 Servlet service()方法并将请求对象和响应对象作为参数进行传递。

           3° 终止阶段

       当web 应用被终止,或者Servlet 容器终止运行,或者Servlet 类重新装载时,会调用 destroy() 方法 , 比如重启 tomcat ,或者 redeploy web 应用。


三、Servlet基本使用

       1.Get请求和Post请求的处理 :

               以提交一个简单的form表单为例,register.html代码如下 :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Register</title>
</head>
<body>
    <h1>User Register</h1>
    <form action="http://localhost:8080/Servlet_Demo/tryServlet" method="post">
        username:<input type="text" name="username"/> <br/><br/>
        <input type="submit" value="register"/>
    </form>
</body>
</html>

image.gif

               在TryServlet类中定义doGet和doPost方法,分别用于处理GET和POST请求,改进后的TryServlet类代码如下 :

package intro;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
 * @author : Cyan_RA9
 * @version : 21.0
 */
/** 一个类只有实现了Servlet接口,才能被当作Servlet使用。 */
public class TryServlet implements Servlet {
    //创建TryServlet实例时会调用init方法,该方法只会被调用一次。
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("init方法被调用");
    }
    //返回ServletConfig对象,即返回Servlet的配置信息
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    /*
        (1)service方法用于处理浏览器的请求(包括get/post)
        (2)每当浏览器请求一次Servlet时,都会调用一次service方法。
        (3)当Tomcat调用该方法时,会将请求的数据封装成实现了ServletRequest接口的request对象,
            通过servletRequest对象,可以得到用户提交的数据。
        (4)servletResponse对象可以用于返回数据给Tomcat,Tomcat解析得到对应的数据后,
            会再把数据封装成HTTP响应的方式,发送给浏览器,浏览器再解析并显示。
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service is invoked...");
        /*
            ServletRequest类中没有getMethod方法,
            因此要将其转换为它的子接口类型HttpServletRequest.
         */
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String method = httpServletRequest.getMethod();
        System.out.println("method = " + method);
        if ("GET".equals(method)) {
            doGet();
        } else if ("POST".equals(method)) {
            doPost();
        }
    }
    //处理GET请求
    public void doGet() {
        System.out.println("doGet() is invoked");
    }
    //处理POST请求
    public void doPost() {
        System.out.println("dePost() is invoked");
    }
    //返回servlet信息,使用较少
    @Override
    public String getServletInfo() {
        return null;
    }
    //该方法是在servlet被销毁时被Tomcat调用,只调用一次
    @Override
    public void destroy() {
        System.out.println("destroy方法被调用。");
    }
}

image.gif

               运行效果 :

image.gif编辑

      2.开发Servlet的正确姿势(HttpServlet) :

               在实际项目中,都是使用继承 HttpServlet 类开发 Servlet 程序,更加便捷。

               HttpServlet类的类图如下 :

image.gif编辑

               HttpServlet直接继承自GenericServlet类(抽象类),而GenericServlet类中实现了Servlet接口的全部五个方法HttpServlet还提供了doGet和doPost方法,并且在实现的service方法中已经做了对method类型的判断;因此,HttpServlet底层走得——其实还是Servlet那一套,只不过人家帮我们封装起来了

               有了HttpServlet后,开发Servlet的步骤如下 ——

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

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

       3. 在web.xml 中配置 Servlet 程序

               以NBServlet为演示类,代码如下 :

package advance;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @author : Cyan_RA9
 * @version : 21.0
 */
public class NBServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("NBServlet's doGet is invoked~");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("NBServlet's doPost is invoked~");
    }
}

image.gif

               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>TryServlet</servlet-name>
        <servlet-class>intro.TryServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>TryServlet</servlet-name>
        <url-pattern>/tryServlet</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>NBServlet</servlet-name>
        <servlet-class>advance.NBServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>NBServlet</servlet-name>
        <url-pattern>/nBServlet</url-pattern>
    </servlet-mapping>
</web-app>
<!--
1.<servlet>:
    (1)<servlet-name>指给当前Servlet取名(由程序员手动指定,但一般取类名),该名字唯一。
    (2)<servlet-class>此处为Servlet类的全路径(全类名);Tomcat在反射生成该Servlet时需要使用。
2.<servlet-mapping>:
    (1)<servlet-name>同上
    (2)<url-pattern>是该servlet访问URL的配置(路径)———一般采取类名首字母小写的形式.
        当前访问形式:http://localhost:8080/Servlet_Demo/tryServlet
-->

image.gif

               运行效果(如下GIF图):

image.gif编辑

      3.注解方式开发Servlet :

               使用@WebServlet注解代替web.xml配置文件,eg : @WebServlet(urlPatterns = {"/nbServlet", "/nBServlet"}),可以同时配置多个url,同时生效

               @WebServlet注解类源码如下 :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package jakarta.servlet.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
    String name() default "";
    String[] value() default {};
    String[] urlPatterns() default {};
    int loadOnStartup() default -1;
    WebInitParam[] initParams() default {};
    boolean asyncSupported() default false;
    String smallIcon() default "";
    String largeIcon() default "";
    String description() default "";
    String displayName() default "";
}

image.gif

               若使用@WebServlet的注解方式,首次向Tomcat发送请求时,Tomcat会在IDEA的包下进行扫描,如果发现某个类使用了@WebServlet注解进行修饰,就认为该类是一个Servlet类,继而会读取@WebServlet注解中的urlPattern属性。注意——Tomcat在读取@WebServlet的过程中,就会获取到该Servlet的全类名(全路径,正名)

               其余的步骤与“web.xml”配置的方式大同小异

               以Test类为演示类,代码如下 :

package advance;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @author : Cyan_RA9
 * @version : 21.0
 */
@WebServlet(urlPatterns = {"/TTT", "/tee"},
        loadOnStartup = 1,
        initParams = {@WebInitParam(name="n1", value="v1"), 
                @WebInitParam(name = "n2", value = "v2")})
public class Test extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Test's doGet is invoked");
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Test's doPost is invoked");
    }
}

image.gif

               运行效果(如下GIF图):

image.gif编辑

       PS :

       WebInitParam注解类源码如下 :

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package jakarta.servlet.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebInitParam {
    String name();
    String value();
    String description() default "";
}

image.gif

       4.URL匹配的4种方式:

           1° 精确匹配

       eg : @WebServlet(urlPatterns={"/TTT", "/tee"})

       精确匹配模式下,只有输入的URL与注解定义的URL完全匹配才能成功找到Servlet资源(推荐)

           2° 目录匹配

       eg : @WebServlet("/TTT/*")

       目录匹配模式下,只要符合/*前面的目录即可,*表示可以后面可以任意写,并且支持多级目录

           3° 扩展名匹配

       eg : @WebServlet("*.action")

       扩展名匹配模式下,前面随便写,只要符合指定的后缀名即可。注意——使用扩展名匹配时前面不能带 / , 否则 tomcat 报错(与带/的匹配模式冲突

           4° 任意匹配

       eg : @WebServlet("/")  or  @WebServlet("/*")

       / /*的配置,会匹配所有的请求(不推荐)

           5° Δ注意事项Δ

       (1) 当Servlet配置了"/",会覆盖掉Tomcat的DefaultServlet,会导致无法访问静态资源。(因为/的优先级比DefaultServlet高,浏览器发出的对静态资源的请求会被当做是对Servlet的请求而匹配);可以到tomcat/conf/web.xml下查看默认配置的DefaultServlet。

       因此,不建议使用任意匹配/ 和 /*

       (2) 4种URL匹配模式的优先级遵守:精确路径 > 目录路径 > 扩展名路径 > /* > / > DefaultServlet。


四、Servlet(上)总结

      (1) 了解最基本的“实现Servlet”接口的开发方式;

       (2) 掌握浏览器请求Servlet的流程分析(联系浏览器请求静态资源的流程分析);

      (3) 熟悉Servlet调用的生命周期;

       (4) 掌握“继承HttpServlet类”的开发方式;且明白其底层原理

      (5) 熟悉注解方式开发Servlet的使用,以及与web.xml方式的区别。

       System.out.println("END--------------------------------------------------------------------------------");

目录
相关文章
|
4月前
|
缓存 Java 应用服务中间件
javaweb实训第三天上午——Servlet(1)
Servlet基础 课程介绍 Servlet基础; (掌握) 基本结构 生命周期 执行流程 接收参数 响应数据
54 0
|
5月前
|
小程序 Java 应用服务中间件
【JavaWeb学习】—Servlet(十三)
【JavaWeb学习】—Servlet(十三)
|
8月前
|
安全 Java 应用服务中间件
【JavaWeb】Tomcat底层机制和Servlet运行原理
网络通信:Tomcat使用Java的Socket API来监听特定的端口(通常是8080),接收来自客户端的HTTP请求。 线程池:Tomcat使用线程池来处理并发的请求。当有新的请求到达时,Tomcat会从线程池中获取一个空闲线程来处理该请求,这样可以提高处理效率。 生命周期管理:Tomcat负责管理Servlet和其他Web组件的生命周期,包括初始化、请求处理和销毁等阶段。(init(), run())
|
8月前
|
数据安全/隐私保护
JavaWeb用户信息管理系统-创建登录业务的Servlet
JavaWeb用户信息管理系统-创建登录业务的Servlet
29 0
|
4月前
|
存储 前端开发 Java
JavaWeb:servlet+jsp+mybatis商品管理增删改查
商品管理通常包括增加(添加)、删除、修改和查询商品信息
59 1
JavaWeb:servlet+jsp+mybatis商品管理增删改查
|
4月前
|
安全 Java
javaweb实训第四天下午——员工管理系统-JSP&Servlet&JDBC综合练习-CRUD
1.课程介绍 Servlet细节; (掌握) 员工信息相关的CRUD; (掌握) 部门信息相关的CRUD; (掌握) 2.Servlet细节 2.1.多种匹配方式
41 0
|
4月前
|
编解码 应用服务中间件 数据库
|
5月前
|
小程序 应用服务中间件 数据库连接
|
7月前
|
存储 设计模式 JavaScript
掌握JavaWeb开发的必备技能:Servlet、JSP、Cookie、Session、EL、JSTL详解 ~~~~B站老杜--Servlet-JSP-课堂笔记(三)
当某个特殊的事件发生(特殊的事件发生其实就是某个时机到了。)之后,被web服务器自动调用。 思考一个业务场景
48 0
|
8月前
|
Java 中间件 应用服务中间件
【JavaWeb】知识总结Ⅶ(Servlet)
什么是 Servlet? Servlet(Server Applet),全称Java Servlet,未有中文译文。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。