java 从 Tiles 视图 (JSP) 访问 Spring bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2848415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 23:08:03  来源:igfitidea点击:

Accessing Spring beans from a Tiles view (JSP)

javaspringjspspring-mvctiles

提问by sinuhepop

In Spring MVC I can access my beans in JSP using JstlView's exposedContextBeanNames (or exposeContextBeansAsAttributes). For example, then, in my JSP I can write (${properties.myProperty). But when the same JSP is a part of a tiles view, these properties aren't accessible. Is possible to configure Tiles properly or access these properties in another way?

在 Spring MVC 中,我可以在 JSP 中使用 JstlView 的暴露的ContextBeanNames(或exposeContextBeansAsAttributes)访问我的bean。例如,然后,在我的 JSP 中,我可以编写 (${properties.myProperty)。但是,当同一个 JSP 是磁贴视图的一部分时,这些属性是不可访问的。是否可以正确配置 Tiles 或以其他方式访问这些属性?

I'm using Spring MVC 3.0.2 and Tiles 2.2.1. Here's a bit of my configuration:

我使用的是 Spring MVC 3.0.2 和 Tiles 2.2.1。这是我的一些配置:

<bean id="tilesViewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
    <property name="order" value="1"/>
    <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />
</bean> 

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
    <property name="order" value="2"/>
    <property name="prefix" value="/WEB-INF/views/"/>
    <property name="suffix" value=".jsp"/>
    <property name="exposedContextBeanNames">
        <list><value>properties</value></list>
    </property>
</bean>

EDIT:I've implemented Skaffman's solution.

编辑:我已经实施了 Skaffman 的解决方案。

TilesExposingBeansViewResolver.java:

TilesExposingBeansViewResolver.java:

package es.kcsolutions.util.spring.servlet.view;

import org.springframework.web.servlet.view.*;

public class TilesExposingBeansViewResolver extends UrlBasedViewResolver {

    private Boolean exposeContextBeansAsAttributes;
    private String[] exposedContextBeanNames;

    public void setExposeContextBeansAsAttributes(boolean exposeContextBeansAsAttributes) {
        this.exposeContextBeansAsAttributes = exposeContextBeansAsAttributes;
    }

    public void setExposedContextBeanNames(String[] exposedContextBeanNames) {
        this.exposedContextBeanNames = exposedContextBeanNames;
    }

    @Override
    protected AbstractUrlBasedView buildView(String viewName) throws Exception {
        AbstractUrlBasedView superView = super.buildView(viewName);
        if (superView instanceof TilesExposingBeansView) {
            TilesExposingBeansView view = (TilesExposingBeansView) superView;
            if (this.exposeContextBeansAsAttributes != null) view.setExposeContextBeansAsAttributes(this.exposeContextBeansAsAttributes);
            if (this.exposedContextBeanNames != null) view.setExposedContextBeanNames(this.exposedContextBeanNames);
        }
        return superView;
    }

}

TilesExposingBeansView.java:

TilesExposingBeansView.java:

package es.kcsolutions.util.spring.servlet.view;

import java.util.*;
import javax.servlet.http.*;
import org.springframework.web.context.support.ContextExposingHttpServletRequest;
import org.springframework.web.servlet.view.tiles2.TilesView;

public class TilesExposingBeansView extends TilesView {

    private boolean exposeContextBeansAsAttributes = false;
    private Set<String> exposedContextBeanNames;

    public void setExposeContextBeansAsAttributes(boolean exposeContextBeansAsAttributes) {
        this.exposeContextBeansAsAttributes = exposeContextBeansAsAttributes;
    }

    public void setExposedContextBeanNames(String[] exposedContextBeanNames) {
        this.exposedContextBeanNames = new HashSet<String>(Arrays.asList(exposedContextBeanNames));
    } 

    protected HttpServletRequest getRequestToExpose(HttpServletRequest originalRequest) {
        if (this.exposeContextBeansAsAttributes || this.exposedContextBeanNames != null) 
        return new ContextExposingHttpServletRequest(originalRequest, getWebApplicationContext(), this.exposedContextBeanNames);
        return originalRequest;
    }

    @Override
    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest requestToExpose = getRequestToExpose(request);
        exposeModelAsRequestAttributes(model, requestToExpose);
        super.renderMergedOutputModel(model, requestToExpose, response);
    }

}

