進一步理解get和set

做CRUD的功能時,我們常常會定義一個和表對應的實體類信息,然後這個實體類信息的屬性和表中的字段一一對應,然後加上每個屬性的get和set方法;更規範的做法是,在此基礎上再加一個DTO類,它與實體類

長得幾乎一樣,但是這個類不直接和表關聯。

 

之前一直不明白爲何要再定義一個dto類,也覺得get和set方法不外乎是:

public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}

 這種“千篇一律”的寫法。。直到最近做了對字段加解密的活,才被虐得很慘。。

 

下面就以對email字段來加解密,說一說我的收穫。

假設有一個和表對應的實體類Info(Hibernate):

@SuppressWarnings("serial")
@Table(name = "INFO")
@Entity
public class Info extends BasicEntity {
	@Column(name = "EMAIL")
	private String email;
	
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}
}

 還有一個對應的DTO:

public class InfoDTO  {
	
	private String email;
	
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}
}

 現在如果要對email字段加解密,就是在數據庫裏看到的是密文,在前端UI看到的是明文。此時就跟get和set有關了。。

我們在此不討論如何加解密。一般而言,Entity的set方法用於保存入庫,get方法用於從庫裏取數據,你會很正常的想到這樣:

@SuppressWarnings("serial")
@Table(name = "INFO")
@Entity
public class Info extends BasicEntity {
	@Column(name = "EMAIL")
	private String email;
	
	public String getEmail() {
		email = ....(emial);//解密的僞代碼
		return email;
	}

	public void setEmail(String email) {
		email = ....(emial);//加密的僞代碼
		this.email = email;
	}
}

 set方法沒有問題,但是get方法就是一個“陷阱”!在首次解密數據庫裏的密文email時,確實能在前端正常顯示明文,但是同時數據庫裏的email字段也會變成明文!我們在第二次以後再去訪問時,因爲已經是

明文,再解密的話就會報錯!

所以get方法也可能改變數據庫裏的值,因爲一旦你在get方法裏對該字段做了邏輯處理後,email是全局變量,會直接影響數據庫裏面的值!一般我們只認爲set會改變庫裏的值,而get不會。但是要看get方法裏

有沒有對變量做邏輯處理,這就顛覆了"固化"的思維。

此時DTO類就派上用場啦!可以這樣改造,保持Entity實體類的get方法不變,DTO類的get方法再做解密!如:

@SuppressWarnings("serial")
@Table(name = "INFO")
@Entity
public class Info extends BasicEntity {
	@Column(name = "EMAIL")
	private String email;
	
	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		email = ....(emial);//加密的僞代碼
		this.email = email;
	}
}

 DTO類:

public class InfoDTO  {
	
	private String email;
	
	public String getEmail() {
		email = ....(emial);//解密的僞代碼
		return email;
	}

	public void setEmail(String email) {
		
		this.email = email;
	}
}

 這樣,無論你訪問多少次。數據庫裏的密文會一直保持,我們可以通過debug知道代碼的執行順序是:

Entity類的get方法從數據庫裏取出密文->DTO類的set方法把Entity類get到的值賦給自己->DTO類的get方法把自己get到的值做處理(直接顯示或做處理)

 

從這個角度,可以將DTO類理解成一個數據的備份,不直接與數據庫掛鉤,也就不會影響數據庫裏的值

 

還有一種情景是UI輸入查詢/添加或修改去保存,這是一個與上面方向相反的過程。

此時DTO類可以用於收集form查詢或添加/修改表單的數據,其實也可以用Map,看字段值的多少了。

同樣,如果我們考慮email這個字段,用戶輸入的肯定是明文,存到數據庫裏需是密文,此時因爲在Entity類裏set方法直接是加密的了,所以我們要保持在DTO裏get到的值是明文,執行順序:

用戶輸入明文->DTO類的set方法來保存輸入信息->DTO類的get方法來獲得輸入->Entity類的set方法加密

 

這時候我們會發現,如果在DTO類的get方法裏還保留解密邏輯,就會出錯,所以此時DTO的get方法又不能加了。

 

這就引申出一個問題,我們一般DTO當作Entity類和UI之間的介質,當他要作爲接收參數的角色時,get方法裏也不能加邏輯處理,此時需要注意!此時,我們只能用其他參數接收載體如Map

所以當字段需要做邏輯處理,不再是傳統的get和set時,需要注意get和set對值的改變!

 

下面一張圖是我對get和set的理解(圖是用wps畫的,很渣勿噴~)



 以上加解密只是一個例子,用於說明字段不再是單純get和set時需要注意的地方!!!

  • 04d9ac46-4073-334f-96c6-772b0ef5e172-thumb.png
  • 大小: 34.9 KB
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章