一、問題初探
我今天在使用Ribbon 遠程調用的時候
消費者去消費服務端所提供的服務,在使用Post請求中的PostForEntity傳遞參數的時候,我是這樣寫的
Ribbon 消費端:
User 是一個 Pojo 對象,代碼如下:
public class User {
private Integer id;
private String name;
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
get... and set ...
}
Ribbon 服務端:
就是一個很簡單的Ribbon 遠程調用的一個操作,報如下錯誤:
跟入源碼:
然后就不明覺厲了,第一開始比較煩躁,一直以為是消費端的問題,因為錯誤是從消費服務端報出來的。后來經過冷靜發現,上述代碼是在處理服務端響應的時候報出來的,應該還是服務端報錯來的錯誤。
2019-04-14 13:56:27.183 WARN 3500 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not construct instance of com.service.provider.pojo.User: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.service.provider.pojo.User: no suitable constructor found, can not deserialize from Object value (missing default constructor or creator, or perhaps need to add/enable type information?)
at [Source: java.io.PushbackInputStream@25979c35; line: 1, column: 2]
代碼並不能看懂什么意思,求助google,從stackoverflow上找到了問題的答案:
沒有加默認的構造函數?????? 這是什么鬼? 默認的構造函數和JSON解析有什么關系?
但是能夠解決問題了,我檢查了一遍我一直以為我的值沒有傳遞過去,但我看已經傳遞到服務端了(避免了一個白痴問題)。
二、問題原因
華麗的分割線
事實印證了我是個菜比。
事情是這樣的
Ribbon的消費者向服務者提供的數據轉換是要把對象轉換為二進制數據,這個過程稱之為序列化
而服務端收到二進制的數據再轉換為對應的對象,這個過程稱之為反序列化
序列化會把對象保存在磁盤中,或允許直接在網絡中直接傳輸對象
反序列化就是收到二進制的數據,再轉換為對應的對象。
而實現對象序列化的方法有兩種:
1. 實現序列化接口
2. 提供無參構造函數
而上面報錯的原因就是因為沒有提供默認的構造函數或者實現序列化接口!!!!!
三、解決問題
添加無參構造函數
解決問題一,再上面的Pojo類上添加默認的構造函數
public class User {
private Integer id;
private String name;
public User(){}
public User(Integer id, String name) {
this.id = id;
this.name = name;
}
get and set...
}
再次調用接口,客戶端能夠打印出來對應的日志