Grails(8)Guide Book Chapter 7 The Web Layer Groovy Server Pages
Grails(8)GuideBookChapter7TheWebLayerGroovyServerPages
7.1.13AsynchronousRequestProcessing
7.2GroovyServerPages(GSP)
7.2.1GSPBasics
GSPsupportstheusageof<%%>scriptletblockstoembedGroovycode.(discouraged)
<%=%>syntaxtooutputvalues.
7.2.1.1VariablesandScopes
<%now=newDate()%>
<%=now%>
Wedefineavariable,andusethatlaterinthesamepage.
application-Thejavax.servlet.ServletContextinstance
applicationContext-TheSpringApplicationContextinstance
flash-Theflashobject
grailsApplication-TheGrailsApplicationinstance
out-Theresponsewriterforwritingtotheoutputstream
params-Theparamsobjectforretrievingrequestparameters
request-TheHttpServletRequestinstance
response-TheHttpServletResponse
session-TheHttpSessioninstance
webRequest-TheGrailsWebRequestinstance
7.2.1.2LogicandIteration
<%[1,2,3,4].each{num->%>
<p><%="Hello${num}!"%></p>
<%}%>
<%if(params.hello=='true')%>
<%="hello!"%>
<%else%>
<%="Goodbye!"%>
IfoundthereisnoendtagintheGSPabove.Itwillconfuseme.
7.2.1.3PageDirectives
Theimportdirectiveletsusimportclassesintothepage.
<%@pageimport="java.awt.*"%>
<%@pagecontentType="text/json"%>
7.2.1.4Expressions
AGSPexpressionissimilartoaJSPELexpression.${expr}
Hello${params.name}
7.2.2GSPTags
7.2.2.1VariablesandScopes
<g:setvar="now"value="${newDate()}"/>//setjava.util.Dateinstance
<g:setvar="myHTML">
Somere-usablecodeon:${newDate()}
</g:set>//sethtmlcontent
<g:setvar="bookService"bean="bookService"/>//setservicebean
Therearefollowingscopes>
page-Scopedtothecurrentpage(default)
request-
flash
session
application
<g:setvar="now"value="${newDate()}"scope="request"/>
7.2.2.2LogicandIteration
<g:iftest="${session.role=='admin'}">
…snip...
</g:if>
<g:else>
…snip...
</g:else>
<g:eachin="${[1,2,3]}"var="num">
<p>Number${num}</p>
</g:each>
7.2.2.3SearchandFiltering
StephenKing'sBooks:
<g:findAllin="${books}"expr="it.author=='StephenKing'">
<p>Title:${it.title}</p>
</g:findAll>
TheexprattributecontainsaGroovyexpressionthatcanbeusedasafilter.
<g:grepin="${books}"filter="NonFictionBooks.class">
<p>Title:${it.title}</p>
</g:grep>
filterbyClass?
7.2.2.4LinksandResources
<g:linkaction="show"id="1">Book1</g:link>
<g:linkaction="show"id="${currentBook.id}">${currentBook.name}</g:link>
<g:linkcontroller="book">BookHome</g:link>
<g:linkcontroller="book"action="list">BookList</g:link>
<g:linkurl="[action:'list',controller:'book']">BookList</g:link>
<g:linkparams="[sort:'title',order:'sac',author:currentBook.author]"
action="list">BookList</g:link>
7.2.2.5FormsandFields
FormBasics
<g:formname="myForm"url="[controller:'book',action:'list']">…</g:form>
FormFields
textField
passwordField
checkBox
radio-Forinputfieldsoftype'hidden'
hiddenField
select
EachoftheseallowsGSPexpressionsforthevaluepart.
<g:textFieldname="username"value="${user.username}"/>
MultipleSubmitButtons
<g:actionSubmitvalue="Update"action="update"/>
7.2.2.6TagsasMethodCalls
7.2.3ViewsandTemplates
TemplateBasics
Grailsusestheconventionofplacinganunderscorebeforethenameofaviewtoidentifyitasatemplate.
grails-app/views/book/_bookTemplate.gsp
<divclass="book"id="${book?.id}">
<div>Title:${book?.title}</div>
<div>Author:${book?.author?.name}</div>
</div>
<g:rendertemplate="bookTempalte"model="[book:myBook]"/>
<g:rendertemplate="bookTemplate"var="book"collection="${bookList}"/>
SharedTemplates
Passmorepathtotherendertemplate
<g:rendertemplate="/shared/mySharedTemplate"/>
TheTemplateNamespace
TemplatesinControllersandTagLibraries
Wecanalsorendertemplatesfromcontrollersusingtherendercontrollermethod.ThisisusefulforAjaxapplications.
defbookData(){
defb=Book.get(params.id)
render(template:"bookTemplate",model:[book:b])//firstthebookisthenamein//template,secondbisthevariable.
}
Alternatively,moreclear
defbookData(){
defb=Book.get(params.id)
Stringcontent=g.render(template:"bookTemplate",model:[book:b])
rendercontent
}
7.2.4LayoutswithSitemesh
CreatingLayouts
GrailsleveragesSitemesh,adecoratorengine.Layoutsarelocatedinthegrails-app/views/layoutsdirectory.
<html>
<head>
<title><g:layoutTitledefault="Anexampledecorator"/></title>
<g:layoutHead/>
</head>
<bodyonload="${pageProperty(name:'body.onload')}">
<divclass="menu">…snip…</menu>
<divclass="body">
<g:layoutBody/>
</div>
</div>
</body>
</html>
Thekeyelementsareasfollow:
layoutTitle
layoutHead
layoutBody
TriggeringLayouts
Thereareafewwaystotriggeralayout.Thesimplestistoaddametatagtotheview:
<html>
<head>
<title>AnExamplePage</title>
<metaname="layout"content="main"/>
</head>
<body>Thisismycontent!</body>
</html>
Inthiscasealayoutcalledgrails-app/views/layouts/main.gsp
SpecifyingALayoutInAController
Anotherwaytospecifyalayoutistospecifythenameofthelayoutbyassigningavaluetothe"layout"propertyinacontroller.Forexample,
classBookController{
staticlayout='customer'
deflist(){…}
}
Thenthelayoutgrails-app/views/layouts/customer.gspwhichwillbeappliedtoallviewsthattheBookControllerdelegatesto.
staticlayout='custom/customer'
grails-app/views/layout/custom/customer.gsptemplate
LayoutbyConvention
layoutbyconventionmeansthat
classBookController{
deflist(){…}
}
grails-app/views/layouts/book.gspwillbeappliedtoallviewsthattheBookControllerdelegatesto.
Alternatively,wecancreatealayoutcalledgrails-app/views/layouts/book/list.gspwhichwillonlybeappliedtothelistactionwithintheBookController.
Theapplicationdefaultlayoutis
grails-app/views/layouts/application.gsp
ThisisconfiguredinConfig.groovy
grails.sitemesh.default.layout='myLayoutName'
InlineLayouts
<g:applyLayoutname="myLayout"template="bookTemplate"collection="${books}"/>
Server-SideIncludes
7.2.5StaticResources
7.2.5.1Includingresourcesusingtheresourcetags
Pullinginresourceswithr:require
Touseresources,wecanindicatewhichresourcemodulesitrequires.
<r:requiremodule="jquery"/>
<r:requiremodules="query,main,blueprint,charting"/>
Addingpage-specificJavaScriptcodewithr:script
<r:scriptdispostion="head">
window.alert('Thisisattheendof<head>');
</r:script>
Linkingtoimageswithr:img
<r:imguri="/images/logo.png"/>
7.2.5.2Otherresourcetags
7.2.5.3Declaringresources
7.2.5.6Debugging
7.2.8GSPDebugging
Viewingthegeneratedsourcecode
?showSource=true
7.3.6UsingJSPTagLibraries
<%@taglibprefix="fmt"uri="http://java.sun.com/jsp/jstl/fmt"%>
7.4.4MappingtoResponseCodes
staticmappings={
"403"(controller:"errors",action:"forbidden")
"404"(controller:"errors",action:"notFound")
"500"(controller:"errors",action:"serverError")
}
staticmappings={
"403"(view:"/errors/forbidden")
"404"(view:"/errors/notFound")
"500"(view:"/errors/serverError")
}
7.4.5MappingtoHTTPmethods
staticmappings={
"/product/$id"(controller:"product"){
action=[GET:"show",PUT:"update",DELETE:"delete",POST:"save"]
}
}
7.4.6MappingWildcards
staticmappings={
"/images/*.jpg"(controller:"image")
}
References:
http://grails.org/doc/latest/guide/index.html
http://grails.org/doc/latest/guide/theWebLayer.html#asynchronousRequestProcessing