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