通过 <jsp:useBean> 访问的会话作用域 CDI bean 似乎与在 servlet 中不同

Session scoped CDI bean accessed via <jsp:useBean> seems to be a different one than in servlet

我想将 CDI SessionScoped bean 注入 JSP 页面。

import javax.enterprise.context.SessionScoped;
import java.io.Serializable;

@SessionScoped
public class UserSessionBean implements Serializable {

    private String email = "email";

    public UserSessionBean(){}

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

当我以这种方式使用 bean 时,它工作正常,我在 JSP 页面上看到了初始值。

<jsp:useBean id="userSessionBean" class="package.UserSessionBean"/>
<jsp:getProperty name="userSessionBean" property="email"/>

当我将同一个 bean 注入到我从 API 中的另一个 servlet 调用的服务中时,就会出现问题。在这种情况下,我没有在 JSP 页面上获得更新值。看起来我在 JSP 页面和服务内部使用 @Inject annotation

得到了不同的 beans

有人可以建议如何在 JSP 和从 servlet 访问的服务层中使用相同的 SessionScoped bean 吗?

删除 <jsp:useBean><jsp:getProperty> 标签。他们早于 servlets, EL and CDI. Those tags are intented for JSP pages which doesn't make use of any custom servlet or MVC framework provided servlet. See also a.o. jsp:useBean scope.

CDI 方法是简单地将 @Named 注释放在 bean 上 class 以在 EL 中为其命名。

@Named
@SessionScoped
public class UserSessionBean implements Serializable {}

名称默认为小写的 class 名称。因此,上述 CDI 托管 bean 将在 ${userSessionBean} 之前在 EL 中可用。这也适用于普通 JSP 页面。

<p>Email: <c:out value="${userSessionBean.email}" /></p>

就是这样。您可以在您的服务甚至 servlet 中继续使用 @Inject 来获取相同的实例。请注意,上面 JSP 片段中的 JSTL <c:out> 并不是打印值所必需的。自从 JSP 2.0 没有它你也可以做得很好。

<p>Email: ${userSessionBean.email}</p>

但是JSP作为一个相当侏罗纪的视图技术没有像Facelets has. The <c:out> must be used to escape user-controlled input to prevent potential XSS attack holes. See also a.o. XSS prevention in JSP/Servlet web application这样的内置XSS预防。

最后但同样重要的是,确保您的学习资源跟上当前可用的版本。那些 <jsp:useBean> 标签来自上个世纪。