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


简单做法

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就可以调整相应业务逻辑的路由配置


评论区

JFinal

2016-10-28 16:22

这样封装以后,又将开发效率再次提升了。贴代码可以点击编辑器代码语言按钮,选择java语言,这样保存以后的代码就有语法高亮,可读性会提升几个级别。感谢分享

绝尘

2016-10-29 18:37

精益求精,不错,学习了

sphsyv

2016-11-01 08:55

不过看样子好像不适应json格式的参数。例如,我前台是批量datagrid编辑,传递到后台的参数类似于[{name:'',id:''},{name:'',id:''},{}.....],意思就是批量修改名称

tonysb

2017-11-09 13:57

@sphsyv 再怎么传,到后台总归是key-value的形式,如果是json的话,你后台接到value之后,用json框架转换下就能得到自己的数据了

热门分享

扫码入社