哥几个来学 Servlet 啦 ~~
目录
🌲一、什么是 Servlet
🌳二、第一个 Servlet 程序
🍇1. 创建项目
🍈2. 引入依赖
🍉3. 创建目录
🍊4. 编写代码
🍋5. 打包程序
🥭6. 部署程序
🍍7. 验证程序
🌴三、更方便的部署方式
🍁1. 安装 Smart Tomcat 插件
🍂2. 配置 Smart Tomcat 插件
🌵四、Servlet 的运行原理
🌾五、Servlet 的生命周期
🌲一、什么是 Servlet
Servlet 是一种实现 动态页面 的技术,是一组 Tomcat 提供给程序员的 API,定义了 Java 类 被浏览器访问到(被 Tomcat 识别)的规则,能够帮助程序员简单高效地开发一个 web app。
那么问题来了,什么是 动态页面?
我们先来认识一些什么是 静态页面:
静态页面 就是内容始终固定的页面,即使用户不同/时间不同/输入的参数不同,页面的内容也不会发生变化。(除非网站的开发人员修改源代码,否则页面内容始终不变)。
比如 Tomcat 的主页:
动态页面:
而 动态页面 指的就是 用户不同/时间不同/输入的参数不同,页面的内容发生变化。
比如我们的 CDSN :
🌳二、第一个 Servlet 程序
🍇1. 创建项目
注意:这里我们使用的不再是 “intelliJ” ,而是 “Maven” 。
🍈2. 引入依赖
Maven 项目创建完毕后,会自动生成一个 pom.xml 文件。
我们需要在 pom.xml 中引入 Servlet API 依赖的 jar 包:
🍕① 在中央仓库搜
Maven Repository: Search/Browse/Explore (mvnrepository.com)https://mvnrepository.com/🍔② 然后搜索 "servlet",一般第一个结果就是:
🍟③ 选择版本,Servlet 的版本要和 Tomcat 匹配,如果我们使用 Tomcat 8.5, 那么就需要使用 Servlet 3.1.0 版本。
🌭④ 把中央仓库中提供的 xml 复制到项目的 pom.xml 中
首先要在 这段代码的外围加上 dependencies 标签:
然后再将代码复制进去
porn.xml的完整代码是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>ServletHelloWorld</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
🍉3. 创建目录
当项目创建好了之后,IDEA 会帮我们自动创建出一些目录:
这些目录中:
- src 表示源代码所在的目录
- main/java 表示源代码的根目录。后续创建.java 文件就放到这个目录中
- main/resources 表示项目的一些资源文件所在的目录
- test/java 表示测试代码的根目录
除了这些目录,我们还需要创建一些新的目录/文件
🍖① 创建 webapp 目录 在 main 目录下,和 java 目录并列,创建一个 webapp 目录
🍗② 创建 web.xml 然后在 webapp 目录内部创建一个 WEB-INF 目录,并创建一个 web.xml 文件
🥩③ 编写 web.xml
往 web.xml 中拷贝以下代码:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>
这些代码,我们可以看成是一些约定,可以帮助我们将资源部署到 Tomcat 里~~
webapp 目录就是未来部署到 Tomcat 中的一个重要目录,我们可以往 webapp 中放一些静态资源,比如 html,css 等。
在这个目录中还有一个重要的文件 web.xml ,Tomcat 找到这个文件才能正确处理 webapp 中的动态资源。
🍊4. 编写代码
在 java 目录中创建一个类 HelloServlet,让它实现 Servlet 的接口,重写 Servlet 的方法。
代码如下:
import javax.servlet.*;
import java.io.IOException;
@WebServlet("/hello")
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("Hello Servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
这个的作用是提供路径 url,待会执行程序时会用到这个 url~~
千万不要漏了 “ hello ” 前面的 “ / ” !!!!!
这上面的五个方法,我们待会儿再详细讲。
我们目前只在 service() 方法里加了一行代码而已:
🍋5. 打包程序
使用 maven 进行打包,打开 maven 窗口,然后展开 Lifecycle ,双击 package 即可进行打包:
如果比较顺利的话,能够看到 SUCCESS 这样的字样:
如果代码/配置/环境存在问题,可能会提示 BUILD FAILED,可以根据具体提示的错误信息具体解决。
打包成功后,可以看到在 target 目录下,生成了一个 jar 包:
这样的 jar 包并不是我们需要的,Tomcat 需要识别的是另外一种 war 包格式。
jar 包和 war 包的区别:
- jar 包是普通的 java 程序打包的结果,里面会包含一些 .class 文件。
- war 包是 java web 的程序,里面除了会包含 .class 文件之外,还会包含 HTML、CSS、 JavaScript、图 片、以及其他的 jar 包。打成 war 包格式才能被 Tomcat 识别!!!
另外这个 jar 包的名字太复杂了,我们也希望这个名字能更简单一点。
因此,我们需要:
🧇① 在 pom.xml 中新增一个 packing 标签,表示打包的方式是打一个 war 包:
<packaging>war</packaging>
🥞② 在 pom.xml 中再新增一个 build 标签,内置一个 finalName 标签,表示打出的 war 包的名字是 HelloServlet:
<build>
<finalName>HelloServlet</finalName>
</build>
完整的 pom.xml 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>ServletHelloWorld</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<packaging>war</packaging>
<build>
<finalName>HelloServlet</finalName>
</build>
</project>
重新使用 maven 打包,可以看到生成的新的 war 包的结果:
🥭6. 部署程序
把 war 包拷贝到 Tomcat 的 webapps 目录下:
启动 Tomcat , Tomcat 就会自动把 war 包解压缩:
🍍7. 验证程序
此时通过浏览器访问 127.0.0.1:8080/HelloServlet/hello
这个路径里的:
“127.0.0.1:8080” 是环回地址
“HelloServlet” 是我们的文件名
“hello” 则是这里面的url
就可以看到结果了(结果在 Tomcat 服务器上显示的):
我们多次点击刷新,那么 Tomcat 服务器就会多次执行 service() 方法里的代码:
🌴三、更方便的部署方式
手动拷贝 war 包到 Tomcat 的过程比较麻烦,我们还有更方便的办法。此处我们使用 IDEA 中的 Smart Tomcat 插件完成这个工作。
🍁1. 安装 Smart Tomcat 插件
🥗① 菜单 -> 文件 -> Settings
🥙② 选择 Plugins,选择 Marketplace,搜索 "tomcat",点击 "Install"
🥪③安装完毕之后,会提示 "重启 IDEA"
🍂2. 配置 Smart Tomcat 插件
🍘① 点击右上角的 "Edit Configurations"
🍙② 选择左侧的 "Smart Tomcat"
🍚③ 在 Name 这一栏填写一个名字(可以随便写)
在 Tomcat Server 这一栏选择 Tomcat 所在的目录,其他的选项不必做出修改。
其中 Context Path 默认填写的值是项目名称 ,这会影响到后面咱们的访问页面
🍛④ 点击 OK 之后,右上角变成了
点击绿色的三角号,IDEA 就会自动进行编译、部署、启动 Tomcat 的过程
此时 Tomcat 日志就会输出在 IDEA 的控制台中,可以看到现在就不再乱码了。
🍜⑤ 访问页面
在浏览器中使用 localhost:8080/HelloServlet/hello 来访问页面:
localhost:8080/HelloServlet/hello
控制台会执行 service() 方法里的代码:
🌵四、Servlet 的运行原理
在 Servlet 的代码中我们并没有写 main 方法,那么对应的 doGet 代码是如何被调用的呢?响应又是如何返回给浏览器的?
🦪1.当服务器接收到客户端浏览器的请求后,会解析请求的 URL 路径,获取访问的 Servlet 的资源路径。
🍣2.Tomcat 通过 Socket 读取到这个请求(一个字符串),会根据 url 中的 路径 判定这个请求 是 请求的一个静态资源还是动态资源。如果是静态资源,直接找到对应的文件把文件里的内容通过 Socket 返回。如果是动态资源,才会执行到 Servlet 的相关逻辑。
🍤3.Tomcat 会根据 url 中的 Context Path 和 Servlet Path 确定要调用哪个 Servlet 实例的方法。
🌾五、Servlet 的生命周期
我们先来回顾一下我们上面代码里的 5 个方法:
方法名称 | 功能/调用时机 |
init | 初始化方法,在 Servlet 实例化之后被调用一次,只会执行一次 |
getServletConfig | 获取 ServletConfig 对象,也就是 Servlet配置。(了解即可) |
service | 提供服务的方法,每次服务器被访问时执行,可以执行多次 |
getServletInfo | 获取 ServletInfo 对象,也就是 Servlet的信息。(了解即可) |
destory | 销毁方法,在 服务器 正常关闭时被调用,只会执行一次 |
现在我们分别在 init() 、service() 、destory() 方法里加入 “System.out.println("执行 XXX 方法");”
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet("/hello")
public class HelloServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("执行 init 方法");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("执行 service 方法");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("执行 destroy 方法");
}
}
来观察一下结果
当我们第一次访问 localhost:8080/HelloServlet/hello 的时候,控制台输出结果如下:
当我们多次访问这个网站时:
当我们关闭服务器的时候:
下面我们来通过上述现象来解析一下 Servlet 的生命周期:
🍦1.被创建:执行 init 方法,只执行一次
Servlet 什么时候被创建?
- 默认情况下,第一次被访问时,Servlet 被创建
- 也可以在服务器启动的时候进行创建,不过需要在 web.xml 进行配置(如果我们的 init()方法 要初始化的资源比较多,或者有其他的 Servlet 依赖这个 Servlet 的时候,可以在服务器启动的时候进行创建)
Servlet 的 init()方法只执行一次,说明 Servlet 在内存中只存在一个对象,因此难免会出现多线程安全问题:比如 抢票 APP ,就涉及到许多的客户端对一个Servlet进行修改操作。
那么我们应该尽量避免在 Servlet 中创建成员变量,及时创建了成员变量,也不要去修改它。
🍧2.提供服务:执行 service()方法,执行多次
每次访问 Servlet 时,Service 方法都会被调用一次。
🍨3.被销毁:执行 destroy()方法,只执行一次
Servlet 被销毁前执行(就像临终遗言)。只有服务器正常关闭,才会执行 destroy()方法。
小结:
Servlet 是一种实现 动态页面 的技术,是一组 Tomcat 提供给程序员的 API。它的生命周期有 init、service、destroy,就像人的一生:出生、工作、死亡~~
下一篇我们着重讲解 HttpServlet ~~