柔情似水 发表于 2015-1-18 11:29:34

JAVA网站制作之JSP的运转内情

再举这样一个例子:如果你想对一个数字取绝对值,你会怎么做呢?java的做法是intc=Math.abs(-166);而ruby的做法是:c=-166.abs。呵呵,这就看出了java与ruby的区别。js常常有伴侣问起,JSP和Servlet之间有甚么区分,二者之间又有甚么接洽?实在Servlet手艺的呈现工夫很早,是事先为了Java的服务器端使用而开辟的。人人都晓得Applet是使用小程序,Servlet就是服务器端小程序了。但在Microsoft公司的ASP手艺呈现后,利用Servlet举行呼应输入时一行行的输入语句就显得十分愚笨,关于庞大结构大概显现页面更是云云。JSP就是为了满意这类需求在Servlet手艺之上开辟的。可见,JSP和Servlet之间有着内涵的血缘干系,在进修JSP时,假如可以捉住这类接洽,就可以更深入地舆解JSP的运转机理,到达事半功倍的效果。

本文将经由过程对一个JSP运转历程的分析,深切JSP运转的内情,并从全新的视角论述一些JSP中的手艺要点。

HelloWorld.jsp

我们以Tomcat4.1.17服务器为例,来看看最复杂的HelloWorld.jsp是怎样运转的。

代码清单1:HelloWorld.jsp

HelloWorld.jsp
<%
Stringmessage="HelloWorld!";
%>
<%=message%>



  这个文件十分复杂,仅仅界说了一个String的变量,而且输入。把这个文件放到Tomcat的webappsROOT目次下,启动Tomcat,在扫瞄器中会见http://localhost:8080/HelloWorld.jsp,扫瞄器中的输入为“HelloWorld!”

  让我们来看看Tomcat都做了甚么。转到Tomcat的workStandalonelocalhost\_目次下,能够找到以下的HelloWorld_jsp.java,这个文件就是Tomcat剖析HelloWorld.jsp时天生的源文件:

  代码清单2:HelloWorld_jsp.java

packageorg.apache.jsp;

importjavax.servlet.*;
importjavax.servlet.http.*;
importjavax.servlet.jsp.*;
importorg.apache.jasper.runtime.*;

publicclassHelloWorld_jspextendsHttpJspBase{
......
publicvoid_jspService(HttpServletRequestrequest,
HttpServletResponseresponse)throwsjava.io.IOException,ServletException
{
JspFactory_jspxFactory=null;
javax.servlet.jsp.PageContextpageContext=null;
HttpSessionsession=null;
ServletContextapplication=null;
ServletConfigconfig=null;
JspWriterout=null;
Objectpage=this;
JspWriter_jspx_out=null;

try{
_jspxFactory=JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=ISO-8859-1");
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;

Stringmessage="HelloWorld!";
out.print(message);
}catch(Throwablet){
out=_jspx_out;
if(out!=null&&out.getBufferSize()!=0)
out.clearBuffer();
if(pageContext!=null)pageContext.handlePageException(t);
}finally{
if(_jspxFactory!=null)_jspxFactory.releasePageContext(pageContext);
}
}
}



  从下面能够看出,HelloWorld.jsp在运转时起首剖析成一个Java类HelloWorld_jsp.java,该类承继于org.apache.jasper.runtime.HttpJspBase基类,HttpJspBase完成了HttpServlet接口。可见,JSP在运转前起首将编译为一个Servlet,这就是了解JSP手艺的关头。

  我们还晓得JSP页面中内置了几个对象,如pageContext、application、config、page、session、out等,你大概会奇异,为何在JSP中的代码片段中能够间接利用这些内置对象。察看_jspService()办法,实践上这几个内置对象就是在这里界说的。在对JSP文件中的代码片段举行剖析之前,先对这几个内置对象举行初始化。

  起首,挪用JspFactory的getDefaultFactory()办法猎取容器完成(本文中指Tomcat4.1.17)的一个JspFactory对象的援用。JspFactory是javax.servlet.jsp包中界说的一个笼统类,个中界说了两个静态办法set/getDefaultFactory()。set办法由JSP容器(Tomcat)实例化该页面Servlet(即HelloWorld_jsp类)的时分置进,以是能够间接挪用JspFactory.getDefaultFactory()办法失掉这个JSP工场的完成类。Tomcat是挪用org.apache.jasper.runtime.JspFactoryImpl类。

  然后,挪用这个JspFactoryImpl的getPageContext()办法,添补一个PageContext前往,并赋给内置变量pageConext。别的内置对象都经过该pageContext失掉。详细历程见下面的代码,这里不再赘述。该页面Servlet的情况设置终了,入手下手对页面举行剖析。HelloWorld.jsp页面仅仅界说了一个String变量,然后间接输入。剖析后的代码以下:

  代码清单3:JSP页面剖析后的代码片段