Spring configuration:

弹簧配置:

    <bean id="tilesViewResolver" class="es.kcsolutions.util.spring.servlet.view.TilesExposingBeansViewResolver">
        <property name="order" value="1"/>
        <property name="viewClass" value="es.kcsolutions.util.spring.servlet.view.TilesExposingBeansView"/>
        <property name="exposedContextBeanNames">
            <list><value>properties</value></list>
        </property>
    </bean> 

If you have some problem, take a look at TilesExposingBeansView.renderMergedOutputModel. I've made some tests, but maybe it's necessary to make a lot more.

如果您有问题,请查看 TilesExposingBeansView.renderMergedOutputModel。我已经做了一些测试,但也许有必要做更多的测试。

采纳答案by skaffman

As you've noticed, this functionality is part of InternalResourceViewResolverand InternalResourceView, whereas the Tiles stuff inherits directly from UrlBasedViewResolverand AbstractUrlBasedView, so you can't make use of it.

正如您所注意到的,此功能是InternalResourceViewResolverand 的一部分InternalResourceView,而 Tiles 内容直接从UrlBasedViewResolverand继承AbstractUrlBasedView,因此您无法使用它。

Looking at the code, there's no reason why this stuff couldn't have been put into AbstractUrlBasedView. The magic happens in InternalResourceView.getRequestToExpose, and it looks perfectly applicable to AbstractUrlBasedViewtoo.

查看代码,没有理由不能将这些东西放入AbstractUrlBasedView. 魔法发生在InternalResourceView.getRequestToExpose,它看起来也完全适用于AbstractUrlBasedView

In the short term, I suggest subclassing UrlBasedViewResolverand TilesView, copying the getRequestToExposestuff from InternalResourceView. In the longer term, I encourage you to file a issue with SpringSourceasking them to move this functionality up the class hierarchy into AbstractUrlBasedView, making it more widely available.

在短期内,我建议子类化UrlBasedViewResolverTilesViewgetRequestToExposeInternalResourceView. 从长远来看,我鼓励您向SpringSource提出问题,要求他们将此功能向上移动到类层次结构中AbstractUrlBasedView,使其更广泛地可用。

回答by Francesco Carlucci

Have you tried to use ServletContextAttributeExporterin xml configuration file?

您是否尝试过在 xml 配置文件中使用ServletContextAttributeExporter

<bean
    class="org.springframework.web.context.support.ServletContextAttributeExporter">
    <property name="attributes">
        <map>
            <entry key="<bean key here>">
                <ref bean="<bean name here" />
            </entry>
        </map>
    </property>
</bean>

回答by Brian

As of Spring 3.0 there is now a TilesViewResolver.

从 Spring 3.0 开始,现在有一个TilesViewResolver

Convenience subclass of UrlBasedViewResolver that supports TilesView (i.e. Tiles definitions) and custom subclasses of it.

The view class for all views generated by this resolver can be specified via the "viewClass" property. See UrlBasedViewResolver's javadoc for details.

Note: When chaining ViewResolvers, a TilesViewResolver will check for the existence of the specified template resources and only return a non-null View object if the template was actually found.

Since: 3.0 Author: Juergen Hoeller

UrlBasedViewResolver 的便捷子类,支持 TilesView(即 Tiles 定义)及其自定义子类。

此解析器生成的所有视图的视图类可以通过“viewClass”属性指定。有关详细信息,请参阅 UrlBasedViewResolver 的 javadoc。

注意:当链接 ViewResolvers 时,TilesViewResolver 将检查指定的模板资源是否存在,并且只有在实际找到模板时才返回一个非空的 View 对象。

自:3.0 作者:Juergen Hoeller