Lab 6 JSP/Servlet 实验目的 1)复习和掌握JSP, Servlet, JavaBean编程,MC模式 2)学习使用表达式语言(EL)进行表达式求解,访问Java对象的性质以及调用 JavaBean或其 他Java对象的方法 3)学习使用JSP标准标签库(JSTL)提供流程控制及局部变量设置 4)通过使用EL和JS仉L简化JSP页面 实验任务 改写LAB6,把原有JSP页面的 Scriptlet替换成EL和JSTL 实验要求 使用MvC模式实现,JSP文件中尽量不能出现Java代码 实验参考材料 EL&JSTL介绍.pdf及授课ppt 实验环境 Servlet/JSP容器: Apache Tomcat5.5或以上 JDK: Sun JDE1.5或以上 浏览器: Internet Explorer6或以上, Firefox1.5或以上 IDE: My Eclipse5.1或以上 实验交付物 war 请将自己编写的以上文件打包上传到ftp上的 WORK UPLOAD/1ab7/你的学号目录下,其中 号目录需要自己建立。 实验提示 可以在新建LAB7项目的时候导入JSTL库,如下图所示:
Lab 6 JSP/Servlet 实验目的 1) 复习和掌握JSP, Servlet, JavaBean编程,MVC模式 2) 学习使用表达式语言(EL)进行表达式求解,访问Java对象的性质以及调用JavaBean或其 他Java对象的方法 3) 学习使用JSP标准标签库(JSTL)提供流程控制及局部变量设置 4)通过使用EL和JSTL简化JSP页面 实验任务 改写LAB6,把原有JSP页面的Scriptlet替换成EL和JSTL 实验要求 使用MVC模式实现,JSP文件中尽量不能出现Java代码 实验参考材料 EL&JSTL介绍.pdf及授课ppt 实验环境 Servlet/JSP 容器:Apache Tomcat 5.5 或以上 JDK:Sun JDK 1.5 或以上 浏览器:Internet Explorer 6 或以上,Firefox 1.5 或以上 IDE:MyEclipse5.1或以上 实验交付物 Lab7.war 请将自己编写的以上文件打包上传到ftp 上的WORK_UPLOAD/lab7/你的学号目录下,其中学 号目录需要自己建立。 实验提示: 可以在新建LAB7项目的时候导入JSTL库,如下图所示:
New J2EE Web project 置 eb Project Detai1s Project Nane Lab? 凶 Use default1 cation rtry元p13h5106 GAlwor brows Web root folder WebRoot Context root URL/Lab J2EE Specification Level ○2EE1 ⊙J2EE1.4【 default EAdd JSTL libraries to WEB-INE/ib folder ○JsTL1.0 ⊙JsTL1.1 Open in New Window 11rem/》cha19mer” 14 fring selectedcat request getParemeter("ce eatore. Product curItem estore. prodi 其卫1et 4> Build Fath “p tem. deEP Alt+shi ftts Refactor Add Web Service Capabilities FS Close Unrelated Projeet Open in Expl a fron Local H: .age Rewove All validation Markers
如果在 LAB6 的基础上修改,可以右键点击项目,按下图所示方式导入 JSTL 库
JSP20技术手册 第六章 Expression language 6-1EL简介 6-1EL简介 EL全名为 Expression language,它原本是JSTL1.0为方便存取数据所自定义的语言。当时EL 只能在JSTL标签中使用,如下 Kc: out value="S( 3 +7"> 程序执行结果为10。但是你却不能直接在JSP网页中使用: Hi S username ) 到了JSP2.0之后,EL已经正式纳入成为标准规范之一。因此,只要是支持 Servlet2.4/JSP 2.0的 Container,就都可以在JSP网页中直接使用EL了 除了JSP2.0建议使用EL之外, JavaServer Faces(JSR-127)也考虑将EL纳入规范,由此 可知,EL如今已经是一项成熟、标准的技术。 注意 假若您所用的 Container只支持 Servlet2.3/J5P1.2,如: Tomcat4,1.29,您就不能在 JSP网页中直接使用EL,必须安装支持 Servlet2.4/JsP2.0的 Container。 6-2EL语法 EL语法很简单,它最大的特点就是使用上很方便。接下来介绍EL主要的语法结构: SIsessionScope user sex 所有EL都是以${为起始、以}为结尾的。上述EL范例的意思是:从 Session的范围中,取得 用户的性别。假若依照之前 JSP Scriptlet的写法如下: User user =(User)session. getAttribute("user") String sex= user get Sex() Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 第六章 Expression Language 6-1 EL 简介 6-1 EL 简介 EL 全名为 Expression Language,它原本是 JSTL 1.0 为方便存取数据所自定义的语言。当时 EL 只能在 JSTL 标签中使用,如下: 程序执行结果为 10。但是你却不能直接在 JSP 网页中使用: Hi ! ${ username } 到了 JSP 2.0 之后,EL 已经正式纳入成为标准规范之一。因此,只要是支持 Servlet 2.4 / JSP 2.0 的 Container,就都可以在 JSP 网页中直接使用 EL 了。 除了 JSP 2.0 建议使用 EL 之外,JavaServer Faces( JSR-127 ) 也考虑将 EL 纳入规范,由此 可知,EL 如今已经是一项成熟、标准的技术。 注意 假若您所用的 Container 只支持 Servlet 2.3/JSP 1.2,如:Tomcat 4.1.29,您就不能在 JSP 网页中直接使用 EL,必须安装支持 Servlet 2.4 / JSP 2.0 的 Container。 6-2 EL 语法 EL 语法很简单,它最大的特点就是使用上很方便。接下来介绍 EL 主要的语法结构: ${sessionScope.user.sex} 所有 EL 都是以 ${ 为起始、以} 为结尾的。上述 EL 范例的意思是:从 Session 的范围中,取得 用户的性别。假若依照之前 JSP Scriptlet 的写法如下: User user = (User)session.getAttribute("user"); String sex = user.getSex( );
JsP20技术手册 两者相比较之下,可以发现EL的语法比传统 JSP Scriptlet更为方便、简洁。 6-2-1.与[]运算符 EL提供.和[]两种运算符来存取数据。下列两者所代表的意思是一样的 S[sessionScope user sex] 等于 SIsessionScope. user["sex"]1 和[]也可以同时混合使用,如下 S(sessionScope shoppingCart [O]. pricel 回传结果为 shopping Cart中第一项物品的价格。 不过,以下两种情况,两者会有差异 (1)当要存取的属性名称中包含一些特殊字符,如.或-等并非字母或数字的符号,就一定 要使用[],例如 s luser. My-Name I 上述是不正确的方式,应当改为: (2)我们来考虑下列情况: S(sessionScope user [data]) 此时,data是一个变量,假若data的值为"sex"时,那上述的例子等于s{ sessionScopeusersex}; 假若data的值为"name"时,它就等于${ session Scope.username}。因此,如果要动态取值时,就可以 用上述的方法来做,但.无法做到动态取值。 接下来,我们更详细地来讨论一些情况,首先假设有一个EL: Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 两者相比较之下,可以发现 EL 的语法比传统 JSP Scriptlet 更为方便、简洁。 6-2-1 .与 [ ] 运算符 EL 提供 . 和 [ ] 两种运算符来存取数据。下列两者所代表的意思是一样的: ${sessionScope.user.sex} 等于 ${sessionScope.user["sex"]} . 和 [ ] 也可以同时混合使用,如下: ${sessionScope.shoppingCart[0].price} 回传结果为 shoppingCart 中第一项物品的价格。 不过,以下两种情况,两者会有差异: (1) 当要存取的属性名称中包含一些特殊字符,如 . 或 – 等并非字母或数字的符号,就一定 要使用 [ ],例如: ${user.My-Name } 上述是不正确的方式,应当改为: ${user["My-Name"] } (2) 我们来考虑下列情况: ${sessionScope.user[data]} 此时,data 是一个变量,假若 data 的值为"sex"时,那上述的例子等于${sessionScope.user.sex}; 假若 data 的值为"name"时,它就等于${sessionScope.user.name}。因此,如果要动态取值时,就可以 用上述的方法来做,但 . 无法做到动态取值。 接下来,我们更详细地来讨论一些情况,首先假设有一个 EL:
JSP20技术手册 xpr-alexpr- (1)当expr-a的值为nu时,它会回传nul (2)当expr-b的值为mull时,它会回传null (3)当expr-a的值为一Map类型时 假若! value-a. containsKey( value-b)为真,则回传null 否则回传 value-a.get( value-b)。 (4)当expr-a的值为List或 array类型时 ●将 value-b的值强制转型为int,假若不能转型为int时,会产生 error。 然后,假若 value-a.get( value-b)或 Array.get( value-a, value-b)产生 Array IndexOutOfBounds Except ion或 IndexOutOfBoundsException时,则回传null ●假若 value-a.get( value-b)或 Array.get( value-a, value-b)产生其他的异常时,则会产生 erro 最后都没有任何异常产生时,回传 value-a.get( value-b)或Aray.get( value-a, value-b)。 (5)当 expra的值为 JavaBean对象时 ●将 value-b的值强制转型为 String ●假若 getter产生异常时,则会产生eror。若没有异常产生时,则回传 getter的结果。 6-2-2EL变量 EL存取变量数据的方法很简单,例如:S{ username}它的意思是取出某一范围中名称为 username 的变量。因为我们并没有指定哪一个范围的 username,所以它的默认值会先从Page范围找,假如 找不到,再依序到 Request、 Session、 Application范围。假如途中找到 username,就直接回传, 不再继续找下去,但是假如全部的范围都没有找到时,就回传nu1l(见表6-1) Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 ${expr-a[expr-b]} (1) 当 expr-a 的值为 null 时,它会回传 null。 (2) 当 expr-b 的值为 null 时,它会回传 null。 (3) 当 expr-a 的值为一 Map 类型时: ● 假若 !value-a.containsKey(value-b)为真,则回传 null。 ● 否则回传 value-a.get(value-b)。 (4) 当 expr-a 的值为 List 或 array 类型时: ● 将 value-b 的值强制转型为 int,假若不能转型为 int 时,会产生 error。 ● 然 后 , 假 若 value-a.get(value-b) 或 Array.get(value-a, value-b) 产 生 ArrayIndexOutOfBoundsException 或 IndexOutOfBoundsException 时,则回传 null。 ● 假若 value-a.get(value-b)或 Array.get(value-a, value-b)产生其他的异常时,则会产生 error。 ● 最后都没有任何异常产生时,回传 value-a.get(value-b)或 Array.get(value-a, value-b)。 (5) 当 expr-a 的值为 JavaBean 对象时: ● 将 value-b 的值强制转型为 String。 ● 假若 getter 产生异常时,则会产生 error。若没有异常产生时,则回传 getter 的结果。 6-2-2 EL 变量 EL 存取变量数据的方法很简单,例如:${username}。它的意思是取出某一范围中名称为 username 的变量。因为我们并没有指定哪一个范围的 username,所以它的默认值会先从 Page 范围找,假如 找不到,再依序到 Request、Session、Application 范围。假如途中找到 username,就直接回传, 不再继续找下去,但是假如全部的范围都没有找到时,就回传 null(见表 6-1):
JSP20技术手册 表6-1 属性范围 在EL中的名称 Page Scop Requestscope Session Session Scope Application ApplicationScope 自动搜索顺序 我们也可以指定要取出哪一个范围的变量(见表6-2) 表6-2 sipage Scope username 取出Page范围的 username变量 s frequestScope username 取出 Request范围的 username变量 Isession Scope. username 陬出 Session范围的 username变量 s{ applicationScope, username}取出 Application范围的 username变量 其中, page Scope、 request Scope、 session Scope和 application Scope都是EL的隐含对象,由 它们的名称可以很容易猜出它们所代表的意思,例如:${ session Scope. username}是取出 Session 范围的 username变量。这种写法是不是比之前JSP的写法: String username =(String) session. getAttribute( username") 容易、简洁许多。有关EL隐含对象在6-3节中有更详细的介绍。 6-2-3自动转变类型 除了提供方便存取变量的语法之外,它另外一个方便的功能就是:自动转变类型,我们来看 下面这个范例 Separa. count 20 假若窗体传来 coun t的值为10时,那么上面的结果为30。之前没接触过JSP的读者可能会认为 上面的例子是理所当然的,但是在JSP1.2之中不能这样做,原因是从窗体所传来的值,它们的类 型一律是 String,所以当你接收之后,必须再将它转为其他类型,如:int、 float等等,然后才能 执行一些数学运算,下面是之前的做法 String str count request getParameter("count") Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 表 6-1 属性范围 在 EL 中的名称 Page PageScope Request RequestScope Session SessionScope Application ApplicationScope 自动搜索顺序 我们也可以指定要取出哪一个范围的变量(见表 6-2): 表 6-2 范 例 说 明 ${pageScope.username} 取出 Page 范围的 username 变量 ${requestScope.username} 取出 Request 范围的 username 变量 ${sessionScope.username} 取出 Session 范围的 username 变量 ${applicationScope.username} 取出 Application 范围的 username 变量 其中,pageScope、requestScope、sessionScope 和 applicationScope 都是 EL 的隐含对象,由 它们的名称可以很容易猜出它们所代表的意思,例如:${sessionScope.username}是取出 Session 范围的 username 变量。这种写法是不是比之前 JSP 的写法: String username = (String) session.getAttribute("username"); 容易、简洁许多。有关 EL 隐含对象在 6-3 节中有更详细的介绍。 6-2-3 自动转变类型 EL 除了提供方便存取变量的语法之外,它另外一个方便的功能就是:自动转变类型,我们来看 下面这个范例: ${param.count + 20} 假若窗体传来 count 的值为 10 时,那么上面的结果为 30。之前没接触过 JSP 的读者可能会认为 上面的例子是理所当然的,但是在 JSP 1.2 之中不能这样做,原因是从窗体所传来的值,它们的类 型一律是 String,所以当你接收之后,必须再将它转为其他类型,如:int、float 等等,然后才能 执行一些数学运算,下面是之前的做法: String str_count = request.getParameter("count");
JSP20技术手册 int count Integer parseInt (str count) count count 20 接下来再详细说明EL类型转换的规则 (1)将A转为 String类型 ●假若A为 String时:回传A ●否则,当A为null时:回传" ●否则,当A. tostring()产生异常时:错误! ●否则,回传A. toString() (2)将A转为 Number类型的N ●假若A为null或"”时:回传0 ●假若A为 Character时:将A转为 new Short(( short)a. charvalue()) ●假若A为 Boolean时:错误! ●假若A为№ umber类型和N一样时:回传A ●假若A为№ umber时 假若N是 BigInteger时 假若A为 BigDecima1时:回传A. toBiglnteger() 否则,回传 BigInteger. valueof(A. longvalue()) 假若N是 BigDecimal时: 假若A为 Biglnteger时:回传A. toBigDecimal() 否则,回传 BigDecimal. valueof(A. doublevalue()) ·假若N为Byte时:回传 new Byte(A. bytevalue()) 假若N为 Short时:回传 new Short(A. shortvalue()) 假若N为 Integer时:回传 new Integer(A. intvalue()) Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 int count = Integer.parseInt(str_count); count = count + 20; 接下来再详细说明 EL 类型转换的规则: (1) 将 A 转为 String 类型 ● 假若 A 为 String 时:回传 A ● 否则,当 A 为 null 时:回传 "" ● 否则,当 A.toString( )产生异常时:错误! ● 否则,回传 A.toString( ) (2) 将 A 转为 Number 类型的 N ● 假若 A 为 null 或 "" 时:回传 0 ● 假若 A 为 Character 时:将 A 转为 new Short((short)a.charValue( )) ● 假若 A 为 Boolean 时:错误! ● 假若 A 为 Number 类型和 N 一样时:回传 A ● 假若 A 为 Number 时: ·假若 N 是 BigInteger 时: ·假若 A 为 BigDecimal 时:回传 A.toBigInteger( ) ·否则,回传 BigInteger.valueOf(A.longValue( )) ·假若 N 是 BigDecimal 时: ·假若 A 为 BigInteger 时:回传 A.toBigDecimal( ) ·否则,回传 BigDecimal.valueOf(A.doubleValue( )) ·假若 N 为 Byte 时:回传 new Byte(A.byteValue( )) ·假若 N 为 Short 时:回传 new Short(A.shortValue( )) ·假若 N 为 Integer 时:回传 new Integer(A.intValue( ))
JsP20技术手册 假若N为Long时:回传 new Long(A. longvalue() 假若N为 Float时:回传 new Float(A. floatvalue()) 假若N为 Double时:回传 new Double(A. doublevalue()) 否则,错误! ●假若A为 String时: 假若N是 BigDecimal时 假若 new BigDecimal(A产生异常时:错误! 否则,回传 new BigDecimal(A 假若N是 BigInteger时 ·假若 new BigInteger(A)产生异常时:错误! ·否则,回传 new BigInteger(A) 假若N. valueof(A)产生异常时:错误! ·否则,回传N. valueof(A) 否则,错误 (3)将A转为 Character类型 ●假若A为null或""时:回传(char)0 ●假若A为 Character时:回传A ●假若A为 Boolean时:错误! ●假若A为 Number时:转换为 Short后,然后回传 Character ●假若A为 String时:回传A. charAt(0) ●否则,错误! (4)将A转为 Boolean类型 Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 ·假若 N 为 Long 时:回传 new Long(A.longValue( )) ·假若 N 为 Float 时:回传 new Float(A.floatValue( )) ·假若 N 为 Double 时:回传 new Double(A.doubleValue( )) ·否则,错误! ● 假若 A 为 String 时: ·假若 N 是 BigDecimal 时: ·假若 new BigDecimal(A)产生异常时:错误! ·否则,回传 new BigDecimal(A) ·假若 N 是 BigInteger 时: ·假若 new BigInteger(A)产生异常时:错误! ·否则,回传 new BigInteger(A) ·假若 N.valueOf(A)产生异常时:错误! ·否则,回传 N.valueOf(A) ● 否则,错误! (3) 将 A 转为 Character 类型 ● 假若 A 为 null 或 "" 时:回传 (char)0 ● 假若 A 为 Character 时:回传 A ● 假若 A 为 Boolean 时:错误! ● 假若 A 为 Number 时:转换为 Short 后,然后回传 Character ● 假若 A 为 String 时:回传 A.charAt(0) ● 否则,错误! (4) 将 A 转为 Boolean 类型
JsP20技术手册 ●假若A为null或""时:回传 false ●否则,假若A为 Boolean时:回传A ●否则,假若A为 String,且 Boolean. valueof(A)没有产生异常时:回传 Boolean. valueof(A) ●否则,错误! 6-2-4EL保留字 EL的保留字如表6-3: 表6-3 gt le false instanceof mpty d Imod 所谓保留字的意思是指变量在命名时,应该避开上述的名字,以免程序编译时发生错误 6-3EL隐含对象 笔者在“第五章:隐含对象( Implicitω bject)”中,曾经介绍过9个JSP隐含对象,而E本 身也有自己的隐含对象。EL隐含对象总共有11个(见表6-4): 表6-4 隐含对象 Page Context javax. servlet. ServletContext表示此JSP的 PageContext java util. Map 取得Page范围的属性名称所对应的值 RequestScope java util. Map 陬取得 Request范围的属性名称所对应 的值 session Scope java util. Map 取得 Session范围的属性名称所对应 的值 lapplication Scopeljava util Map 取得 Application范围的属性名称所 对应的值 如同 Jjavautil.Map ServletRequest.get quest tParameter (string ame)。回传 String类型的值 tring 续表 隐含对象 paramValues java util. Map 如同 Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 ● 假若 A 为 null 或 "" 时:回传 false ● 否则,假若 A 为 Boolean 时:回传 A ● 否则,假若 A 为 String,且 Boolean.valueOf(A)没有产生异常时:回传 Boolean.valueOf(A) ● 否则,错误! 6-2-4 EL 保留字 EL 的保留字如表 6-3: 表 6-3 And eq gt true Or ne le false No lt ge null instanceof empty div mod 所谓保留字的意思是指变量在命名时,应该避开上述的名字,以免程序编译时发生错误。 6-3 EL 隐含对象 笔者在“第五章:隐含对象(Implicit Object)”中,曾经介绍过 9 个 JSP 隐含对象,而 EL 本 身也有自己的隐含对象。EL 隐含对象总共有 11 个(见表 6-4): 表 6-4 隐含对象 类 型 说 明 PageContext javax.servlet.ServletContext 表示此 JSP 的 PageContext PageScope java.util.Map 取得 Page范围的属性名称所对应的值 RequestScope java.util.Map 取得 Request 范围的属性名称所对应 的值 sessionScope java.util.Map 取得 Session 范围的属性名称所对应 的值 applicationScope java.util.Map 取得 Application 范围的属性名称所 对应的值 param java.util.Map 如同 ServletRequest.getParameter(String name)。回传 String 类型的值 续表 隐含对象 类 型 说 明 paramValues java.util.Map 如同
JSP20技术手册 隐含对象 ServletRequest. ge tParameterValues(String name)。回传 String口类型的值 header Java util. Map 如同 ServletRequest. getHeader( String ame)。回传 String类型的值 如同 Servletrequest. getHeaders( String headervalues java util. Map )。回传 String[类型的值 cookie Java. ut 如同 HttpservletrequEst. getCookies() 如同 initParam javautil. Map ServletContext getInitParameter(String name)。回传 String类型的值 这11个隐含对象( Implicit Object),笔者将它分成三类: 1.与范围有关的隐含对象 applicationScope requestScope 2.与输入有关的隐含对象 paran paramvalues 3.其他隐含对象 cookie header headervalues initParam 接下来笔者会依照上面的分类顺序,为读者介绍这些隐含对象。 6-3-1属性( Attribute)与范圉( Scope Java爱好者htp/ w.javafan. net制作
JSP2.0 技术手册 Java 爱好者 http://www.javafan.net 制作 隐含对象 类 型 说 明 ServletRequest.getParameterValues(String name)。回传 String []类型的值 header java.util.Map 如同 ServletRequest.getHeader(String name)。回传 String 类型的值 headerValues java.util.Map 如同 ServletRequest.getHeaders(String name)。回传 String []类型的值 cookie java.util.Map 如同 HttpServletRequest.getCookies( ) initParam java.util.Map 如同 ServletContext.getInitParameter(String name)。回传 String 类型的值 这 11 个隐含对象(Implicit Object),笔者将它分成三类: 1. 与范围有关的隐含对象 applicationScope sessionScope requestScope pageScope 2. 与输入有关的隐含对象 param paramValues 3. 其他隐含对象 cookie header headerValues initParam pageContext 接下来笔者会依照上面的分类顺序,为读者介绍这些隐含对象。 6-3-1 属性(Attribute)与范围(Scope)