第一章 Servlet的入门

1.1 Web资源的概念

Web资源就是运行在服务器上的资源,它一共分为两类: 静态资源以及动态资源

1.1.1 静态资源

静态资源就是web页面中供人们浏览的数据始终是不变,例如我们之前所学习的html、css、js、图片、音视频等等都属于静态资源

1.1.2 动态资源

动态资源就是web页面中供人们浏览的数据是由程序产生的,不同的用户或者不同时间点访问web页面看到的内容各不相同,例如我们后续要学习的Servlet、JSP(不学)、Thymeleaf等等都是动态资源

1.2 Servlet的概念

请求和响应过程:
请求和响应过程.JPG

1.2.1 什么是Servlet

Servlet = (Server + Applet)是运行在服务端(Tomcat)的Java小程序,是sun公司提供一套定义动态资源规范; 从代码层面上来讲Servlet就是一个接口

1.2.2 Servlet的作用

用来接收、处理客户端请求、响应给浏览器Web资源。在整个Web应用中,Servlet主要负责接收处理请求、协同调度功能。我们可以把Servlet称为Web应用中的『控制器Controller』

1.2.3 Servlet的作用的图示

要实现的效果

img002.png

1.3 Servlet的入门案例

1.3.1 目标

在页面上点击超链接,由Servlet处理这个请求,并返回一个响应字符串:Hello,I am Servlet

1.3.2 思路

img006.png

1.3.3 实现步骤

第一步: 创建动态Web module

第二步:创建html页面

  1. <!--
  2. 使用绝对路径: /部署的项目名/要访问的资源路径
  3. -->
  4. <a href="/webday05/hello">访问HelloServlet</a>

第三步:创建HelloServlet类

package com.atguigu.servlet;

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

/**
 * 包名:com.atguigu.servlet
 *
 * @author Leevi
 * 日期2021-06-07  09:03
 * 编写Servlet的步骤:
 * 1. 编写一个类实现Servlet接口,并且重写里面的方法: 主要是要重写service方法
 * 2. 重写service方法,service方法中就是接收、处理请求,并且将信息响应给客户端
 * 3. 配置Servlet的映射路径(供客户端访问的路径):在web/WEB-INF/web.xml中配置
 */
public class HelloServlet implements Servlet {

    @Override
    public void init(ServletConfig config) throws ServletException {

    }

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

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        //使用响应输出流向浏览器输出: Hello,I am Servlet
        res.getWriter().write("Hello,I am Servlet");
    }

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

    @Override
    public void destroy() {

    }
}

第四步:在web.xml中配置HelloServlet

配置文件位置:WEB-INF/web.xml

img008.png

<!--配置HelloServlet的映射路径-->
<servlet>

    <!--相当于给该Servlet取个名,我们可以就使用Servlet的类名/类名首字母改小写-->
    <servlet-name>helloServlet</servlet-name>

    <!--你要配置的那个Servlet的全限定名-->
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>

</servlet>

<servlet-mapping>

    <!--和servlet标签中的servlet-name保持一致-->
    <servlet-name>helloServlet</servlet-name>

    <!--这就是要给HelloServlet配置的映射路径,以/开头-->
    <url-pattern>/hello</url-pattern>

</servlet-mapping>

『映射路径』:Servlet并不是文件系统中实际存在的目录或文件,所以为了方便浏览器访问,我们创建了映射路径来访问它。

1.3.4 客户端请求Servlet执行流程

Servlet的请求过程.JPG

1.3.5 小结

需求:在浏览器上点超链接能够访问Java程序

img009.png

1.4 概念梳理

1.4.1 原生Tomcat

安装在电脑上的实实在在的Tomcat软件

1.4.2 IDEA中的Tomcat实例

通过idea的配置在idea上集成的Tomcat实例,其实还是使用的原生的Tomcat软件

1.4.3 IDEA中的Web工程

程序员使用IDEA编写的动态Web工程,该工程只是用于程序员编码,实际上部署运行在Tomcat服务器中的并不是这个工程

1.4.5 访问资源的地址

访问静态资源

/Web应用名称/静态资源本身的路径

/Web应用名称/映射路径

1.4.6 Web应用名称(项目名)

注意Web应用名不是你工程或者Module的名字,而是你在部署时候的ApplicationContext的内容
img014.png

第二章 Servlet的进阶

2.1 Servlet的生命周期和生命周期方法

2.1.1 什么是Servlet的生命周期

Servlet的生命周期就是servlet从创建到销毁的过程,我们所要去探讨的就是Servlet对象在什么时候创建出来以及在什么时候销毁。当然创建和销毁Servlet对象的工作是不需要我们去做的

2.1.2 Servlet对象什么时候创建

