这篇文章, 我主要分享JavaWeb动态网页开发.要谈JavaWeb动态网页开发.我们就要来了解Servlet, 所以我会按如下进行分享
Servlet的规范
Servlet的请求流程
Servlet初始化参数
Servlet继承体系的设计原因
Servlet请求和响应
主要围绕Servlet的原理
和Servlet的应用
两条主线来分享.Servlet的原理:
包含Servlet的规范
、Servlet的基本请求流程
、Servlet继承体系的设计原因
Servlet的应用:
包含Servlet初始化参数
、Servlet请求和响应
1.什么是Servlet规范
Servlet是一套规范, 所谓的规范就是做了约束
.
是一个规范
.Servlet是一个规范,所谓的规范就是Servlet约束了一些东西, 主要约束了容器
、约束了项目目录结构
,约束了我们的代码
.是一个组件
. Servlet也可以看成是一个组件, 因为一个遵循Servlet规范的程序可以跑在实现Servlet规范的容器中。
Servlet的规范
2.如何编写一个最简单的Servlet的步骤
创建一个HelloServlet类继承自HttpServlet.。
复写其service方法, 在其中编写业务逻辑处理请求。
配置web.xml. 增加xml中的servlet对象和servlet-mapping对象.其中servlet对象用来关联我们的类,并给这个类一个别名。servlet-mapping对象用来映射servlet和和访问的资源名。这样才来告诉tomcat容器, 一旦请求来了, 该根据资源名去找哪个servlet做处理。
3.如何研究Servlet对象的生命周期
Servlet对象生命周期依赖于容器, 因为Servlet规范已经约定了Servlet对象必须放在实现Servlet规范的容器中运行, 换区话说Servlet对象从出生到死亡都由容器调度。所以容器负责Servlet的创建、初始化、运行、释放
.
要了解Servlet具体的生命周期, 我们先介绍以下上个方法.这三个方法是Servlet的生命周期方法.
生命周期方法
init(ServletConfig); 负责初始化Servlet.
service(ServletRequest, ServletResponse); 负责处理请求.
destory(); 负责释放Servlet.
观察Servlet的生命周期
我们可以创建一个HelloServlet如下, 并且给它提供一个无参构造方法, 分别在上面上个生命周期方法中做打印, 来研究其调用顺序.
创建HelloServlet, 继承自HttpServlet.复写
其生命周期方法
package com.sweetcs.web.servlet;import java.io.IOException;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class HelloServlet extends HttpServlet{ public HelloServlet() { // TODO Auto-generated constructor stub System.out.println("Servlet构造方法"); } @Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub super.init(config); System.out.println("Servlet init"); } @Override protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { System.out.println("Servlet service"); } @Override public void destroy() { // TODO Auto-generated method stub super.destroy(); System.out.println("Servlet destroy"); } }
web.xml中配置资源名的要交个哪个servlet处理
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true"> <display-name>Welcome to Tomcat</display-name> <description> Welcome to Tomcat </description> <servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.sweetcs.web.servlet.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HelloServlet</servlet-name> <url-pattern>/hello</url-pattern> </servlet-mapping> </web-app>
第一次访问http://127.0.0.1:8080/hello打印输出
第一次访问
第二、三次访问http://127.0.0.1:8080/hello打印输出
第二、三次访问
通过上述观察可以发现,第一次访问是依次调用了构造方法
、init方法
、service方法
.但是什么时候Servlet对象的destory方法才会调用呢?我们进行以下两种方式验证。
第一种停止tomcat的运行, 点击带有叉号的猫
点击带有叉号的猫
输出如下,说明调用了destory方法, Servlet被正确的释放掉.
打印出destory
第二种直接终止程序.
点击小红点终止程序
输出如下, 说明Servlet对象的destory方法没有被容器调用, 也就是说Servlet没有被正确的释放掉.
根据上述实验验证,我们可以得出以下结论
总结
Servlet的生命周期是先由容器
创建Servlet对象, 所以会调用其构造方法
.然后再调用init方法进行初始化, 最后调用service方法处理请求.由次可以见Servlet只在第一次访问时候创建
.创建完后容器就调用了servlet的init方法.Servlet对象在整个容器中只有一份,属于单例
.因为多次的相同url的请求过来, 都没有再调用构造方法, 显然没有在创建新的Sevlet对象.Servlet必须提供无参数构造器
.由于Sevlet对象不是我们手动创建的, 而是交给容器负责。在这里我们使用的是tomcat容器.而tomcat容器是使用反射技术Class clazz = Class.forName();
和clazz.newInstance()
创建Servlet对象.所以我们必须提供无参构造器.当然Java中如果你不提供构造器, 默认就会存在一个无参构造器。要正确的让Servlet得到释放
, 必须得停止tomcat容器.如果是程序异常中断, Servlet并不能得到释放.
4.Servlet请求流程
我们了解了Servlet的规范、Servlet的生命周期、接着我们研究下我们从浏览器
通过http协议请求相应的资源的时候。服务器端的Servlet从接受到请求的到响应的流程.
1.当
tomcat服务器
接受到浏览器
的请求时, 会进行URL的解析.将URL分解出ContextPath
和ResourceName
.即上下文路径
和资源名称
.2.解析完成后,
tomcat会去读取其conf/server.xml
中的所有Context对象
.(我把Context元素叫对象)3.然后根据
ContextPath
的值和Context对象
的path属性
进行比较, 找到对应的Context对象。
如果没有找到对应的Context对象就报404 Not Found
.
如果有找到对应的Context对象则进入第4步.(如下是一个Context元素<Context docBase='xxx' path='contextPath' />
)4.读取Context对象的docBase属性值,即为项目的部署路径所在地址.tomcat会根据该地址取读取其下的
WEB-INF/web.xml
配置文件.5.解析
web.xml
中的所有Servlet-Mapping对象, 并用ResouceName和Servlet-Mapping对象的url-pattern比较.如果知道到匹配的进入第6步, 否者也是报404 Not Found
.6.根据找到的Servlet-Mapping对象的servlet-name继续找到Servlet对象对应的全限定类名.
7.
尝试去 Servlet缓存池获取对应的Servlet对象
.根据全限定类名取对应的Servlet对象.如果取到, 则直接调用其service方法(传入已经创建好的request和reponse对象)8.如果Servlet缓存池中没有对应的对象, 则使用反射技术, 加载解析出来的全限定类名.并调用其newInstance()方法创建Servlet对象.
9.创建ServletConfig对象, 该对象即代表web.xml.调用Servlet对象的init方法.
servlet.init(config)
调用Servlet对象的service方法处理请求, 相应数据.
servlet.service(request, response)
如果有重复的请求进来, 则进入第7步.
注意
server.xml
文件配置了contextPath.web.xml
配置了资源名称.server.xml
文件让tomcat根据contextPath去找到对应的根目录地址.web.xml
文件根据tomcat根据资源名称知道对应的Servlet类,再通过反射技术创建Sevlet对象.
5.Servlet初始化参数
了解完Servlet的请求流程, 我们也就明白了底层是如何创建Servlet对象, 同时知道了配置文件的作用。接着我们就顺着该流程的第一个步骤, 创建并初始化Servlet对象, 想来了解下Servlet的初始化参数.
5.1 init(config)
什么是初始化参数, 即Servlet在创建后, 我们可能会需要它附带一些属性, 并且我们用配置好的参数来初始化这些Servlet.这些参数都是配置在web.xml
的<Servlet元素>
中.
如下我们给HelloServlet配置初始化参数, 并读取出来查看.
web.xml配置, 在servlet元素
中添加init-param元素
<servlet> <servlet-name>HelloServlet</servlet-name> <servlet-class>com.sweetcs.web.servlet.HelloServlet</servlet-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </servlet>
Java代码
public class HelloServlet extends HttpServlet{ private ServletConfig config; public HelloServlet() { // TODO Auto-generated constructor stub System.out.println("Servlet构造方法"); } @Override public void init(ServletConfig config) throws ServletException { // TODO Auto-generated method stub super.init(config); this.config = config; System.out.println("Servlet init"); } @Override protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException { System.out.println("Servlet service"); String encoding = config.getInitParameter("encoding"); System.out.println(encoding); } @Override public void destroy() { // TODO Auto-generated method stub super.destroy(); System.out.println("Servlet destroy"); } }
启动tomcat, 并浏览器输入http://127.0.0.1:8080/hello.打印如下,可以正确的将配置参数读取出来.
Servlet构造方法 Servlet init Servlet service UTF-8
作者:sixleaves
链接:https://www.jianshu.com/p/6d7fcf8120cc