在 grails 服务中使用 g.render

Posted

技术标签:

【中文标题】在 grails 服务中使用 g.render【英文标题】:Using g.render in a grails service 【发布时间】:2010-12-19 03:46:12 【问题描述】:

我正在尝试,但默认情况下似乎没有将 g 提供给服务。有没有办法让模板引擎在服务中呈现视图?我可能会以错误的方式解决这个问题。我希望将视图从部分模板呈现为字符串,然后将生成的字符串作为 JSON 响应的一部分发回以用于 AJAX 更新。

有什么想法吗?

【问题讨论】:

对于多年后浏览此页面的任何搜索者,不要忘记从服务渲染模板意味着模板不会具有与从渲染时相同的上下文控制器;因此,如果您在 GSP 中使用例如 createLink,则需要指定 controlleraction 【参考方案1】:

我完全同意 John 的论点 - 在服务中执行 GSP 通常是一个糟糕的设计决策。但没有规则没有例外!如果您仍想这样做,请尝试以下方法:

class MyService implements InitializingBean 
    boolean transactional = false
    def gspTagLibraryLookup  // being automatically injected by spring
    def g

    public void afterPropertiesSet() 
        g = gspTagLibraryLookup.lookupNamespaceDispatcher("g")
        assert g
    

    def serviceMethod()     
       // do anything with e.g. g.render
    

使用 gspTagLibraryLookup bean,您当然可以访问服务中所有其他所需的 taglib。

【讨论】:

能力越大,责任越大!做这样的事情时要小心——在做之前确保你知道在服务中渲染 gsp 的原因:) 我的意图是渲染一个模板,然后用 JSON 返回,这样就可以插入生成的 html。我打算将逻辑封装在服务中,但发现在每个控制器中手动返回 JSON 也可以,并且 g.render 已经可用。感谢大家的意见。 还有一个问题……如果服务依赖于控制器,就很难为服务创建单元测试。 我需要它从单个条目服务(一种命令模式)返回一些 HTML。这是非常少数。非常感谢【参考方案2】:

现在在 Grails 2 中使用 PageRenderer 变得更加简单。例如:

class SomeService 
    def groovyPageRenderer

    void someMethod() 
        String html = groovyPageRenderer.render(view: '/email/someTemplateName')
    

API - http://grails.org/doc/latest/api/grails/gsp/PageRenderer.html

更完整的例子 - http://mrhaki.blogspot.com/2012/03/grails-goodness-render-gsp-views-and.html

【讨论】:

差点错过你的答案,谢谢你的补充。现在使用新 Grails 看起来很流畅 简单易行。但是Stefan's answer 为任何标签提供解决方案。谢谢;)【参考方案3】:

我的建议是在控制器中执行此操作。服务应该具有可重用的逻辑并且不依赖于视图模板,将这项工作留给控制器。使用服务获取您需要传递给模板的数据,但将与模板交互的工作留给控制器。

【讨论】:

抱歉,即使您的回答是一个很好的建议,它也不是一个可以接受的答案:即使不推荐,也有一些方法可以实现所询问的内容。【参考方案4】:

这里有一个类似于Stefan's的解决方案,但更简单一些

import org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib
import org.springframework.context.ApplicationContext
import org.springframework.context.ApplicationContextAware

class MyService implements ApplicationContextAware 

    private ApplicationTagLib g

    void setApplicationContext(ApplicationContext applicationContext) 
        g = applicationContext.getBean(ApplicationTagLib)

        // now you have a reference to g that you can call render() on
    

【讨论】:

以上是关于在 grails 服务中使用 g.render的主要内容,如果未能解决你的问题,请参考以下文章

<g:applyLayout /> 和 <g:render template /> 有啥区别

在域类中使用 grails 服务

在 Grails 单元测试中注入服务

使用石英的 grails 服务

生产环境中的 Grails 服务返回 Null

Grails 2.4.3:使用 REST 服务