java后台怎么接收枚举,如何删除对Java枚举值的依赖?

[记住差距:我知道最好的解决方案是完全摆脱枚举,但这不是评论中提到的今天的选项,但是它计划用于(远)未来.

我们有两个部署单元:前端和后端.前端使用枚举并在后端使用枚举作为参数调用EJB服务.但是枚举经常变化,所以我们不希望后端知道它的值.

字符串常量

一个可能的解决方案是使用String常量而不是枚举,但这会在前端引起很多小的变化.我正在寻找一个解决方案,它会在前端产生尽可能少的变化.

包装类

另一种解决方案是使用与枚举具有相同接口的包装类.枚举成为一个包装类,枚举值成为该包装器中的常量.我必须编写一些反序列化代码来确保对象标识(如枚举那样),但我不知道它是否是正确的解决方案.如果使用不同的类加载器怎么办?

包装器类将实现Java接口,它将替换后端中的枚举.但即使如此,deserialiaztion代码也会在后端执行吗?

包装类的示例:

public class Locomotion implements Serializable {

private static final long serialVersionUID = -6359307469030924650L;

public static final List list = new ArrayList();

public static final Locomotion CAR = createValue(4654L);

public static final Locomotion CYCLE = createValue(34235656L);

public static final Locomotion FEET = createValue(87687L);

public static final Locomotion createValue(long type) {

Locomotion enumValue = new Locomotion(type);

list.add(enumValue);

return enumValue;

}

private final long ppId;

private Locomotion(long type) {

this.ppId = type;

}

private Object readResolve() throws ObjectStreamException {

for (Locomotion enumValue : list) {

if (this.equals(enumValue)) {

return enumValue;

}

}

throw new InvalidObjectException("Unknown enum value '" + ppId + "'");

}

@Override

public int hashCode() {

final int prime = 31;

int result = 1;

result = prime * result + (int) (ppId ^ (ppId >>> 32));

return result;

}

@Override

public boolean equals(Object obj) {

if (this == obj) {

return true;

}

if (obj == null) {

return false;

}

if (!(obj instanceof Locomotion)) {

return false;

}

Locomotion other = (Locomotion) obj;

if (ppId != other.ppId) {

return false;

}

return true;

}

}

你有没有同样的问题?你是怎么解决的?

解决方法:

好的,让我看看我是否理解.你之前这么说

“The frontend uses an enum and calls

an EJB service at the backend with the

enum as a parameter. But the enum

changes frequently, so we don’t want

the backend to know its values”

当你说“值”时,我假设你指的是你在枚举构造函数中传递的数值,而不是枚举常量本身.

因此,这意味着前端和后端将有两个不同版本的枚举类,但它们中的枚举常量将是相同的.

我只假设通过RMI进行通信(但这在你的帖子中并不完全清楚).

现在,枚举的序列化/反序列化与其他对象的工作方式不同.根据Java序列化规范,当序列化枚举时,只序列化其名称.当它被反序列化时,它是使用Enum.valueOf(name)方法构建的.

因此,您的原始包装器提议不起作用,因为服务器由于规定的Enums序列化将永远不会知道客户端中枚举的实际值.

最重要的是,如果您打算将枚举传递给服务器,则没有可能的方法来执行您假装执行的操作,因为如果隐含序列化,前端中的值将永远不会到达后端.

如果暗示RMI,一个好的解决方案是使用代码移动性,这样您就可以将有问题的类放在服务器和客户端都可访问的存储库中,并且当前端开发人员更改类定义时,您可以将类发布存储库和服务器可以从那里获取它.

另一个可能的解决方案是你可以停止使用Java Enum并使用带有最终常量的Java类,就像我们过去在枚举之前所做的那样,这样你就可以确保在发送它们时它的值被正确地序列化了到了后端.

有点像这样

public class Fruit implements Serializable{

private static final long serialVersionUID = 1L;

public final Fruit ORANGE = new Fruit("orange");

public final Fruit LEMON = new Fruit("lemon");

private String name;

private Fruit(String name){

this.name = name;

}

}

这样您就可以完全控制反序列化时发生的事情,并且您的包装模式可能会以这种方式工作.

这种类型的构造不能完全替换枚举,例如,它不能在switch语句中使用.但是,如果这是一个问题,您可以使用此对象作为发送到服务器的参数,并让服务器使用其枚举类的版本重建枚举.

因此,您的枚举可以有两个新方法,一个用于从枚举本身构建Java实例:

public static Fruit toFruit(FruitEnum enum);

public FruitEnum valueOf(Fruit fruit);

您可以使用它们来转换服务器参数的来回版本.

标签:java,enums,serialization,dependency-management,classloader

来源: https://codeday.me/bug/20190630/1339529.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值