grails入门

Grails是搭建在Groovy之上的一个开源MVC Web开发框架,它分别用Domain Class、View、Controller对应于MVC的模型、视图和控制器。可以简单的把一个Domain Class理解为数据库中的一张表,Grails在底层通过Hibernate将Domain Class和数据库的表进行映射。View在Grails中指的是GSP页面(不是JSP),它用来显示用户界面。GSP和JSP类似,既可以编写静态网页的元素,也可以嵌入Groovy代码实现动态内容,Controller在Grails中充当着重要的角色:它可以响应用户的请求,可以接收用户提交的表单,还可以访问模型的数据,并传递给View。

Grails非常强调惯例优于配置,在grails-app下,所有领域类都放在domain目录,控制器保存在controllers目录,视图则放在views目录。

conf下的配置文件

1.resources.groovy:Spring的bean在这里配置

以前要在applicatioinContext.xml中配置的bean你可以挪到这里来,凡是这里定义的bean,你都可以直接注入到controller和service中使用。

2.BootStrap.groovy

如果要在程序启动或结束后自动做一些工作,在这里。

destroy一般不用,因为你只有通过命令或者停止服务等正常方式来停止服务,才能调用destroy,不能保证destroy被调用。

脚手架(Scaffolding)

这个术语来源于Rails框架,用来生成提供数据库CRUD操作接口的工件(Artifact)。如今被扩展,表示在项目中按照规约(Convention)去实现相应约定的接口。

对于动态脚手架,应用脚手架不使用模板代码或模板,而是使用如反射和Groovy的MetaClass类来实现。

 

 

控制器

Grails会为每个请求创建一个新的控制器,因此无需担心本地域的线程安全。

(1)简单地委托给一个合适的视图。

(2)操作领域模型,然后将它在视图上显示。

(3)直接写入响应的writer对象中。

(4)重定向到另外一个操作或另外一个控制器中的操作。

控制器的定义,由脚手架生成,名称以Controller结尾,前面是URI中上下文路径部分。在控制器中使用闭包的属性来定义操作,该属性名会映射到URI的第三部分。

当Grails在URI路径只有控制器的上下文路径,而没有指定操作名的情况下会使用默认的操作:

(1)如果控制器中只定义了一个操作,那么该操作就为默认操作。

(2)如果控制器定义了一个index操作,那么这个index操作为默认操作。

(3)如果控制器定义一个String类型的defaultAction属性,那么该属性所指的操作就为默认操作。

Grails spring-security-core plugin

1.SpringSecurityService

grails.plugin.springsecurity.SpringSecuirtyService提供了安全工功能, 它是一个正常的Grails 服务, 可以注入到controller, service, taglib等.

def springSecurityService

(1)getCurrentUser

为当前验证的用户获取domain class实例,实例的id会被保存,这个方法使用domain类和id重新加载实例,如果UserDetails实例不是GrailsUser,会使用username加载。

如果你只是想使用id,应该使用loadCurrentUser。

(2)loadCurrrentUser

这个方法使用GORM加载方法来创建一个代理实例。

(3)isLoggedIn

检测是否有已经登录的用户。

(3)getAuthentication

获取当前用户的Authentication,如果已经验证,那返回UsernamePasswordAuthenticationToken.

如果没有认证,默认激活AnonymousAuthenticationFilter。它会返回一个grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken实例,用标准的org.springframework.security.core.userdetails.User实例作为它的Principal,角色是ROLE_ANONYMOUS。

(4)getPrincipal

获取当前登录用户的Principal,如果已经认证,principal会是grails.plugin.springsecurity.userdeatils.GrailsUser,可以使用自建的UserDetailService替代。

(5)encodePassword

默认使用bcrpt,可以在application.groovy中通过grails.plugins.springsecurity.password.algorithm属性来配置。

(6)updateRole

如果使用Requestamp来secure URLS,当你更新role name时,会影响Requestmap定义。

(7)deleteRole

(8)clearCachedRequestmaps

(9)reauthenticate

2.SpringSecurityUtils

有一些静态方法,不依赖注入即可用。

(1)authoritiesToRoles

从GrantedAuthority集合是提出role names

(2)getPrincipalAuthorities

获取当前登录用户的authorities,如果用户没有登录会是空(永远不会是null)

(3)parseAuthoritiesString

把逗号分隔的role 串为GrantedAuthority列表。

(4)ifAllGranted

检查当前用户是否有所有指定的roles

(5)isNotGranted

检查当前用户是否没有当前指定的roles

(6)ifAnyGranted

(7)getSecurityConfig

grails-app/conf/application.groovy+插件默认配置

(8)loadSecondaryConfig

(9)reloadSecurityConfig

(10)isAjax

检查request是否由ajax发起,一般是检查X-Request-With请求头+XMLHttpRequest值。

可以在application.groovy中使用ajaxCheckClosure来检查请求是否为Ajax request。

(11)registerProvider

(12)registerFiter

(13)isSwitched

检查当前用户是否转化为另一个用户

(14)getSwitchedUserOriginalUsername

(15)doWithAuth

3.URL Properties

(1)apf.filterProcessesUrl:默认值/login/authenticate,表示login form的post url,Spring Security filter会拦截。

(2)apf.usernameParameter:默认值“username”,login form的用户名。

(3)apf.passwordParameter:默认值 "password",login form的密码。

(4)apf.allowSessionCreation:默认值 “true”,是否允许认证来创建一个HTTP session。

(5)apf.postOnly:默认值“true”,是否只允许POST登录请求

(6)apf.continueChainBefore:默认值“false”,在filter chain中是否继续调用后续的filter

