`
toking79
  • 浏览: 23013 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

Tomcat源码系列4--Tomcat中Servlet处理流程

阅读更多

本次谈一下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请求处理的时序图


 
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请求处理的时序图


 
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请求结束后,程序逐层回调,得到返回结果。

 

  • 大小: 7 KB
  • 大小: 24.2 KB
2
1
分享到:
评论
1 楼 cwj158 2012-03-11  
请教下:
JSP转换为java程序为什么要交给WEB容器来做呢?
不同的WEB容器生成的JAVA是不是不同呢?

相关推荐

    tomcat源码,servlet-api源码

    《深入理解Tomcat源码与Servlet-API》 ...综上所述,深入研究Tomcat源码和Servlet-API不仅能提升我们的开发技能,还能帮助我们更好地理解和优化Java Web应用的性能,从而在实际工作中发挥更大的价值。

    tomcat-redis-session-manager源码

    《深入解析Tomcat-Redis-Session-Manager源码》 在现代Web应用中,服务器端会话管理是一个至关重要的部分,特别是在高并发、分布式环境中。Tomcat作为最流行的Java Servlet容器,提供了丰富的功能来支持这一需求。...

    3-6Tomcat处理源码实现与异步Servlet源码实现(1).mp4

    3-6Tomcat处理源码实现与异步Servlet源码实现(1).mp4

    jakarta-servletapi-4-src.zip servlet源码

    本篇文章将围绕jakarta-servletapi-4-src.zip这个源码包,深入剖析Servlet API 4.0的关键特性与实现原理。 一、Servlet接口与生命周期 Servlet接口是所有Servlet的基础,它定义了Servlet的主要方法,如`init()`, `...

    tomcat-servlet-api-9.0.0.M10-sources.jar

    tomcat-servlet-api-9.0.0.M10 源码jar包,包里是源码文件,可以直接做jar包使用也可以学习里面的源码调试。

    Tomcat源码apache-tomcat-8.5.47-src.zip

    Apache Tomcat是一个开源的Java Servlet容器,主要用于实现Java EE中的Web应用规范,特别是Servlet和JavaServer Pages (JSP)。源码分析对于开发者来说是一种深入理解软件内部运作机制的重要途径。`apache-tomcat-...

    servlet源码 servlet-api-src javax.servlet.Servlet源码

    总的来说,理解和研究`servlet-api-src`中的`javax.servlet.Servlet`源码对于任何Java Web开发者来说都是一个重要的学习步骤。它不仅可以帮助我们深入理解Servlet的工作原理,还可以提升我们在实际项目中的开发效率...

    Tomcat8亲测可用 tomcat-redis-session-manager的jar包

    标题中的“Tomcat8亲测可用 tomcat-redis-session-manager的jar包”指的是一个专为Tomcat8设计的,用于管理session的扩展组件。这个组件实现了将Tomcat应用服务器中的用户session数据存储到Redis分布式缓存系统中,...

    apache-tomcat-7.0.81-src 源码免费下载

    9. **错误处理与日志系统**:Tomcat使用自定义的日志框架,源码中`logging`目录下的类定义了如何记录和处理错误信息。 10. **网络编程**:Tomcat底层使用NIO(非阻塞I/O)和BIO(阻塞I/O)模型,这在`java/org/...

    tomcat-connectors-1.2.48-src

    - **处理请求**:Tomcat worker接收到请求后,通过Servlet容器处理它。 - **返回响应**:Tomcat完成处理后,将响应通过`mod_jk`回传给HTTPD,最后由HTTPD发送回客户端。 5. **性能优化** `tomcat-connectors-...

    apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src的源码

    这个压缩包包含了两个版本的Tomcat源码:apache-tomcat-7.0.62-src和apache-tomcat-6.0.39-src,这两个版本分别代表了Tomcat在不同时间点的开发状态和技术特性。 首先,让我们从Apache Tomcat 6.0.39源码开始分析。...

    apache-tomcat-6.0.37

    4. **日志与错误处理**:Tomcat的日志信息默认存储在logs目录下,包括catalina.out、host-manager、manager等日志文件,这对于调试和监控系统状态非常有用。 5. **安全管理**:Tomcat提供了用户管理和角色定义,...

    Java学生课程成绩-教师信息管理系统,Servlet+Mysql+Jsp+Tomcat,优秀毕业设计,计算机必看!

    Java学生课程成绩-教师信息管理系统,Servlet+Mysql+Jsp+Tomcat,优秀毕业设计,计算机必看! Java学生课程成绩-教师信息管理系统,Servlet+Mysql+Jsp+Tomcat,优秀毕业设计,计算机必看! Java学生课程成绩-教师...

    tomcat 源码分析系列文档

    4. "Tomcat源码分析(4)容器处理链接之责任链模式.doc":分析了Tomcat如何利用责任链模式来处理请求,使得请求可以被多个处理器(如过滤器)有序处理。 5. "tomcat加载类的顺序.doc":详细说明了Tomcat加载类的具体...

    apache-tomcat-6.0.35和apache-tomcat-6.0.35 src

    Apache Tomcat是一款开源的Java Servlet容器,主要用于实现JavaServer Pages (JSP)、Servlet和Java EE的Web应用程序。在这个压缩包中,包含了两个版本:`apache-tomcat-6.0.35` 和 `apache-tomcat-6.0.35 src`。前者...

    tomcat8源码

    Apache Tomcat 8.5.23 源码分析 Apache Tomcat 是一个开源的、免费的Web服务器和Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,...因此,对Tomcat源码的学习对于Java Web开发者来说是至关重要的。

    apache-tomcat-6.0.53-src

    【Apache Tomcat 6.0.53 源码包】是Java Web应用程序服务器,主要用于部署和运行Servlet和JSP应用。这个源码包包含了Tomcat的核心代码,对于开发者而言,它是一个宝贵的学习资源,可以帮助理解Tomcat的工作原理以及...

    apache-tomcat-9.0.8-src源码资源

    通过对`apache-tomcat-9.0.8-src`源码的深入研究,我们可以了解到Tomcat如何处理网络请求,怎样管理Web应用,以及如何实现各种高级特性。这对于开发者来说是一份宝贵的学习资料,可以帮助他们更好地优化应用程序,...

    apache-tomcat-6.0.29.zip

    在本压缩包"apache-tomcat-6.0.29.zip"中,包含的是Apache Tomcat 6.0.29版本的源码、配置文件、库文件以及相关的文档资料。 Tomcat 6.0.29是Apache Tomcat的一个稳定版本,发布于2010年,支持Java EE 5规范。以下...

    tomcat-servlet-api-9.0.0.M17-sources.jar

    tomcat-servlet-api-9.0.0.M17 源码jar包,包里是源码文件,可以直接做jar包使用也可以学习里面的源码调试。

Global site tag (gtag.js) - Google Analytics