默认情况下是在第一次有请求访问该Servlet实例的时候才会创建该Servlet对象

2.1.3 Servlet对象什么时候销毁

在服务器关闭,或者当前项目从服务器中移除的时候会销毁当前项目中的所有Servlet对象

2.2 Servlet的生命周期方法

2.2.1 什么是Servlet的生命周期方法

在Servlet的生命周期中必然会经历的方法我们称之为Servlet的生命周期方法,总共包含三个方法:init、service、destroy

2.2.2 init方法

该方法会在Servlet实例对象被创建出来之后执行,我们可以在该方法中获取当前Servlet的初始化参数,以及进行一些读取配置文件之类的操作

2.2.3 service方法

该方法会在Servlet实例对象每次接收到请求的时候均执行,我们可以在该方法中接收、处理请求,以及将客户端需要的数据响应给客户端

2.2.4 destroy方法

该方法会在Servlet实例对象销毁之前执行,我们可以在该方法中做一些资源回收、释放、关闭等等操作

2.3 配置Servlet提前创建

有时候我们需要在Servlet创建的时候做一些资源加载等等耗时操作,所以如果Servlet在第一次接收请求的时候才创建的话必然会影响用户的访问速度,所以此时我们需要让Servlet提前创建,将Servlet的创建提前到服务器启动的时候。

通过修改web.xml中Servlet的配置可以实现:

<!-- 配置Servlet本身 -->
<servlet>
    <!-- 全类名太长,给Servlet设置一个简短名称 -->
    <servlet-name>HelloServlet</servlet-name>

    <!-- 配置Servlet的全类名 -->
    <servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>

    <!-- 配置Servlet启动顺序 -->
    <load-on-startup>1</load-on-startup>
</servlet>

2.4 ServletConfig的介绍(了解)

2.4.1 接口概览

img020.png

2.4.2 接口方法介绍

方法名 作用
getServletName() 获取HelloServlet定义的Servlet名称
getServletContext() 获取ServletContext对象
getInitParameter() 获取配置Servlet时设置的『初始化参数』,根据名字获取值
getInitParameterNames() 获取所有初始化参数名组成的Enumeration对象

2.4.3 获取Servlet的初始化参数

我们可以在web.xml中对Servlet配置初始化参数,接下来可以在Servlet的init方法中获取配置的初始化参数的值

web.xml代码

<!--配置DispatcherServlet-->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>com.atguigu.servlet.DispatcherServlet</servlet-class>

    <!--配置当前Servlet的初始化参数-->
    <init-param>
        <param-name>configLocation</param-name>
        <param-value>springMVC.xml</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/dispatcher</url-pattern>
</servlet-mapping>

HelloServlet代码

package com.atguigu.servlet;

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

/**
 * 包名:com.atguigu.servlet
 *
 * @author Leevi
 * 日期2021-06-07  10:41
 * 模拟它是SpringMVC中的一个类
 */
public class DispatcherServlet implements Servlet {
    private String filePath;
    @Override
    public void init(ServletConfig config) throws ServletException {
        //使用ServletConfig对象读取初始化参数
        filePath = config.getInitParameter("configLocation");
    }

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

    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        //目标:读取使用的springMVC的配置文件----->InputStream
        InputStream is = DispatcherServlet.class.getClassLoader().getResourceAsStream(filePath);
        System.out.println(is);
    }

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

    @Override
    public void destroy() {

    }
}

2.5 Servlet的体系结构

2.5.1 类型关系

img024.png

Servlet接口有一个实现类是GenericServlet,而GenericServlet有一个子类是HttpServlet,我们创建Servlet的时候会选择继承HttpServlet,因为它里面相当于也实现了Servlet接口,并且对一些方法做了默认实现;而且子类的功能会比父类的更加强大

2.5.2 方法关系

img025.png

我们编写Servlet类继承HttpServlet的时候,只需要重写doGet()和doPost()方法就行了,因为HttpServlet重写了service()方法,在service()方法中判断请求方式,根据不同的请求方式执行doXXX()方法

2.6 使用Idea直接创建Servlet

2.6.1 创建步骤

img022.png

img023.png

2.6.2 创建后的代码

web.xml代码

<!-- IDEA会自动生成servlet标签 -->
<servlet>
    <servlet-name>QuickServlet</servlet-name>
    <servlet-class>com.atguigu.servlet.QuickServlet</servlet-class>
</servlet>

<!-- 我们自己补充servlet-mapping标签 -->
<servlet-mapping>
    <servlet-name>QuickServlet</servlet-name>
    <url-pattern>/QuickServlet</url-pattern>
</servlet-mapping>

Servlet代码

public class QuickServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //在doPost()方法中调用doGet(),这样的话就只需要重写doGet()方法就能处理post和get请求
        doGet(request,response);
    }

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

    }
}

