▲点击上方卡片一键关注
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091935171910557526111.png)
♬ 点上方绿标可收听本期冠程科技推送的音频
![](http://ldjg88.com/zb_users/upload/2024/05/20240531000627171708518712641.gif)
作者 | 文字代表述说来源 | 今日头条Servlet与Servlet容器关系Servlet比较这两个的区别, 就得先搞清楚Servlet 的含义, Servlet (/ˈsərvlit/ ) 翻译成中文就是小型应用程序或者小服务程序, 与之相类似的是Server (/ˈsɜːrvər/), 翻译过来是服务器的意思, 可见这二者承担类似的功能,但是Servlet更轻量。
web开发的本质就一句话:客户端和服务器交换数据于是使用 Java 的 Socket 套接字进行编程,去处理客户端来的 tcp 请求,经过编解码处理读取请求体,获取请求行,然后找到请求行对应的处理逻辑步入服务器的处理中,处理完毕把对应的结果返回给当前的 Socket 链接,响应完毕,关闭 Socket。
上述过程中, 建立连接、传输数据、关闭连接等过程是tomcat容器帮你做了这些事情, 而拿到请求行之后去找对应的 url 路由,这一部分是谁做的呢?是Servlet ! 简单来说Servlet就是一段处理 web 请求的逻辑。
具体来说Servlet具有以下几个特点:Servlet是用Java编写的Server端程序,它与协议和平台无关Servlet运行于Java-enabled Web Server中Java Servlet可以动态地扩展Server的能力,并采用请求-响应模式提供Web服务。
最早支持Servlet技术的是JavaSoft的Java Web Server此后,一些其它的基于Java的Web Server开始支持标准的Servlet APIServlet的主要功能在于交互式地浏览和修改数据,生成动态Web内容。
上面六点中,最需要被记住的是Servlet可以动态地扩展Server的能力,并采用请求-响应模式提供Web服务JDK中的Servlet是一个接口:复制publicinterfaceServlet{public。
voidinit(ServletConfigconfig)throwsServletException;publicServletConfiggetServletConfig();publicvoidservice(ServletRequest
req,ServletResponseres)throwsServletException,IOException;publicStringgetServletInfo();publicvoiddestroy();
}可以看到Servlet 是一个接口, 规定了请求从容器到达 web 服务端的规范,详细内容在后面的Servlet生命周期中详细梳理,这儿简单概括三个重要步骤是:init():初始化请求的时候要做什么service():
拿到请求的时候要做什么destory():处理完请求销毁的时候要做什么所有实现 Servlet 的实现方都是在这个规范的基础上进行开发那么 Servlet 中的数据是从哪里来的呢?答案就是 Servlet 容器。
容器才是真正与客户端打交道的那一方一个容器中 Servlet 可以有多个, 常见的Servlet容器Tomcat,它监听了客户端的请求端口,根据请求行信息确定将请求交给哪个Servlet 处理,找到处理的Servlet之后,调用该Servlet的 service() 方法,处理完毕将对应的处理结果包装成ServletResponse 对象返回给客户端。
Servlet容器现在讲讲Servlet容器, 前面说过看Servlet只是一个接口或者说是规范, 那么就势必有具体实现, 而Servlet具体实现或者说包装器是Wrapper, 直接管理Wrapper的容器就是Context, 一个 Context 对应一个 Web 工程, 也就是说Context 容器如何运行将直接影响 Servlet 的工作。
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091935171910557569054.png)
由图可以知道, Tomcat底层是Context, Context负责管理Servlet包装类Wrapper下面创建一个实例对象并调用 start 方法就可以很容易启动 Tomcat,我们还可以通过这个对象来增加和修改 Tomcat 的配置参数,如可以动态增加 Context、Servlet 等。
我们就选择 Tomcat7 自带的 examples Web 工程,并看看它是如何加到这个 Context 容器中的复制//给 Tomcat 增加一个 Web 工程:Tomcattomcat=getTomcatInstance();
FileappDir=newFile(getBuildDirectory(),"webapps/examples");tomcat.addWebapp(null,"/examples",appDir.getAbsolutePath
());tomcat.start();ByteChunkres=getUrl("http://localhost:"+getPort()+"/examples/servlets/servlet/HelloWorldExample"
);assertTrue(res.toString().indexOf("
Hello World!
")>0);上述代码是创建一个 Tomcat 实例并新增一个 Web 应用,然后启动 Tomcat 并调用其中的一个 HelloWorldExample Servlet,看有没有正确返回预期的数据。复制//Tomcat 的 addWebapp 方法的代码如下:publicContextaddWebapp(Hosthost,Stringurl,Stringpath){silence(url);Context
ctx=newStandardContext();ctx.setPath(url);ctx.setDocBase(path);if(defaultRealm==null){initSimpleAuth();
}ctx.setRealm(defaultRealm);ctx.addLifecycleListener(newDefaultWebXmlListener());ContextConfigctxCfg=
newContextConfig();ctx.addLifecycleListener(ctxCfg);ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML"
);if(host==null){getHost().addChild(ctx);}else{host.addChild(ctx);}returnctx;}添加一个 Web 应用时将会创建一个 StandardContext 容器,并且给这个 Context 容器设置必要的参数(url 代表这个应用在 Tomcat 中的访问路径; path 代表这个应用实际的物理路径) 其中最重要的一个配置是 ContextConfig,【ContextConfig监听器】继承了 【LifecycleListener 监听器接口】,它是在调用清单 2 时被加入到 StandardContext 容器中。
当 Context 容器初始化状态设为 init 时,添加在 Context 容器的 Listener 将会被调用【ContextConfig监听器】将会负责整个 Web 应用配置文件的解析工作最后将这个 Context 容器加到父容器 Host 中。
Servlet生命周期Servlet生命周期分为四个部分: 实例化==>初始化==>执行处理==>销毁实例化new , 服务器第一次被访问时,加载一个Servlet容器,只会被加载一次初始化init:创建完Servlet容器后,会调用仅执行一次的init()初始化方法,用于初始化Servlet对象,无论多少台客户端在服务器运行期间访问都不会再执行init()方法。
可以在继承的GenericServlet这个抽象类中看到初始化方法:复制publicvoidinit()throwsServletException{}而在我们的Servlet类中应继承调用该方法:复制
publicvoidinit()throwsServletException{super.init();}创建Servlet对象的时机:Servlet容器启动时:读取web.xml配置文件中的信息,构造指定的Servlet对象,创建ServletConfig对象,同时将ServletConfig对象作为参数来调用Servlet对象的init方法。
在Servlet容器启动后:客户首次向Servlet发出请求,Servlet容器会判断内存中是否存在指定的Servlet对象,如果没有则创建它,然后根据客户的请求创建HttpRequest、HttpResponse对象,从而调用Servlet 对象的service方法。
Servlet:Servlet容器在启动时自动创建Servlet,这是由在web.xml文件中为Servlet设置的属性决定的从中我们也能看到同一个类型的Servlet对象在Servlet容器中以单例的形式存在。
执行处理执行处理——service()方法它是Servlet的核心,负责响应客户的请求每当一个客户请求一个HttpServlet对象,该对象的Service()方法就要调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。
在HttpServlet中已存在Service()方法默认的服务功能是调用与HTTP请求的方法相应的do功能HttpServlet的抽象类提供了doGet()、doPost()……等方法对应了request请求的发送方法,与之相匹配:。
复制protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException
{Stringprotocol=req.getProtocol();Stringmsg=lStrings.getString("http.method_get_not_supported");if(protocol
.endsWith("1.1")){resp.sendError(405,msg);}else{resp.sendError(400,msg);}}protectedvoiddoPost(HttpServletRequest
req,HttpServletResponseresp)throwsServletException,IOException{Stringprotocol=req.getProtocol();String
msg=lStrings.getString("http.method_post_not_supported");if(protocol.endsWith("1.1")){resp.sendError(
405,msg);}else{resp.sendError(400,msg);}}上面是操作性最高的部分销毁销毁——destroy:在服务器关闭或重启时,Servlet会调用destroy方法来销毁,将Servlet容器标记为垃圾文件,让GC做回收处理。
我们编写的Servlet是调用了GenericServlet抽象类的destroy方法:复制@Overridepublicvoiddestroy(){super.destroy();}Servlet工作原理
1、首先简单解释一下Servlet接收和响应客户请求的过程:客户发送一个请求,Servlet是调用service()方法对请求进行响应,service()方法中对请求的方式进行了匹配选择调用doGet,doPost等这些方法,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。
在Servlet接口和GenericServlet中是没有doGet()、doPost()等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。
2、每一个自定义的Servlet都必须实现Servlet的接口,Servlet接口中定义了五个方法,其中比较重要的三个方法涉及到Servlet的生命周期,分别是上文提到的init(),service(),destroy()方法。
GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。
所以我们定义Servlet的时候只需要继承HttpServlet即可3、Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest、ServletResponse 强转为HttpRequest 和 HttpResponse。
4、另外,Servlet是单例模式,线程是不安全的,因此在service()方法中尽量不要操作全局变量但实际上,可以通过使用session和application来代替全局变量,只是会加大服务器负载Servlet处理请求的过程
客户端发送请求给服务器容器根据请求及web.xml判断对应的Servlet是否存在,如果不存在则返回404容器根据请求及web.xml判断对应的Servlet是否已经被实例化,若是相应的Servlet没有被实例化,则容器将会加载相应的Servlet到Java虚拟机并实例化。
调用实例对象的service()方法,并开启一个新的线程去执行相关处理。调用servce方法,判断是调用doGet方法还是doPost方法。业务完成后响应相关的页面发送给客户端。
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091935171910557516643.jpeg)
如果我们的文章对你有帮助,就把我们“设为星标”吧!↓↓↓3秒加星标,这样就不容易错过文章推送啦!
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091936171910557633339.png)
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091936171910557686062.gif)
请长按下方图片识别二维码 关注冠程科技为客户创造价值与客户共同成长
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091936171910557692126.png)
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091937171910557711717.png)
![](http://ldjg88.com/zb_users/upload/2024/06/20240623091937171910557795332.gif)
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。