使用Groovy on Grails实现Ruby on Rails15分钟创建的Blog

本文介绍如何使用Grails框架快速构建一个包含用户认证、RSS订阅、评论及AJAX功能的简易博客。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

事先说明,我对Ruby只懂个皮毛。而Rails则没有接触过。看了视频后,还是能看懂的,语法什么的大概都能猜到意思。现在学习Grails,所以想用Grails来实现看看。

先分析下,视频里面所讲的Blog的内容。以Grails的名词来解释。(不知道Rails里面的专业术语。。。。)

1.首先是两个领域模型,Post和Comment。是一对多的关系。Post里面有title和body属性,不能为空。Comment里面持有Post的id以及body属性。
2.身份的验证。发布,编辑Post需要身份验证。
3.实现RSS浏览Post
4.回复Comment
5.AJAX实现动态显示添加的Comment

下面就开始使用Grails来实现这个Blog。开发工具是Intellij Idea + Grails插件。

首先,创建Blog项目,和创建Java项目是类似的。如果你爱用命令行那就敲命令吧。

创建完了项目,那么就开始着手实现了,当然是先创建两个领域模型Post和Comment.

class Post {
static hasMany = [comment:Comment]

String title
String body
}
class Comment {
Post post
String body
}

如果使用过任何ORM框架,那么这段代码没有难理解的地方吧!

静态的hasMany设置是个Groovy的hashmap:键是comment;值是Comment类.

接着创建Post和Comment的CRUD.
新建两个Controller,GroovyController和CommentController。如下所示。


class PostController {
def scaffold = Post
}
class CommentController {
def scaffold = Comment
}


def scaffold = ***的意思就是创建最基本的CRUD。这样你就可以运行项目了。看看效果。

[img]/upload/attachment/67683/e3e0f0a7-ee0d-39af-b92b-0ae8baaf3caf.png[/img]

框框内就是两个Controller。首先看看PostController。在你点击了NewPost之后,你会立刻发现两个问题。Body在Title的上方,Body的输入区域是textfield,而一般应该是textarea。先不管这个,随便输入点信息进去,是没有问题的。说明目前基本流程对了,那么下面开始修改刚才说的问题,并给Title和Body加上不能为空的限制。其实排序和限制可以说是一样的东西。往下看。

打开Post领域模型。修改代码如下


class Post {
static hasMany = [comment:Comment]

String title
String body

static constraints = {
title(maxLength:50,blank:false)
body(blank:false)
}
}

这个闭包应该很好理解吧?title长度不能超过50,不能为空,body也不能为空。而排序也已经被完成了。Grails会按照限制里面的顺序来列出内容。但是这里需要重新启动服务。否则不会出先效果。重启服务器试试看吧。
顺个便给Comment也加个限制。

class Comment {
Post post
String body

static constraints = {
post()
body(blank:false)
}
}


这里对post没有限制,但是如果你想要post在body前面,那么需要这么写。

接着修改页面显示。你需要general-all controller。我没有在Intellij Idea里面找到哪里可以做此操作(希望知道的告知一声,谢谢。)手动删除PostController和CommentController.使用命令行到项目的根路径下面。输入grails generate-all。在出现提示:Domain Class name not specified. Please enter:时,输入Post。结束以后再次输入grails generate-all,接着输入Comment。这样就可以了。

现在你会发现两个Controller里面多了很多代码,不管这些。到views目录下面,找到post目录,里面会有四个gsp文件(类似jsp的东西,学过jsp,看gsp没障碍)。刚才出问题的是add.gsp。进入此页面。找到body,将input标签替换为textarea标签即可,这里有个问题,<textarea></textarea>需要这样写,否则会有问题。至少我这里是。

接着就是身份验证了。
视频里面是使用了一个filter来过滤的(看着是挺简单的)。也没写页面什么,迷惑。
在Grails里面我是这么实现的!添加一个新的领域模型User来控制访问权限,登录后存放到session里面,然后编辑或创建的时候检查session。没有则转到登录页面。
这里也和视频里面一样就不查数据库了,检验用户名和密码是否都为admin,是就登录,否则就还在登录页面。
先建立User领域模型。然后generall-all。


class User {
String userId
String password

static constraints = {
userId(blank:false)
password(minLength:6,blank:false)
}
}


接着手动的创建登录页面和添加action。
这里的动作比较大一点。在UserController里面添加如下代码


def login = {
if (request.method == "GET") {
session.userId = null
def userInstance = new User()
}
else {
if(params.userId == "admin" && params.password == "admin"){
def userInstance = new User(userId:params.userId,password:params.password)
session.userId = userInstance.userId
redirect(controller: 'post')
}else {
flash['message'] =
'Please enter a valid user ID and password'
}
}
}

如果登录成功则跳转到post控制器,否则打印错误信息。
再在views目录下的user里面添加一个login.gsp,添加如下代码。


<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8"/>
<meta name="layout" content="main" />
<title>Log in</title>
</head>
<body>
<div class="body">
<h1>Please log in</h1>
<g:if test="${flash.message}">
<div class="message">${flash.message}</div>
</g:if>
<g:hasErrors bean="${race}">
<div class="errors">
<g:renderErrors bean="${user}" as="list" />
</div>
</g:hasErrors>
<g:form controller="user" method="post" >
<div class="dialog">
<table>
<tr class='prop'>
<td valign='top' class='name'>
<label for='userId'>User ID:</label>
</td>
<td valign='top' class='value '>
<input type="text" maxlength='8'
name='userId'
value='${user?.userId}'/>
</td>
</tr>
<tr class='prop'>
<td valign='top' class='name'>
<label for='password'>
Password:
</label>
</td>
<td valign='top' class='value '>
<input type="password" maxlength='8'
name='password'
value='${user?.password}'/>
</td>
</tr>
</table>
</div>
<div class="buttons">
<span class="button">
<g:actionSubmit value="Log in" />
</span>
</div>
</g:form>
</div>
</body>
</html>


现在登录就做好了,怎样把他给添加到流程里面去。这里需要一个Filter,在conf文件夹里面创建一个LoginFilters的groovy类,一定要以Filters结尾。
添加如下代码:

class LoginFilters {
def filters = {
loginCheck(controller: 'post', action: '*') {
before = {
if (!session.userId) {
if (actionName.equals('create')||actionName.equals('delete')||actionName.equals('update')||actionName.equals('edit')) {
redirect(controller: 'user', action: 'login')
return false
}
}
}
}
}
}

作用就是,当post里面调用的是create,delete,edit或者update Action的时候,如果没有登录则跳转到登录页面。

这样,权限就设置好了。再进行一下改进,因为这里只要登录成功后就会跳转到list页面,这肯定有问题,应该先记录用户要登录的页面,在登录成功后,再跳转到那个页面。

修改LoginFilters,如下


class LoginFilters {
def filters = {
loginCheck(controller: 'post', action: '*') {
before = {
if (!session.userId) {
if (actionName.equals('create')||actionName.equals('delete')||actionName.equals('update')||actionName.equals('edit')) {
def originalRequestParams =[controller:controllerName,action:actionName]
originalRequestParams.putAll(params)
session.originalRequestParams = originalRequestParams

redirect(controller: 'user', action: 'login')
return false
}
}
}
}
}
}


再修改下,UserController里面的login Action,如下


def login = {
if (request.method == "GET") {
session.userId = null
def userInstance = new User()
}
else {
if(params.userId == "admin" && params.password == "admin"){
def userInstance = new User(userId:params.userId,password:params.password)
session.userId = userInstance.userId

def redirectParams =session.originalRequestParams ?session.originalRequestParams :[controller:'post']

redirect(redirectParams)
}else {
flash['message'] =
'Please enter a valid user ID and password'
}
}
}


这样身份验证就完全添加好了。

接着是RSS功能.

Grails并没有对RSS或者Atom提供直接支持。你可以通过控制器render方法的XML能力来构造RSS或者ATOM。尽管如此,还是有一个Feeds 插件 (基于流行的 ROME 开发库)来为Grails提供RSS和Atom的生成器 (Grails参考手册13.3 )

插件可以到http://plugins.grails.org/下载。
或者使用命令行,到项目根路径下键入grails install-plugin feeds
然后在,PostController里添加一个Action

def feed = {
render(feedType:"rss", feedVersion:"2.0") {
title = "My test feed"
link = "http://localhost:8080/Blog/post/feed"
description = "The funky Grails news feed"

Post.list().each() { post ->
entry(post.title) {
link = "http://localhost:8080/Blog/post/show/${post.id}"
post.body // return the content
}
}
}
}


