Skip to content

Servlet

Servlet-入门

Servlet的基本概述

什么是Servlet

Server: 服务器

let: 小程序

可以运行在服务器上的一段小程序(Java)

Servlet与普通Java程序的区别

  • 类必须实现 Servlet 接口
  • 运行在应用服务器中,Tomcat 就是一个 Web 容器
  • 能够接收浏览器发送的请求,并且做出响应给浏览器

Servlet应用场景

Servlet-Case-Login

Servlet的作用【重点】

  1. 接收数据
  2. 处理数据
  3. 响应数据

创建Web项目

创建Java项目

create-project-1

create-project-2

create-project-3

create-project-4

添加 Web 项目支持

在项目名称处,右键,选择Add Framework Support 注意,不是.idea目录,也不是src目录 web-support-1

勾选Web Application (4.0)后,选择OKweb-support-2

此时在项目窗口,会出现新目录: webweb-support-3

项目配置

选择Add Configration...project-config-1

点击Add按钮 project-config-2

选择Tomcat Server -> Local之后,点击OKproject-config-3

点击Fix按钮 project-config-4

点击OK按钮 project-config-5

Idea-Update-Resource

添加Servlet支持

servlet-support-1

servlet-support-2

servlet-support-3

servlet-support-4

Servlet开发步骤

  • 新建普通的 Java 类;实现 Servlet 接口,重写 service 方法
  • 配置 Servlet
    • 映射路径
    • 类路径

Servlet 2.5

目标

tex
需求:
 1、编写java程序接收浏览器发送的请求
 2、接收到请求后,在控制台打印输出"Hello Servlet 2.5"

实现

第一步

  • 创建一个普通 Java 类;实现 Servlet 接口,重写 service 方法
java
package com.futureweaver.servlet;

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

/**
 * 1. 创建一个普通Java类;实现Servlet接口,重写service方法
 * 2. 配置Servlet
 *    2.1 配置映射路径
 *    2.2 配置类路径
 */
public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    // 当浏览器发起请求时,访问该Servlet,service方法会自动调用
    @Override
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        System.out.println("Hello Servlet 2.5");
    }

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

    @Override
    public void destroy() {

    }
}

第二步

  • 在 web.xml 中配置 Servlet
xml
<!-- 每个项目都会有的一个核心配置文件,此文件用于配置浏览器与Servlet之间的关系 -->

<?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">
  
    <!-- 配置HelloServlet类路径 -->
    <!-- 通过url-pattern,需要找到Servlet程序 -->
    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <!-- 第四步,通过servlet-name,找到对应的Servlet类 -->

        <servlet-class>com.futureweaver.servlet.HelloServlet</servlet-class>
        <!-- 第三步,通过servlet-class找到对应的类,填写唯一路径,"包名+类名" -->
    </servlet>

    <!-- 配置HelloServlet映射路径 -->
    <!-- 浏览器需要向Servlet发送请求,浏览器的url与Servlet要映射起来,mapping: 映射 -->
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <!-- 第二步,此名字需要唯一 -->

        <url-pattern>/hello</url-pattern>
        <!-- 第一步,url-pattern,资源路径,浏览器输入hello,就可以访问到Servlet -->
    </servlet-mapping>

</web-app>

第三步

  • 启动 Tomcat,访问:http://localhost:8080/JavaWeb_day01_servlet_war_exploded/hello,查看控制台运行结果

DAEED4E6-07D9-4F4E-B8C9-59A187C06F04

Servlet的执行流程分析

FB1DA718-9C57-4284-9743-3C112DE374BC

注意:部署描述符非重点。

