原因
使用Controller的形參及注解@ModelAttribute來接收頁面傳來的數據,但是該形參類型中的屬性過多,不想一一判斷,就想有沒有偷懶的方法。
搜索一番,找到一個不錯的思路:利用反射獲取所有字段,再判斷內容是否為null。
初步代碼如下
/** * 注意,如果order是null,也返回true。 * * @param order * @return */ private boolean isOrderAllFieldNull(Order order){ if(order == null){ return true; } Class<Order> cls = Order.class; Field[] fields = cls.getDeclaredFields(); for(Field field : fields){ try{ field.setAccessible(true); if(field.get(order)!=null){ return false; } } catch(IllegalAccessException e){ } } return true; }
問題
上面的代碼有不少問題,例如沒考慮排除serialVersionUID,甚至沒考慮基本類型是有默認值的,更沒考慮Order中的屬性可能設有默認值。。。
貌似離題萬里了,但是因為這里需要的是判斷頁面有無傳值進來,而不是真的判斷Order對象的內容是否為空!
就是說,前面的出發點錯了!囧
於是又寫了代碼如下(還是錯的。。):
/** * 目的,判斷是否有賦值。 * 不能傳入null對象!!! * * @param obj * @return * @throws Exception */
public <T> boolean isAllFieldStill(T obj) throws Exception { Class cls = obj.getClass(); T t2 = (T) cls.getConstructor().newInstance();// 創建一個新的對象,用於對比數據
Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { field.setAccessible(true); // 訪問所有字段 // if (field.getName().equals("serialVersionUID")) {// 無視掉序列化ID // continue; // }
if (field.get(obj) != null) { // 卧槽,基本類型做不到啊
if (field.getType().getName().equals("byte") || field.getType().getName().equals("short") || field.getType().getName().equals("int") || field.getType().getName().equals("long")) { // 判斷
if ((int) field.get(obj) != (int) field.get(t2)) { return false; } } else if (field.getType().getName().equals("boolean")) { // 判斷
if ((boolean) field.get(obj) != (boolean) field.get(t2)) { return false; } } else if (field.getType().getName().equals("float")) { // 判斷
if ((float) field.get(obj) != (float) field.get(t2)) { return false; } } else if (field.getType().getName().equals("double")) { // 判斷
if ((double) field.get(obj) != (double) field.get(t2)) { return false; } } else { // 都是引用類型了(引用類型需要有equals方法) // 判斷....
if (!field.get(obj).equals(field.get(t2))) { return false; } } return false; } } return true; }
寫到上面的判斷的時候,突然瘋了。。。
於是有代碼如下:
/** * 目的,判斷是否有賦值。蛋疼,直接equals就行!!!強制要求重寫equals即可。 * 不能傳入null對象!!! * * @param obj * @return * @throws Exception */
public <T> boolean isAllFieldStill2(T obj) throws Exception { Class cls = obj.getClass(); T t2 = (T) cls.getConstructor().newInstance();// 創建一個新的對象,用於對比數據
if (t2.equals(obj)) { return true; } else { return false; } }
然后想的是,我干嘛要這么麻煩,直接new個對象再equals一下不就得了。。。
結論就是
卧槽卧槽卧槽
況且況且況且
----------------------------------------------------------------------------------------------
請忽略掉上面的內容
因為剛想起來頁面提交內容的時候,默認提交所有字段,哪怕沒有內容!
而springmvc的converter會將其映射成各種類型的零值(null或其他),再賦值給形參對象。
如果形參類型的屬性都是引用類型,且沒有設置默認值,那么所有屬性都是null。所以就是要判斷所有屬性是否為空。還得排除掉serialVersionUID。
另外,這個項目中,第一次請求是沒有任何內容的,這個時候Controller中形參對象怎么處理?
----------------------------------------------------------------------------------------------
2016-06-23
C++Primer,看到使用構造函數設置值來區分空對象和具有實際值的對象,突然想到本文的需求。
完全可以在spring中提供一個全null的對象和一個默認初始化的對象,從而用於對比。
只要注入Controller即可,這樣就免去了重復創建的成本。