深入刨析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
深入刨析tomcat 之---第21篇 tomcat 对jsp页面支持的实现原理的更多相关文章
- 深入刨析tomcat 之---第13篇 tomcat的三种部署方法
writedby 张艳涛 一般我们都知道将web 应用打成war包,放到tomcat的webapp目录下,就是部署了,这是部署方法1 第2种部署方法我们也知道,就是讲web应用的文件夹拷贝到webap ...
- 深入刨析tomcat 之---第3篇 HTTP/1.1 长连接的实现原理
writedby 张艳涛 长连接是HTTP/1.1的特征之一,1.1出现的原因是因为一个客户请求一个网页,这是一个http请求,这个网页中如果有图片,那么也会变为一个http请求,对于java客户端, ...
- 深入刨析tomcat 之---第8篇 how tomcat works 第11章 11.9应用程序,自定义Filter,及注册
writed by 张艳涛, 标签:全网独一份, 自定义一个Filter 起因:在学习深入刨析tomcat的学习中,第11章,说了调用过滤链的原理,但没有给出实例来,自己经过分析,给出来了一个Filt ...
- 深入刨析tomcat 之---第2篇,解决第3章bug 页面不显示内容http://localhost:8080/servlet/ModernServlet?userName=zhangyantao&password=1234
writedby 张艳涛7月2日, 在学习第4张的过程中,发现了前一篇文章写的是关于1,2张的bug不用设置response响应头,需要在servlet的service()方法里面写是错误想 serv ...
- 深入刨析tomcat 之---第14篇 对应19章,使用manager管理 web应用
writedby 张艳涛 第19章讲的是管理程序,当一个tomcat启动的时候,能通过远程浏览器能访问tomcat,启动web应用,关闭web应用,查看web应用 怎么实现的呢? 在webapp 文件 ...
- Orchard 刨析:导航篇
之前承诺过针对Orchard Framework写一个系列.本应该在昨天写下这篇导航篇,不过昨天比较累偷懒的去玩了两盘单机游戏哈哈.下面进入正题. 写在前面 面向读者 之前和本文一再以Orchard ...
- 30s源码刨析系列之函数篇
前言 由浅入深.逐个击破 30SecondsOfCode 中函数系列所有源码片段,带你领略源码之美. 本系列是对名库 30SecondsOfCode 的深入刨析. 本篇是其中的函数篇,可以在极短的时间 ...
- 温故知新-多线程-深入刨析volatile关键词
文章目录 摘要 volatile的作用 volatile如何解决线程可见? CPU Cache CPU Cache & 主内存 缓存一致性协议 volatile如何解决指令重排序? volat ...
- Orchard 刨析:Logging
最近事情比较多,有预研的,有目前正在研发的,都是很需要时间的工作,所以导致这周只写了两篇Orchard系列的文章,这边不能保证后期会很频繁的更新该系列,但我会写完这整个系列,包括后面会把正在研发的东西 ...
随机推荐
- 12:media配置以及后端指定资源暴露
django需要用到的静态文件默认都是放在static目录下 而针对后期用户上传的静态文件也应该统一存储 # media配置:规定用户上传的静态文件存储位置 MEDIA_ROOT = os.path. ...
- 【模拟7.27】题(liu_runda的神题)(卡特兰数,组合数)
考场的SB经验不再分享 case 0: 一道组合计数的水题,具体不再讲可以看以前的相似题 case 1: 很明显的卡特兰计数,我们把长度为n的序列看成01串 关于卡特兰计数的详细的讲解 由此可知我们需 ...
- SqlServer中offset..fetch 的使用问题
好久没更新了,最近忙的很,也生病了,重感冒,555~~~ 早上抽的一丝空闲,来讲讲SqlServer中的分页问题.其实用过了多种数据库,分页这问题已经是老生常谈的问题了.不管是开发什么类型的网站,只要 ...
- 重新整理 .net core 实践篇—————领域事件[二十九]
前文 前面整理了仓储层,工作单元模式,同时简单介绍了一下mediator. 那么就mediator在看下领域事件启到了什么作用吧. 正文 这里先注册一下MediatR服务: // 注册中间者:Medi ...
- 【Python】(六)Python数据类型-列表和元组,九浅一深,用得到
您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本文分十个章节介绍数据类型中的列表(list)和元组(tuple),从使用说到底层实现,包您满意 干货满满,建议收藏,需要用到时常看看. 小伙伴们 ...
- Fiber 树的构建
我们先来看一个简单的 demo: import * as React from 'react'; import * as ReactDOM from 'react-dom'; class App ex ...
- Linux中Crontab的用法
1.crontab的概念: crontab命令用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于"crontab"文件中,以供之后读取和执行.可以使用它在每天的 ...
- Software Architecture软件架构(方法、模式与框架)纵横谈
Software Architecture软件架构是啥 随着软件行业的发展,软件的规模越来越大,"Software Architecture软件架构"这个名词开始频繁出现.&quo ...
- RabbitMQ 常用知识点总结
基础 为什么使用 MQ? 1.削峰:在某个模块接收到超过最大承受的并发量时,可以通过 MQ 排队来使这些削减同一时刻处理的消息量.减小并发量. 2.解耦:在发送 MQ 处理业务时,可以使业务代码与当前 ...
- LeetCode周赛5214
我去,暴力超时,没啥人情味了.难受,一看答案,结果是dp的题目... 思路分析: 1.用个表记录下每个数当前的最大长度,同时是等差,说明有上一个数,那么当前的长度就是上一个数最大加一