0

问候,StackOverFlow 成员。我刚刚开始学习如何使用 Java Enterprise Beans 和 Java Persistence API 等技术编写支持 Web 的应用程序。

NetBeans 官方网站目前提供了一个捆绑包,(据说)允许我开发上述应用程序。一个大小约为 213 MB 的捆绑包。

现在是这样:假设我想模拟登录网站的过程。你知道,当我登录亚马逊时,我的会话数据存储在我的浏览器中,这就是他们能够显示诸如“欢迎,米格尔·马丁斯”或“米格尔·马丁斯的推荐购买”之类的内容的方式, 正确的?正确的。好吧,这就是我要做的(让我们从 index.jsp 开始):

<%@page import="beans.UserBeanRemote"%>
<%@page import="entities.SimplifiedUser"%>
<%@page import="beans.BeanFacade"%>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
   "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>JSP Page</title>
    </head>
    <body>
        <%
            UserBeanRemote userBean = BeanFacade.getUserBean();
            userBean.setAuthenticatedUser(session, new SimplifiedUser("Miguel Martins", "password"));
            SimplifiedUser authenticatedUser = userBean.getAuthenticatedUser(session);
            if (authenticatedUser == null) {
                out.write("No user is authenticated.");
            }
            else {
                out.write("There is an authenticated user. Username: " + authenticatedUser.getUserName());
            }
        %>
    </body>
</html>

很简单,对吧?我的意图是(显然)调用 setAuthenticatedUser 方法来存储会话数据,然后调用 getAuthenticatedUser 方法基本上询问“谁在这个 Web 浏览器中进行了身份验证?”

这就是我对其余部分的编程方式。请记住,这应该是一个简单/简约的应用程序,用于学习目的。

BeanFacade.java

package beans;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class BeanFacade {
    private static InitialContext context;

    private static void initializeContext() throws NamingException {
        if (context == null) {
            context = new InitialContext();
        }
    }

    public static UserBeanRemote getUserBean() throws NamingException {
        initializeContext();
        return (UserBeanRemote) context.lookup("java:global/SimplifiedAuthentication/SimplifiedAuthentication-ejb/UserBean!beans.UserBeanRemote");
    }
}

用户Bean.java

package beans;

import entities.SimplifiedUser;
import javax.ejb.Stateless;
import javax.servlet.http.HttpSession;

@Stateless
public class UserBean implements UserBeanRemote {

    @Override
    public void setAuthenticatedUser(HttpSession session, SimplifiedUser user) {
        session.setAttribute("authenticated_user", user);
    }

    @Override
    public SimplifiedUser getAuthenticatedUser(HttpSession session) {
        return (SimplifiedUser) session.getAttribute("authenticated_user");
    }
}

UserBeanRemote.java(显然是UserBean的远程接口)

package beans;

import entities.SimplifiedUser;
import javax.ejb.Remote;
import javax.servlet.http.HttpSession;

@Remote
public interface UserBeanRemote {
    public void setAuthenticatedUser(HttpSession session, SimplifiedUser user);
    public SimplifiedUser getAuthenticatedUser(HttpSession session);
}

最后但同样重要的是,SimplifiedUser.java。这就是我想要存储为会话数据的内容。

package entities;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class SimplifiedUser implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    private String userName;
    private String password;

    public SimplifiedUser() {
    }

    public SimplifiedUser(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }

    public String getUserName() {
        return userName;
    }
}

然而,令我沮丧的是,当我运行该项目时,它向我抛出了一个异常:

HTTP 状态 500 -

类型异常报告

信息

描述服务器遇到一个内部错误 () 阻止它完成这个请求。

例外

org.apache.jasper.JasperException: javax.ejb.EJBException: java.rmi.MarshalException: CORBA BAD_PARAM 1330446342 也许;嵌套异常是:java.io.NotSerializableException:

根本原因

javax.ejb.EJBException:java.rmi.MarshalException:CORBA BAD_PARAM 1330446342 也许;嵌套异常是:java.io.NotSerializableException:

根本原因

java.rmi.MarshalException: CORBA BAD_PARAM 1330446342 也许;嵌套异常是:java.io.NotSerializableException:

根本原因

java.io.NotSerializableException:

根本原因

org.omg.CORBA.BAD_PARAM:vmcid:OMG 次要代码:6 完成:也许

note 异常的完整堆栈跟踪及其根本原因可在 GlassFish Server Open Source Edition 3.0.1 日志中找到。GlassFish Server 开源版 3.0.1

而且,经过一些老式的调试(“注释掉”),似乎异常的原因是这样的:

session.setAttribute("authenticated_user", user);

和这个:

return (SimplifiedUser) session.getAttribute("authenticated_user");

这表明,不知何故,他们不希望我将我的用户数据(也不检索它)存储在 HttpSession 实例中。

有人知道为什么吗?首先将 Serializable 对象存储在 HttpSession 实例中不是完全合法的吗?如果是这样,那么这里到底发生了什么?

谢谢你,米格尔·马丁斯

4

1 回答 1

0

我很抱歉,StackOverflow 成员。在我和我的一位项目同事之间进行了一些非常有启发性的讨论后,我意识到了我的方式的错误。长话短说,似乎例外是由于我传递给 EJB 的所有内容都必须是可序列化的。当然,HttpSession 实例是不可序列化的。

但是,即使它是可序列化的,我的那个同事也清楚地向我证明,毫无疑问,HttpSession 实例永远不应该离开 Web 层并传递到其他层(在这种情况下,EJB 层)。因此,我试图做的事情......我做错了。

根据我的同事自己的说法,正确的方法是创建一个全新的 User 类,专门用于 Web 层(即我们最终有两个类,一个带有 @Entity 注释的 User 类,另一个类,后来被称为“UserViewModel”,遵循一种称为 ViewModel 模式的设计模式。基本上,这个“第二个用户类”是原始类的简化版本,旨在专门用于 Web 层。

因此,向我的同事表示敬意,他向我展示了我的方式错误。但是,如果有人对此有其他要说的,请说出来。

于 2010-10-12T21:01:17.290 回答