深入刨析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("\n<html>\n<body>\n${msg}\n</body>\n</html>\n"); } 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