Deployment Descriptor - web.xml

  1. Tomcat 启动时会将 web.xml 文件加载到 Tomcat 内存中
  2. Tomcat 在接收到 Web 请求时,会根据 web.xml 当中指定的***资源路径(http://localhost:8080/JavaWeb_.../hello)***去匹配相应的资源。
  3. 当浏览器地址栏中地址资源(hello)匹配到 web.xml 中的映射路径(url-pattern),会通过 web.xml 当中的类路径(servlet-class)访问到对应的 Servlet 类
  4. 在 Servlet 的 Java EE 规范当中,Tomcat 接收到 Web 请求时,它会去调用相应的 Servlet 类当中的 service 方法
  5. 浏览器发送的请求内容在 request 对象当中,Servlet 响应给浏览器的内容在 response 当中。【后续课程讲解】

Servlet 3.0

Servlet 2.5的缺点

  1. web.xml 中配置过多 servlet 不便于管理,容易出错
  2. 注解开发使得开发更灵活,效率更高

目标

tex
需求:
 1、编写java程序接收浏览器发送的请求(使用注解形式)
 2、接收到请求后,在控制台打印输出"Hello Servlet 3.0"

步骤

2 Servlet开发步骤 相同

实现

第一步

  • 创建一个普通 Java 类 AnnotationServlet,实现 Servlet,在 service 方法中打印信息;
java
package com.futureweaver.servlet;

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

/**
 * 1. 创建一个普通Java类,实现Servlet,重写service方法
 * 2. 配置Servlet
 *    2.1 配置映射路径
 *    2.2 配置类路径
 */
public class AnnotationServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    // 当浏览器发起请求时,访问该Servlet,service方法会自动调用
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 3.0");
    }

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

    @Override
    public void destroy() {

    }
}

第二步

  • 在这个类上面添加注解:@WebServlet("/annDemoServlet")
java
package com.futureweaver.servlet;

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

/**
 * 1. 创建一个普通Java类,实现Servlet,重写service方法
 * 2. 配置Servlet
 *    2.1 配置映射路径
 *    2.2 配置类路径
 */
@WebServlet(name = "AnnotationServlet", urlPatterns = "/annotation")
public class AnnotationServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    // 当浏览器发起请求时,访问该Servlet,service方法会自动调用
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 3.0");
    }

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

    @Override
    public void destroy() {

    }
}

第三步

  • 启动 tomcat 访问:http://localhost:8080/JavaWeb_day01_servlet_war_exploded/annotation

21755461-1F9B-4E5B-AEE8-7DF4571570D0

Servlet 2.5 & Servlet 3.0 对比

CA8E6BB4-A6B5-4CDB-B414-75138607BA2F

Servlet 3.0 简写形式

java
package com.futureweaver.servlet;

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

/**
 * 1. 创建一个普通Java类,实现Servlet,重写service方法
 * 2. 配置Servlet
 *    2.1 配置映射路径
 *    2.2 配置类路径
 */
@WebServlet("/annotation")
public class AnnotationServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {

    }

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

    // 当浏览器发起请求时,访问该Servlet,service方法会自动调用
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello Servlet 3.0");
    }

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

    @Override
    public void destroy() {

    }
}

小结

  • Servlet 的定义

    • 可以运行在服务器上的小程序
  • Servlet 的作用

    • 接收数据
    • 处理数据
    • 响应数据
  • Servlet 的开发步骤

    1. 新建普通的 Java 类,实现 Servlet 接口,重写 service 方法
    2. 配置 Servlet
    • 映射路径
    • 类路径
  • Servlet 3.0 注解配置时,需要配哪些(简写)

    • @WebServlet("/anno")

回顾-注解

java
// abc与value具备同样的行为
public @interface CustomAnno {
    private String name;
    private String[] value;
    private String[] abc;
}
java
@CustomAnno(name="name", value="zhangsan")
java
@CustomAnno(value="zhangsan")

// 与以下配置方式等价

@CustomAnno("zhangsan")
java
@CustomAnno(name="name")

// 不与以下等价
@CustomAnno("name")

WebServlet 注解

  • urlPatterns
  • value

urlPatterns与value具备同样的行为

java
@WebServlet(value="/anno")

// 二者等价

@WebServlet(urlPatterns = "/anno")

// 三者等价

@WebServlet("/anno")

项目文件夹当中

  • hello
    • demo1.html

