如何在sitemesh装饰器中获取模型属性或spring的bean?

Posted

技术标签:

【中文标题】如何在sitemesh装饰器中获取模型属性或spring的bean?【英文标题】:How to obtain model attribute or spring's bean in sitemesh decorator? 【发布时间】:2011-04-26 13:10:58 【问题描述】:

我正在使用带有站点网格的 Spring 3。我想在 sitemesh 中定义的装饰器页面中引用 spring 上下文 bean。

问题是 SiteMesh 过滤器在 Spring 上下文之外工作,因此 sitemesh 装饰器 jsp 页面上的请求对象是本机 HttpServletRequest,而不是具有访问上下文等有用函数的包装器。

有没有办法以某种方式配置 spring 和 sitemesh 以访问装饰器页面中的 Spring 上下文?

【问题讨论】:

如果您包含一些配置,特别是查看解析器,也许有人可以更轻松地帮助您。如果您禁用 Sitemesh 过滤器,您暴露的 bean 是否可以访问?我从未使用过 Sitemesh,但我在使用 Tiles 时遇到了类似的问题:***.com/questions/2848415/… 他应该不需要包含任何内容 - 问题不在于配置,这是因为 SiteMesh 将页面装饰在 Spring Context 之外 【参考方案1】:

我通过重新实现 sitemesh 过滤器解决了这个问题:

@Component
class SitemeshSpringFilter extends PageFilter implements ApplicationContextAware 
    ApplicationContext applicationContext;

    @Override
    public void doFilter(ServletRequest rq, ServletResponse rs,
            FilterChain chain) throws IOException, ServletException 
        def newRq = new ContextExposingHttpServletRequest(
                rq, getApplicationContext(), null);

        super.doFilter(newRq, rs, chain);
    

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
    throws BeansException 
        this.applicationContext = applicationContext;
    

在 web.xml 中,声明这个过滤器:

<filter>
    <filter-name>sitemeshSpringFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>sitemeshSpringFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

现在,sitemesh 过滤器将使用 ContextExposingHttpServletRequest 代替普通请求。

【讨论】:

【参考方案2】:

我遇到了同样的问题,并通过使用过滤器解决了我的问题。我创建了一个环境过滤器,可用于为所有请求设置环境数据。在过滤器中自动装配您需要访问的 bean。

@Component
public class EnvironmentFilter extends OncePerRequestFilter 

    @Autowired
    Object bean;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException 

        request.setAttribute("bean", bean); // add bean or just specific properties of bean.

        filterChain.doFilter(request, response);

    


在 web.xml 中配置过滤器,确保过滤器映射使用与 Sitemesh 过滤器相同的模式。

<filter>
    <filter-name>environmentFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>environmentFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

您的过滤器设置的属性现在可以从您的装饰器页面获得。

【讨论】:

【参考方案3】:

我不知道有什么方法可以满足您的要求,但还有另一种选择。您可以在控制器方法参数中声明 HttpServletRequest。如果 Sitemesh 需要使用模型对象,只需将它们放在请求中即可。无论支持上下文是 servlet 请求还是 Spring MVC 模型,JSP 代码看起来都完全相同。

【讨论】:

【参考方案4】:

首先为你喜欢的任何东西创建一个单例,我只是设置一个字符串,但任何类都可以工作:

public class MySiteEnvironment 

    private String someConfigurationParameter;

    public String getSomeConfigurationParameter() 
        return someConfigurationParameter;
    

    public void setSomeConfigurationParameter(String someConfigurationParameter) 
        this.someConfigurationParameter = someConfigurationParameter;
    

    /* SINGLETON */
    private static final MySiteEnvironment INSTANCE = new MySiteEnvironment();

    private MySiteEnvironment() 
    

    public static MySiteEnvironment getInstance() 
        return INSTANCE;
    

接下来需要注入值:

<bean id="mySiteEnvironment" class="MySiteEnvironment" factory-method="getInstance">
        <property name="someConfigurationParameter" value="myValueOrBean"/>
    </bean>

最后你通过以下方式访问它:

<%@ page import="MySiteEnvironment" %>
<% pageContext.setAttribute("env", MySiteEnvironment.getInstance()); %> 

现在可以使用表达式语言来访问环境了

【讨论】:

以上是关于如何在sitemesh装饰器中获取模型属性或spring的bean?的主要内容,如果未能解决你的问题,请参考以下文章

Servlet 页面装饰:人们使用 Tiles、Sitemesh 还是其他东西?

是否可以使用 Sitemesh 在 JSP 中直接定义装饰器?

如何在 Python 的方法装饰器中使用类属性?

如何在 Python 中访问装饰器中的类属性?

使用 sitemesh/decorator装饰器装饰jsp页面(原理及详细配置)

SiteMesh2-示例工程