通过实现 Spring 的 ThemeSource 类,使用 hibernate 实现 Spring 主题

发布于 2024-12-06 17:56:46 字数 322 浏览 1 评论 0原文

有谁知道如何在 spring 中使用自定义 ThemeSource ?我见过很多关于如何使用 ResourceBundleThemeSource 将主题与属性文件一起使用的示例。然而,我还没有看到如何使用 hibernate 存储各种属性(例如单个 css 属性),使用自定义 ThemeSource 读取属性,并且仍然能够在 jsp 中使用 spring 主题标签。

我知道我可以创建一个控制器并使用 hibernate 从数据库中获取这些属性,但我更感兴趣的是如何使用 Spring 的 ThemeSource 实现来做到这一点。

如果有人有任何想法或例子,我将不胜感激。

谢谢

Does anyone know how to use a custom ThemeSource in spring? I have seen many examples on how to use themes with property files using ResourceBundleThemeSource. Yet I have seen nothing on how to use hibernate to store vairous properties (such as a single css property) , read the properties with a custom ThemeSource and still be able to use the spring theme tags in the jsp.

I know I can create a controller and fetch these properties from the database with hibernate but I am more interested on knowing how to do this with Spring's ThemeSource implementation.

If anyone has any ideas or examples I'd appreciate it.

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

各空 2024-12-13 17:56:47

要在 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 的主题 类型 => SimpleTheme< /a>

请注意,ThemeSource 期望 Spring 的 MessageSource,这意味着在您的情况下,存储在数据库中的主题属性需要“转换”才能与 MessageSource 接口一起使用。

您可以编写自己的DatabaseDrivenMessageSource,也可以从获取它现在

,所有这些变量都就位后,这里是一个自定义的DatabaseThemeSource(它将成为一个themeSource bean):

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
}

To use themes in your web application, you must set up an implementation of the org.springframework.ui.context.ThemeSource interface. To use a custom ThemeSource implementation you can register a bean in the application context with the reserved name themeSource. The web application context automatically detects a bean with that name and uses it.

Here is the ThemeSource interface:

package org.springframework.ui.context;

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

The only dark horse here is a Theme type, which in fact is nothing more than:

package org.springframework.ui.context;

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

And in fact there is already a convenience implementation of Theme type from Spring => SimpleTheme

Notice that ThemeSource expects a Spring's MessageSource, which means that theme attributes that are stored in a database, in your case, would need to be "converted" to be used with a MessageSource interface.

You can either write your own DatabaseDrivenMessageSource, or just take it from here

Now, having all these variables in place, here is a custom DatabaseThemeSource ( that will become a themeSource bean ):

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
}
臻嫒无言 2024-12-13 17:56:47

tolitius 给出的答案可以很好地工作,但对于现实世界的使用,我认为您需要结合某种缓存。

对您网站的每个请求都需要您的主题,但是您是否希望每个请求都访问您的数据库只是为了查找一些颜色?主题通常不是很大并且不会经常改变。因此,它们非常适合加载到内存中并将其保留在那里。这就是我们对运行的网站所做的事情,我们在内存中保留了大约 50 个主题,这些主题在启动时从 Hibernate 加载。它使得服务主题请求变得非常快。

当然,核心类是您的 DatabaseThemeSource bean,它实现 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 会话和 LazyLoadingExceptions 等问题。它也更高效,因为您可以构造只需一次必要的 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 查找快速访问主题的元素。我们已经使用它有一段时间了,它对我们来说非常有效。

The answer that tolitius gives would work fine, but for real-world use I think that you need to incorporate some kind of caching.

Every request to your website is going to need your theme, but do you want every request to hit your database just to look up some colours? Themes usually aren't very large and don't change very often. So they're a good candidate for loading into memory and keeping them there. This is what we do with a site that we run, we keep about 50 themes in memory which are loaded from Hibernate on startup. It makes serving theme requests very quick.

The core class is, of course, your DatabaseThemeSource bean, which implements ThemeSource. If you have a cache library available such as Ehcache you could use that, but most people have fairly few themes and so a simple Map will do for that cache. We use something like this:

@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();
        }
    }
}

Then you'll need to implement a MessageSource that holds all the individual components of your theme. It's worth copying the individual elements of your theme from your Hibernate object into a dedicated MessageSource so that you don't have any problems with closed Hibernate sessions and LazyLoadingExceptions etc. It's also more efficient, because you can construct the necessary MessageFormat objects just once instead of having to do so on each request:

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);
    }

}

The end result is that it's quick. All your themes are kept in memory, and the elements of the themes are accessed rapidly though a simple Map lookup. We've been using this for a while and it works very well for us.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文