Stringmessage="HelloWorld!";
out.print(message);



  定制标签的剖析历程

  在一其中年夜型的Web使用中,一般利用JSP定制标签来封装页面显现逻辑。分析容器对定制标签的剖析历程,对我们深切了解定制标签的运转机理十分有匡助。上面我们以Struts1.1b中附带的struts-example使用的主页运转为例加以申明。

  包括定制标签的index.jsp

  Struts1.1b的下载地点是http://jakarta.apache.org/struts/index.html。将下载的包解压,在webapps目次下能够找到struts-example.war。将该War包拷贝到Tomcat的webapps目次下,Tomcat会主动安装此使用包。在扫瞄器中经由过程http://localhost:8080/struts-example会见struts-example使用,将显现使用的首页(见)。



  图一使用的首页

  代码清单4:index.jsp

<%@pagecontentType="text/html;charset=UTF-8"language="java"%>
<%@tagliburi="/WEB-INF/struts-bean.tld"prefix="bean"%>
<%@tagliburi="/WEB-INF/struts-html.tld"prefix="html"%>
<%@tagliburi="/WEB-INF/struts-logic.tld"prefix="logic"%>
<html:htmllocale="true">
<head>
<title><bean:messagekey="index.title"/></title>
<html:base/>
</head>
<bodybgcolor="white">
……
</body>
</html:html>



  我们仅以index.jsp中的<bean:message/>标签的剖析为例举行剖析,看容器是如何把这个自界说标签剖析成HTML输入的。下面代码省略了页面的别的显现部分。起首,检察下面扫瞄器中页面的源文件:

<htmllang="zh">
<head>
<title>MailReaderDemonstrationApplication(Struts1.0)</title>
</head>
<bodybgcolor="white">
……
</body>
</html>



  可见,容器已把<bean:messagekey="index.title"/>交换成一个字串,显现为页面的题目。

  剖析历程

  那末,JSP容器是如何完成剖析的呢?检察在事情目次jakarta-tomcat-4.1.17workStandalonelocalhoststruts-example下剖析后的index_jsp.java文件:

  代码清单5:index_jsp.java

packageorg.apache.jsp;

