《Spring Boot in Action》【6. Grails】
来源:互联网 发布:linux安装谷歌浏览器 编辑:程序博客网 时间:2024/05/16 17:01
6. Grails
6.1 使用GORM持久化数据
GORM(Grails object-relational mapping)Book实体:
package readinglistimport grails.persistence.*@Entityclass Book { Reader reader String isbn String title String author String description}
要在Spring Boot项目中使用GORM,加入依赖:
compile("org.grails:gorm-hibernate4-spring-boot:1.1.0.RELEASE")
这是通过Hibernate,如果你使用MongoDB,也是可以的:
compile("org.grails:gorm-mongodb-spring-boot:1.1.0.RELEASE")
GORM Reader实体:
package readinglistimport grails.persistence.*import org.springframework.security.core.GrantedAuthorityimport org.springframework.security.core.authority.SimpleGrantedAuthorityimport org.springframework.security.core.userdetails.UserDetails@Entityclass Reader implements UserDetails { String username String fullname String password Collection<? extends GrantedAuthority> getAuthorities() { Arrays.asList(new SimpleGrantedAuthority("READER")) } boolean isAccountNonExpired() { true } boolean isAccountNonLocked() { true } boolean isCredentialsNonExpired() { true } boolean isEnabled() { true }}
ReadingListController
package readinglistimport org.springframework.beans.factory.annotation.Autowiredimport org.springframework.boot.context.properties.ConfigurationPropertiesimport org.springframework.http.HttpStatusimport org.springframework.stereotype.Controllerimport org.springframework.ui.Modelimport org.springframework.web.bind.annotation.ExceptionHandlerimport org.springframework.web.bind.annotation.RequestMappingimport org.springframework.web.bind.annotation.RequestMethodimport org.springframework.web.bind.annotation.ResponseStatus@Controller@RequestMapping("/")@ConfigurationProperties("amazon")class ReadingListController { @Autowired AmazonProperties amazonProperties @ExceptionHandler(value=RuntimeException.class) @ResponseStatus(value=HttpStatus.BANDWIDTH_LIMIT_EXCEEDED) def error() { "error" } @RequestMapping(method=RequestMethod.GET) def readersBooks(Reader reader, Model model) { List<Book> readingList = Book.findAllByReader(reader) model.addAttribute("reader", reader) if (readingList) { model.addAttribute("books", readingList) model.addAttribute("amazonID", amazonProperties.getAssociateId()) } "readingList" } @RequestMapping(method=RequestMethod.POST) def addToReadingList(Reader reader, Book book) { Book.withTransaction { book.setReader(reader) book.save() } "redirect:/" }}
Groovy SecurityConfig:
package readinglistimport org.springframework.context.annotation.Configurationimport org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilderimport org.springframework.security.config.annotation.web.builders.HttpSecurityimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapterimport org.springframework.security.core.userdetails.UserDetailsService@Configurationclass SecurityConfig extends WebSecurityConfigurerAdapter { void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/").access("hasRole('READER')") .antMatchers("/**").permitAll() .and() .formLogin() .loginPage("/login") .failureUrl("/login?error=true") } void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService( { username -> Reader.findByUsername(username) } as UserDetailsService) }}
6.2 用GSP编写视图
目前为止我们都是使用Thymeleaf作为模板引擎,Grails项目同时提供了Groovy Server Pages(GSP)的自动配置,添加如下依赖:
compile("org.grails:grails-gsp-spring-boot:1.0.0")
接下来,把Thymeleaf readingList.html改写成readingList.gsp,同样是放在src/main/resources/templates路径下:
<!DOCTYPE html><html> <head> <title>Reading List</title> <link rel="stylesheet" href="/style.css"></link> </head> <body> <h2>Your Reading List</h2> <g:if test="${books}"> <g:each in="${books}" var="book"> <dl> <dt class="bookHeadline"> ${book.title} by ${book.author} (ISBN: ${book.isbn}") </dt> <dd class="bookDescription"> <g:if test="book.description"> ${book.description} </g:if> <g:else> No description available </g:else> </dd> </dl> </g:each> </g:if> <g:else> <p>You have no books in your book list</p> </g:else> <hr/> <h3>Add a book</h3> <form method="POST"> <label for="title">Title:</label> <input type="text" name="title" value="${book?.title}"/><br/> <label for="author">Author:</label> <input type="text" name="author" value="${book?.author}"/><br/> <label for="isbn">ISBN:</label> <input type="text" name="isbn" value="${book?.isbn}"/><br/> <label for="description">Description:</label><br/> <textarea name="description" rows="5" cols="80"> ${book?.description} </textarea> <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> <input type="submit" value="Add Book" /> </form> </body></html>
需要注意的是,我们有一个隐藏域来放CSRF(Cross-Site Request Forgery)token,Spring Security要求在POST请求中有这个token,Thymeleaf会自动在渲染的HTML中加入这个token,但在GSP中,你得显式指定。
6.3 混合Spring Boot和Grails 3
Grails是一个建立在Spring,Groovy,Hibernate等之上的高层框架,目前,Grails 3建立在Spring Boot之上,所以对于Grails开发者和Spring Boot开发者来说,都有很好的开发体验。
在Mac OS X和大部分Unix系统上,安装Grails最方便的方法是使用SDKMAN:
$ sdk install grails
在Windows或者不能使用SDKMAN的系统上,你只好下载,解压并把bin目录添加到环境变量里去,检查安装是否成功:
$ grails -version
创建Grails项目
$ grails create-app readinglist
运行:
$ grails run-app
因为Grails 3的Gradle脚本使用了Spring Boot插件,所以也可以使用bootRun运行:
$ gradle bootRun
当然也可以打包运行:
$ gradle build...$ java -jar build/lib/readingList-0.1.jar
定义domain
$ grails create-domain-class Book
它会创建两个文件:Book.groovy和BookSpec.groovy,后面一个文件是测试Book类的Spock specification,初始是空的,Book.groovy在grails-app/domain/readingList目录下,像这样:
package readinglistclass Book { static constraints = { }}
我们添加一些字段:
package readinglistclass Book { static constraints = { } String reader String isbn String title String author String description}
静态变量constraints是用来定义验证约束的,这里我们不关心。
编写Grails控制器
有几种命令可以创建Controller:
- create-controller——创建一个空的Controller
- generate-controller——生成包含指定domain类型CRUD操作的骨架Controller
- generate-all——生成包含指定domain类型CRUD操作的骨架Controller以及视图
我们使用第一个:
$ grails create-controller ReadingList
该命令会在grails-app/controllers/readingList目录下创建一个ReadingListController:
package readinglistclass ReadingListController { def index() { }}
此时该控制器已经可以处理/readingList请求了,会返回grails-app/views/readingList/index.gsp视图(暂时还不存在)
package readinglistimport static org.springframework.http.HttpStatus.*import grails.transaction.Transactionalclass ReadingListController { def index() { respond Book.list(params), model:[book: new Book()] } @Transactional def save(Book book) { book.reader = 'Craig' book.save flush:true redirect(action: "index") }}
接下来就是编写GSP页面,和6.2中的差不多:
<!DOCTYPE html><html> <head> <meta name="layout" content="main"/> <title>Reading List</title> <link rel="stylesheet" href="/assets/main.css?compile=false" /> <link rel="stylesheet" href="/assets/mobile.css?compile=false" /> <link rel="stylesheet" href="/assets/application.css?compile=false" /> </head> <body> <h2>Your Reading List</h2> <g:if test="${bookList && !bookList.isEmpty()}"> <g:each in="${bookList}" var="book"> <dl> <dt class="bookHeadline"> ${book.title}</span> by ${book.author} (ISBN: ${book.isbn}") </dt> <dd class="bookDescription"> <g:if test="${book.description}"> ${book.description} </g:if> <g:else> No description available </g:else> </dd> </dl> </g:each> </g:if> <g:else> <p>You have no books in your book list</p> </g:else> <hr/> <h3>Add a book</h3> <g:form action="save"> <fieldset class="form"> <label for="title">Title:</label> <g:field type="text" name="title" value="${book?.title}"/><br/> <label for="author">Author:</label> <g:field type="text" name="author" value="${book?.author}"/><br/> <label for="isbn">ISBN:</label> <g:field type="text" name="isbn" value="${book?.isbn}"/><br/> <label for="description">Description:</label><br/> <g:textArea name="description" value="${book?.description}" rows="5" cols="80"/> </fieldset> <fieldset class="buttons"> <g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" /> </fieldset> </g:form> </body></html>
- 《Spring Boot in Action》【6. Grails】
- Spring-boot IN Action(1)
- 《Spring Boot in Action》【1. 起步】
- 《Spring Boot in Action》【3. 自定义配置】
- 《Spring Boot in Action》【4. 测试】
- 《Spring Boot in Action》【5. Groovy】
- 《Spring Boot in Action》【7. Actuator】
- 《Spring Boot in Action》【8. 部署】
- 《Spring Boot in Action》【A. 开发者工具】
- Grails in Action:完成啦
- 《Spring Boot in Action》【2. 开发第一个应用】
- 8.2 Spring Boot集成Groovy、Grails开发
- Spring in action 读书笔记
- Spring in action
- Spring in Action
- Spring in Action
- Spring in action笔记
- 读书笔记:spring in action
- C# 运算符大全(按照操作数个数分类)
- 深入分析JavaWeb技术内幕系列之---DNS域名解析过程
- c++ STL map解析
- Android stdio 解决HAXM安装不上问题
- 使用webmagic搭建一个简单的爬虫
- 《Spring Boot in Action》【6. Grails】
- Flex 学习之路之十九 panel面板对话框传值
- [Unity]Unity3D编辑器插件扩展和组件扩展
- 解决python报错IndentationError: expected an indented block的方法
- Eclipse Ivy 搭建项目仓库
- java对象持久化保存的方法小结
- 机器学习第3章第10节 : 改变声音音量并绘制图谱
- 有效的括号序列-LintCode
- codevs 1961 躲避大龙