现在,我们的时钟显示了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)的更多相关文章

  1. 零元学Expression Blend 4 &ndash; Chapter 43 如何指定Childwindow PopUp位置

    原文:零元学Expression Blend 4 – Chapter 43 如何指定Childwindow PopUp位置 有网友询问我有关Childwindow是否能指定弹出位置? 其实只要透过小小 ...

  2. 用纯JS做俄罗斯方块 - 简要思路介绍(1)

    大家都知道俄罗斯方块是一款大众化的游戏了,我很小的时候就玩过,今年已经25岁了,可以说俄罗斯方块确实是历史悠久,做俄罗斯方块是我上个星期开始的想法.也许是由于自己从来没有写过这种东西吧,所以有生疏.代 ...

  3. Spark中常用工具类Utils的简明介绍

    <深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...

  4. WPF入门教程系列六——布局介绍与Canvas(一)

    从这篇文章开始是对WPF中的界面如何布局做一个较简单的介绍,大家都知道:UI是做好一个软件很重要的因素,如果没有一个漂亮的UI,功能做的再好也无法吸引很多用户使用,而且没有漂亮的界面,那么普通用户会感 ...

  5. EL表达式介绍

    EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${ ...

  6. 第四节 数据格式化和ModelAttribute注解的介绍

    从来都不坦荡,情绪都写在脸上:不开心的时候,不爱说话,笑也勉强. 课堂笔记,如果这么写,不仅仅是手速,还要有语速, 这样不太适合! --胖先生 关于数据传递: 客户端传递数据到服务端: 1.使用普通的 ...

  7. Vue.js介绍

    http://www.cnblogs.com/keepfool/p/5619070.html Vue.js介绍 Vue.js是当下很火的一个JavaScript MVVM库,它是以数据驱动和组件化的思 ...

  8. APP自动化框架LazyAndroid使用手册(3)--核心API介绍

    作者:黄书力 概述 在前一篇博文中,简要介绍了一款安卓UI自动化测试框架LazyAndroid (http://blog.csdn.net/kaka1121/article/details/53204 ...

  9. Wpf 之Canvas介绍

    从这篇文章开始是对WPF中的界面如何布局做一个较简单的介绍,大家都知道:UI是做好一个软件很重要的因素,如果没有一个漂亮的UI,功能做的再好也无法吸引很多用户使用,而且没有漂亮的界面,那么普通用户会感 ...

随机推荐

  1. RESTful WebService入门

    RESTful WebService入门   RESTful WebService是比基于SOAP消息的WebService简单的多的一种轻量级Web服务,RESTful WebService是没有状 ...

  2. UDP丢包和无序 问题的解决方法

    最近在做一个项目,在这之前,做了个验证程序. 发现客户端连续发来1000个1024字节的包,服务器端出现了丢包现象. 纠其原因,是服务端在还未完全处理掉数据,客户端已经数据发送完毕且关闭了. 我用过s ...

  3. asp.net Twilio

    Imports System.Net Imports System.Text Imports Twilio Public Class clsTwilioSMS Public Shared Functi ...

  4. 公交wifi运营平台分析

    一.前言背景 昨晚下午,老板让看一些车载公交wifi后台管理的一些东西,这个随着移动端设备而兴起的wifi战,慢慢的也会越演越烈. 现在于很多人在外面的时候,进入一家店首先看的不是菜单,而是问一句“你 ...

  5. fedora如何设置上网

    设置方法如下:第一步:激活网卡.Fedora Linux系统装好后默认的网卡是eth0,用下面的命令将这块网卡激活.# ifconfig eth0 up.第二步:设置网卡进入系统时启动 .想要每次开机 ...

  6. Java开发工具MyEclipse的设置自动联想功能

    最近初学Java,正在使用MyEclipse来编写新的项目,刚开始打开MyEclipse感觉这个工具既陌生又熟悉,熟悉之处在于编辑器的几大共通之处它都具备,比如说基本的设置.编辑区.调试区都是类似的, ...

  7. source insight快捷键及使用技巧

      source insight快捷键及使用技巧 退出程序                             : Alt+F4 重画屏幕                             ...

  8. Java I/O 扩展

    Java I/O 扩展 标签: Java基础 NIO Java 的NIO(新IO)和传统的IO有着相同的目的: 输入 输出 .但是NIO使用了不同的方式来处理IO,NIO利用内存映射文件(此处文件的含 ...

  9. maven常用构建命令

    mvn -v 查看maven版本 compile   编译项目 install   将项目加入到本地仓库中 clean   删除target test    测试 package     打包

  10. UVa 11489 (博弈) Integer Game

    一个数字能被3整除就等价于这个数的各个数字之和被3整除. 所以一开始的时候先要拿一个能使剩下的数字是3的倍数的数. 然后就一直拿0.3.6.9直到某人不能再拿为止. #include <cstd ...