importjavax.servlet.*;
importjavax.servlet.http.*;
importjavax.servlet.jsp.*;
importorg.apache.jasper.runtime.*;
publicclassindex_jspextendsHttpJspBase{
//为一切的定制标签订义处置器池类的援用
privateorg.apache.jasper.runtime.TagHandlerPool;
_jspx_tagPool_bean_message_key;
……
//页面类机关办法
publicindex_jsp(){
_jspx_tagPool_bean_message_key=
neworg.apache.jasper.runtime.TagHandlerPool();
……
}

publicvoid_jspService(HttpServletRequestrequest,
  HttpServletResponseresponse)
  throwsjava.io.IOException,ServletException{
……
_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;
……
if(_jspx_meth_html_html_0(pageContext))
return;
……
}
//页面在处置加入时开释一切定制标签的属性
publicvoid_jspDestroy(){
_jspx_tagPool_bean_message_key.release();
……
}
}



  天生的index_jsp.java承继于org.apache.jasper.runtime.HttpJspBase。研讨这个文件为我们懂得定制标签的运转机理供应了路子。

  从下面能够看出,Tomcat在剖析一个JSP页面时,起首为每个定制标签订义并实例化了一个TagHandlerPool对象。页面的处置办法掩盖父类的_jspService()办法,_jspService办法起首初始化情况,为内置对象赋值。因为index.jsp页面全体由一个<html:html/>标签包裹,Tomcat对每个标签都发生一个公有办法加以完成。<html:html/>标签的处置办法是_jspx_meth_html_html_0()。这个办法的定名标准人人也能够从这里看出,就是“_jspx_meth+标签的前缀+标署名+该标签在JSP页面同类标签中呈现的序号”。别的标签都被包括在该标签中,以是别的标签在_jspx_meth_html_html_0()办法中举行剖析。详细的代码完成请拜见赛迪网http://linux.ccidnet.com期刊扫瞄2003年第6期。

  在_jspx_meth_html_html_0()办法中,起首从_jspx_tagPool_html_html_locale池中失掉一个org.apache.struts.taglib.html.HtmlTag的实例,然后设置这个tag实例的页面高低文及下级标签,因为html:html标签是页面的最顶层标签,以是它的parent是null。然后对该标签的内容举行剖析。HTML代码间接输入,上面次要看看<html:html></html:html>标签之间包括的<bean:messagekey="index.title"/>标签的剖析。对bean:message标签的剖析相似于html:html,Tomcat也将其放进一个独自的办法_jspx_meth_bean_message_0()中举行。

  bean:message标签的剖析

  代码清单7:_jspx_meth_bean_message_0()办法片段

//对message定制标签的处置办法
privateboolean_jspx_meth_bean_message_0(
javax.servlet.jsp.tagext.Tag_jspx_th_html_html_0,
javax.servlet.jsp.PageContextpageContext)throwsThrowable{
JspWriterout=pageContext.getOut();
/*----bean:message----*/
org.apache.struts.taglib.bean.MessageTag
_jspx_th_bean_message_0=
(org.apache.struts.taglib.bean.MessageTag)
_jspx_tagPool_bean_message_key.get(
org.apache.struts.taglib.bean.MessageTag.class);
_jspx_th_bean_message_0.setPageContext(pageContext);
_jspx_th_bean_message_0.setParent(_jspx_th_html_html_0);
_jspx_th_bean_message_0.setKey("index.title");
int_jspx_eval_bean_message_0=_jspx_th_bean_message_0.doStartTag();
if(_jspx_th_bean_message_0.doEndTag()==javax.servlet.jsp.tagext.Tag.SKIP_PAGE)
returntrue;
_jspx_tagPool_bean_message_key.reuse(_jspx_th_bean_message_0);
returnfalse;
}



  一样,对html:bean也必要从池中失掉一个标签类的实例,然后设置情况。这里不再赘述。我们只专注对MessageTag定制标签类特别的处置部分。定制标签类的开辟不在本文会商局限以内。在index.jsp中界说了一个bean:message标签,并设置了一个属性:<bean:messagekey="index.title"/>。Tomcat在剖析时,挪用MessageTag对象的key属性设置办法setKey(),将该属性置进。然后挪用MessageTag的doStartTag()和doEndTag()办法,完成剖析。假如doEndTag()办法的前往值为javax.servlet.jsp.tagext.Tag.SKIP_PAGE,标明已完成剖析,前往true,Tomcat将当即中断残剩页面代码的实行,并前往。不然把该MessageTag的实例放回池中。

  标签类对象实例的池化

  为了进步运转效力,Tomcat对一切的定制标签类举行了池化,池化事情由org.apache.jasper.runtime.TagHandlerPool类完成。TagHandlerPool类次要有两个办法,代码以下:

  代码清单8:TagHandlerPool.java

