作用
可以簡潔的完成參數檢驗,在進行業務邏輯代碼前進行前置判斷。並且避免了冗長的if語句。guava將所有檢驗的API都放置於Preconditions類中。
API
Preconditions類大致分為6種提供參數檢驗的方法,每種方法都有三個重載方法。重載方法的參數意義是:
- 僅有待校驗的參數:拋出的異常中沒有錯誤消息;
- 有一個Object對象作為額外參數:拋出的異常使用Object.toString() 作為錯誤消息;
- *有一個String對象作為額外參數,還有一個Object[]參數,這兩個參數也是適用於異常錯誤消息的,處理的方式類似於String.format將Object的參數按順序替換掉String中的占位符(如%s)
-
方法聲明(不包括額外參數) 描述 檢查失敗時拋出的異常 checkArgument(boolean) 檢查boolean是否為true,用來檢查傳遞給方法的參數。 IllegalArgumentException checkNotNull(T) 檢查value是否為null,該方法直接返回value,因此可以內嵌使用checkNotNull。。 NullPointerException checkState(boolean) 用來檢查對象的某些狀態。 IllegalStateException checkElementIndex(int index, int size) 檢查index作為索引值對某個列表、字符串或數組是否有效。index>=0 && index<size *。 IndexOutOfBoundsException checkPositionIndex(int index, int size) 檢查index作為位置值對某個列表、字符串或數組是否有效。index>=0 && index<=size *。 IndexOutOfBoundsException checkPositionIndexes(int start, int end, int size) 檢查[start, end]表示的位置范圍對某個列表、字符串或數組是否有效* IndexOutOfBoundsException
實例
如:我們在做登錄操作的方法中,在未用前置條件前,代碼可能會如下:
1 public User login(String userName,String password){ 2 if(StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)){ 3 throw new RuntimeException("用戶名或密碼不能為空"); 4 } 5 User user = userService.queryUserByUserNameAndPassword(userName,password); 6 if(null == user){ 7 throw new RuntimeException("用戶名或密碼錯誤"); 8 } 9 //…………………………………………省略業務邏輯………………………………………… 10 }
當使用了Preconditions類后
public User login(String userName,String password){ Preconditions.checkArgument(!(StringUtils.isEmpty(userName) || StringUtils.isEmpty(password)),"用戶名或密碼不能為空"); User user = userService.queryUserByUserNameAndPassword(userName,password); Preconditions.checkNotNull(user,"用戶名或密碼錯誤"); //…………………………………………省略業務邏輯………………………………………… }
思考
相信大家也發現了,Preconditions類與Assert斷言類的思想基本是一致的,通過這個思想,我們也可以實現屬於自己的斷言類從而提升自己的開發效率。
假設一個場景,我們是基於接口開發工作的,接口通過JSON傳遞數據給前端。此時我們先定義一個JSON的結構。
public class ResponseEntity<T> implements Entity<T>,Serializable{ private static final long serialVersionUID = 1L; //數據實體 private T data; //結果碼 private Integer code; //錯誤描述 private String message; //………… }
自定義一個異常類
public class GlobException extends RuntimeException{ private static final long serialVersionUID = 1L; private String message; private Integer code; }
定義自己的前置條件類(斷言類)
/** * 斷言類 * @author cjl */ public abstract class Assert { /** * 斷言對象不為空,若對象為空則報異常 * @param obj 待校驗對象 * @param message 異常信息 */ public static void notNull(Object obj,String message){ if(obj == null) throw new GlobException(message); } /** * 斷言對象不為空,若對象為空則報異常 * @param obj 待校驗對象 */ public static void notNull(Object obj){ Assert.notNull(obj, "The Object can't null"); } /** * 斷言數字不能為零,若數字為零則報異常 * @param num 待校驗數字 * @param message 異常信息 */ public static void notZero(Integer num,String message){ Assert.notNull(num); if(num.intValue() == 0) throw new GlobException(message); } /** * 斷言數字不能為零,若數字為零則報異常 * @param num 待校驗數字 */ public static void notZero(Integer num){ Assert.notZero(num,"The number can't equals zero"); } /** * 斷言字符串不能為空,若字符串為空則報異常 * @param string 待校驗字符串 * @param message 異常信息 */ public static void notEmpty(String string,String message){ if(StringUtils.isEmpty(string)) throw new GlobException(message); } /** * 斷言字符串不能為空,若字符串為空則報異常 * @param string 待校驗字符串 */ public static void notEmpty(String string){ Assert.notEmpty(string,"The string can't empty"); } /** * 斷言該布爾值為true,若為false則拋異常 * @param expression 待校驗布爾值 * @param message 異常信息 */ public static void isTrue(boolean expression,String message){ if(!expression) throw new GlobException(message); } /** * 斷言該布爾值為true,若為false則拋異常 * @param expression 待校驗布爾值 */ public static void isTrue(boolean expression){ Assert.isTrue(expression,"The expression not true"); } }
這時候在定義一個全局異常處理類,這里使用的是Spring Mvc的@ControllerAdvice注解
** * 全局異常處理 * @author cjl */ @ControllerAdvice public class ExceptionHandlers { @SuppressWarnings("rawtypes") @ResponseBody @ExceptionHandler(GlobException.class) public ResponseEntity<?> exceptionHandler(GlobException exception){ outException(exception); return new ResponseEntity(exception); } /** * 異常輸出 * @param exception */ private void outException(GlobException exception) { String content = String.format("****************系統發生異常(%s)************************", exception.getMessage()); System.out.println(content); } }
和上面的例子一樣,我們現在實現一個完成登錄的接口。
@RequestMapping("/login") public ResponseEntity<?> login(String userName,String password){ Assert.isTrue(!(StringUtils.isEmpty(userName)||StringUtils.isEmpty(password)),"用戶名或密碼不能為空"); User user = userService.queryByUserNameAndPassword(userName, password); Assert.notNull(user,"用戶名或密碼錯誤"); return ResponseEntity.success(user); }
現在我們傳用戶名和密碼,其中賬號為空:
接下來傳錯誤的用戶名和密碼
正確的賬號密碼,完成登錄