2010-06-15 103 views
0

基本上,我希望能夠將過濾器內創建的對象分配給每個控制器從中擴展的基礎控制器中的成員。任何可能的方式來做到這一點?如何訪問Grails中基礎控制器的構造函數中的控制器動態屬性?

下面是我的嘗試,但沒有得到它的工作。

我想要實現的是讓我所有的控制器擴展一個基礎控制器。基礎控制器的構造函數將用於爲其成員分配值,這些值將從會話映射中拉出。下面的例子。

文件的grails-app /控制器/ HomeController.groovy:

class HomeController extends BaseController { 
    def index = { 
     render username 
    } 
} 

文件的grails-app /控制器/ BaseController.groovy:

abstract class BaseController { 
    public String username 

    public BaseController() { 
     username = session.username 
    } 
} 

當運行該應用程序,所示的輸出是:

2010-06-15 18:17:16,671 [main] ERROR [localhost].[/webapp] - Exception sending context initialized event to listener instance of class org.codehaus.groovy.grails.web.context.GrailsContextLoaderListener 
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.RuntimeException: Unable to locate constructor with Class parameter for class org.codehaus.groovy.grails.commons.DefaultGrailsControllerClass 
    ... 
Caused by: java.lang.RuntimeException: Unable to locate constructor with Class parameter for class org.codehaus.groovy.grails.commons.DefaultGrailsControllerClass 
    ... 
Caused by: java.lang.reflect.InvocationTargetException 
    ... 
Caused by: org.codehaus.groovy.grails.exceptions.NewInstanceCreationException: Could not create a new instance of class [com.my.package.controller.HomeController]! 
    ... 
Caused by: groovy.lang.MissingPropertyException: No such property: session for class: com.my.package.controller.HomeController 
    at com.my.package.controller.BaseController.<init>(BaseController.groovy:16) 
    at com.my.package.controller.HomeController.<init>(HomeController.groovy) 
    ... 
2010-06-15 18:17:16,687 [main] ERROR core.StandardContext - Error listenerStart 
2010-06-15 18:17:16,687 [main] ERROR core.StandardContext - Context [/webapp] startup failed due to previous errors 

而且該應用程序無法運行。

這只是一個例子,因爲在我的情況下,我不想將一個用戶名分配給一個字符串值,而是從會話地圖中拉出一些對象。正在過濾器中設置從會話中拉出的對象。

我看到的替代方案是能夠在過濾器執行過程中訪問控制器的實例。那可能嗎?

請幫忙!謝謝一堆!

回答

4

您通常無法在Grails構件的構造函數中做太多工作。您可以使用攔截這個雖然:

abstract class BaseController { 
    protected String username 

    def beforeInterceptor = { 
     username = session.username 
    } 
} 

這在6.1.5節中描述的http://grails.org/doc/latest/

+0

感謝您的回答!問題是當一個具體的控制器(HomeController)定義了一個beforeInterceptor本身時,BaseController的beforeInterceptor將不會被調用。試圖通過具體控制器編譯使用'super.beforeInterceptor()'來調用它,但在運行時拋出: org.codehaus.groovy.runtime.InvokerInvocationException:java.lang.StackOverflowError \t at java.lang.Thread.run (Thread.java:619) 產生的原因:在com.my.package.controller.HomeController $ _closure1.doCall(HomeController.groovy) \t ... 任何方式來解決這個問題java.lang.StackOverflowError的 \t?謝謝! – djule5 2010-06-16 12:00:24

+2

由於它是一個Closure,super.beforeInterceptor()不能工作。但你可以讓攔截器委託給一個可以被覆蓋的真實方法: def beforeInterceptor = {prepareCall()} protected void prepareCall(){username = session.username} – 2010-06-16 16:04:36

0

您可以使用請求範圍的服務......

0

作爲一個規則,我d注意不要將狀態直接放入控制器;一般來說控制器(不管框架)通常都是無狀態的。我會堅持使用像請求和會話這樣的標準webapp狀態結構來存儲和傳輸數據。

針對您的特殊情況下,我會做下列之一:

  • 如果輕量級的數據(元),我想將它們存儲在會話,只是訪問它們需要:
    例如渲染session.username

  • 如果是動態或數據庫驅動的數據,我會創建一個服務並根據需要提取數據: homeService.getUser()。用戶名

  • 作爲與上面討論的Burt的變體,您可以使用過濾器填充請求或會話值。