探索guava(一)——前置条件Preconditions类

作用

可以简洁的完成参数检验,在进行业务逻辑代码前进行前置判断。并且避免了冗长的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);
}

 

现在我们传用户名和密码,其中账号为空:

接下来传错误的用户名和密码 

正确的账号密码,完成登录

posted @ 2017-08-03 22:01  凯乐君  阅读(6380)  评论(0编辑  收藏  举报