《The Definitive Guide to Grails》 学习笔记三 (对应第5章)

1. JSP: 为了支持页面的动态输出,在传统的静态HTML上混合了Java代码
(scriptlets:<%.......%>),这也是JSP最被牛人们所诟病的特性,因为

这会导致JSP被滥用,把原本属于Controller的操作混入View层,破坏了

MVC的清晰结构,如果任其发展下去,最终整个系统的代码将无法维护。为了解

决这一问题,JSP支持定制的标签(tag)来提供对页面进行逻辑抽象,于是就有

了JSTL和EL。

 

2. GSP:真是既生瑜何生亮,grails在JSP的基础上又搞了一套GSP。既然JSP已经
完善了自己,那为啥grails还要多此一举呢?这不是违背了它经常吹嘘的
DRY(Don't Repeat Yourself)原则吗?我带着这个疑问仔细看了半天,终于明白
了,人家这么做确实是有道理的!(今天大半夜的我咋这么多废话呢)
说来说去,其实根本原因就在于Groovy的运行环境动态特性。要配合grails的优
点,view层就需要把握Groovy的运行时间环境和动态的方法调度,并且实现更简便
灵活的表达式(例如GPath,Groovy bean,GString等),这是JSP做不到或者做的
不优雅的,所以GSP就应运而生了。
GSP其实和JSP非常相似,除了JSP提供的request,response,session等对象,GSP
还提供了flash对象(用于当前和下一个request之间的数据传递,既然在
Controller里支持了,当然在view层也要支持)以及out对象(一个
java.io.Writer实例,对应response的输出)。

 

3. Groovy scriptlets,GStrings,及Tags:从下面几个例子可以看出实现动态输
出的几种方式,
scriptlets和Html混用,破坏了代码的结构:
<% 3.times { %>
<p>Print it 3 times! </p>
<% } %>

GString则比较优雅:
<p> ${album.title} </p>

grails Tags提供了简洁、优雅、易于扩展的标签:
<g:set var="album" value="${album.title}"/>

 

4. 内置的grails Tags:包含了变量赋值(g:set)、逻辑判断
(g:if,g:elseif,g:else)、 Iterative(g:each,g:while)、过滤
(g:collect,g:findAll),这些都无需在directive里Import 就可以直接使用。

 

5. 动态的Tags:动态Tags指的是通过tag libraries类(存放在grails-
app/taglib目录下)提供的标签,标签名对应的是一个标签库里的方法调用,例如:
<a href ="<g:createLink action="list"/> A dynamic link </a> 和
<a href ="${createLink(action: 'list')}"> A dynamic link</a>,一个是常规
的标签,一个是方法调用,执行结果是完全一样的,但方法调用的方式显然更清
晰,避免了因为标签嵌套导致代码的可读性下降。
还有这个输入数据validate结果设置输入框对应的div的CSS class(scaffold的缺
省处理方式,validate不通过,则设置边框为红色)的方式也很简单明了:
<div class = "${hasErrors(bean:album, field:'title', 'errors')}">
........
</div>
这里的hasErrors标签也是作为方法调用的。

 

6. 其他Tags:
g:link:创建一个链接,该链接可以绑定controller,action,params,并根据
URL mappings的设置自动根据环境参数生成URL;
(注:GSP标签另一个重要特性:属性可以表示为[key:value]的map,将多个属性
值进行组合,减少标签的多层嵌套)
g:createLink:和g:link相似,区别在于它只产生text,而不是HTML链接,可以用
于传统的<a href标签或者作为JS变量值;
g:createLinkTo:产生web应用的context path内的一些资源的链接,我理解为
application的一个内部uri,不知道对不对;
g:form:使用POST方法提交表单数据,指定controller和action
g:textField:文本数据,通过name属性定义该数据在params里的参数名
g:checkBox,g:radio,选择项(第一个是只能选true/false,第二个name属性定
义了一个组,在这一组里有多个value对应各个选项)
g:select:从列表中选择,更具体的也有
g:currencySelect,g:localeSelect,g:timeZoneSelect。
(前面三个有标签功能上可能会有重叠,需要实际尝试一下)
g:datePicker:产生一个时间,可以通过其中的一个参数precision来设定时间的
精度,例如year, month, day, minute, hour, second。这种灵活性对于我们的数
据表作用很大,因为很多日期数据并不能完全准确,例如病人的发病时间,可能病
人只能记得大概是去年4月,要精确到日就很难了,这种灵活的结构就非常有用。
g:hasErrors可以和g:eachError配合使用,逐个处理数据提交validation过程中出
现的错误。此外还有 g:renderErrors标签可以用来显示错误信息。

 

7. 创建定制的标签:通过扩展自定义的标签,能够更好地确保view和controller
分离。在JSP中自定义标签需要考虑多种属性、body以及嵌套的各层标签之间的层
次关系,API会变得极其复杂,而且标签要在TLD(tag library descriptor)中登
记相关的信息,导致标签的重载需要重启服务器。但是在Groovy中,由于GString
和closure的动态特征,这一切都变得简单了,只需要在grails-app/taglib增加一
个TagLib类,在其中通过closure里的attrs和body定义标签的逻辑,在view中就可
以直接调用了。

为了避免和内置的标签重名,可以在TagLib类定义namespace属性,如:
class NewTestTagLib{

    static namespace = 'gn'
    def newTest = { attrs, body ->
    attrs.times?.toInteger().times { n->
        body(n)
        }
    }
}
这样在view中引用的方式就变成了
<gn: newTest times="5">
Hello World No. ${it}
</gn: newTest>
这样就完成了一个新的自定义标签,该标签可以自动按照times属性中的值重复输
出指定的内容。

 

你可能感兴趣的:(数据结构,jsp,bean,grails,groovy)