localhost:8080/hello/ 结果: 找不到任何页面 原因: 在Tomcat核心配置文件(web.xml)当中

xml
<welcome-file-list>
    <file>index.html</file>
    <file>index.htm</file>
    <file>index.jsp</file>
    <file>demo1.html</file>
 </welcome-file-list>

Servlet-深入

【扩展】Servlet3.0新特性

  • 注解支持

    该版本新增了若干注解,用于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述符从该版本开始不再是必选的了。

  • 支持 web 模块

  • 支持 Servlet 异步处理

  • 文件上传 API 简化

【注意】详细信息请参考《Servlet3.0 新特性全解.md》

Servlet生命周期【重点】

生命周期指的是一个对象从创建到销毁的过程。

目标

  • 理解 Servlet 是何时创建的

    tex
    第一次被访问时
  • 理解 Servlet 是被谁创建的

    tex
    Tomcat
  • 理解 Servlet 怎么知道自己被创建

    tex
    init方法内部
  • 理解 Servlet 是何时销毁的

    tex
    项目停止/卸载时
  • 理解 Servlet 是被谁销毁的

    tex
    Tomcat
  • 理解 Servlet 如何感知自己被销毁

    tex
    destroy方法内部
  • 理解 Servlet 被创建了几次

    tex
    1次
  • 理解 Servlet 是否线程安全

    tex
    不安全

实现

第一步
  • 创建一个普通类 LifeCycleServlet,实现 Servlet 接口并重写所有抽象方法;
java
package com.futureweaver.servlet;

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

public class LifeCycleServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("LifeCycleServlet init method invoked");
    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello LifeCycleServlet");
    }

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

    @Override
    public void destroy() {
        System.out.println("LifeCycleServlet destroy method invoked");
    }
}
第二步
  • 配置 Servlet
java
package com.futureweaver.servlet;

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

@WebServlet("/lifecycle")
public class LifeCycleServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("LifeCycleServlet init method invoked");
    }

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

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("Hello LifeCycleServlet");
    }

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

    @Override
    public void destroy() {
        System.out.println("LifeCycleServlet destroy method invoked");
    }
}
第三步
  • 通过地址:http://localhost:8080/JavaWeb_day01_servlet_war_exploded/lifecycle 访问,查看打印信息:

84D49D3C-426D-4CFF-80D0-2AF8FAE3C26F

第四步
  • 关闭 tomcat

01C2054A-918C-43CF-8E2D-0F0AC5437032

图解生命周期

java
Class<HelloServlet> servletClz = Class.forName("com.futureweaver.web.HelloServlet");

Servlet servlet = servletClz.newInstance();

servlet.init();

Servlet-Lifecycle

Servlet-Thread.png

注意:Servlet 线程不安全

小结

  • Servlet 是何时创建的?

  • Servlet 是被谁创建的?

  • Servlet 如何感知自己被创建?

  • Servlet 是何时销毁的?

  • Servlet 是被谁销毁的?

  • Servlet 如何感知自己被销毁?

  • Servlet 被创建了几次?

  • Servlet 是否线程安全?

Servlet启动时加载【掌握】

问题

tex
普通的Servlet对象在我们第一次访问的时候创建,开发中,如果我们需要在服务器启动的时候,初始化Servlet对象。
有些Servlet有特殊的用途,需要在tomcat启动之后就立即被创建。就类似我们java代码中的静态代码块,需要提前被加载。

步骤

tex
1. 在web.xml中给LifeCycleServlet的类路径添加以下配置
<load-on-startup>2</load-on-startup>

2. 在LifeCycleServlet的WebServler注解中配置loadOnStartup参数。
@WebServlet(value = "/lifecycle", loadOnStartup = 2)

实现

第一步

  • 在 web.xml 中给 LifeCycleServlet 的映射添加以下配置:
xml
    <servlet>
        <servlet-name>LifeCycleServlet</servlet-name>
        <servlet-class>com.futureweaver.servlet.LifeCycleServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>LifeCycleServlet</servlet-name>
        <url-pattern>/lifecycle</url-pattern>
    </servlet-mapping>

