在Java中,transient
关键字用于标记不希望被序列化的字段。序列化是将对象的状态转换为字节流的过程,以便保存到文件或通过网络传输。反序列化是将字节流恢复为对象的过程。
在数据传输对象(DTO,Data Transfer Object)中使用transient
关键字时,表示该字段在对象序列化时应被忽略。这在某些情况下非常有用,比如:
- 敏感数据:有些数据可能是敏感的,不希望在序列化后被保存或传输。例如,密码字段。
- 临时数据:有些数据是临时的,仅在对象的生命周期内有效,不需要被持久化。
- 不需要传输的数据:有些数据对于接收方可能是无用的,不需要传输。
import java.io.*;
public class test {
public static void main(String[] args) throws IOException {
UserDTO user = new UserDTO("john_doe", "super_secret_password");
File test = new File("test");
test.createNewFile();
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(test))) {
oos.writeObject(user);
System.out.println();
} catch (IOException e) {
e.printStackTrace();
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(test))) {
UserDTO deserializedUser = (UserDTO) ois.readObject();
System.out.println("Username: " + deserializedUser.getUsername());
System.out.println("Password: " + deserializedUser.getPassword()); // This will print 'null'
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
static class UserDTO implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private transient String password; // This field will not be serialized
public UserDTO(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class RestTemplateExample {
public static void main(String[] args) {
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
UserDTO user = new UserDTO("john_doe", "super_secret_password", "details_to_ignore");
HttpEntity<UserDTO> requestEntity = new HttpEntity<>(user, headers);
ResponseEntity<UserDTO> responseEntity = restTemplate.exchange(
"https://example.com/api/users",
HttpMethod.POST,
requestEntity,
UserDTO.class
);
UserDTO responseUser = responseEntity.getBody();
if (responseUser != null) {
System.out.println("Response User: " + responseUser.getUsername());
} else {
System.out.println("No response received!");
}
}
}
class UserDTO {
private String username;
private String password;
@JsonIgnore
private transient String details; // This field will be ignored during serialization
public UserDTO() {}
public UserDTO(String username, String password, String details) {
this.username = username;
this.password = password;
this.details = details;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
}
但是在网络交互的时候,使用RestTemplate
的 exchange
方法时,传输的 DTO(数据传输对象)会自动进行序列化和反序列化,这个时候Spring 默认用于处理 JSON 序列化和反序列化的库。默认情况下,Jackson 并不会忽略 transient
字段。这意味着,即使一个字段被标记为 transient
,它仍然会包含在 JSON 序列化过程中。
@JsonIgnore
注解告诉 Jackson 在序列化和反序列化过程中忽略这个字段。
@JsonIgnore
private transient String details;