欢迎大家赞助一杯啤酒🍺 我们准备了下酒菜:Formal mathematics/Isabelle/ML, Formal verification/Coq/ACL2, C++/F#/Lisp
Grails
Grails关注将"规约编程"(coding by convention)引入Groovy。它是一个开放源网络应用构架, 对Groovy语言起到杠杆作用,并且对Java网络开发起到补足作用。你可以用Grails 作为独立开发环境, 它隐藏了所有的配置细节,也可以将它同和入你的Java商务逻辑。
Grails关注与使开发最简化,而且Grails的解决方案来自于广泛的开发者,不只局限于Java社区。
Grails构建在开源技术如Spring、Hibernate和SiteMesh之上,提供了一个类似于Rails 的平台可以与Java平台无缝集成. Groovy是一种“动态”或指令语言。动态语言一般用来加速和简化程序撰写。与Python或Ruby等其他指令语言不同的是,用Groovy撰写的程序,可与Java虚拟器结合。
Install
wget http://download.huihoo.com/grails/grails-bin-1.0.1.zip GRAILS_HOME= C:\grails-1.0.1 or /usr/local/grails-1.0.1 Add the "%GRAILS_HOME%\bin" directory to your PATH environment variable Add the "%GRAILS_HOME%\ant\bin directory to your PATH environment variable. grails create-app my-project cd my-project grails create-domain-class Book
my-project\grails-app\domain\Book.groovy
class Book { String title String author }
my-project\grails-app\conf\BootStrap.groovy
class BootStrap {
def init = { servletContext -> // Create some test data new Book(author:"Stephen King",title:"The Shining").save() new Book(author:"James Patterson",title:"Along Came a Spider").save() } def destroy = { } }
my-project\grails-app\controllers\BookController.groovy
class BookController { def scaffold = Book } grails run-app http://localhost:8080/my-project/ http://localhost:8080/my-project/book 运行成功 :)
To upgrade your existing Grails projects you must run:
grails clean grails upgrade
NetBeans
http://wiki.netbeans.org/groovy
PostgreSQL
More Detail: http://blogs.sun.com/tomdaly/entry/regperf_v1_running_the_grails
CRUD
Create
def p = new Person(name:"Jack", age:32, lastVisit:new Date()) p.save()
Read
def p = Person.get(1) assert 1 == p.id
Update
def p = Person.get(1) p.name = "Peter" p.save()
Delete
def p = Person.get(1) p.delete()
GORM
One-to-one
class Face { Nose nose } class Nose { static belongsTo = [face:Face] } new Face(nose:new Nose()).save() // ok
def f = Face.get(1) f.delete() // both Face and Nose deleted
One-to-many
class Author { static hasMany = [ books : Book ] String name } class Book { static belongsTo = [author:Author] String title }
Many-to-many
class Book { static belongsTo = Author static hasMany = [authors:Author] String title } class Author { static hasMany = [books:Book] String name }
Grails 1.0.3 Scaffolding feature does not currently support many-to-many relationship and hence you must write the code to manage the relationship yourself
Grails ManyToMany GORM Example
GPath: Groovy's ability to manipulate collections via GPath and methods like sort, findAll and so on combined with GORM results in a powerful combination.
def books = Book.list() def books = Book.list(offset:10, max:20) def books = Book.list(sort:"title", order:"asc") def book = Book.get(23) def books = Book.getAll(23, 93, 81) def book = Book.findByTitle("The Stand")
Usage
grails help
- grails bootstrap
- grails bug-report
- grails clean
- grails compile
- grails console
- grails create-app
- grails create-controller
- grails create-domain-class
- grails create-integration-test
- grails create-plugin
- grails create-script
- grails create-service
- grails create-tag-lib
- grails create-unit-test
- grails doc
- grails generate-all
- grails generate-controller
- grails generate-views
- grails help
- grails init
- grails install-plugin
- grails install-templates
- grails list-plugins
- grails package
- grails package-plugin
- grails package-plugins
- grails plugin-info
- grails release-plugin
- grails run-app
- grails run-app-https
- grails set-proxy
- grails set-version
- grails shell
- grails stats
- grails test-app
- grails upgrade
- grails war
Service
Services in Grails are seen as the place to put the majority of the logic in your application, leaving controllers responsible for handling request flow via redirects and so on.
grails create-service simple
Plugins
grails list-plugins
To find more info about plugin type 'grails plugin-info [NAME]'
To install type 'grails install-plugin [NAME] [VERSION]'
grails install-plugin yui 2.5.0
For further info visit http://grails.org/Plugins
GSP
<html> <body> <%-- This is my comment --%> // <%="Hello GSP!" %> JSP-style comment <%="Hello GSP!" %> </body> </html> <%@ page import="java.awt.*" %> <%@ page contentType="text/json" %>
GSP Tags
<g:example attr="${new Date()}" attr2="[one:'one', two:'two']"> Hello world </g:example>
Ext
grails install-plugin ext or grails install-plugin ext 2.0.2 Ext has installed under your project's /web-app/js/ext/2.0.2
More Detail: http://grails.org/Ext+Plugin
Using ExtJS Layouts with Grails Layouts
GWT
grails install-plugin gwt grails create-gwt-module <module> grails compile-gwt-modules grails create-gwt-page grails events grails run-gwt-client
More Detail: http://www.grails.org/GWT+Plugin
GWTGrailsTutorial: http://code.google.com/p/derjanandhisblog/wiki/GWTGrailsTutorial
JSON
def list = { def results = Book.list() render(contentType:"text/json") { books { for(b in results) { book(title:b.title) } } } }
Result
[ {title:"ActiveRecord Tutorial"}, {title:"Grails Tutorial"} ]
Web Flow
Grails supports the creation of web flows built on the Spring Web Flow project.
class BookController { … def shoppingCartFlow = { showCart { on("checkout").to "enterPersonalDetails" on("continueShopping").to "displayCatalogue" } … displayCatalogue { redirect(controller:"catalogue", action:"show") } displayInvoice() } }
Web flows don't require an HTTP session, but instead store their state in a serialized form, which is then restored using a flow execution key that Grails passes around as a request parameter. This makes flows far more scalable than other forms of stateful application that use the HttpSession and its inherit memory and clustering concerns.
Tutorials
Build Your First Grails Project: A Grails-Powered Blog
NetBeans
Groovy and Grails 在开发版中已经可用 http://wiki.netbeans.org/groovy
开发版: http://deadlock.netbeans.org/hudson/job/trunk/lastSuccessfulBuild/artifact/nbbuild/dist/zip/
REST
As an example the following mappings provide a RESTful API URL mappings for the BookController:
static mappings = { "/product/$id"(controller:"product"){ action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"] } }
SOAP
Grails supports SOAP through the XFire plug-in which uses the popular XFire SOAP stack to integrate SOAP support into Grails.
class BookService { static expose=['xfire'] Book[] getBooks() { Book.list() as Book[] } } http://127.0.0.1:8080/your_grails_app/services/book?wsdl
Ajax
Ajax with GWT
Ajax with Prototype
Ajax with Dojo
Validation
class User { String login String password String email Integer age
static constraints = { login(size:5..15, blank:false, unique:true) password(size:5..15, blank:false) email(email:true, blank:false) age(min:18, nullable:false) } }
Testing
grails test-app SimpleController BookController
Unit Testing
Integration Testing
Functional Testing
Grials support for Canoo WebTest via a plug-in.
grails install-plugin webtest
Internationalization
grails-app/i18n
messages.properties messages_zh.properties messages_de.properties messages_es.properties
etc.
Security
class SecurityFilters { def filters = { loginCheck(controller:'*', action:'*') { before = { if(!session.user && actionName != "login") { redirect(controller:"user",action:"login") return false }} } } }
Acegi
JSecurity
class ExampleController extends JsecAuthBase { static accessControl = { // All actions require the 'Observer' role. role(name: 'Observer') // The 'edit' action requires the 'Administrator' role. role(name: 'Administrator', action: 'edit') // Alternatively, several actions can be specified. role(name: 'Administrator', only: [ 'create', 'edit', 'save', 'update' ]) } … }
RSS and Atom
Feeds plug-in available for Grails that provides a RSS and Atom builder using the popular ROME library.
def feed = { render(feedType:"rss", feedVersion:"2.0") { title = "My test feed" link = "http://your.test.server/yourController/feed" Article.list().each() { entry(it.title) { link = "http://your.test.server/article/${it.id}" it.content // return the content } } } }
Grails and Spring
Grails and Hibernate
Scaffolding
class BookController { def scaffold = Book def changeAuthor = { def b = Book.get( params["id"] ) b.author = Author.get( params["author.id"] ) b.save() redirect(action:show) } }
Deployment
grails war /glassfish-v2ur2/domains/domain1/applications/j2ee-modules/blog.war
Mobile
相关项目
Samples
http://svn.codehaus.org/grails/trunk/grails-samples/
成功应用
http://www.grails.org/Success+Stories