然后开始添加Comment,你在保存完Post后,应该发现了,Post的show页面里面就有一个Comment的字段来显示Comment。而Comment本来就有add方法,所以只需要两个整合一下就可以了,将Comment的create.gsp页面的form内容copy到Post的show.gsp页面里面去。在g:form标签里面添加一个属性

controller="comment"

因为这个页面现在有两个form,而此页面默认的controller是PostController,所以修改此controller为Comment。然后修改一下CommentController里的save Action,重定向修改为

redirect(controller:'post',action:'show',id:commentInstance.post.id)

即保存后还跳转到此post的show.gsp页面。页面结构就先不管了,功能是实现了。很简单吧!(我摸索了差不多1天时间 :cry: )

最后就是添加AJAX了。
Grails默认装载Prototype 库,但是通过Plug-in 系统提供像Dojo , Yahoo UI 和 Google Web Toolkit 等其他框架的支持.(Grails中文参考手册).
这里就使用默认支持的Prototype。在Post的show.gsp页面的head标签里面添加,Prototype支持。

<g:javascript library="prototype" />


最后就是AJAX实现,就是使用一个标签和render就可以了。将页面里面提交comment的按钮修改为AJAX按钮。同时将g:form里面的属性都去掉就可以了。

<div class="buttons">
<g:submitToRemote controller="comment" action="save" update="[success:'comments',failure:'error']" value="CreateComment"/>
</div>

这里的update就是动态刷新用的,成功就刷新id为comments的标签,否则就是id为error的标签。
修改下save Action.将rediect修改为render。这里应该是我对Grails不熟悉的原因。由于在gsp里面列Comment的标签是g:each,我不知道是否可以动态的改变它,我没找到办法,或者就是不可以。我直接在ul上加的comments id。然后在save Action里面组装了一下得到的Comments,返回一个str.

def save = {
def commentInstance = new Comment(params)
if(!commentInstance.hasErrors() && commentInstance.save()) {
flash.message = "Comment ${commentInstance.id} created"
def comments = Comment.findAllByPost(commentInstance.post)
def str = ""
comments.each {str = str + "<li>" + it + "</li>"}
render(str)
// redirect(controller:'post',action:'show',id:commentInstance.post.id)
}
else {
render(view:'create',model:[commentInstance:commentInstance])
}
}

这样,整个Blog就搞定了。页面上差异肯定是比较大一点,修改就行了。功能和ruby的基本相同了。有一点不同的应该是RSS那里,ruby会在浏览器的地址栏出现一个rss标签,而这里只能输入地址,应该也是可以的,我刚接触而已,做个实验罢了。如果熟悉Grails,相信15分钟之内是能搞定这个的!

ps:附件不知道会不会乱码,linux下打的包。。。。
内容概要:本书《Deep Reinforcement Learning with Guaranteed Performance》探讨了基于李雅普诺夫方法的深度强化学习及其在非线性系统最优控制中的应用。书中提出了一种近似最优自适应控制方法,结合泰勒展开、神经网络、估计器设计及滑模控制思想,解决了不同场景下的跟踪控制问题。该方法不仅保证了性能指标的渐近收敛,还确保了跟踪误差的渐近收敛至零。此外,书中还涉及了执行器饱和、冗余解析等问题,并提出了新的冗余解析方法,验证了所提方法的有效性和优越性。 适合人群:研究生及以上学历的研究人员,特别是从事自适应/最优控制、机器人学和动态神经网络领域的学术界和工业界研究人员。 使用场景及目标:①研究非线性系统的最优控制问题,特别是在存在输入约束和系统动力学的情况下;②解决带有参数不确定性的线性和非线性系统的跟踪控制问题;③探索基于李雅普诺夫方法的深度强化学习在非线性系统控制中的应用;④设计和验证针对冗余机械臂的新型冗余解析方法。 其他说明:本书分为七章,每章内容相对独立,便于读者理解。书中不仅提供了理论分析,还通过实际应用(如欠驱动船舶、冗余机械臂)验证了所提方法的有效性。此外,作者鼓励读者通过仿真和实验进一步验证书中提出的理论和技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值