<Chapter 2>2-2-2-1.介绍JSPs,JSTL,和EL(Introducing JSPs, JSTL, and EL)
现在,我们的时钟显示了UTC时区的时间。我们希望我们的应用可以让用户自定义时区,并且为将来的访问记住用户的偏好。为了做到这一点,我们使用Google帐户来识别哪个用户正在使用这个应用。
在我们深入了解之前(Before we go any further),我们应当介绍一种保持HTML和我们的servlet代码相分离的方法。这允许我们分别维护应用的外观和业务逻辑(business logic),业务逻辑代码实现了我们应用的主要目标,使得我们的逻辑易于测试,应用的外观易于改变。典型的是,你将会使用模板系统以文件形式来定义应用的外观,文件包括THML,CSS,JavaScrpt以及用于放动态数据的保留空白。在Java中很多好的模板系统可供选择,比如Apache Velocity。
对于这个例子,我们使用Java Servlet Pages,或JSPs。JSPs是J2EE的标准部分,它意味着你不需要安装任何其他的东西就可以使用它们。一个JSP包含文本(HTML)、定义这页逻辑的Java代码的混合。JSP编译为一个servlet(The JSP compiles to a servlet),就像我们已经定义的ClockServlet,它等同于写HTML部分和评价Java部分(that's equivalent to writing out the HTML portions,and evaluating the Java portions)。在某种意义上,JSPs仅仅是写servlet代码的另一种方式。
JSPs经常被批评为太强大了。因为从一个JSP中可以获得整个Java语言,所以存在这样的风险:业务逻辑可能会写到模板中,而你不再进行有效的分离。为了缓和这点,JSP规范的后续版本包含了新的方法来描述模板逻辑,这就有意地使得没有整个Java代码强大:Java Servlet Templating Language(JSTL)和JSP Expression Language(EL)。我们为这个例子,以及在本书的其他需要模板化输出的地方,使用这些特性。
编辑ClockServlet.java成类似例2-12。
例2-12.显示Google帐户和链接的ClockServlet.java代码
package clock; import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.SimpleTimeZone;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.*; import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory; @SuppressWarnings("serial")
public class ClockServlet extends HttpServlet{
public void doGet(HttpServletRequest req,HttpServletResponse resp)
throws IOException,ServletException{
SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
fmt.setTimeZone(new SimpleTimeZone(0,"")); UserService userService = UserServiceFactory.getUserService();
User user = userService.getCurrentUser();
String loginUrl = userService.createLoginURL("/");
String logoutUrl = userService.createLogoutURL("/"); req.setAttribute("user",user);
req.setAttribute("loginUrl",loginUrl);
req.setAttribute("logoutUrl",logoutUrl);
req.setAttribute("currentTime",fmt.format(new Date())); resp.setContentType("text/html"); RequestDispatcher jsp = req.getRequestDispatcher("/WEB-INF/home.jsp");
jsp.forward(req,resp);
}
}
接下来,在你的项目的war/WEB-INF/目录创建一个新的文件叫做home.jsp,并添加类似例2-13的内容。
例2-13.显示Google帐户和链接的ClockServlet.java代码
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>The Time Is ...</title>
</head>
<body>
<c:choose>
<c:when test="${user != null}">
<p>
Welcome,${user.email}!
You can <a href="${logoutUrl}">sign out</a>.
</p>
</c:when>
<c:otherwise>
<p>
Welcome!
<a href="${loginUrl}">Sign in or register</a> to customize.
</p>
</c:otherwise>
</c:choose>
<p>The time is:${currentTime}</p>
</body>
</html>
使用Eclipse,你可以让开发服务器在你编辑代码时一直运行。当你保存对代码做的变更时,Eclipse会编译类,并且如果它编译成功的话,Eclipse会将新的类注入已经运行的服务器中。在大多数情况下,你可以简单地在浏览器中重载页面,它将会使用新的代码。
如果你不使用Eclipse,通过键入Crl-C来使开发服务器宕机。再次编译你的项目,然后重启这个服务器。
在你的浏览中重载新版本的时钟应用。新的页面类似于在前面的图2-5中的Python例子。
下面是我们将要说明的在本书中的关于JSPs、JSTL、EL的内容。
・记住home.jsp代表一个servlet。在这个情况下,希望某些属性被设置在它的上下文中。ClockServlet通过在HttpServletRequest对象的setAttribute()方法设置属性来调用home.jsp。然后转发这个请求和响应到home.jsp servlet。
・转发是发生在home.jsp servlet的RequestDispatcher中。在这个情况下,我们将home.jsp放在/WEB-INF/目录下,因此servlet容器不会将它映射到URL。如果JSP位于/WEB-INF/的外面,对于那个路径(来自WAR的根目录)的URL会映射到JSP servlet,并且servlet容器会直接调用它(假设没有显式URL模式匹配这个URL)。
・请求实例的getRequestDispatcher()方法拿到JSP的路径并且返回它的RequestDispatcher。确保路径以正斜杠开始。
・为了调用JSP,ClockServlet调用RequestDispatcher的forward()方法,把HttpServletRequest和HttpServletResponse对象作为参数。forward()方法可能抛出ServletException;在这个例子中,我们仅仅在doGet()中增加了throws语句。
・一个JSP包含文本(HTML)和特别格式化的指令。这个例子包含一个指令,<@ taglib ...%>,它会加载JSTL标签库。你可能还看到了<%...%>,它包含成为servlet某部分的Java代码,以及<%=...%>,它包含Java表达式,它的字符串形式被打印到页面。
・<c:choose>...</c:choose>、<c:when>...</c:when>、<c:otherwise>...</c:otherwise>是JSTL标签的例子。这些由来自第一行的taglib导入命令导入的/jsp/jstl/core标签库。c:是和导入命令的库相关的前缀。这儿,当用户登录时,<c:choose>结构提交<c:when>块,否则提交<c:otherwise>块。
・${user != null}是EL表达式的例子。一个EL表达式可以出现在文档的文本中,就是它的值被提交到的文本位置,JSTL标签属性中,就是它的值被标签使用的位置。表达式${logoutUrl}表达ClockServlet设置的logoutUrl属性的String值。${user.email}是访问一个值得JavaBean属性的例子:这个值等价于调用User对象值得getEmail()方法。${user!=null}展示一个EL表达式如何使用简单操作符的,在这个情况下生成一个被<c:when test="...">使用的boolen值。
对于本书,我们将坚持用JSPs,JSTL,和EL的简单特性,并且不提供额外的解释。更多关于这些J2EE特性的解释,参看Brian Basham等的Head First Servlet and JSP(O'Reilly)。
※当使用请求dispatchers时,当URL模式/*映射到你的部署解释器中的一个servlet时要注意。显式的URL映射会复写默认的JSP路径映射,并且当决定这个路径的servlet时,请求dispatcher会honor it。如果你有一个可能匹配JSP路径的/*URL映射,你必须有一个显式的JSP URL映射在部署解释器中复写它:
<servlet>
<servlet-name>home-jsp</servlet-name>
<jsp-file>/WEB-INF/home.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>home-jsp</servlet-name>
<url-pattern>/WEB-INF/home.jsp</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>clock</servlet-name>
<servlet-class>clock.ClockServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>clock</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
注意在/WEB-INF/的一个映射依旧是隐藏的(from clients)。对于/WEB-INF/home.jsp的请求会返回一个404没有找到错误,并且不会调用JSP servlet。
<Chapter 2>2-2-2-1.介绍JSPs,JSTL,和EL(Introducing JSPs, JSTL, and EL)的更多相关文章
- 零元学Expression Blend 4 – Chapter 43 如何指定Childwindow PopUp位置
原文:零元学Expression Blend 4 – Chapter 43 如何指定Childwindow PopUp位置 有网友询问我有关Childwindow是否能指定弹出位置? 其实只要透过小小 ...
- 用纯JS做俄罗斯方块 - 简要思路介绍(1)
大家都知道俄罗斯方块是一款大众化的游戏了,我很小的时候就玩过,今年已经25岁了,可以说俄罗斯方块确实是历史悠久,做俄罗斯方块是我上个星期开始的想法.也许是由于自己从来没有写过这种东西吧,所以有生疏.代 ...
- Spark中常用工具类Utils的简明介绍
<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...
- WPF入门教程系列六——布局介绍与Canvas(一)
从这篇文章开始是对WPF中的界面如何布局做一个较简单的介绍,大家都知道:UI是做好一个软件很重要的因素,如果没有一个漂亮的UI,功能做的再好也无法吸引很多用户使用,而且没有漂亮的界面,那么普通用户会感 ...
- EL表达式介绍
EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${ ...
- 第四节 数据格式化和ModelAttribute注解的介绍
从来都不坦荡,情绪都写在脸上:不开心的时候,不爱说话,笑也勉强. 课堂笔记,如果这么写,不仅仅是手速,还要有语速, 这样不太适合! --胖先生 关于数据传递: 客户端传递数据到服务端: 1.使用普通的 ...
- Vue.js介绍
http://www.cnblogs.com/keepfool/p/5619070.html Vue.js介绍 Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思 ...
- APP自动化框架LazyAndroid使用手册(3)--核心API介绍
作者:黄书力 概述 在前一篇博文中,简要介绍了一款安卓UI自动化测试框架LazyAndroid (http://blog.csdn.net/kaka1121/article/details/53204 ...
- Wpf 之Canvas介绍
从这篇文章开始是对WPF中的界面如何布局做一个较简单的介绍,大家都知道:UI是做好一个软件很重要的因素,如果没有一个漂亮的UI,功能做的再好也无法吸引很多用户使用,而且没有漂亮的界面,那么普通用户会感 ...
随机推荐
- OSSEC 安装执行./install.sh详细信息
下载好ossec安装文件后解压得到如下目录 [root@localhost ~]# cd ossec-hids-/ [root@localhost ossec-hids-]# ll total drw ...
- 通过jcifs.jar 创建远程文件和文件夹
package com.project.remoteUrl;import java.io.File;import java.io.InputStream;import java.io.OutputSt ...
- 转 Difference between WCF and Web API and WCF REST and Web Service
http://www.dotnet-tricks.com/Tutorial/webapi/JI2X050413-Difference-between-WCF-and-Web-API-and-WCF-R ...
- Map集合案例
1.获取字符串中每一个字母出现的次数. 比如"aababcabcdabcde",结果为:a(5)b(4)c(3)d(2)e(1) 分析如下: package mapexercise ...
- eclipse(STS,myeclipse)老是报ThreadPoolExecutor$Worker.run()
资料地址:http://stackoverflow.com/questions/6290470/eclipse-debugger-always-blocks-on-threadpoolexecutor ...
- 写给系统管理员的25个PHP安全实践
PHP是广泛使用的开源服务端脚本语言.通过HTTP或HTTPS协议,Apache Web服务允许用户访问文件或内容.服务端脚本语言的错误配置会导致各种问题.因此,PHP应该小心使用.以下是为系统管理员 ...
- (六)CSS伪元素
CSS伪元素用于向某些选择器设置特殊效果. 伪元素的用法和伪类相似: selector:pseudo-element {property:value;} CSS类也可以与伪元素配合使用: select ...
- LTDFZ
开关稳压器
- Android开发之MD5加密
将字符串进行MD5加密,返回加密后的字符串 public static String encode(String password) { try { StringBuffer sb = new Str ...
- C++ 中字符串标准输入的学习及实验
声明:下面实验中[]里面表示要输入里面的符号,[]符号本身并未输入 1.cin>> cin使用空白(空格.制表符.回车)来确定字符串的结束位置. cin会将换行符留在输入输出队列中. #i ...