<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,功能做的再好也无法吸引很多用户使用,而且没有漂亮的界面,那么普通用户会感 ...
随机推荐
- 深度分析Java的ClassLoader机制(源码级别)
写在前面:Java中的所有类,必须被装载到jvm中才能运行,这个装载工作是由jvm中的类装载器完成的,类装载器所做的工作实质是把类文件从硬盘读取到内存中,JVM在加载类的时候,都是通过ClassLoa ...
- 项目用到异步加载头像LasyList
package com.leo.proforjob; import android.content.Context; import android.graphics.drawable.Drawable ...
- 素数筛法--SPOJ Problem 2 Prime Generator
质数(prime number)又称素数,除了1和它本身外,不能整除以其他自然数,换句话说就是该数除了1和它本身以外不再有其他的因数:否则称为合数.最小的质数是2. 要判断一个整数N是不是质数很简单, ...
- html5 touch事件实现触屏页面上下滑动(一)
最近做的做那个app的项目由于用overflow:hidden导致了很多问题,于是决定研究下html5的touch事件.想找个全面点的帖子真是难死了,虽然好多关于html5 touch的文章但大多都是 ...
- java知识积累——单元测试和JUnit(二)
首先来复习一下几个重要知识点,然后接着进行一些介绍.在上一篇文章中,我曾经贴过下面这张图片: 在Which method stubs would you like to create?这里,现在结合4 ...
- [HDOJ4578]Transformation(线段树,多延迟标记)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578 四种操作:查询.加法.乘法.改数.应该是需要维护三个lazy标记,然后就是套路了.查询是区间内所 ...
- MyBatis学习总结4--解决字段名与实体类属性名不相同的冲突
在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定是完全相同的,如果直接在xml映射文件中使用sql进行映射,会造成返回值为空的情况,下面阐述解决方案: 测试所用表和数据 create t ...
- 关于post get ajax
今天写程序时 出现了下面问题: 前台 $.post('ajax/GetDataAjax.ashx', { 'mode': 'DEL', 'BM_ID': bm_id }, function (res ...
- BootStrap弹窗
效果图: 注意引入的文件,js文件要在前面 Bootstrap框架中的模态弹出框,分别运用了“modal”.“modal-dialog”和“modal-content”样式,而弹出窗真正的内容都放置在 ...
- createElement 创建DOM元素
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...