我想以各种时间间隔保存注入的有状态bean的数据:更改-保存-
更改保存…我正在使用核心序列化,问题是所有字节数组都相同。我相信代理是序列化的,因为如果以后反序列化其中一个数组,则会得到Bean的当前状态。
序列化示例未捕获Bean中的更改:
@Stateful
@RequestScoped
public class State implements Serializable {
private static final long serialVersionUID = 1L;
@Inject
StatelessBean bean; // assume it's needed
private List<String> list = new ArrayList<>();
public void add() {
list.add("S");
}
}
这是一个JAX-RS类:
@Stateless
@Path("t1")
public class ChickensResource {
@Inject
State state;
@GET
@Path("/test")
public String test() {
state.add();
byte[] b0 = serialize(state);
System.out.println(b0.length + " " + Arrays.toString(b0));
state.add();
byte[] b1 = serialize(state);
System.out.println(b1.length + " " + Arrays.toString(b1)); // prints same as b0
System.out.println(b0.length + " " + Arrays.toString(b0)); // prints same thing
}
public static <T extends Serializable> byte[] serialize(T s) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos))
{
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
我要做的只是将列表保存在其中,State
因为这是相关数据。我还尝试了JSON序列化,并且给出了IOException
,但是我正在尝试核心序列化。
使用JavaEE7和Wildfly 10.1。
由于各种原因,直接序列化CDI bean很危险:
但是,此问题的目的是以某种方式保存CDI bean的状态,以便以后可以将其还原。这可以通过使用另一个保存CDI
bean状态的对象来实现。该其他对象不受CDI管理,即由创建new
,并且可序列化。每个需要保持其状态的CDI
bean都有一对setState(state)
/ getState()
方法-
它们甚至可以是接口的一部分。你可能希望每个对象传播setState(state)
/ getState()
它的合作者了。
请参阅Memento设计模式。如果您熟悉它,也可以在JSF状态保存/恢复机制中实现。
从状态接口开始的一些示例代码(还有其他有效的方法):
interface HasState<S extends Serializable> {
S getState();
void setState(S state);
}
然后是具有协作者的服务本身,以及相关的状态对象:
class SomeServiceState implements Serializable {
private String someData;
private Long someId;
private List<String> list;
private CollaboratorState collaboratorState;
// accessors
}
@RequestScoped
public class SomeService implements HasState<SomeServiceState> {
// COLLABORATORS
@Inject
Collaborator collaborator; // assume it's needed
// INTERNAL STATE
private String someData;
private Long someId;
private List<String> list = new ArrayList<>();
public void add() {
list.add("S");
}
// ...
public SomeServiceState getState() {
SomeServiceState state = new SomeServiceState();
state.setSomeData(someData);
state.setSomeId(someId);
state.setList(new ArrayList<>(list)); // IT IS PROBABLY SAFER TO COPY STATE!
// SEE HOW STATE GETS EXTRACTED RECURSIVELY:
state.setCollaboratorState(collaborator.getState());
return state;
}
public void setState(SomeServiceState state) {
someData = state.getSomeData();
someId = state.getSomeId();
list = new ArrayList<>(state.getList());
// SEE HOW STATE GETS APPLIED RECURSIVELY:
collaborator.setState(state.getCollaboratorState());
}
}
合作者及其状态遵循相同的模式:
class CollaboratorState implements Serializable {
private String anyName;
// accessors
}
@RequestScoped
class Collaborator implements HasState<CollaboratorState> {
// you get the point...
}
以及示例用法,遵循问题中的代码:
@Stateless
@Path("t1")
public class ChickensResource {
@Inject
SomeService someService;
@GET
@Path("/test")
public String test() {
someService.add();
byte[] b0 = serialize(someService.getState());
// ...
}
public static <T extends Serializable> byte[] serialize(T s) {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos))
{
oos.writeObject(s);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
编辑:如果服务的客户端需要知道服务具有状态,则客户端和服务可能比期望的耦合得多。一种解决方法是修改HasState
以处理不透明的对象:
interface HasState {
Object getState();
void setState(Object state);
}
客户端的状态包含每个协作者的状态的列表:
class SomeServiceState implements Serializable {
private String someData;
private Long someId;
private List<String> list;
private List<Object> collaboratorsState;
// accessors
}
客户端仅在扩展时将协作者添加到状态HasState
:
public Object getState() {
SomeServiceState state = new SomeServiceState();
state.setSomeData(someData);
state.setSomeId(someId);
state.setList(new ArrayList<>(list));
if( collaborator instanceof HasState ) {
state.getCollaboratorsState().add(collaborator.getState());
}
return state;
}
我使用的是Spring Kafka 1.1.2-Spring Boot 1.5.0 RC版本,并且配置了一个自定义值serialiser/Deserialiser类,扩展/。这些类确实使用Jackson ObjectMapper,它可以通过构造函数提供。 是否可以从Spring上下文中注入ObjectMapper?我已经配置了一个ObjectMapper,我希望在序列化/反序列化程序中重用它。
我需要序列化/反序列化特定枚举: 我有个例外: 我如何通过GSON序列化/反序列化它?
我们希望序列化Java类的模式,以便任何字段或类上存在的所有注释也序列化到模式中。 我没有找到这样做的工具。 Avro不处理非字符串映射键,FasterXML不处理循环引用。它们都不会将注释序列化到模式中。 是否有任何Java JSON(反)序列化程序可以做到这一点?
我按照本指南将Micronaut Serialization与Jackson注释一起使用。当我创建一个抽象类和一个类时,我可以使用和来正确序列化类的对象。 但是,当我使用类型的属性序列化的对象但使用运行时类型时,该属性被序列化为。 下面的代码应该解释了我的问题。请注意,我正在使用,当我将其替换为时,它会按预期工作。 有没有一种方法可以使用注释使其工作?
我正在尝试配置序列化程序实例,以便在storm拓扑中使用。 非常感谢
问题内容: 我想在使用Jackson时定义我的自定义序列化策略(要包括的字段)。我知道,我可以使用视图/过滤器来做到这一点,但是它引入了非常不好的一件事- 使用字段名称的字符串表示形式,这会自动导致自动重构出现问题。 如何迫使Jackson序列化仅带注释的属性,仅此而已? 问题答案: 如果禁用所有自动检测,则应仅序列化已注释的属性-无论是属性本身还是吸气剂。这是一个简单的例子: