• 深入刨析tomcat 之---第21篇 tomcat 对jsp页面支持的实现原理


    writedby 张艳涛

    web技术,以前的动态网页技术多是jsp页面,比如点击一个菜单目录,直接访问了一个LRJSDetailInput.jsp页面,这个页面

    有<html><body><form><table>标签,有对应的js,当对某个button标签设置了onClick方法后就调用js中的方法将

     <INPUT class=cssButton VALUE="查   询" TYPE=button  onClick="queryDetailData();"> 
    <INPUT class=cssButton VALUE="下 载" TYPE=button onClick="downLoadData();">

    在js中为

    function downLoadData()
    {
        if(checkValid() == false){
            return false;
        } 
        tSQL ="select c.belongyear,c.belongquarter,c.recomname,c.recontcode,c.riskcode,c.costcernter,NVL(c.cessprem,0),NVL(c.reprocfee,0),NVL(c.claimbackfee,0),NVL(c.adjustfee,0),NVL(c.balancelend,0),c.year,c.month from LRJSDetail c where 1=1  "
            +getWherePart('belongyear','belongyear')
            +getWherePart('belongquarter','belongquarter')
            +getWherePart('recontcode','recontcode')
            +getWherePart('riskcode','riskcode')
            +getWherePart('recomname','recomname')
                +getWherePart('costcernter','costcernter')
                +getWherePart('year','year')
                +getWherePart('month','month')
            ;
    
        tSQL+=" order by c.belongquarter,c.recomname,c.recontcode,c.riskcode,c.costcernter";
        fm.action="./LRJSDetailDownload.jsp?querySql="+tSQL;
        fm.submit();
    }

    把数据提供并访问LRJSDetailDownload.jsp

    对于传过去的form表单中的数据如何获取呢?
    比如说一个table中

            <table class= common border=0 width=100%>
                  <TR  class= common>
                            <TD  class= title>起始日期</TD>
                  <TD  class= input> 
                      <Input name=StartDate class='coolDatePicker' dateFormat='short' verify="起始日期|notnull&Date" elementtype=nacessary> 
                  </TD> 
                  <TD  class= title>终止日期</TD>
                  <TD  class= input> 
                      <Input name=EndDate class='coolDatePicker' dateFormat='short' verify="终止日期|notnull&Date" elementtype=nacessary> 
                  </TD> 
                 
                </TR>
                <TR class= common>
                 <TD  class= title>再保合同号</TD>
                  <TD class= input>
                       <Input class= common name="ReContCode" id="ReContCode" > 
                   </TD>
                   <TD  class= title>险种号</TD>
                  <TD class= input>
                       <Input class= common name="RiskCode" id="RiskCode" > 
                   </TD>
                   </TR>
                    <TR class= common>
                 <TD  class= title>团单号</TD>
                  <TD class= input>
                       <Input class= common name="GrpContNo" id="GrpContNo" > 
                   </TD>
                   <TD  class= title>个单号</TD>
                  <TD class= input>
                       <Input class= common name="ContNo" id="ContNo" > 
                   </TD>
                   </TR>
                   <TR class= common>
                 <TD  class= title>PolNo</TD>
                  <TD class= input>
                       <Input class= common name="PolNo" id="PolNo" > 
                   </TD>
                   <TD  class= title>操作者</TD>
                  <TD class= input>
                       <Input class= common name="Operator" id="Operator"  > 
                   </TD>
                   </TR>
            </table>

    对于其中的input标签 有一个name= ReContCode,value就是你填入输入框中的值

    那么你取数据就这样取

    在你提交表格的jsp中

    <%    String tStartDate=request.getParameter("StartDate"); 
        String tEndDate=request.getParameter("EndDate"); 
        String tReContCode=request.getParameter("ReContCode"); 
        String tRiskCode=request.getParameter("RiskCode"); 
        String tGrpContNo=request.getParameter("GrpContNo"); 
        String tContNo=request.getParameter("ContNo"); 
        String tPolNo=request.getParameter("PolNo"); 
        String tOperator=request.getParameter("Operator"); 
    %>

    本质上就是将数据放入到了request对象中了;注意要有这个<% %>

    那么tomcat是如何解析jsp的呢?


    现在看工程的实现tomcat/webapp/app1/WEB-INF/下面有一个go.jsp文件

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <body>
    ${item}
    </body>
    </html>

    url访问地址

    http://localhost:8080/app1/go

    配置应用内web.xml

    <web-app>
      <servlet>
        <servlet-name>Modern</servlet-name>
        <servlet-class>ModernServlet</servlet-class>
      </servlet>
      <servlet>
        <servlet-name>Primitive</servlet-name>
        <servlet-class>PrimitiveServlet</servlet-class>
      </servlet>
      <servlet>
        <servlet-name>gojsp</servlet-name>
        <jsp-file>/WEB-INF/go.jsp</jsp-file>
      </servlet>
      <servlet-mapping>
        <servlet-name>Modern</servlet-name>
        <url-pattern>/Modern</url-pattern>
      </servlet-mapping>
      <servlet-mapping>
        <servlet-name>Primitive</servlet-name>
        <url-pattern>/Primitive</url-pattern>
      </servlet-mapping>
      <servlet-mapping>
        <servlet-name>gojsp</servlet-name>
        <url-pattern>/go</url-pattern>
      </servlet-mapping>
    </web-app>

    能比较发现对于jsp文件的配置是和servlet不一样的,servlet有一个servlet-class的属性值,

    现在描述一个实现过程

    • 第一步读取web.xml文件,在app1的standardcontext中生成俩重要信息
      • HashMap  servletMappings 这里面是
      • 为每个servlet生成一个standardWrapper,并且放到standarcontext的children变量内

    那么当我们浏览器中开始访问go时候

    connector 调用调用engine的invoke==>调用host.invoke==>调用context.invoke==>调用wrapper.invoke

    调用standardwrappervalue.invoke,

    ==>进入 instance = loadServlet();

    进入

    这里就是关键,如果是jsp的wrpper他是没有dervletClass的所以进入到if括号内Wrapper jspWrapper = (Wrapper) ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);

    public static final String JSP_SERVLET_NAME = "jsp";

    这句话是在context内找一个叫jsp的wrapper,这个wrapper是哪里来的呢?答案是tomcat/conf/web.xml文件目录下定义的

        <servlet>
            <servlet-name>jsp</servlet-name>
            <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
            <init-param>
                <param-name>logVerbosityLevel</param-name>
                <param-value>WARNING</param-value>
            </init-param>
            <init-param>
                <param-name>fork</param-name>
                <param-value>false</param-value>
            </init-param>
            <load-on-startup>3</load-on-startup>
        </servlet>

    那么其实找到的就是

    这个org.apache.jasper.servlet.JspServlet的servlet 现在和go.jsp还没建立联系呢

    接着进入

    入service方法

    那么进入了JspServlet类内部了

    最后

    新建了个JspServletWrapper,

    进入到jsp对应的servlet,

    package org.apache.jsp;
    
    import javax.servlet.*;
    import javax.servlet.http.*;
    import javax.servlet.jsp.*;
    import org.apache.jasper.runtime.*;
    
    public class go_jsp extends HttpJspBase {
    
    
      private static java.util.Vector _jspx_includes;
    
      public java.util.List getIncludes() {
        return _jspx_includes;
      }
    
      public void _jspService(HttpServletRequest request, HttpServletResponse response)
            throws java.io.IOException, ServletException {
    
        JspFactory _jspxFactory = null;
        javax.servlet.jsp.PageContext pageContext = null;
        HttpSession session = null;
        ServletContext application = null;
        ServletConfig config = null;
        JspWriter out = null;
        Object page = this;
        JspWriter _jspx_out = null;
    
    
        try {
          _jspxFactory = JspFactory.getDefaultFactory();
          response.setContentType("text/html;charset=UTF-8");
          pageContext = _jspxFactory.getPageContext(this, request, response,
                      null, true, 8192, true);
          application = pageContext.getServletContext();
          config = pageContext.getServletConfig();
          session = pageContext.getSession();
          out = pageContext.getOut();
          _jspx_out = out;
    
          out.write("
    <html>
    <body>
    ${msg}
    </body>
    </html>
    ");
                                } catch (Throwable t) {
          out = _jspx_out;
          if (out != null && out.getBufferSize() != 0)
            out.clearBuffer();
          if (pageContext != null) pageContext.handlePageException(t);
        } finally {
          if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
        }
      }
    }

    那么整个就分析完成了,其实这里还提到tomcat是如何解析jsp的,和新建go_jsp.class文件的,和新建的路径在哪里

    先说路径

    在tomcat根目录的work文件夹中

    在这里

    编译 this.jspCompiler.isOutDated(),这里创建编译文件路径和确定是否已经编译过了,编译过了不会再次编译

    看这个complier对象

    进入

    就不想看了

    最后

    然后是

    先结束了吧,后面是看不下去了.

    顺便记录下,el表达式本质上就是从request中根据key 取得value

  • 相关阅读:
    【干货】国外程序员整理的 C++ 资源大全–日常工作,我觉得用处确实很大,所以分享
    android实例 listview与sqlite数据绑定
    Android整理:SQlite数据库的使用以及通过listView显示数据
    Android之SimpleAdapter简单实例和SimpleAdapter参数说明
    LinearLayout里面的空间居中对齐
    context.startActivity(Intent intent)方法启动activity
    Context.startActivity出现AndroidRuntimeException
    ListFragment 使用ListView and 自定义Adapter
    匿名类型
    元组Tuple
  • 原文地址:https://www.cnblogs.com/zytcomeon/p/15049149.html
Copyright © 2020-2023  润新知