继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

JFinal框架之App接口极速开发:参数自动化校验

Coley_5
关注TA
已关注
手记 86
粉丝 8548
获赞 6550

这里写图片描述
简单做法
Controller中

public void regist(){
        String name = getPara("name");
        String password = getPara("password");
        String mobile = getPara("mobile");
        boolean result = service.regist(name,password,mobile);
        if(result){
            // 注册成功
        }else{
            // 注册失败
        }
    }
    public void login(){
        String name = getPara("name");
        String password = getPara("password");
        String mobile = getPara("mobile");
        User user = service.login(password,mobile);
        if(user != null){
            // 登录成功
        }else{
            // 登录失败
        }
    }

Service中

public boolean regist(String name,String password,String mobile){
        if(name == null || name.equals("")){
            return false;// 或抛出异常
        }
        if(password == null || password.equals("")){
            return false;// 或抛出异常
        }
        if(mobile == null || mobile.equals("")){
            return false;// 或抛出异常
        }

        // 注册逻辑
        ...
        // dao
    }
    public User login(String password,String mobile){

        if(mobile == null || mobile.equals("")){
            return null;  // 或抛出异常
        }
        if(password == null || password.equals("")){
            return null; // 或抛出异常
        }

        // 登录逻辑
        ...
        // dao
    }

接下来开始重构以上代码
要重构就得先抽取,再捋一遍业务逻辑
①客户端发出请求
②服务器收到请求
③路由分配给相应的Controller
④获取数据参数
⑤调用service
⑥对参数进行相应的校验
⑦根据不同的业务处理相关的逻辑
⑧调用相应的dao层进行数据持久层处理
⑨返回相应数据结果到客户端

其中④⑥⑨是所有的业务执行的都是相同的操作。一个一个来抽取。
④获取所有参数: 这一步比较简单,在Controller层中首先获取所有请求参数,存放到一个Map集合中,把这个Map集合作为参数传递到service层。
我们可以通过 request.getParameterMap()获取到所有的参数信息

    public Map<String, String[]> getParaMap() {
        return request.getParameterMap();
    }

由于返回的是key为String值却是String[]数据,操作不是很方便,我们可以自定义一个包装类来存放参数集合,便于获取

package white.yu.bug.utils;

import java.util.Map;

public class ParamsMap {

    private Map<String, String[]> map;

    public ParamsMap(Map<String, String[]> map) {
        this.map = map;
    }

    public String get(String key) {
        return get(key, null);
    }

    public String get(String key, String defValue) {
        String result = getValue(key);
        return result != null && !"".equals(result) ? result : defValue;
    }

    public Integer getInt(String key, Integer defValue) {
        return toInt(getValue(key), defValue);
    }

    public Integer getInt(String key) {
        return toInt(getValue(key), null);
    }

    private String getValue(String key) {
        String[] strs = map.get(key);
        if (strs == null || strs.length == 0) {
            return null;
        } else {
            return strs[0];
        }
    }

    private Integer toInt(String value, Integer defaultValue) {
        if (value == null || "".equals(value.trim()))
            return defaultValue;
        return Integer.parseInt(value);
    }

}

⑥⑨一并进行处理:
思路:首先我们在service层加上一个标记注解,标记当前需要校验那些字段,在Controller中index()方法中反射调用service层的方法,取出service层的注解标记,进行相应的校验,并执行相应的service业务逻辑。创建一个统一返回数据格式,处理之后返回到Controller统一返回给客户端
创建一个注解

@Documented
@Target(ElementType.METHOD)
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface ParamsCheck {
    String[] nullCheck();
}

(注:这里为了简单只做了简单的判空校验,如果需要其他如手机号,身份证等校验,再加上即可)
在BaseController中声明一路由代理方法

