您的位置:首页 > Web前端 > JavaScript

[JSP]JSP到Servlet的转换

2015-11-28 14:44 656 查看
1. JSP生命周期:

1) JSP即JavaServer Pages的简称,即Java服务器生成页面,见名知意;

2) JSP和Servlet是一体两面,JSP页面最终会被转换成Servlet的Java类;

3) 在J2EE标准下,JSP的生命周期是这样的:

xxx.jsp的源码文件 --转译--> xxx_jsp.java的Servlet源码 --编译--> xxx_jsp.class的类文件 --进入正式的Servlet生命周期--> ...

4) 只有在第一次请求JSP页面时才会发生转译、编译的过程,所以在第一次请求页面时响应会慢很多;

2. xxx.jsp到xxx_jsp.java的转译结果:

1) 伪代码表示大致为:

public final class xxx_jsp extends HttpJspBase {
// 略...

public void _jspInit() {
// JSP语句转译过来的代码,如果JSP代码中定义过初始化初始化方法的话
}

public void _jspDestroy() {
// JSP语句转译过来的代码,如果JSP代码中定义过资源回收方法的话
}

public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
// 以下每一个数据都对应着JSP的隐式对象,这些变量名都可以直接在JSP代码中使用,相当于一种JSP的环境变量
// 略...
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
// 略...

// 接着是加载这些JSP隐式对象,即“JSP的换件变量”
// 略...
pageContext = 获取pageContext的方法;
session = pageContext.getSession();
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
out = pageContext.getOut();
// 略...

try {
// 略...
// JSP转译过来的语句,其中包换重要的画面输出语句
// 略...
} catch (Throwable t) {
// 略...
} finally {
// 略...
}
}
}

2) 可以看到三个_jsp方法分别对应着HttpServlet的init、destroy和service方法,只不过该jsp类是直接继承自HttpJspBase类;

3) 其次是命名规则上:如果JSP文件命名为XXX,则转译后的jsp类名称就是XXX_jsp;

i. 看以看到类名_jsp后缀和方法名_jsp前缀相同;

ii. 其实_jsp这个名称在J2EE中是有特殊含义的,是指一个动词,即从JSP代码转译而来;

iii. 所以XXX_jsp就是指从XXX.jsp转译而来的"XXX"Servlet类,而_jspInit就是指从JSP代码中的初始化函数转译而来的init方法的意思;

3. HttpJspBase类:

1) 既然JSP转译类是直接继承自HttpJspBase类,既然其中含有类init、destroy和service方法那么该类必然继承自HttpServlet类;

2) 看一下HttpJspBase类源码的大致结构:

public abstract class HttpJspBase extends HttpServlet implements HttpJspPage {
// 略...

public void jspInit() {}
public void _jspInit() {}
public final void init(ServletConfig config) throws ServletException {
super.init(config);
jspInit();
_jspInit();
}

// 略...

public void jspDestroy() {}
public void _jspDestroy() {}
public final void destroy() {
jspDestroy();
_jspDestroy();
}

public abstract void _jspService(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException;
public final void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
_jspService(request, response);
}
}
3) 可以看到这是一个纯虚类,除了init(config: ServletConfig)、destroy、service三个方法是事先定义好的,基本不能改变,其余以jsp和_jsp打头的都是空的,都是留给今后要派生的类来实现的;

4) _jsp和jsp方法:

i. 前面讲过了,_jsp前缀的方法都是经过JSP代码转译而来的,所以在派生类xxx_jsp中这些_jsp方法的内容都是转译而来的,都是“已经存在”的;

ii. jsp方法才是真正的空方法,在派生类中仍然是空的,这些方法是专门用来满足一些特殊需求的,只有在转译后打开xxx_jsp.java源码文件后才能添加,直接在JSP代码中无法实现这些方法;

iii. 可以看到只有init和destroy方法提供了非转译型jsp方法,而service规定必须只能使用转译型_jsp,即服务内容直接用JSP代码实现无需再跑到转译后的Servlet代码中直接用Java语言实现了,这是J2EE的规定,因为JSP就是为了简化service的编写,所以何必要那么麻烦地继续使用Java代码呢?

iv. 从上面的源码中可以看出,都是先调用Java非转译代码再执行JSP代码(转译型代码);

v. 转译型代码(_jsp方法)都是由Web容器来维护的,用户不得修改,只有非转译行代码(jsp方法)用户可以修改;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: