按前文的开发指南写了一个一对多的例子,期间发现由于时间的推移,新版本1.3.4的规约已经做得很强大了,只是敲几个grails命令就可以完成基本简单开发
但是一个完整的系统需要【权限】,【页面美化】,【编码转义】等
1,权限的实现非常简单,按此文加入acegi权限
http://grails.org/AcegiSecurity%20Plugin%20-%20Basic%20Tutorial 很有意思的2点是
a,需要单独增加ROLE_USER角色
b,自动生成的controller会在ide工具下报类引用错误
acegi说难不难,说易不易,如果要实现基本的路径权限控制,配置SecurityConfig.groovy几个参数即可,而要做细粒度的权限分配,则不是一件易事
2,页面的美化主要有三个事情要做
a,修改layout/main.gsp
由于在view部分采用了sitemesh框架,因此理解了装饰的思想就很容易的将修改main.gsp
grails还有一个很贴心的设计,就是${resource(dir:'css',file:'main.css')} 和<g:link
controller="mydomain">blabla</g:link>,这2个标签,分别解决了因context造成的资源访
问和url路径问题
b,增加一个覆盖main.css的project.css
main.css的作用是设置基本增删改查页面的默认样式,且不说font-size:11px的设置,银灰色主色调也不一定和项目要求一致,这样就必
须新增一个project.css来定义新的外观。而这新的定义,必须基于generate-all生成的gsp页面html+css规范
开发新定义,首先要知道css优先权的计算方式,其次会利用firebug进行开发调试
c,修改本地化的配置文件
按钮和动作的提示语言还是英文的,需要开发者在messages_zh_CN.properties增加相应的中文配置,这个修改,一般要求ide工具安装ProEditor
3,编码转义
所谓编码转义需求,就是在数据库存值,而在显示时,显示其的含义(label),举例子就是一个实体类的状态,目前的流行做法是使用枚举类,如文所写
http://hi.baidu.com/limp_t/blog/item/5b63ab34228935305bb5f503.html 在实际应用中,实在看不到枚举类的持久化在grails项目有什么的优点,因此我将key和label都写类(附1)里
最神奇的一点就是没有看到任何中文帖子提到类型转换的bug...英文帖子倒是在其开发团队的jira上声称fix 到没有放出例子
无奈只能在controller类里面增加类型转换的类(附2)了
最后就是分别在create/show/edit/list(附3)里面修改相应的代码
一周的学习,觉得grails的学习重点
1 domain constraints mapping
2 controller
3 grais tag
advanced
4 custom grails command 主要是定做项目的generate-all命令
5 grails plugin
6 grails 和 分布式 一个流程多个view的应用太多了
grails是一个赞的框架,一周的学习居然找回了当年写php的感觉,还夹杂了些写js的感觉
而最重要的是,我有和产品经理一起天马行空的时间
有意思的是用grails做关键字在51job搜索,北京提供的职位不超过20个,想想ssh从引入到如今的烂大街用了4-5年 grails成为明日培训班的必要教材也不是不可想象的
知易行难,欢迎大家继续关注grails系列
========== 附1 =================================
public enum AgencyType {
PROXY("P","P AG"),
DIRECT("D","D AG");
AgencyType(String key, String value) {
this.key = key;
this.label = value;
}
private String key;
private String label;
@Override
public String toString() {
return key;
}
public String getLabel(){
return label;
}
public static AgencyType getType(String key){
AgencyType [] types = AgencyType.values();
for(AgencyType type : types){
if(type.toString().equals(key)){
return type;
}
}
return null;
}
}
========== 附2 =================================
def save = {
params.type = AgencyType.getType(params.type.toString())
def agencyInstance = new Agency(params)
if (agencyInstance.save(flush: true)) {
//.
}
else {
//
}
}
========== 附3 =================================
// for create edit
<g:select name="type" from="${AgencyType.values()}" optionValue="label"></g:select>
//for show list
${fieldValue(bean: agencyInstance, field: "type.label")}