1、Java程序设计,JSP技术,1. JSP技术概述,对JSP技术的需求 JSP框架 JSP的优点 对JSP的误解 JSP的生命周期 为什么依旧需要了解servlet,对JSP的需求,使用servlet可以容易地完成下述任务: 读取表单数据 读取HTTP请求报头 设置HTTP状态代码和响应报头 使用cookie以及进行会话跟踪 跨servlet共享数据 跨请求记录数据 但使用servlet也有不尽如人意的地方: Servlet中HTML的编写和维护都比较困难 不能使用标准的HTML工具 非Java人员难以处理servlet中的HTML,JSP框架,思想: 页面的大部分内容使用常规的HTML 用特
2、殊的标签将servlet代码标记出来 JSP看作是含有Java代码的HTML,servlet是含有HTML的Java代码 整个JSP页面最终转换成servlet(仅执行一次),实际被调用的是servlet(每个请求) 示例:,Order ConfirmationOrder Confirmation Thanks for ordering !,尽管JSP技术能够做的事情并不比servlet多,但JSP可以使下述任务更为容易: JSP中HTML的编写和维护更为简单 能使用标准的HTML工具,比如DreamWeaver 可以对开发团队进行划分:Java开发人员和Web开发人员。 JSP鼓励我们: 将
3、创建内容(Java)代码同表示内容的(HTML)代码分离开来。,对JSP的误解,忘记JSP技术是服务器端的技术 浏览器不支持JSP,它们看到是JSP输出的HTML,因此不会将JSP代码发送给浏览器 JSP与JavaScript不同 混淆JSP的转换期和请求期 JSP页面需要转换为servlet,servlet编译后载入到服务器中,初始化并运行。 JSP页面仅在修改后第一次被访问时才转换为servlet并进行编译。 载入到内存中、初始化和执行遵循servlet的一般规则。,JSP的生命周期,为什么依旧需要了解servlet,理解JSP如何工作 JSP调用的servlet代码 知道什么时候使用se
4、rvlet更佳 JSP处理的是表示问题 对于输出二进制数或操作HTTP但不明确输出的应用适宜用servlet 如何混合使用servlet和JSP 实际中往往是将servlet和JSP两项技术结合起来使用,2. 在JSP中调用Java代码,静态和动态文本 简单和复杂应用中JSP的使用 JSP表达式 servlet和JSP页面对类似任务的处理 JSP scriptlet JSP声明 预定义变量,静态和动态文本,JSP文档由静态文本和动态文本组成 静态文本: JSP文档中的HTML部分; 遵循HTML语法规范; Web服务器将这些内容原封不动地传给客户端浏览器。包括HTML的注释“” 动态文本: J
5、SP文档中被“”括起来的内容,JSP脚本元素的类型,表达式 格式: 求expression值并将结果插入到servlet的输出中。即会产生类似于out.print(expression)的语句,注意expression后没有“;” scriptlet 格式: 将Java语句插入到servlet的_jspService方法中(由service调用) 声明 格式: 逐字地插入到servlet类的定义体中,不在任何方法之内,即定义servlet类的成员变量和成员方法。,限制JSP页面内的Java代码,若在JSP文档中需要调用25行Java代码时有两种选择: 将25行Java代码直接放在JSP页面中
6、将这25行代码放在单独的Java类中,在JSP页面中用一行代码调用它 为什么第二种选择更好? 开发:我们可以在Java开发环境(编辑器或IDE)中编写单独的类,而非在HTML环境中。 调试:如果代码中含有语法错误,在编译时就能够直接看到。简单的打印语句可以直接看到结果。 工作划分:项目组可分为Java程序员和HTML美工。 测试:我们可以编写测试过程,每次更改后都通过循环进行上万次的测试。 重用:多个页面都可以使用同一个类。,使用包的重要性,不论任何Java类的class文件(servlet、普通Java类)均部属在以下目录中: WEB-INF/classes/包名/ JSP所调用的Java类
7、必须放到包中 JSP页面转换成的servlet一般会被声明在某一个包中,若Java类放到默认包中(没有package语句),则该servlet与所调用的Java类不处于同一个包中,而该servlet中又没有使用import语句,从而使得该servlet不能访问该Java类。 建议:总是把Java类放到包中。,JSP表达式,格式结果 表达式被求值,转换成字符串,将按照它在JSP页面中出现的位置插入到HTML页面中。 即,表达式的值被放在_jspService中的out.print方法中输出。 示例 当前时间: 您的主机名: XML兼容的语法 Java Expression 在单个页面中不能混合使
8、用不同的版本。如果使用jsp:expression就必须整个页面都使用XML。,JSP/servlet的对应,原始的JSP所产生的具有代表性的servlet代码,A Random Number ,public void _jspService(HttpServletRequest request,HttpServletResponse response) throwsServletException, IOException response.setContentType(“text/html“);HttpSession session = request.getSession(true);J
9、spWriter out = response.getWriter();out.print(“A Random Number“);out.print(Math.random();. ,预定义变量,在JSP页面中可以使用几个已定义的变量(相当于_jspService方法中的局部变量) request HttpServletRequest(service/doGet的第一个参数) response HttpServletResponse(service/doGet的第二个参数) out 用来将输出发送到客户程序的Writer(JspWriter带缓冲的版本) session 与请求关联的HttpS
10、ession(除非用page指令的session属性将之禁止) application ServletContext(用于数据共享),,JSP表达式的应用,功能: 显示当前的系统时间 显示服务器的信息 显示Session ID 显示表单数据“testParam”的值 实现: 创建java.util.Date的对象获得当前系统时间 调用application.getServerInfo()方法获得服务器信息 调用session.getId() 方法获得Session ID 调用request.getParameter(“testParam”)方法获得表单数据 代码:Expressions.jsp
11、,servlet和JSP的比较,功能:( 分别用JSP和Servlet实现) 输出3个指定的表单参数的值 实现: 用servlet实现 用JSP实现 代码: ThreeParams.java ThreeParams.jsp,JSP Scriptlet,格式s结果 代码被逐字地插入到servlet的_jspService方法中 示例XML兼容的语法 Java Code 注意:jsp:scriptlet全部小写,JSP/servlet之间的对应关系,原始的JSP所产生的具有代表性的servlet代码,foo/没有“;”/有“;”,public void _jspService(HttpServle
12、tRequest request,HttpServletResponse response)throws ServletException, IOException response.setContentType(“text/html“);HttpSession session = request.getSession();JspWriter out = response.getWriter();out.print(“foo“);out.print(bar();baz();. ,JSP scriptlet:示例,功能: 根据表单参数“bgColor”设置页面的颜色 实现: 使用scriptle
13、t检查缺失或异常的表单数据 使用JSP表达式设置背景颜色 代码: BGColor.jsp,使用scriptlet将JSP文件的某些部分条件化,要点 scriptlet中的代码会被原封不动地插入到_jspService方法中 scriptlet之前或之后的HTML会转换成print语句 scriptlet包含的java语句不一定要完整,但完整的表达式常常更清楚且易于维护 例如, Have a nice day!Have a lousy day! ,if (Math.random() nice day!“); else out.println(“Have a lousy day!“); ,转换为J
14、ava代码,JSP声明,格式结果 代码被生成到servlet类的定义中,_jspService方法以外(即,定义成员变量和成员方法) 示例设计上的考虑 使用JSP声明成员变量可以用来实现跨请求持续性数据的存储,但对于方法而言,通常在单独的Java类中定义更好一些。 XML兼容的语法 Java Code,JSP声明和servlet之间的对应关系,原始的JSP注意:避免使用JSP声明方法,而是将randomHeading定义为单独Java类的静态方法,Some Heading “ + Math.random() +“); %,生成的servlet代码,public class xxxx exten
15、ds JspPage private String randomHeading() return (“ + Math.random() + “);private int i=0;public void _jspService(HttpServletRequest request,HttpServletResponse response) throwsServletException, IOException response.setContentType(“text/html“);HttpSession session = request.getSession(true);JspWriter
16、out = response.getWriter();out.println(“Some Heading“);out.println(randomHeading();out.println( i );. ,声明的例子,功能: 打印出自服务器启动以来,页面被请求的次数 实现:代码: AccessCounts.jsp,3. JSP的page指令,page指令的用途 指定导入类 指定页面的MIME类型 会话的共享 指定处理JSP错误的页面,page指令的用途,为根据JSP页面生成的servlet的结构 导入哪些类 该servlet扩展哪个类 产生哪种MIME类型 如何处理多线程 servlet是否共
17、享会话 输出缓冲区的大小的行为 由哪个页面来处理意外的错误,import属性,格式目的 在servlet定义的顶部生成导入语句 注意 默认情况下JSP导入:java.lang.*; javax.servet.*; javax.servlet.jsp.*; javax.servlet.http.* Import属性是page指令中唯一一个允许在同一文档中多次出现的属性 page指令可以出现在文档的任何位置;但import属性应放在相应包首次使用之前 JSP使用的类必须放在常规的servlet目录中:即,/WEB-INF/classes/包名/目录中 JSP中使用的Java类必须放到包中,cont
18、entType和pageEncoding属性,格式目的 指定由JSP页面生成的servlet生成的页面的MIME类型及字符集 注意 servlet的默认MIME类型为“text/plain”,JSP的默认类型为“text/html; ISO-8859-1”,因此若只需改变字符集则使用pageEncoding属性更简单 contentType属性值不能在请求期间计算得出,但可以通过% response.setContentType(“MIME-Type”)有条件地设置文档的MIME类型,条件性地生成Excel电子表格,功能 根据用户输入的表单参数条件性地输出Excel表格或普通HTML表格 实现
19、 通过request.getParameter(“format”)获取用户需要的输出类型 通过response.setContentType(“application/vnd.ms-excel”);设置页面的输出类型 代码 ApplesAndOranges.jsp 注意 page指令的contentType属性的值不能在运行期间计算出,因此需要使用response.setContentType在scriptlet动态地设置页面的的contentType属性,session属性,格式目的 指定页面不是会话的一部分 注意 默认地,session是属于会话。 如果网站的流量较大,可以节省服务器端的内
20、存。 要想真正起到作用,除了第一个页面外,同一客户会话中所访问的所有的相关网页都必须关闭会话。,errorPage属性,格式目的 指定一个JSP页面,抛出的任何异常如果未在当前页面内被捕获,则由该页面进行处理。 注意 指定的错误处理页面可以通过“exception”变量来访问所抛出的异常。 errorPage属性仅用于指定特定页面的错误页面web.xml文件允许我们指定适用于整个应用的错误页面,当任何确定的异常或确定的HTTP状态代码产生时,都会使用该页面来处理。( 元素),isErrorPage属性,格式(默认值) 目的 表示当前页面是否可以作为其他JSP页面的错误页面。 注意 名为exce
21、ption的新预定义变量会被创建,并能够在错误页面中对其进行访问。 只能将其作为紧急备份;明确地处理尽可能多的各种异常。 不要忘记一定要检查查询数据中的值是否缺失或异常,错误页面:示例,程序 Login.htmlServletLogin.java, Subscribe.jsp, ShoppingError.jsp ProductList.jsp,指令的XML语法,格式如:的XML等价格式为 注意: 不能在同一页面中混用XML格式和传统格式 XML中大小写敏感,jsp:directive为小写字母,4. 在JSP页面中包含文件,使用jsp:include在请求期间包含页面 使用(include指
22、令)在页面转换期间包含文件 为什么jsp:include一般要好于include指令,在请求期间包含文件: jsp:include,格式目的 为了能够更新被包含的内容,但不改变包含该内容的那些主JSP页面 包含内容 HTML页面的内容 纯文本文件的内容 JSP页面的输出 Servlet的输出 注意 被包含的JSP内容不能影响主页面,只使用被包含JSP页面的输出。 不要忘记结尾的斜杠。 以斜杠开头的相对URL按照相对于Web应用进行解析,而非相对于服务器的根目录。 可以包含WEB-INF目录中的文件。,jsp:include示例:新闻头条页面,功能: 将易变的内容(新闻)放到被包含文件中,通过主
23、页面包含它们,当更新新闻时,不用修改主页面。 实现: 使用jsp:include动作 代码: 主页面:WhatsNew.jsp 被包含页面:Item1.html,Item2.html,Item3.html 注意: 被包含页面中不能包含DOCTYPE,BODY等标签,否则会使包含后的主页面包含两套这样的标签,从而变得不合法。,在页面转换期间包含文件: ,格式目的 将被包含文件的内容逐字地插入到主页面中,然后对产生的单个JSP文件进行编译。 在多个页面重用JSP内容,且需要被包含的JSP页面能够影响主页面。 注意 服务器不一定检测被包含文件的更改,因此,只要被包含文件发生更改,就需要更新主JSP文
24、件的修改时间。,Include指令示例:脚注重用,功能 被包含文件统计包含文件被访问的次数、访问时间以及客户端的主机名 实现 主页面通过将被包含文件ContactSection.jsp包含进来 包含文件中定义存放访问计数的成员变量accessCount 注意:不能用jsp:include包含该文件,否则所有主页面将共用一个该被包含页面生成的servlet,从而得到的访问计数不正确。,jsp:include与的比较,应该使用哪种方式?,尽量使用jsp:include 对被包含页面的更改不需要任何手动的更新 jsp:include和include指令(include)在速度上的区别并不显著 仅当被
25、包含文件中定义了主页面要用的成员变量或方法或者被包含文件设置了主页面的响应报头时才因该使用include指令(),如: 被包含页面snippet.jsp中主页面中.,5. JavaBean组件在JSP文档中的应用,bean的优点 bean的创建 bean类在服务器上的安装 访问bean属性 显式地设置bean的属性 根据请求参数自动设置bean的属性 多个servlet和JSP页面间共享bean,背景知识:java bean是什么?,遵循某些特定约定的Java类 必须具备一个零参数(空)的构造函数 显式地定义这样一个构造函数或者省略所有的构造函数都能满足这项要求 不应该有公开的实例变量(字段)
26、 使用存取方法而非允许对字段直接访问 持续性的值应该能够通过getXxx和setXxx方法来访问 如果类有getTitle方法,返回String,我们就说类有一个名为title的String属性 布尔型的属性使用isXxx,而非getXxx 有关bean的更多内容,参见http:/ 示例:StringBean.java,使用bean:基本任务,创建bean对象,jsp:useBean 在最简单的情况下,该元素构建一个新的bean。用法如下:获取bean对象的属性,jsp:getProperty 这个元素读取并输出bean属性的值。用法如下:设置bean对象的属性,jsp:setProperty
27、 这个元素修改bean的属性(即调用形如setXxx的方法)。常见的用法如下: ,创建bean:jsp:useBean,格式创建一个package.Class的对象,并将该对象的引用赋给_jspServcie方法中的局部变量name 目的 不需用到显式的Java编程就能够创建Java类的实例(XML兼容的语法) 注意 属性class的值必须是类的完全限定名,不论是否已导入该类可以认为等同于 但jsp:useBean拥有下面两项额外的优势: 从请求参数中设置bean对象的值更容易 在页面和servlet间共享bean对象更容易,访问bean的属性:jsp:getProperty,格式目的 不需用
28、到显式的Java编程就可以访问bean的属性(即调用getXxx方法) 注意 在jsp:useBean中bean名由id属性给出,而在jsp:getProperty和jsp:setProperty中bean名由name属性给出。等价于,设置bean属性:jsp:setProperty,格式目的 不需用到显式的Java编程就可以设置bean的属性(即调用setXxx方法) 注意 等价于,jsp:setProperty 和jsp:getProperty示例,功能 通过jsp:setProperty设置StringBean的属性 通过jsp:getProperty获取StringBean属性的值 代
29、码 StringBean.java StringBean.jsp 注意 bean和Java类安装在常规的Java目录中 /WEB-INF/classes/PackageName,设置bean的属性案例1: 显式的转换和赋值,功能 通过显式获取表单数据并将其转换为恰当类型后用jsp:setProperty给bean的对应属性赋值 代码 SaleEntry.java SaleEntry1-Form.htm SaleEntry1.jsp,示例2: 将单个属性与输入参数关联,JSP中使用jsp:setProperty的param属性可实现将bean属性与表单数据的输入参数关联 param属性指定一个输
30、入表单参数 若bean属性类型为基本数据类型及其外包类类型,可以自动将表单数据(String类型)转换为与bean属性类型一致的数据 若请求中没有指定参数,则不采取任何动作(并不传递null到对应属性) 如: 若请求参数的名称与bean属性的名称相同还可以省略param属性 代码: SaleEntry.java SaleEntry2-Form.htm SaleEntry2.jsp,示例3: 将所有属性与输入参数关联,使用“*”作为jsp:setProperty的property属性的值来将所有bean的属性与同名输入参数关联,并且 值来自于名称与属性名相匹配的请求参数 执行简单的自动类型转换
31、对于没有与请求参数与之匹配的bean属性则不采取任何动作,因此表单bean不一定一次填充完毕 自动类型转换不能防止不合法的值 bean属性的名称和请求参数名大小写敏感 代码 SaleEntry.java, SaleEntry3-Form.htm, SaleEntry3.jsp,共享bean,可以使用scope属性来指定bean存储的位置 不论scope的取值如何均绑定到_jspService中的局部变量;但scope的取值不同,该bean的可访问区域也不同可以让多个servlet或JSP页面共享bean 允许根据条件创建bean对象 仅当不存在已有对象的情况下才创建新的对象,scope属性的取
32、值(1),page (或) 默认值。除了绑定到_jspService方法的局部变量中,bean对象还绑定到pageContext对象中。 每个页面和每个请求都有不同的pageContext对象,因此scope=“page”时表示不共享bean request() 除了绑定到_jspService方法的局部变量中,bean对象还绑定到ServletRequest对象中 可以通过getAttribute访问到它,scope属性的取值(2),session() 除了绑定到_jspService方法的局部变量中,bean对象还绑定到与当前请求关联的HttpSession中 和普通的会话对象一样,在常规
33、servlet中可以使用getAttribute访问bean。 application() 除了绑定到_jspService方法的局部变量中, bean对象还绑定到ServletContext中(通过application变量或调用getServletContext()来访问)。 ServletContext由同一Web应用中的所有servlet共享(或服务器上的所有servlet在没有另外定义Web应用的情况下)。,bean的条件化操作,bean的条件化创建 仅当找不到相同id和scope的bean时,jsp:useBean才会引发bean新实例的创建。 如果找到相同id和scope的bea
34、n,则仅仅是将已经存在的bean绑定到由id指定的变量。 bean属性的条件化设置 替换为 语句 这些语句(一般为jsp:setProperty元素)仅当创建新的bean时才执行,如果找到现有的bean,则不执行。,bean的条件化创建示例,功能 创建一个在scope=“application”的bean,将创建该bean对象时,所处的页面保存到该bean的firstPage属性中 记录一系列页面(3个)被访问的次数 实现 通过bean属性的条件化设置,在创建bean对象时将所处的页面保存到该bean的firstPage属性中 将更新accessCount属性(访问计数)的jsp:setProperty语句放在非条件代码中 代码: AccessCountBean.java,SharedCounts1.jsp,SharedCounts2.jsp,SharedCounts3.jsp,