protected void invoke(Class<?> clazz) throws IllegalAccessException,
            IllegalArgumentException, InvocationTargetException,
            InstantiationException, NoSuchMethodException, SecurityException {
        String action = getPara();  //  --- 如果请求的url是www.white.com/api/user/regist 则getPara()获取到的是 regist

        Map<String, String[]> paraMap = getParaMap(); // 获取所有参数
        ApiResult<?> r = null;
        if (paraMap.size() == 0) {
            // 没有参数的情况
            Method method = clazz.getDeclaredMethod(action);
            r = (ApiResult<?>) method.invoke(clazz.newInstance());
        } else {
            Method method = clazz.getDeclaredMethod(action, ParamsMap.class);
            //获取注解信息
            ParamsCheck annotation = method.getAnnotation(ParamsCheck.class);
            if (annotation != null) {
                String[] params = annotation.nullCheck();
                for (int i = 0; i < params.length; i++) {
                    // 判空校验
                    if (paraMap.get(params[i]) == null) {
                        // 如果为空,则直接返回相应的错误信息
                        renderJson(ApiResult.paramError(params[i]));
                        return;
                    }
                }
            }
            r = (ApiResult<?>) method.invoke(clazz.newInstance(),
                    new ParamsMap(paraMap));
        }
        renderJson(r);

    }

定义一个统一返回数据格式

package white.yu.bug.utils;

public final class ApiResult<T> {
    /**
     * 请求成功
     */
    public static final int SUCCESS = 2000;
    /**
     * 请求失败
     */
    public static final int ERROR = 4000;
    /**
     * 参数缺失或错误
     */
    public static final int PARAMS_ERROR = 4001;

    /**
     * 返回码
     */
    private int code;

    /**
     * 返回数据
     */
    private T data;

    /**
     * 错误消息提示
     */
    private String msg;

    private ApiResult(int code, T data) {
        this.code = code;
        this.data = data;
    }
    private ApiResult(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    private ApiResult(int code) {
        this.code = code;
    }

    public static <T> ApiResult<T> success() {
        return new ApiResult<T>(SUCCESS);
    }

    public static <T> ApiResult<T> success(T data) {
        return new ApiResult<T>(SUCCESS, data);
    }

    public static <T> ApiResult<T> error() {
        return new ApiResult<T>(ERROR);
    }
    public static <T> ApiResult<T> paramError() {
        return new ApiResult<T>(PARAMS_ERROR);
    }

    public static <T> ApiResult<T> paramError(String key) {
        return new ApiResult<T>(PARAMS_ERROR,"[ "+key + " ]is null");
    }

    public static <T> ApiResult<T> error(int code) {
        return new ApiResult<T>(code);
    }
    public static <T> ApiResult<T> error(String msg) {
        return new ApiResult<T>(ERROR,msg);
    }
    public static <T> ApiResult<T> error(int code,T data) {
        return new ApiResult<T>(code, data);
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

}

使用

public class UserController extends BaseController{

    public void index(){
        try {
            invoke(UserServiceImpl.class);
        } catch(NoSuchMethodException e) {
            renderJson(ApiResult.error(404));
            e.printStackTrace();
        } catch (Exception e) {
            renderJson(ApiResult.error(500));
            e.printStackTrace();
        }
    }

}
public class UserServiceImpl implements UserService{

    @ParamsCheck(nullCheck={"name","mobile","password"})
    public ApiResult<?> regist(ParamsMap params) {
        String name = params.get("name");
        String mobile = params.get("mobile");
        String password = params.get("password");
        // 调用 dao 层进行处理
        System.out.println("调用 dao 层进行处理"); 
        System.out.println("注册成功"); 
        return ApiResult.success(name +":"+mobile + ":"+password);
    }

}

效果
参数缺失
这里写图片描述
参数完整
这里写图片描述

这里我只做了简单的空值校验,同理也可加上身份证信息,号码信息,长度,数据格式等的校验。
在Controller中也可对Service进行相应的工程模式等的动态获取方式,可以不通过Handler就可以调整相应业务逻辑的路由配置

打开App,阅读手记
5人推荐
发表评论
随时随地看视频慕课网APP