publicclassTagHandlerPool{
privatestaticfinalintMAX_POOL_SIZE=5;
privateTag[]handlers;
publicsynchronizedTagget(ClasshandlerClass)throwsJspException{……}
publicsynchronizedvoidreuse(Taghandler){……}
}



  TagHandlerPool复杂地完成了对标签类的池化,个中MAX_POOL_SIZE是池的初始巨细,handlers是一个Tag的数组,存储标签类的实例。get(ClasshandlerClass)失掉一个指定标签类的实例,假如池中没有可用实例,则新实例化一个。reuse(Taghandler)把handler对象放回池中。

  至此,我们对JSP在容器中的运转历程已了然于胸了。固然每种JSP容器的剖析了局会有差别,但个中的道理都相同。关于编写JSP使用,我们其实不必要干与容器中的运转历程,但假如你对全部底层的运转机制对照熟习,就可以对JSP/Servlet手艺有更深的熟悉。


从一个编程语言的普及程度来将,一个好的IDE是至关中要的,而现在的java的IDE虽然已经很好了,但是和.net比起来还是稍微差一些的,这是个客观事实。java要想普及的更好。DE是必须加以改进的。

莫相离 发表于 2015-1-18 17:16:04

一般学编程语言都是从C语开始学的,我也不例外,但还是可能不学过程语言而直接学面向对象语言的,你是刚接触语言,还是从C开始学比较好,基础会很深点,如果你直接学习JAVA也能上手,一般大家在学语言的时候都记一些语言的关键词,常有的包和接口等。再去做逻辑代码的编写,以后的学习过程都是从逻辑代码编写中提升的,所以这方面都是经验积累的。你要开始学习就从

只想知道 发表于 2015-1-20 12:32:21

不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。

简单生活 发表于 2015-1-26 08:59:51

Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台

金色的骷髅 发表于 2015-2-4 13:26:52

所以现在应用最广泛又最好学的就是J2EE了。 J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。

不帅 发表于 2015-2-5 20:26:28

Java 编程语言的风格十分接近C、C++语言。

小妖女 发表于 2015-2-5 21:27:54

是一种为 Internet发展的计算机语言

若天明 发表于 2015-2-6 20:43:12

Java是一种计算机编程语言,拥有跨平台、面向对java

分手快乐 发表于 2015-2-8 11:36:30

所以现在应用最广泛又最好学的就是J2EE了。 J2EE又包括许多组件,如Jsp,Servlet,JavaBean,EJB,JDBC,JavaMail等。要学习起来可不是一两天的事。那么又该如何学习J2EE呢?当然Java语法得先看一看的,I/O包,Util包,Lang包你都熟悉了吗?然后再从JSP学起。

再见西城 发表于 2015-2-25 10:10:54

不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。

山那边是海 发表于 2015-3-2 19:38:07

你快去找一份Java的编程工作来做吧(如果是在校学生可以去做兼职啊),在实践中提高自己,那才是最快的。不过你得祈祷在公司里碰到一个高手,而且他 还愿意不厌其烦地教你,这样好象有点难哦!还有一个办法就是读开放源码的程序了。我们知道开放源码大都出自高手,他们设计合理,考虑周到,再加上有广大的程序员参与,代码的价值自然是字字珠叽,铿锵有力(对不起,偶最近《金装四大才子》看多了)。

变相怪杰 发表于 2015-3-4 02:40:32

科学超级计算机、移动电话和互联网,同时拥有全球最大的开发者专业社群。

柔情似水 发表于 2015-3-6 18:30:46

是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言

小魔女 发表于 2015-3-8 21:32:23

是一种使网页(Web Page)由静态(Static)转变为动态(Dynamic)的语言

蒙在股里 发表于 2015-3-16 14:21:11

是一种将安全性(Security)列为第一优先考虑的语言

第二个灵魂 发表于 2015-3-22 23:13:49

是一种由美国SUN计算机公司(Sun Microsystems, Inc.)所研究而成的语言
页: [1]
查看完整版本: JAVA网站制作之JSP的运转内情