从 jsp 访问 Spring MVC DI bean

Posted

技术标签:

【中文标题】从 jsp 访问 Spring MVC DI bean【英文标题】:Accessing Spring MVC DI beans from jsp 【发布时间】:2010-01-15 14:14:55 【问题描述】:

在某些 MVC 框架中,如果您希望执行某些代码并呈现某些局部视图,则可以从视图中调用控制器操作。我不确定在 Spring MVC 中正确的方法是什么

我想要一组 JSP 模板。其中一些将是页面布局,其中一些将是小组件,例如分页器、登录框、菜单、标签云等。这些组件中的每一个都需要一些 bean 或控制器操作来将一些数据设置到 ViewAndModel 中,以便视图可以使用它.

问题是我不想在每次调用中设置所有这些对象。我的注册控制器只关心注册处理。那么现在我该怎么做呢?如何从视图中调用 DI bean 或控制器来准备部分视图?或者我应该创建一些映射?还是我从完全错误的角度解决问题?

【问题讨论】:

【参考方案1】:

Spring-MVC 可以将应用程序上下文的 bean 暴露给视图层,如果您希望这样做的话。

例如,InternalResourceViewResolver 可以被指示公开上下文中的每个 bean,或者只是指定的。查看exposeContextBeansAsAttributes 和exposedContextBeanNames 属性。

例如,假设您想将 bean beanAbeanB 公开给您的 JSP。您将在您的上下文中声明视图解析器:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <property name="exposedContextBeanNames">
      <list>
         <value>beanA</value>
         <value>beanB</value>
      </list>
   </property>
</bean>

或者,只公开每个 bean:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <property name="exposeContextBeansAsAttributes" value="true"/>
</bean>

这是否是一个好主意是另一个问题,但 Spring 确实为您提供了选择。

【讨论】:

优秀答案 :-) 现在,一旦我将控制器暴露给 jsp,我就可以真正调用它并获取菜单实例。我不确定最后我将如何做,因为我可以看到耦合可以快速增加,但至少我有办法做到!再次感谢!【参考方案2】:

国际海事组织 在 viewResolver bean 配置中添加使用暴露的ContextBeanNames(也有可能使用全局标志,不推荐)

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="exposedContextBeanNames">
 <list>
  <value>beanName</value>
 </list>

在你的 JSP 中使用

$beanName.property

【讨论】:

【参考方案3】:

使用 InternalResourceViewResolver 的一个关键部分似乎是在处理 jsp 页面时需要将 Spring 参与到代码流中。 如果您直接访问 jsp 页面或以其他方式绕过任何基于 Spring 的操作(例如,由于 web.xml 中的登录配置,可能通过内部转发到 jsp 页面),那么这将不起作用。

但是,可以配置您的应用程序,以便某些 bean 可以访问任何可以通过以下方式访问 ServletContext(又名 applicationScope)的 ServletContextAttributeExporter 类的使用。

在你的 spring 配置中,添加:

<bean id="mybean" .../>
<bean class="org.springframework.web.context.support.ServletContextAttributeExporter">
    <property name="attributes">
        <map>
            <entry key="attrname" value-ref="mybean"/>
        </map>
    </property>
</bean>

然后,在 JSP 页面中,您可以通过以下方式访问该 bean:

$applicationScope.attrname

或者如果您知道在更具体的范围内没有“attrname”属性,只需:

$attrname

显然这将无法引用请求或会话范围的 bean,但如果您需要访问单例 bean,那么它会很好用。

【讨论】:

【参考方案4】:

你可以使用spring:eval标签:

...
<spring:eval expression="@properties.getProperty('myProp')" var="myProp" />
$myProp
...

@properties 是 Spring 上下文中属性的 bean 名称。请注意,这种方法不使用exposedContextBeanNames,因此它可以与Tiles Views 一起使用,例如(TilesViewResolver 没有这样的属性)。

【讨论】:

【参考方案5】:

永远不要从 jsp 视图访问业务组件;像 sitemesh 这样的东西可以用来将多个视图合并为一个。 Jsps 也不应该直接调用控制器方法

【讨论】:

很好,这就是我想要弄清楚的,我如何将必要的东西传递给我的部分视图文件,这样我就不必在同一个控制器中启动它们。我的控制器不必关心其他 ModelAndView 属性。理想情况下,我将包括部分(或调用控制器操作),它会调用负责它的控制器并准备来自 bean 等的所有数据。然后它将被传递到部分视图并呈现。至少我认为这对我有用:-) 如果部分视图都是同一个请求-响应循环的一部分,那么主视图可以为所有部分视图设置所有模型数据(当然作为请求参数) 我的主视图是 home.jsp,它包括 menu.jsp。 “设置所有模型数据”是什么意思?你的意思是这样的吗? 我在这里遇到的问题是我不想设置 $我可以拥有的每个控制器的 menu 实例。我想在一个单独的“模块”中处理这个问题。我认为必须有一些简单的方法来处理这种用例:-) 我刚到春天,看不到它:-) 很抱歉之前没有详细解释——我是在手机上打字!!! :) 现在,IIRC,您可以设置在控制器中呈现视图所需的所有“模型”数据。为此,您可以将它们添加到在 ModelAndView 中充当“模型”的 java.util.Map。 Map 的所有条目都作为请求范围属性公开,并可供属于该请求-响应周期的所有 JSP 使用。所以你的控制器应该能够只添加所有部分视图所需的所有数据,然后每个部分视图将使用它所需的属性子集进行渲染。 我在帖子中看到您不想为控制器中的每个非相关部分视图设置所有数据 - 这是有充分理由的。我想你可以有过滤器或拦截器来设置不相关的属性。那种或某种形式的链接(尽管链接很快就会失控)。【参考方案6】:

基于注释的方法来解决 JSP 中 Spring bean 的使用问题。

Spring MVC + JSP 瓦片:

@Bean
public ViewResolver tilesViewResolver() 
  final UrlBasedViewResolver = new UrlBasedViewResolver();
  ...
  viewResolver.setExposeContextBeansAsAttributes(true);
  viewResolver.setExposedContextBeanNames("myBean");
  return viewResolver;

在我的 .jsp 中:

<c:set var="myBeanData" scope="request" value="$myBean.myMethod()"/>
<a id="id" href="$myBeanData">Link</a>

【讨论】:

以上是关于从 jsp 访问 Spring MVC DI bean的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC 下index.jsp访问

spring mvc 访问不到 js css

springmvc工程启动成功 啥也访问不了

Spting +Spring MVC+spring date jsp +hibernate+jq

spring boot学习02如何在spring boot项目中访问jsp

spring3 mvc 中怎么从当前action跳到另一个action中