(7)apf.storeLastUsername:默认值“false”,是否在http session中保存用户名

(8)failureHandler.defaultFailureUrl:默认值“/login/authfail?login_error=1”,登录失败的重定向url。

(9)failureHandler.ajaxAuthFailUrl:默认值,“/login/authfail?ajax=true”,ajax登录失败的重定向url。

(10)failureHandler.exceptionMappings:默认值 none,异常类名的map(AuthenticationException的子类)

(11)failureHandler.useForward:默认值false,是否渲染error page

(12)failureHandler.allowSessionCreation:默认值true,是否启用session创建来保存验证失败异常。

(13)sucessHandler.default:默认值“/”

(14)sucessHandler.alwarysUseDefault:默认值false。

...

The Application Class

每一个新的Grails application在grails-app/init目录下都有一个Application类,此类继承自GrailsAutoConfiguration,有一个static void main方法,表示可以作为一个正常的应用运行。

1.定制扫描

默认Grails会扫描所有的sources目录,用于查找controller,domain类等。如果有一些在其它的jar包中,你可以重写packageNames方法来定制扫描路径 。

class Application extends GrailsAutoConfiguration {
    @Override
    Collection<String> packageNames() {
        super.packageNames() + ['my.additional.package']
    }

    ...
}

2.注册额外的bean

只要使用@Bean注解即可。

class Application extends GrailsAutoConfiguration {
    @Bean
    MyType myBean() {
        return new MyType()
    }

    ...
}

3.生命周期

实现了GrailsApplicationLifeCycle接口,所有的插件都实现了这个接口。你可以重写一些插件钩子的方法。

class Application extends GrailsAutoConfiguration {
    @Override
    Closure doWithSpring() {
        {->
            mySpringBean(MyType)
        }
    }

    ...
}

对象关系映射(GORM)

GORM是Grails的对象关系映射(ORM)的实现,实际上它使用的是Hibernate。因为有Groovy的动态特性支持,因此GORM既支持动态类型也支持静态类型,再加上Grails的规约,现在创建Grails的领域类只需要更少的配置就可以了。

1.count

数据库相关实例的个数。

2.constraints

声明有效约束定义。

class Book {
   String title
   Author author
   static constraints = {
        title(blank:false, nullable:false, size:5..150)	
        author(nullable:false)
   }	
}

可以通过调用validate方法进行验证。

def b = new Book()
assert !b.validate()

在运行时会对这些约束进行验证。

b.constraints.each {
      println it.name
      println it.maxSize
}

3.mapping

自定义映射是使用静态的mapping块定义在你的域类中:

class Person {
  ..
  static mapping = {
  }
}

类映射到数据库的表名可以使用table关键字定制,也可以定制某个列到数据库。

class Person {
  String firstName
  static mapping = {
      table 'people'
      firstName column:'First_Name'
  }
}

Hibernate本身提供了自定义二级缓存的特性,这就需要在grails-app/conf/DataSource.groovy文件中配置。

hibernate {
    cache.use_second_level_cache=true
    cache.use_query_cache=true
    cache.provider_class='org.hibernate.cache.EhCacheProvider'
}

假如在映射代码中启用缺省的缓存,可以通过调用cache方法实现。

class Person {
  ..
  static mapping = {
      table 'people'
      cache true
  }
}

上面的例子中将配置一个读-写缓存包括lazy和non-lazy属性。

4.findAllBy*

动态方法,使用域类的属性来创建Grails query 表达式来查询所有domain类的实例。

class Book {
   Long id
   Long version
   String title
   Date releaseDate
   String author
}
def results = Book.findAllByTitle("The Shining", [max:10, sort:"title", order:"desc", offset:100] )
results = Book.findAllByTitleAndAuthor("The Sum of All Fears", "Tom Clancy")
results = Book.findAllByReleaseDateBetween(firstDate, new Date())
results = Book.findAllByReleaseDateGreaterThanEquals(firstDate)
results = Book.findAllByTitleLike("%Hobbit%")
results = Book.findAllByTitleIlike("%Hobbit%") // (since 0.5) - ignorecase
results = Book.findAllByTitleNotEqual("Harry Potter")
results = Book.findAllByReleaseDateIsNull()
results = Book.findAllByReleaseDateIsNotNull()

GORM支持Dynamic Finder

(1)LessThan

(2)LessThanEquals

(3)GreaterThan

(4)Between

(5)Like

(6)Ilike(不区分大小写)

(7)IsNotNull

(8)IsNull

(9)Not

(10)Equal

(11)NotEqual

(12)And

(13)Or

5.save

保存域类实例到数据库中,会级联保存子实例,只有在配置了flush:true参数时,才会立即持久到数据库中。

b.save(flush:true)

6.事件和自动实现时间戳

GORM支持事件注册,只需要将事件作为一个闭包即可。

(1)beforeInsert事件

class Person {
   Date dateCreated
   def beforeInsert = {
       dateCreated = new Date()
   }
}

(2)beforeUpdate事件

class Person {
   Date dateCreated
   Date lastUpdated
   def beforeInsert = {
       dateCreated = new Date()
   }
   def beforeUpdate = {
       lastUpdated = new Date()
   }
}

(3)beforeDelete事件

class Person {
   String name
   Date dateCreated
   Date lastUpdated
   def beforeDelete = {
      new ActivityTrace(eventName:"Person Deleted",data:name).save()
   }
}

(4)onLoad事件

class Person {
   String name
   Date dateCreated
   Date lastUpdated
   def onLoad = {
      name = "I'm loaded"
   }
}

 

最后欢迎大家访问我的个人网站:1024s​​​​​​​

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值