2011-09-26 118 views
2

有誰知道如何在春季使用自定義ThemeSource?我已經看到很多關於如何使用ResourceBundleThemeSource來使用屬性文件主題的例子。然而,我沒有看到如何使用hibernate來存儲有價值的屬性(比如單個css屬性),使用自定義ThemeSource讀取屬性,並且仍然能夠使用jsp中的spring主題標籤。春天主題通過實現Spring的ThemeSource類休眠

我知道我可以創建一個控制器和從休眠數據庫中獲取這些屬性,但我就知道如何使用Spring的實現ThemeSource接口做到這一點更感興趣。

如果任何人有任何意見或例子我將不勝感激。

感謝

回答

2

若要在Web應用程序中使用的主題,您必須設置org.springframework.ui.context.ThemeSource接口的實現。要使用自定義的ThemeSource實現,您可以在應用程序上下文中使用保留名稱themeSource註冊一個bean。 Web應用程序上下文自動檢測具有該名稱的bean並使用它。

這裏是ThemeSource接口:

package org.springframework.ui.context; 

public interface ThemeSource { 
    Theme getTheme(String themeName); 
} 

這裏唯一的黑馬是一個Theme類型,這實際上無非是:

package org.springframework.ui.context; 

public interface Theme { 
    String getName(); 
    MessageSource getMessageSource(); 
} 

而事實上已經有一個便利來自Spring的Theme類型的執行=>SimpleTheme

注意ThemeSource 預計一個春天的MessageSource,這意味着存儲在數據庫中,你的情況是主題屬性,將需要「轉換」與一個MessageSource接口一起使用。

您可以編寫自己的DatabaseDrivenMessageSource,或者只是把它從here

現在,已具備了所有這些變量,這裏是一個自定義DatabaseThemeSource(這將成爲一個themeSource豆):

public class DatabaseThemeSource implements ThemeSource { 

    private YourThemeDao themeDao; 

    public Theme getTheme(String themeName) { 

     if (themeName == null) { return null; } 

     MessageSource messageSource = new DatabaseDrivenMessageSource(themeDao); 

     theme = new SimpleTheme(themeName, messageSource); 

     return theme; 
    } 

    // init your themeDao 
} 
1

tolitius給出的答案可以正常工作,但對於真實世界的使用,我認爲您需要合併某種緩存。

到您的網站的每個要求都將需要你的主題,但你希望每一個請求,打你的數據庫只是爲了看一些顏色嗎?主題通常不是很大,不經常更改。所以它們是加載到內存並保存在內存中的理想選擇。這是我們使用我們運行的網站所做的,我們在啓動時從Hibernate加載的內存中保留了大約50個主題。它使服務主題的請求非常快。

的核心類,當然,你DatabaseThemeSource豆,它實現ThemeSource。如果你有一個可用的緩存庫,比如Ehcache,你可以使用它,但是大多數人只有很少的主題,所以簡單的Map就可以用於這個緩存。我們用這樣的:

@Component("themeSource") 
public class DatabaseThemeSource implements ThemeSource { 

    @Autowired 
    ThemeDAO themeDAO; 

    private final Map<String, Theme> themeCache; 


    public DatabaseThemeSource() { 
     themeCache = new HashMap<String, Theme>(); 
    } 

    /** 
    * @see org.springframework.ui.context.ThemeSource#getTheme(java.lang.String)  
    */ 
    @Override 
    public Theme getTheme(String themeName) { 
     if (themeName == null) { 
      return null; 
     } 
     Theme theme = themeCache.get(themeName); 
     if (theme == null) { 
      Theme theme = themeDAO.getTheme(themeName); 
      if (theme != null) { 
       MessageSource messageSource = new ThemeMessageSource(theme); 
       theme = new SimpleTheme(themeName, messageSource); 
       synchronized (this.themeCache) { 
        themeCache.put(themeName, theme); 
       } 
      } 
     } 
     return theme; 
    } 

    /** 
    * Clears the cache of themes. This should be called whenever the theme is updated in the database. 
    */ 
    public void clearCache() { 
     synchronized (this.themeCache) { 
      themeCache.clear(); 
     } 
    } 
} 

然後,你需要實現一個MessageSource保存你的主題的所有的各個組件。值得將你的主題的各個元素從你的Hibernate對象複製到專用的MessageSource中,這樣你就可以在關閉Hibernate會話和LazyLoadingException等方面沒有任何問題。它也更有效率,因爲你可以構造必要的MessageFormat對象每個請求必須這樣做:

public class ThemeMessageSource extends AbstractMessageSource { 

    private final Map<String, MessageFormat> messages; 

    public ThemeMessageSource(Theme theme) { 
     messages = new HashMap<String, MessageFormat>(); 
     messages.put("heading1", createMessageFormat(theme.getHeading1(), null)); 
     messages.put("heading2", createMessageFormat(theme.getHeading2(), null)); 
     messages.put("colour1", createMessageFormat(theme.getColour1(), null)); 
     messages.put("colour2", createMessageFormat(theme.getColour2(), null)); 
    } 

    public ThemeMessageSource(Map<String, MessageFormat> messages) { 
     this.messages = messages; 
    } 

    @Override 
    protected MessageFormat resolveCode(String code, Locale locale) { 
     return messages.get(code); 
    } 

} 

最終結果是它很快。所有主題都保存在內存中,通過簡單的Map查找可以快速訪問主題元素。我們已經使用了一段時間,它對我們來說效果很好。

+0

我接受了其他答案後,您一定有回答。這很有意義。我們走了一條不同的方向,讓最終用戶創建自己的主題。保存時會創建一個css文件,並將其存儲在每個請求當前訪問的db中。我還沒有實施緩存解決方案,但計劃這樣做。我很感謝你的迴應,但我現在所能做的只是滿足你的答案。 – blong824