设为首页 收藏本站
查看: 648|回复: 0

[经验分享] Tomcat源码系列4--Tomcat中Servlet处理流程

[复制链接]

尚未签到

发表于 2017-1-25 10:59:07 | 显示全部楼层 |阅读模式
  本次谈一下Servlet的处理流程,不当之处请各位指正。


在经过了「Tomcat启动」,「Tomcat请求处理」等一系列流程后,程序运行到org.apache.catalina.core.ApplicationFilterChain.ApplicationFilterChain.InternalDoFilter()方法,这时会调用servlet的service()方法。 

    void internalDoFilter(ServletRequest request, ServletResponse response) throws
IOException, ServletException{
// filter処理的代码省略。
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse)) {
servlet.service((HttpServletRequest) request, (HttpServletResponse) response);
} else {
servlet.service(request, response);
}
}
  

程序到了这里,会出现三种情况,分别对应着对Servlet,JSP,和静态资源的处理。
 对于Servlet,直接调用开发人员自己编写的#service()方法。
 对于静态资源(HTML页面),servlet会是org.apache.catalina.servlets.DefaultServlet类的一个实例。会调用DefaultServlet的#service()方法。
 对于jsp页面, servlet会是 org.apache.jasper.servlet.JspServlet 类的一个实例。调用JspServlet类的#service()方法。
下面我们将分别从HTML请求和JSP请求两个方面展开来讨论程序运行情况。

一. HTML页面处理过程
以下是HTML请求处理的时序图

DSC0000.gif
 
1.从上示流程图可知首先HttpServlet#service(ServletRequest req, ServletResponse res)被调用。
(javax.servlet.http.HttpServlet.service) 

public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
}
  
2. HttpServlet.service(HttpServletRequest req, HttpServletResponse resp)
被调用。
  (javax.servlet.http.HttpServlet.service) 

protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
//此方法将判断请求的servlet的方法是doGet()、doPost()或是其他的方法,
//此次调用以doGet(req, resp)方法为例。
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
doGet(req, resp);
}
}
  
3. defaultServlet# doGet()被调用。
(org.apache.catalina.servlets.DefaultServlet.doGet) 

protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
//请求服务的资源,包括数据内容
try {
serveResource(request, response, true);
}
}
  

在serveResource()方法中会进行request资源的处理和response资源的创建。通过以上步骤,HTML页面的请求处理完毕,将逐层返回调用,最后将在浏览器端得到HTML页面的显示。

二. JSP页面处理过程
以下是JSP请求处理的时序图

DSC0001.jpg
 
1. 从上图可知首先HttpServlet#service(ServletRequest req,ServletResponse res) 被调用。      
(javax.servlet.http.HttpServlet.service) 

public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
  

2. 由于是JSP资源,接下来JspServlet#service会被调用。
(org.apache.jasper.servlet.JspServlet.service) 

public void service (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// 预编译模式,如果是预编译模式,只是对JSP进行编译,不会返回页面执行结果   
boolean precompile = preCompile(request);   
// 继续JSP请求  
serviceJspFile(request, response, jspUri, null, precompile);
}
}
  

3.jspServlet#serviceJspFile(request, response, jspUri, null, precompile)将被调用。
(org.apache.jasper.servlet.JspServlet.service)

private void serviceJspFile(HttpServletRequest request,
HttpServletResponse response, String jspUri,
Throwable exception, boolean precompile)
throws ServletException, IOException {
JspServletWrapper wrapper =
(JspServletWrapper) rctxt.getWrapper(jspUri);
wrapper.service(request, response, precompile);
}
  

4.jspServletWrapper#service(HttpServletRequest request,
                  HttpServletResponse response,boolean precompile)方法被调用。此方法将进行三个步骤,编译,加载,处理服务请求
(org.apache.jasper.servlet.JspServletWrapper.service) 

public void service(HttpServletRequest request,
HttpServletResponse response,
boolean precompile)
throws ServletException, IOException, FileNotFoundException {
try {                     
// (1) 编译       ☆1     
if (options.getDevelopment() || firstTime ) {
synchronized (this) {
if (firstTime) {
firstTime = false;
}
// The following sets reload to true, if necessary
ctxt.compile();
}
} else {
if (compileException != null) {
// Throw cached compilation exception
throw compileException;
}
}
// (2) 加载servlet类
getServlet();
// (3) 处理服务请求 ☆2            
if (theServlet instanceof SingleThreadModel) {
synchronized (this) {
theServlet.service(request, response);
}
} else {
theServlet.service(request, response);
}
  

☆1 编译
1.首先jspCompiler#compile()将被调用。
(org.apache.jasper.JspCompilationContext.compile) 

public void compile() throws JasperException, FileNotFoundException {
// 创建"jspCompiler"的实例   
createCompiler();   
// 判断是否过期,即是否需要重新编译,这个方法中主要用源代码和编译后的文件的修改时间等因素进行判断   
if (jspCompiler.isOutDated()) {   
try {   
jspCompiler.removeGeneratedFiles();   
jspLoader = null;   
// 执行编译   
jspCompiler.compile();
}
  

2.Compiler#compile(true)将被调用。
(org.apache.jasper.JspCompilationContext.compile)

public void compile()
throws FileNotFoundException, JasperException, Exception
{
compile(true);
}

  

3.Compiler#compile(boolean compileClass)被调用。
(org.apache.jasper.JspCompilationContext.compile) 

public void compile(boolean compileClass)
throws FileNotFoundException, JasperException, Exception
{
compile(compileClass, false);
}
  
4.Compile#compile(boolean compileClass, boolean jspcMode)被调用
(org.apache.jasper.JspCompilationContext.compile) 

public void compile(boolean compileClass, boolean jspcMode)
throws FileNotFoundException, JasperException, Exception
{
if (errDispatcher == null) {
this.errDispatcher = new ErrorDispatcher(jspcMode);
}
try {
String[] smap = generateJava();
if (compileClass) {
generateClass(smap);//生成class文件
}
  

5. 程序运行到此时Compiler#generateJava()被调用。
(org.apache.jasper.compiler.Compiler.generateJava()) 

protected String[] generateJava() throws Exception {
// generate servlet .java file
Generator.generate(writer, this, pageNodes);
writer.close();
writer = null;
}
  
generateJava()方法的作用是将JSP文件转换为Java文件。该部分的功能是由Jasper实现的。
在生成java文件以后,将调用generateClass()方法,将java文件编译成class文件。

☆2 处理服务请求
1.JspServletWrapper#service(request, response)被调用。

2. HttpServlet#service(ServletRequest request, ServletResponse response)被调用。
(javax.servlet.http.HttpServlet.service) 

public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException
{
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
}
  

3.HttpJspBase#Servlet(HttpServletRequest request,
                  HttpServletResponse response)被调用。
(org.apache.jasper.runtime.HttpJspBase.service) 

public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
_jspService(request, response);
}
  

4. _jspService(request, response)被调用。实际上是调用由JSP转换为java程序的_jspService()方法,Servlet请求结束后,程序逐层回调,得到返回结果。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-333238-1-1.html 上篇帖子: Eclipe将web项目部署到Tomcat 下篇帖子: 13.tomcat加载器
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表