注意:如果我们手动删除Servlet类,配置文件是不会删除的

继承父类的调用方式
继承父类的调用方式.JPG

2.7 Servlet的三种映射路径的配置

2.7.1 映射路径的作用

Servlet的映射路径是提供一个让别人能够访问该Servlet的路径,例如Servlet的映射路径是”/hello”,那么在浏览器上访问该Servlet的路径是http://localhost:8080/项目部署名/hello

注意:一个Servlet可以配置多个映射路径,但是多个Servlet不能配置相同的映射路径

2.7.2 映射路径的分类

完全路径匹配

访问当前Servlet的路径需要和配置的映射路径完全一致,例如Servlet的配置是/demo01,那么访问该Servlet的时候的路径也必须是http://localhost:8080/项目部署名/demo01才可以访问到

目录匹配

/ 开始需要以 * 结束,: Servlet里面用的不多, 但是过滤器里面通常就使用目录匹配

例如:  配置/* 访问的路径可写成/任意字符串,比方: /aa, /aaa; 配置 /aa/*  访问的路径可写成/aa/任意字符串,比方: /aa/b , /aa/cc

扩展名匹配

*开头,以.扩展名结束,能够匹配所有以.相同扩展名结尾的请求路径

例如:  *.action;  访问路径可以是 任意字符串.action,比方: aa.action, bb.action, c.action;

缺省配置 /

当所有的Servlet路径都不匹配时,将执行缺省配置的Servlet

第三章 ServletContext对象

3.1 ServletContext的概念

服务器为其部署的每一个应用(项目)都创建了一个ServletContext对象。ServletContext属于整个项目的,该项目中的所有Servlet都可以共享同一个ServletContext对象

3.2 获取ServletContext的API

3.2.1 调用Servlet自身的getServletContext方法获取

ServletContext ServletContext = getServletContext()

3.2.2 调用ServletConfig接口的getServletContext方法

ServletContext ServletContext = servletConfig.getServletContext();
//HttpServletRequest对象也实现了ServletConfig接口,所以也有getServletContext()方法
ServletContext ServletContext = request.getServletContext();

3.3 ServletContext获取全局的初始化参数

3.3.1 在web.xml中配置Web应用级别的初始化参数

<context-param>
    <param-name>username</param-name>
    <param-value>hahahaha</param-value>
</context-param>

3.3.2 在Servlet的doGet方法中获取全局参数

String username = servletContext.getInitParameter("username");
System.out.println("在ServletDemo04中获取全局的初始化参数username=" + username);

3.4 ServletContext作为全局的域对象

3.4.1 什么是域对象

域对象就是在一定的作用域范围内进行数据共享的对象,ServletContext作为全局域对象可以在整个项目的所有动态资源(包含所有Servlet)中进行数据共享

3.4.2 ServletContext作为域对象的API

往全局域对象中存入数据

servletContext.setAttribute("key",value)

从全局域对象中取出数据

Object value = ServletContext.getAttribute("key");

3.4.3 案例

在ServletDemo01中往全局域对象中存入”username”为”aobama”的键值对,然后在ServletDemo02中从全局域对象中根据”username”获取对应的值

ServletDemo01中的代码

//1. 获取ServletContext对象
ServletContext ServletContext = getServletContext();
//2. 存入数据
String str = "周杰棍";
//将str设置到servletContext里面
servletContext.setAttribute("str",str);

ServletDemo02中的代码

//1. 获取ServletContext对象
ServletContext ServletContext = getServletContext();
//2. 取出数据
String str = (String) servletContext.getAttribute("str");
System.out.println("在ServletDemo02中获取ServletContext域对象中的str = " + str);

3.5 获取资源的真实路径

3.5.1 为什么需要用代码获取资源的真实路径

例如我们的目标是需要获取项目中某个静态资源的路径,不是工程目录中的路径,而是部署目录中的路径;我们如果直接拷贝其在我们电脑中的完整路径的话其实是有问题的,因为如果该项目以后部署到公司服务器上的话,路径肯定是会发生改变的,所以我们需要使用代码动态获取资源的真实路径

3.5.2 获取资源真实路径的API

String realPath = servletContext.getRealPath("资源在web目录中的路径");

第四章 Servlet注解开发

4.1 使用注解取代web.xml配置

注解的一大作用,就是取代配置文件,大大减少代码量。由于注解是源码中的写法,因此注解的后期维护没有配置文件方便。

注解开发Web应用程序,是Servlet3.0版本的新特性。

4.2 @WebServlet注解

将注解添加在Servlet接口的实现类上,此时就不在需要配置文件了,只需要为注解添加属性 urlPatterns即可被浏览器访问