【发布时间】:2018-08-25 23:11:12
【问题描述】:
所以我试图将一个对象从客户端发送到服务器,然后我对这个对象做一些事情。我验证了在发送对象时包含数据。当我在调试器中读取我的对象时,它的所有属性都是空的。
下面是我发送对象的地方:
private class registerUser extends Task<Void>
{
Users user;
private static final String code = ".register";
private static final String host = "localhost";
private static final int portNumber = 4444;
private clientThread clientThread;
public registerUser(Users user)
{
this.user = user;
}
@Override
protected Void call() throws Exception
{
try
{
Socket socket = new Socket(host, portNumber);
Thread.sleep(1000);
//Setup I/O
ObjectOutputStream outToServerObject = new ObjectOutputStream(socket.getOutputStream());
//PrintWriter serverOutString = new PrintWriter(socket.getOutputStream(), false);
InputStream serverInString = socket.getInputStream();
//serverOutString.println(code);
// serverOutString.flush();
outToServerObject.writeObject(user);
outToServerObject.flush();
}
catch (IOException e)
{
System.err.println("Fatal Connection error!");
e.printStackTrace();
}
return null;
}
当我按下 GUI 中的按钮时,将使用上述任务,如下所示:
public void btn_registerUser(ActionEvent actionEvent) throws IOException
{
user.setUserName(txt_Username.getText());
user.setFirstName(txt_FirstName.getText());
user.setLastName(txt_LastName.getText());
user.setCity(txt_City.getText());
user.setBirthday(date_Birthday.getValue());
Task<Void> task = new registerUser(user);
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
接收对象的服务器中的代码:
//Setup I/O
this.clientOut = new PrintWriter(socket.getOutputStream(), false);
ObjectInputStream inFromClientObject = new ObjectInputStream(socket.getInputStream());
// Scanner in = new Scanner(socket.getInputStream());
Users user = (Users) inFromClientObject.readObject();
doSomething(user);
还有作为辩论对象的 User.java 类
public class Users implements Serializable
{
/*
Variables
TODO Create a friend list
*/
private transient IntegerProperty userID;
private transient StringProperty userName;
private transient StringProperty firstName;
private transient StringProperty lastName;
private transient StringProperty city;
private transient ObjectProperty<LocalDate> birthday;
private transient ListProperty<String> musicGenre;
private transient List<String> musicGenres = new ArrayList<>();
/**
* Default constructor.
*/
public Users()
{
this(null,null,null,null,null);
}
/**
* Constructor with some initial data.
* Takes in a {@code String} and sets a reference
*
* @param userName
*
*/
public Users(String userName, String firstName, String lastName, String city, LocalDate birthday)
{
this.userName = new SimpleStringProperty(userName);
this.userID = new SimpleIntegerProperty();
this.firstName = new SimpleStringProperty(firstName);
this.lastName = new SimpleStringProperty(lastName);
this.city = new SimpleStringProperty(city);
this.birthday = new SimpleObjectProperty<LocalDate>(birthday);
ObservableList<String> observableList = FXCollections.observableArrayList(this.musicGenres);
this.musicGenre = new SimpleListProperty<String>(observableList);
}
}
我已经省略了 getter 和 setter,因为这个问题已经很长了
所以在调试器中运行服务器时,当我doSomething(user)时,用户的所有属性都为空
*编辑 这些建议正在奏效,但我遇到了问题
private List<String> musicGenreList = new ArrayList<>();
ObservableList<String> observableList = FXCollections.observableArrayList(musicGenreList);
private ListProperty<String> musicGenre = new SimpleListProperty<String>(observableList);
这是我可以将项目添加到 ListProperty 但 observableList 无法序列化的唯一方法
【问题讨论】:
-
transient表示“不要序列化这个值”。所以这正是你所期望的。 JavaFX 属性和集合不可序列化,您真的只想序列化它们的值。为此,您需要实现自定义序列化。见stackoverflow.com/questions/33452847/… 或stackoverflow.com/questions/23187989/… -
您还可以使用具有通常类型属性的所谓 DTO 对象,例如可序列化的
String、Integer等。然后将User对象转换为UserDTO,序列化该DTO,发送,反序列化,从UserDTO构造Users对象并在另一台机器上使用它。 -
或者说,流式 JSON。只要
get和set方法以相同的方式命名,您就可以使用JavaFX 属性序列化对象并将其反序列化为表示与常规JavaBean 属性相同值的对象,反之亦然。 -
@James_D 除了我的 listProperty 之外,这一切都很好,我通过创建一个 arrayList 然后附加一个 FXCollection 可观察的 arraylist 来实现它。然后我创建了一个新的 ListProperty 作为
new SimpleListProperty<String>(observableList);。当然这可以序列化,但这是我将项目添加到列表的唯一方法。有什么想法吗?