2012-10-07 28 views
1

我使用谷歌應用程序引擎,彈簧和瓦片的配置,其中每個控制器的動作導致一些嵌套(瓦片)jsp的渲染集合。一些JSP的元素將被計算/(幾乎)每個控制器設置,例如頁面上的登錄/註銷某個鏈接:我該如何讓Spring爲所有控制器/動作設置某些變量

<% 
com.google.appengine.api.users.UserService userService = 
    com.google.appengine.api.users.UserServiceFactory.getUserService(); 
com.google.appengine.api.users.User user = userService.getCurrentUser(); 
if (user != null) {%> 
    <li class="active"><a href="#feeds">Feeds</a></li> 
    <li class="active"><a href="<%=userService.createLogoutURL("")%>">Logout</a></li> 
<%} else {%> 
    <li class="active"><a href="<%=userService.createLoginURL("")%>">Login</a></li> 
<%}%> 

當然,這是可能的,我也可以做可以簡化這種代碼的靜態類。然而,這不是我喜歡在我的jsp中所擁有的,而且它在模板引擎(像thymeleaf)中可能(可能)不可能執行那樣的代碼。因此,我怎麼做這樣的事情:

@RequestMapping("/foo") 
public class FooController { 
    @RequestMapping(value="/{bar}", method = RequestMethod.GET) 
    public String getMovie(@PathVariable String bar, ModelMap model) { 
     model.addAttribute("bar", bar); 
     model.addAttribute("message", "message"); 
     UserService userService = UserServiceFactory.getUserService(); 
        User user = userService.getCurrentUser(); 
     model.addAttribute("isLoggedIn", user==null); 

     return "somepage"; 

    } 
} 

所以總結:如何防止該isLoggedIn代碼到處複製,最好不是需要調用一些「initUserModel(模型)」方法不同的解決方案。

回答

4

瓷磚知道ViewPreparer的概念。 ViewPreparer在呈現定義之前執行,並且是設置Tiles視圖通用屬性的好地方。這些屬性可以是請求屬性(如下所示)或瓷磚屬性,如上述ViewPreparer tutorial page上的示例所示。

一個ViewPreparer是作爲一個「正常的」春天服務:

@Component 
public class YourViewPreparer implements ViewPreparer { 
    @Autowired 
    private UserService userService; 

    @Override 
    public void execute(TilesRequestContext tilesContext, AttributeContext attributeContext) { 
     // Some magic here to get the HttpRequest... 
     Object[] requestObjects = tilesContext.getRequestObjects(); 
     if (requestObjects.length == 2) { 
      HttpServletRequest request = (HttpServletRequest) requestObjects[0]; 
      User user = userService.getCurrentUser(); 
      request.setAttribute("isLoggedIn", user != null); 
     } 
    } 
} 

然後配置通過設置preparerFactoryClass財產您的TilesConfigurer拿起任何ViewPreparer豆這樣的:

<bean class="org.springframework.web.servlet.view.tiles2.TilesConfigurer" id="tilesConfigurer"> 
    <property name="definitions"> 
     ... 
    </property> 
    <property name="preparerFactoryClass" value="org.springframework.web.servlet.view.tiles2.SimpleSpringPreparerFactory" /> 
</bean> 

,並確定您的視圖聲明中的編寫者。您可以從基本視圖擴展所有視圖,以便只能執行一次編制者聲明。

<definition name="main" preparer="com.example.YourViewPreparer"> 
    ... 
</definition> 

<definition name="myView" extends="main"> 
    ... 
</definition> 

或者,如果您具有除Tiles視圖之外的其他視圖,則還可以實現您自己的HandlerInterceptor

+0

爲什麼你檢查「(requestObjects.length == 2)」? – Herbert

+0

好問題。也許有一些不那麼模糊的方式來確定調用getRequestObjects()返回的對象數組是什麼類型的... TilesRequestContext有兩個實現:ServletTilesRequestContext和JspTilesRequestContext(其中第一個是我們之後的那個)。在查看實現時,ServletTilesRequestContext返回一個帶有兩個元素的Object [],其中JspTilesRequestContext僅返回一個Object [],只有一個元素。 也許它會更清楚地測試返回數組的第0個元素,如'if(requestObjects [0] instanceof HttpServletRequest){}' – James

+0

感謝您的回答。當使用'org.springframework.web.servlet.view.tiles2.SimpleSpringPreparerFactory'時,你不需要(也不應該)用'@ Component'來註釋'YourViewPreparer'。這樣做會導致應用上下文中的'YourViewPreparer'實例永遠不會被使用,因爲'SimpleSpringPreparerFactory'按需創建它自己。 或者,使用'org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory',它可以根據名稱從應用上下文中查找preparer實例。 – sbk

相關問題