JSP的小心得
问题:Web容器(例如Tomcat)是怎么来执行jsp文件的?
首先它会将放在webapps目录下的jsp文件(这里以hello.jsp为例)翻译成hello_jsp.java文件并编译为hello_jsp.class(注意:生成的文件名都是小写字母),存放在Tomcat安装目录\work\Catalina\localhost\webDemo\org\apache\jsp路径下,打开.java源文件,你会看到hello_jsp类继承了httpJspBase类。而HttpJspBase类又是HttpServlet的子类,所以hello_jsp类也就间接实现了Servlet接口,也就是说Web容器把jsp文件转换成了一个servlet类了
然后Web容器根据配置文件(web.xml)和客户端(浏览器)的请求URL来确定使用哪一个servlet类.接下来调用这个servlet类的service()方法。在hello_jsp.java中看不到这个service()方法,并不代表它没有这个方法,只代表它没有重写这个方法。(除了重写之外,从父类继承的方法在其子类中,都是隐藏的,所以你看不到。)那么如果想看看在这个类中从其父类继承得到的方法长什么样?很简单!找到有这个方法的父类,查看方法的源码即可。那么如果需要调用这个类的service()方法怎么办?放心,No problem呀,它会去寻找所有父类里有这个方法的父类,然后再执行这个父类的方法体(在这里我们把这个机制或者行为笑称为“儿子继承的东西没找到,咱不怕,去找老子”),在这里说明一下:在子类中调用继承的方法,这个方法就是子类的方法,即SubClass.method(),只不过执行的方法体内容和其父类中的方法体内容一模一样而已。那么接着咱们就来说说这个父类HttpJspBase,在它的源码中,你会看到两个方法,第一个方法_japService(),被其子类hello_jsp类重写了。另外一个方法,源码如下
public void service(HttpServletRequest quest,HttpServletResponse response) throws ServletException,IOException{
_jspService(request,response);
}
这个父类中的servce()方法,子类hello_jsp继承得到的service方法也就是它。看到没有,多么简单的一个方法呀!上面提过了Web容器在确定使用哪一个sevlet类后,接着要干嘛?当然就是调用这个servlet的service()方法了,开始执行它的方法体,方法体中也没啥复杂的事情,就是调用本类中的_japService()方法,也就是hello_jsp类中的重写父类的_jspService()。
咱们接着看这个重写的_jspService()的方法体,里面有若干个out.write();这个方法的实参不就是jsp文件的HTML内容吗?哦,所以才有我们在浏览器上看到的输出内容。
所以在父类里定义的service()方法的作用我觉得很大:它把我们原始的继承Serlet接口并重写其service()方法的习惯转变为了继承HttpJspBase类并重写其_jspService()方法。这是一种技术上的改进和分支吧,也就造就了JSP技术的发展吧。与之类似的是HttpServlet类,它也间接实现了Servlet接口,重写了service()方法,特别是它继承了元老级的GenericServlet(这个类可是直接实现Servlet接口的第一代类呀,可谓是亲生的嫡长子呀!它提供了很多方法,可以说是一个重大改革,也为HttpServlet铺好了路,关于它以后有空再讲)。那么我们来看看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);
}
HttpServletRequest和HttpServletResponse分别是ServletRequest和ServletResponse的子类,这样经过强转型,再最后调用自己的service方法,成功完成了接口方法到基类方法的转移了呀!还没有完,接下来才是HttpServlet的高明之处:看看他自己定义的那个service()的源码吧
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
} } else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp); } else if (method.equals(METHOD_POST)) {
doPost(req, resp); } else if (method.equals(METHOD_PUT)) {
doPut(req, resp); } else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp); } else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
// String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
比较长,言而言之,就是这些个逻辑实现,将Web容器最先调用servlet类的service()方法转移到了调用servlet类的doGet(),doPOST()等方法上,因为看不到这些底层的实现代码,所以就让我们产生了HttpServlet的入口是doGet()方法的假象。当然这也带来了简化流程的好处:继承了HttpServlet类的子类只要重写doGet (),doPOST()等方法即可。
总结:jsp实质上还是servlet,是一种加强版的servlet技术吧
JSP的小心得的更多相关文章
- ASP.NET MVC Autofac依赖注入的一点小心得(包含特性注入)
前言 IOC的重要性 大家都清楚..便利也都知道..新的ASP.NET Core也大量使用了这种手法.. 一直憋着没写ASP.NET Core的文章..还是怕误导大家.. 今天这篇也不是讲Core的 ...
- 下列哪个为JSP的小脚本的标签?(选择1项)
下列哪个为JSP的小脚本的标签?(选择1项) A.<% %> B.<@ %> C.<%! %> D.<%– %> 解答:A
- Qt使用com组件的一点小心得(使用Qt自带的工具dumpcpp生成.h和.cpp文件)
这几天工作中要用到Qt调用com组件,主要用到的类型有dll和ocx,使用他们的方法很简单:1.将com组件注册到系统中.2.使用Qt自带的工具dumpcpp将com组件生成cpp和头文件.3.然后就 ...
- 拼接Sql语句小心得
在往数据库插入数据时,需要根据数据和数据库中的列信息进行拼接,在本篇文章中,输出小心得.使用语言为 python. 拼接原始列信息 比如待插入数据库列信息为 deptNo,dName, Locate, ...
- BUI Webapp用于项目中的一点小心得
接触BUI也有一段时间,也用在了移动端的项目开发中,总的来说,该框架用起来也挺灵活的,控件可以自由定制,前提是自己能认真地学习该框架的api,因为api里面说的东西比较详细,如果没有仔细看的,可能有些 ...
- 用java编网页的学习流程,我的一些小心得(初学java到高深运用)
(1)java基础:首先得会写int,String,for循环,数组,**等等(熟练各种基础的关键字,各种java自带的排序,随即等等算法)什么是封装,继承,多态,然后private,public,p ...
- RIME-使用小心得
从4月份我才接触到RIME输入法,当时的感觉上相见恨晚的,现在感觉也不错,时至今日,想写点东西,也算是小感触吧. RIME称为中州韵输入法引擎,是开放源代码的输入法软件,其主页是http://rime ...
- 简单而又复杂的jsp(小知识)
JSP中的page标签中的pageEncoding属性和contentType属性 pageEncoding的默认值为ISO-8859-1 contentType的默认属性为:text/html; c ...
- Unity仪表盘显示UGUI制作小心得
最近在做设备仪表参数参数显示,由于模型摆放位置经常修改,加之要求不能在模型的下面添加东西,显示界面的位置也不得不跟着修改,一来二去就烦了,想了解决办法,现在总结如下: 1.仍然在模型下面新建Panel ...
随机推荐
- java连接sql server数据库
1.新建项目,导入包 sqljdbc4.jar或sqljdbc.jar(jdk1.7版本) 2.新建类文件ConnectionDB.java package hello; import java.s ...
- [转]谷歌Chrome浏览器开发者工具教程—JS调试篇
来源:http://blog.csdn.net/cyyax/article/details/51242720 上一篇我们学习了谷歌Chrome浏览器开发者工具的基础功能,下面介绍的是Chrome开发工 ...
- final关键字介绍
许多程序设计语言都有自己的办法告诉编译器某个数据是“常数”.常数主要应用于下述两个方面: (1) 编译期常数,它永远不会改变 (2) 在运行期初始化的一个值,我们不希望它发生变化 对于编译期的常数,编 ...
- MD5简单实例
如图当点击按钮时,会先判断是否第一次登陆,如果是第一次登陆登陆则会弹出设置密码的弹窗,若果登陆过则弹出登陆弹窗 其中输入的密码会用MD5加密下 package com.org.demo.wangfen ...
- 【IOS】Mac和IOS开发资源汇总
本文主要汇集一些苹果开发的资源,会经常更新,建议大家把这篇文章单独收藏(在浏览器中按**command+D**). 今天收录了许多中文网站和博客.大家一定要去感受一下哦. 如果大家有知道不错的站点,可 ...
- JavaScript 面向对象编程(四)的常用方法、属性总结
面向对象的属性.方法.操作符总结,都是干货.想深入掌握面向对象的程序设计模式,必须掌握一下知识点.下列知识点注重于实现,原理还请借鉴<javascript高级程序设计> (基于javasc ...
- jsp页面传输到xxAction.java乱码解决
jsp页面传输到xxAction.java乱码解决:jsp:encodeURI(encodeURI("xx"))java:if(!StringUtils.isBlank(belon ...
- Docker入门系列之二:使用dockerfile制作包含指定web应用的镜像
实现题目描述的这个需求有很多种办法,作为入门,让我们从最简单的办法开始. 首先使用命令docker ps确保当前没有正在运行的Docker实例. 运行命令docker run -it nginx: 然 ...
- PHP Swoole 基于纯真IP库根据IP匹配城市
把纯真IP库读到内存,纯真IP库本来就是有序的,然后每次请求二分查找就行,44WIP查找十几次就搞定了 dispatch_mode最好写3,不然做服务的时候,会导致进程任务分配不均匀. max_req ...
- LeetCodeOJ刷题之14【Longest Common Prefix】
Longest Common Prefix Write a function to find the longest common prefix string amongst an array of ...