服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

jsp页面翻译原理

    众所周知,每一个jsp页面都会被web容器编译成一个java类,供web容器调用,并且生成html叶面回馈给用户。而了解其中的变异方法和规则,对我们学习jsp是非常有好处的,可以说学习好了这个编译原理,就已经学习好了大部分的jsp知识,剩下的工作就只剩下熟记一些tablib和反复应用以使自己更加熟练而已了。。

先来看一下jsp页面所对应的class的基本结构。每一个jsp页面都会被编译成成如下的格式样子,先给一个大致的印象,详细的说明在后面。


public class my$jsp extends httpjspbase {

static {}

public date$jsp() {}

private static boolean _jspx_inited = false;

public final void _jspx_init()
throws org.apache.jasper.runtime.jspexception {};

public void _jsp pageservice(httpservletrequest request,
httpservletresponse response)
throws java.io.ioexception, servletexception {

jspfactory _jspxfactory = null;
pagecontext pagecontext = null;
httpsession session = null;
servletcontext application = null;
servletconfig config = null;
jspwriter out = null;

object page = this;
string _value = null;
try {
if (_jspx_inited == false) {
synchronized (this) {
if (_jspx_inited == false) {
_jspx_init();
_jspx_inited = true;
}
}
}
_jspxfactory = jspfactory.getdefaultfactory();
response.setcontenttype("text/html;charset=iso-8859-1");
pagecontext = _jspxfactory.getpagecontext(this, request, response,
"", true, 8192, true);


application = pagecontext.getservletcontext();
config = pagecontext.getservletconfig();
session = pagecontext.getsession();
out = pagecontext.getout();

// html // begin [file="/date.jsp";from=(0,0);to=(7,6)]
out.write("/r/n/r/n/r/n" +
"/r/n/r/n/r/n" +
"the date is/r/n");
// end
// begin [file="/date.jsp";from=(7,8);to=(7,57)]
out.println((new java.util.date()).tostring());
// end
// html // begin [file="/date.jsp";from=(7,59);to=(10,7)]
out.write("/r/n /r/n /r/n");
// end

} catch (throwable t) {
if (out != null && out.getbuffersize() != 0) {
out.clearbuffer();
}
if (pagecontext != null) {
pagecontext.handlepageexception(t);
}
} finally {
if (_jspxfactory != null) {
_jspxfactory.releasepagecontext(pagecontext);
}
}
}
}

我们可以清楚地看到,这里面最重要的函数就是pageservice,web容器在编译好一个jsp类以后,
就申请这个类的对象,并且直接调用pageservice来获得response,最后返回给客户。
作为细节,我们可以总结如下:

  1. 所有的jsp页面翻译出来的class,都从httpjspbase继承,并且命名为pagename$jsp
  2. 在第一次调用pageservice函数的时候,该class会进行一次初始化,而这个初始化函数是_jspx_init,如果我们想,我们还可以自定义这个函数,来实现jsp页面的初始化。
  3. <% %>这样的代码被转换成什么了?
    这样的代码被直接转成java代码放到pageservice函数里面。
  4. <%! %>这样的代码被转换成什么了?
    这样的代码被翻译成成员函数和成员变量,也就是说,这些声明在jsp的生命周期内都是存在的。
  5. html代码呢?
    html代码直接被写到printwriter里面回馈给用户。非常的直接
  6. 为什么jsp页面有那么多省写方式,比如说session , out , page , context之类。
    这都是在pageservice里面定义的临时变量,具体的初始化可以参看上面的例子代码,每一次调用jsp页面,这些变量都会被重新初始化一次。当然我们也可以方便的声明自己的变量。
  7. 省写方式<%= object.dosomething()%> 这么理解? 这种省写方式调用dosomething所得到的object的tostring(),然后直接写到out里面。相当于:
    out.print(object.dosomethiing().tostring())
  8. javabean 里面的scope定义了作用域范围,这个范围在这里的意思是?
    这是bean对象句柄保存的地方的意思。我们可以想象一下,一个page范围的bean只是pageservice里面的一个局部变量,当一次处理结束后,这个变量就会被java虚拟机回收。而session变量。而request级别的bean就应该是jsp页面的成员变量。而session和application则不能在jsp页面class里面保存,而应该保存在jsp页面的调用对象里面。
  9. 关于<%@ page %>命令,这个就太简单了,只是一个一个的对应为response.setcontenttype()的语句而已。
  10. 关于jsp页面转向问题。这个语句被翻译为getservletcontext().getrequestdispatcher("/list.jsp").forward(req, res);语句。
  11. <%@ include file="included.jsp" %>遇到这个语句,jsp翻译器就会把这个文件的代码和现在文件的代码混合然后一起编译,生成jsp类。这个方法很好,可以让我们统一文档的样式,比如说吧header写成一个文件,,而把footer也写成一个jsp ,并且在index.html里面把这两个文件包含近来,这样,不管content怎么变,上下样式都不会变,有利于样式的统一。

扫描关注微信公众号