天天看点

后台(15)——JSP(1)

<a href="http://blog.csdn.net/lfdfhl/article/details/52415390">探索Android软键盘的疑难杂症</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/53332936">深入探讨Android异步精髓Handler</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/52673536">详解Android主流框架不可或缺的基石</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/53143114">站在源码的肩膀上全解Scroller工作机制</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/52735103">Android多分辨率适配框架(1)— 核心基础</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/52877866">Android多分辨率适配框架(2)— 原理剖析</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/53046113">Android多分辨率适配框架(3)— 使用指南</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51671038">自定义View系列教程00–推翻自己和过往,重学自定义View</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51324275">自定义View系列教程01–常用工具介绍</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51347818">自定义View系列教程02–onMeasure源码详尽分析</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51393131">自定义View系列教程03–onLayout源码详尽分析</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51435968">自定义View系列教程04–Draw源码分析及其实践</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51508727">自定义View系列教程05–示例分析</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51559847">自定义View系列教程06–详解View的Touch事件处理</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51603088">自定义View系列教程07–详解ViewGroup分发Touch事件</a>

<a href="http://blog.csdn.net/lfdfhl/article/details/51656492">自定义View系列教程08–滑动冲突的产生及其处理</a>

Java Server Pages简称JSP,它和Servle一样也是SUN公司定义的一种用于开发动态web资源的技术。JSP的最大的特点在于:写JSP代码就像在写HTML但与HTML只能提供静态数据不同JSP允许开发人员在页面中嵌套java代码从而为用户提供动态数据。所以,可以形象的理解为:JSP = HTML + java

运行后如下图所示:

后台(15)——JSP(1)

哇哈,看到了吧:我们在该index.jsp文件中简单地写了两行java代码,部署应用后浏览器中显示了java代码的运行结果。

看到这我们心里可能就有疑惑了:

浏览器访问JSP页面时Web服务器如何调用并执行一个jsp页面?

Web服务器在执行jsp页面时如何把jsp页面中的html标签发送到客户端?

Web服务器如何执行jsp页面中的java代码?

嗯哼,带着这些疑问,我们继续学习。

其实,jsp之所以可以被web服务器执行并返回给客户端,这是因为jsp从本质上来讲它就是一个Servlet。何出此言呢?我们打开刚才项目在Tomcat的work文件夹,查看其运行后生成的文件,请看下图:

后台(15)——JSP(1)

嗯哼,瞅见了没?依据原来的index.jsp文件生成了对应的index_class.java和index_jsp.class。再打开index_class.java瞅瞅:

index_jsp继承自org.apache.jasper.runtime.HttpJspBase,那我们就继续来看看这个类:

嘿嘿,这个HttpJspBase又继承自HttpServlet。到了这里我们就明白了:jsp文件先会被翻译(转义)成一个HttpServlet子类的java文件再被编译成class文件;至此,jsp文件也就演变成了Servlet。

为了理解jsp的原理,我们来看看HttpJspBase的源码:

源码解析如下:

在HttpServlet的init( )中执行_jspInit( ),请参见代码第9-15行

在HttpServlet的destroy( )中执行_jspDestroy( ),请参见代码第23-26行

在HttpServlet的service( )中执行_jspService( ),请参见代码第32-36行

小结:在HttpJspBase的生命周期方法中会执行jsp相关的生命周期方法

继续看index_jsp.java的代码:

代码解析如下:

index_jsp.java实现了_jspInit( ),请参见代码第16-19行

index_jsp.java实现了_jspDestroy( ),请参见代码第21-22行

index_jsp.java实现了_jspService( ),请参见代码第24-84行

在该方法中提供给了jsp几个非常重要的变量比如:HttpSession、ServletContext、ServletConfig、JspWriter、PageContext等等;它们都叫做JSP的内置对象。看到这我们也发现了:在_jspService( )中JspWriter将原本jsp文件中的标签原封不动地输出到了客户端!这也就是说服务端不会解析和处理原本jsp文件中的标签而是交给了客户端处理。

关于JSP的常用内置对象总结如下:

后台(15)——JSP(1)

请注意:pageContext本身是一个域对象,但是它可操作其它三个域对象即request、session、application,例如它的如下方法:

setAttribute(String name,Object o,int scope); getAttribute(String name,int scope); removeAttribute(String name,int scope);

在这些方法中利用scope指定了操作的范围,其值可取为PageContext.PAGE_SCOPE 、PageContext.REQUEST_SCOPE 、PageContext.SESSION_SCOPE 、PageContext.APPLICATION_SCOPE

pageContext还有一个很强大的方法——findAttribute( ),它会自动依次从page、request、session、application中查找值,找到后就取出值并结束查找。

小结四个域对象:

PageContext、ServletRequest、HttpSession、ServletContext

PageContext : 它所存放的数据在当前页面有效,开发时使用较少

ServletRequest: 它所存放的数据在一次请求(转发)内有效

HttpSession: 它存放的数据在一次会话中有效,使用较多

ServletContext: 它所存放的数据在整个应用范围内都有效,但是因为其有效范围太大不利于数据隔离,应尽量少用

我们知道:从本质上来讲,jsp就是一个Servlet。所以,JSP和Servlet都可以用于开发动态web资源。可是,如果让JSP既用java代码产生动态数据又做页面美化会导致代码难以维护;同理,如果让Servlet既处理逻辑又负责html的显示会导致程序代码可读性非常差。鉴于它们各自的特点,在长期的软件实践中,人们逐渐把Servlet作为web应用中的控制器组件来使用而把JSP作为数据显示模板来使用。

小结:

Servlet负责业务逻辑,即:获取表单数据、处理业务逻辑、分发与重定向

JSP负责数据的显示

请看如下示例:

先写一个login.jsp,表单提交至如下Servlet

在该Servlet中获取表单提交的数据并处理。如果未通过验证则请求转发至login.jsp,如果通过验证则跳转到如下success.jsp

这个例子很简单,但是体现了Servlet与JSP的分工及协作,比如数据的传递和页面的跳转。

继续阅读