第二步

  • 启动 tomcat,观察日志信息:

F657C765-7A9E-43C8-A0B4-7FB4726D8E03

解释

  • number 取值小于 0 或不配置,被访问时才去加载
  • number 取值为 0 时,最先被加载
  • number 取值大于 0 时,数值越小 Servlet 越优先加载

小结

load-on-startup

取值小于 0

tex
默认情况,第一被访问时加载

大于等于 0

tex
数字越小,加载越早;数字越大,加载越晚
注意

配置2或以上

IDEA模板

F1677114-EB27-4665-883F-CD006334D47D

java
package com.futureweaver.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(name = "TemplateServlet")
public class TemplateServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

没有模板的解决方案

template-1

template-2

HttpServlet继承体系【扩展】

Servlet-API-Hierachy

小结

通过 Idea 模板创建的 Servlet,实现自 HttpServlet 类

GenericServlet抽象类实现了Servlet接口,GenericServlet类内部,并没有实现service方法,所以由它的子类去实现 HttpServlet抽象类继承了GenericServlet抽象类,HttpServlet实现了service方法 在service方法内部,处理了请求方式:如果请求方式是GET方式的话,进入到本类的doGet方法内部;如果请求方式是POST方式的话,进入到本类的doPost方法内部

Servlet映射路径匹配策略【了解】

  • 【重点】完全匹配
tex
/welcome/hello
资源路径为/welcome/hello时可以访问
  • 目录匹配【了解】
tex
/user/*
资源路径中含有/user目录均可访问
  • 后缀名匹配【了解】
tex
*.do
资源路径中以.do结尾的均可访问

实现

第一步

  • 创建 MappingRouteServlet 继承 HttpServlet,重写 doGet 方法和 doPost 方法
java
package com.heima.servlet;

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

public class MappingRouteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("请求进来了...............");
    }

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

    }
}

第二步

  • 在 web.xml 中分别给 MappingRouteServlet 做如下配置
xml

    <!--
        Servlet映射路径配置规范:
        1. 完全匹配  		 /user/login		 资源路径为/user/login时可以访问
        2. 目录匹配			/user/*				 资源路径中含有/user目录均可访问
        3. 后缀名匹配	    *.do			     资源路径中以.do结尾的均可访问
        4. 缺省路径			/			         访问的路径找不到,就会去找缺省路径
    -->
    <servlet>
        <servlet-name>MappingRouteServlet</servlet-name>
        <servlet-class>com.heima.servlet.MappingRouteServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MappingRouteServlet</servlet-name>
        <!--1、完全匹配:-->
        <url-pattern>/user/login</url-pattern>
        <!--2、目录匹配:-->
        <url-pattern>/user/*</url-pattern>
        <!--3、后缀名匹配:-->
        <url-pattern>*.do</url-pattern>
        <!--4、缺省路径-->
        <url-pattern>/</url-pattern>
    </servlet-mapping>

第三步

  • 分别用不同的映射路径访问 Servlet

小结

  • Servlet 生命周期

    tex
    创建
    第一次被浏览器访问时,由Tomcat创建,在init方法内部知道自己被创建
    
    销毁
    项目卸载时,由Tomcat销毁,在destroy方法内部知道自己被销毁
    
    次数
    被创建1次,线程不安全
  • 启动时加载

    tex
    load-on-startup
    loadOnStartup
    
    负数: 默认情况,第一次被访问时创建
    非负数: 数字越小,加载越早;数字越大,加载越晚
    
    注意
    2或以上
  • Servlet 继承体系

    Servlet-API-Hierachy

  • 映射路径的 3 种配置方式

    • 完全匹配
    • 目录匹配
    • 后缀名匹配

学习目标总结

  • 能够理解 Servlet 技术概述
  • 能够独立写出 Servlet 的入门程序
  • 能够理解 Servlet 的生命周期
  • 能够应用 Servlet 的接口实现
  • 能够应用 Servlet 的启动时加载
  • 能够应用<url-pattern>的配置