Ao aprender Grails um dos componentes que mais me confundiu foi o SiteMesh. Intuitivamente eu sabia o que estava acontecendo, mas toda vez que buscava escrever a respeito acabava me enrolando.
E acredite: você só conhece de fato algo se consegue descrevê-lo em palavras, por escrito. Trabalhando na última parte da minha série “Grails: do Groovy à Web” que está sendo publicada na Java Magazine tive a certeza de finalmente compreender de fato o que é o SiteMesh e como funciona. E a razão pela qual tinha tanta dificuldade é simples: estava viciado no Tiles.
Enquanto o Tiles é baseado no padrão composição (composite), o SiteMesh é baseado no padrão decorador (decorator). A diferença entre os dois é: no composite temos um layout central que contém uma série de espaços a serem preenchidos por templates.
Já o padrão decorator possui um layout central que também possui espaços a serem preenchidos: a diferença é que apenas os elementos ausentes serão preenchidos. Eu não preciso adicionar todos os componentes tal como estava acostumado na época do Struts 1/Tiles.
Bla bla bla demais, é hora de irmos à prática. No Grails, todos os layouts do SiteMesh ficam armazenados no diretório grails-app/views/layouts. Por padrão já há um layout pré-definido, cujo nome é main.gsp armazenado neste diretório. É importante lembrar que se trata de um arquivo GSP convencional, cujo código exponho abaixo:
<html>
<head>
<title><strong><g:layoutTitle default="Grails" /></strong></title>
<link rel="stylesheet" href="${resource(dir:’css’,file:’main.css’)}" />
<link rel="shortcut icon" href="${resource(dir:’images’,file:’favicon.ico’)}" type="image/x-icon" />
<strong><g:layoutHead /></strong>
<g:javascript library="application" />
</head>
<body>
<div id="spinner" style="display:none;">
<img src="${resource(dir:’images’,file:’spinner.gif’)}" alt="Spinner" />
</div>
<div id="grailsLogo"><a href="http://grails.org"><img src="${resource(dir:’images’,file:’grails_logo.png’)}" alt="Grails" border="0" /></a></div>
<strong><g:layoutBody /></strong>
</body>
</html>
A única diferença entre o arquvo GSP e uma view convencional é a presença de três tags: g:layoutTitle, g:layoutHead, g:layoutBody. Falarei delas logo a seguir, porém antes de continuar, vou expor a view mais idiota possível: algo que não exponha basicamente nada, e cujo código fonte é o seguinte:
<html> <head> <meta name="layout" content="main"/> </head> <body> </body> </html>
Colocando a aplicação para executar, e acessando-a, no entanto, é renderizado algo inicialmente inexperado:
De onde saiu este logotipo do Grails? Do layout main que defini anteriormente. No caso, eu instrui o Grails a usar o SiteMesh ao inserir a seguinte tag na minha view:
<meta name="layout" content="main"/>
Esta tag basicamente diz: “aplique o layout definido no arquivo grails-app/views/layouts/main.gsp a esta view”. E aqui entra a jusitificativa do mesh no nome SiteMesh: ao invés de incluir o conteúdo de um arquivo em outro, o que é feito na realidade é a fusão do conteúdo da view no corpo do layout!
Isto fica claro com a descrição das 3 tags que descrevi acima (consulte a primeira listagem para que fique claro):
g:layoutTitle – define qual será o conteúdo da tag title embutido na tag head. Repare qeu esta tag possui um atributo chamado “default”. Caso na view a tag title já esteja preenchida, será incluido no arquivo HTML final o conteúdo da tag title da view. Caso contrário, o conteúdo será aquele especificado no parâmetro default
g:layoutHead – o conteúdo da tag <head> da view será inserido no local do layout aonde a tag g:layoutHead se encontra.
g:layoutBody – o conteúdo da tag <body> da view será inserido no local do layout aonde a tag se encontra.
Resumindo: no SiteMesh não temos inclusão, mas sim fusão.
Espero que com esta descrição o recurso fique tão claro para vocês quanto pra mim.
Grande abraço e até a próxima!
Aeee entendeu o SiteMesh! Ele é muito bom! =)
Valew show de bola… é o mesmo conceito de facelets
OI Gustavo. Fico feliz que tenha gostado. Mas convém mencionar que não é exatamente a mesma coisa.
No Facelets você tem basicamente substituição de valores. No Sitemesh você tem fusão. Lembre-se disto.
Olá Kico, estou tentando aplicar um css no main.gsp, mas não estou conseguindo.
Sou iniciante em grails também. Estou qrendo customizar minha aplicação.
Oi Amanda, faz o seguinte. Posta o seu problema com detalhes no Grails Brasil (porque tem mais espaço e gente pra ver o seu problema) e eu te ajudo ok?
Grande abraço!
Nós passamos por um problema causado pelo Sitemesh: o filter dele remove a funcionalidade de flush de uma respons text/html.
Explicando melhor: vamos supor que você queira fazer renderização parcial de páginas (como por exemplo faz o Facebook com a implementação de BigPipe) a medida que elas vão sendo processadas. É natural imaginar que o response.writer.flush faria o flush da resposta escrita até o momento. No entanto, o Sitemesh substitui o Writer da response por um que não realiza o flush até o fim do processamento (para poder fazer a fusão dos layouts)
Em resumo: caso você tenha alguma página que precisa fazer flush parcial, você vai querer configurar o sitemesh para excluí-la.
Solução: http://jira.grails.org/browse/GRAILS-5770
Um link melhor descrevendo a solução do problema:
http://jira.grails.org/browse/GRAILS-5773
Pingback: Grails Architecture | Zen Development
Olá Kico,
Não entendi a diferença entre composição e decoração. Poderia explicar melhor esta frase? “a diferença é que apenas os elementos ausentes serão preenchidos”
Obrigado!
André
E se no meu body, eu tiver vários blocos para inserção de código?
No meu caso, meu body tem side bar com um menu e o content.
Como faço nesse caso? Já que no meu layout, só coloco um
Poderia ter algo como
e na outra parte do meu body, eu colocasse
E na minha pagina gsp, eu pudesse informar qual parte vai para o sidebar e qual vai para o content.
Existe alguma uma maneira de fazer isso?
Abs
oi Leonardo, tem como postar esta sua duvida no Grails Brasil? é que costumo resolver este tipo dd duvida por la. assim ajudamos ao mesmo tempo pessoas que possuam a nesna duvida.
Nao sei porque, mas quando exemplifico com codigo html nao aparece nada no post
Motor recente do blog. To melhorando isto aos poucos, valeu pelo toque.