【问题标题】:Accessing data from session-scoped beans in JSP files从 JSP 文件中的会话范围 bean 访问数据
【发布时间】:2025-12-06 06:15:01
【问题描述】:

我正在尝试在 Spring Web MVC 3 中开始使用会话范围的 bean。我将这一行放在我的调度程序配置中:

<bean id="userInfo" class="net.sandbox.sessionbeans.UserInfo" scope="session" />

这里是net.sandbox.sessionbeans.UserInfo

package net.sandbox.sessionbeans;

public class UserInfo {
    public String username;

    public UserInfo() {
        this.username = "Unregistered User";
    }
}

如何访问代表应用程序视图部分的 JSP 文件中的会话范围 bean?我试过这个...

<p align="right">${userInfo.username}</p>

...但这并没有给我预期的结果,即

<p align="right">Unregistered User</p>

相反,我只是得到

<p align="right"></p>

我做错了什么?

【问题讨论】:

  • 不,我没有。我认为在初始化会话时会隐式调用默认构造函数。我需要添加什么?
  • 我没有。我假设userInfo 隐式地与所有视图共享。如何与我的 JSP 共享 UserInfo 对象?

标签: spring jsp spring-mvc


【解决方案1】:

您可以按照问题中的说明进行操作。问题可能出在您的配置中。看看你是否在视图中暴露了你的 bean,像这样:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/" />
    <property name="suffix" value=".jsp" />
    <property name="exposeContextBeansAsAttributes" value="true" />
</bean>

【讨论】:

  • 这是否仅将会话 bean 暴露给视图,或者此配置更改是否有我需要了解的其他副作用?
  • 它将公开所有的bean,而不仅仅是会话范围的bean。我不知道副作用。如果您更愿意指定要公开的 bean,您可以使用exposedContextBeanNames 属性。见static.springsource.org/spring/docs/3.0.x/api/org/…
  • 听起来可能存在潜在的安全风险。为我需要的每个 bean 手动执行 &lt;jsp:useBean&gt; 是否更安全?我可以在页眉中做到这一点,所以这不是不方便或任何事情。
  • @Pieter:为什么会有安全风险?无论如何,这就是 Spring 为您提供解决此需求的机制。我不知道你使用的标签,抱歉。
  • 在将UrlBasedViewResolver 与瓷砖一起使用时,您是否有任何配置提示?
【解决方案2】:

您可以使用 Spring 将单个 bean 公开给 JSTL。

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

        </list>
    </property>
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

【讨论】:

  • 这比将所有 bean 直接暴露给视图更合适。
【解决方案3】:

此答案部分基于问题的 cmets 中发布的一些建议,但后来被发布者删除。我将此添加到需要使用 bean 的每个 JSP 页面:

<jsp:useBean id="userInfo" scope="session" class="net.sandbox.sessionbeans.UserInfo" />

然后我发现this article 详细说明了如何在 JSP 页面中使用 bean。

【讨论】:

  • 这是错误的。 &lt;jsp:useBean /&gt; 提供一个 jsp 会话 bean。这与 spring 应用程序上下文不同。
【解决方案4】:

你需要确保你有

<aop:scoped-proxy/>

在您的 xml 配置中启用。

例如:

<!-- an HTTP Session-scoped bean exposed as a proxy -->
  <bean id="userPreferences" class="com.foo.UserPreferences" scope="session">

        <!-- this next element effects the proxying of the surrounding bean -->
        <aop:scoped-proxy/>
  </bean>

您可以在 Spring 参考指南“Bean 作用域”一章中了解更多信息。

【讨论】:

  • 这给了我一个java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice 错误。我想我会坚持使用&lt;jsp:useBean&gt; 解决方案。
  • 你需要添加罐子。 org.springframework.aop-x.x.x.RELEASE.jar
  • 显然 NetBeans 的预配置 Spring Web 环境不包含您所说的这个 JAR。我在某处读到我应该下载aopalliance.jar 来解决这个问题。但是,如果我删除 &lt;jsp:useBean&gt; 标记(在将 &lt;aop:scoped-proxy/&gt; 添加到 bean 之后),我会在 &lt;% out.print(userInfo.getUserName()); %&gt;(在我的 JSP 文件中)收到 cannot find symbol 错误。
  • @danny.lesnik : 请输入this question
【解决方案5】:

详细说明下面的@sinuhepop 建议。

一个简单的方法是配置spring,以便它将spring bean id作为变量公开给JSTL,这可以通过将exposeContextBeansAsAttributes属性设置为true来完成

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
    <property name="exposeContextBeansAsAttributes" value="true"/>
    <property name="prefix" value="/WEB-INF/jsp/" />
    <property name="suffix" value=".jsp" />
</bean>

如果你有一个像这样配置的 bean

@Component
@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS,value=WebApplicationContext.SCOPE_SESSION)
public class SomeBean {
}

然后在 JSP 页面中,您可以使用名称 ${someBean.someProp} 访问 bean,因为这是 Spring 将自动分配给 SomeBean 的名称,除非 bean 使用诸如 @Component("someName") 之类的名称定义,那么 JSTL 将是${someName.someProp}

【讨论】:

    【解决方案6】:

    为那些想要使用 Spring 5 Java 配置的人更新此答案。将此添加到您的 WebMvcConfigurer

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver("/WEB-INF/view", ".jsp");
        resolver.setExposeContextBeansAsAttributes(true);
        registry.viewResolver(resolver);
    }
    

    相当于其他人提到的这个XML配置:

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/" />
        <property name="suffix" value=".jsp" />
        <property name="exposeContextBeansAsAttributes" value="true" />
    </bean>
    

    请注意,注册表的“方便”流畅 API (registry.jsp(). ...) 无法为您提供配置 exposeContextBean.... 属性的可能性。

    如果可能,您应该考虑使用exposeContextBeanNames。但是,尽可能为您的 bean 名称使用常量,以避免在代码中重复字符串文字。因此,也许可以在某个类中定义一个字符串数组,它收集所有这些常量并将它们公开给您的视图解析器。

    【讨论】: