PS:一个成熟的架构师必须懂得的技术:反射技术。
PS:一个优秀的架构师必须懂得的艺术:偷懒的艺术。
本文整套项目源码打包:链接: http://pan.baidu.com/s/1geGliKV 密码: 3hwc
上文中我们讲过JAVA的APP架构。那么在APP开发中。有一个东西一直让我们反复搬砖。
那是什么呢,没错,参数验证。很快就七夕了,看到这篇文章的友友们,有没有妹子愿意给个机会我送送玫瑰练胆子呢。
所谓参数验证,无非是一个接口需要哪些参数,然而当这些参数是否存在或者存在不满足格式的情况下。要响应一个参数有误的标志。
笔者怀着对妹子守株待兔的心情,写下这篇文章。如何用注解来规避那些各种验证而引发的一大堆if判断。
首先我们建立一个简单的注解。里面包含空验证以及格式的正则。
@Retention(RetentionPolicy.RUNTIME) 在这个注解标记下。当前注解将可以被反射读取到。
@Target(ElementType.FIELD) 代表当前注解用于字段。
如果是spring项目或者web项目,可以用AOP来实现自动验参。笔者近日为了方便,直接在上次的那个APP架构上来进行处理。
那么验证将放在API接口的入口。
调整之后
然后我们来看下效果
如下是当前过滤器的全部代码。
package com.app.server.filter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.app.server.annotation.ParamCheck;
import com.app.server.annotation.ReqType;
import com.app.server.api.base.TurboApi;
import com.app.server.enm.APIRespEnum;
import com.app.server.entity.BeanFieldEntity;
import com.app.server.util.GsonUtil;
import com.app.server.util.PropertUtil;
import com.app.server.util.SpringContextHelper;
import com.app.server.util.StringUtils;
import com.app.server.vo.base.BaseReqVO;
public class APIFilter implements Filter {
private static final String apiFunctionName="execute";
@Override
public void doFilter(ServletRequest servReq, ServletResponse servResp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servReq;
HttpServletResponse response = (HttpServletResponse) servResp;
response.setCharacterEncoding("utf-8");
String apiName = request.getHeader("APIName");
System.out.println("请求接口名:" + apiName);
TurboApi api = (TurboApi) SpringContextHelper.getBean(apiName);
if (api == null) {
writeEnum(response,APIRespEnum.API_NOT_FOUND);
return;
}
try {
//获得接口方法所需ReqVO类型
Class<?> reqVoCla=getAPIParaType(api);
//接受客户端json参数
String json=GsonUtil.getJsonContent(request);
System.out.println("请求参数:"+json);
//获得请求对象
BaseReqVO reqVO=(BaseReqVO) GsonUtil.jsonToObject(json, reqVoCla);
//进行参数验证
APIRespEnum errEnum=checkPara(reqVO);
if(!StringUtils.isNullOrEmpty(errEnum)){
writeEnum(response,errEnum);
return;
}
//执行api方法
Object obj=api.execute(request, reqVO);
//响应json结果
String context=GsonUtil.objectToJson(obj);
writeMsg(response,context);
return;
} catch (Exception e) {
// TODO: handle exception
}
return;
}
private Class<?> getAPIParaType(TurboApi api){
Method method=PropertUtil.getMethod(api.getClass(), apiFunctionName, HttpServletRequest.class,BaseReqVO.class);
Annotation[][] annoss=method.getParameterAnnotations();
for (Annotation[] annos:annoss) {
for (Annotation anno:annos) {
if(anno instanceof ReqType){
return ((ReqType) anno).value();
}
}
}
return null;
}
private APIRespEnum checkPara(BaseReqVO reqVO){
List<BeanFieldEntity> entitys=PropertUtil.getBeanFields(reqVO);
for (BeanFieldEntity entity:entitys) {
ParamCheck check= entity.getSourceField().getAnnotation(ParamCheck.class);
if(!check.allowNull()){
Object obj=PropertUtil.getFieldValue(reqVO, entity.getFieldName());
String msg=check.errorMsg();
if(StringUtils.isNullOrEmpty(obj)){
return getParaErrEnum(APIRespEnum.PARA_IS_NULL,entity.getFieldName(),msg);
}
if(!StringUtils.isNullOrEmpty(check.format())){
if(!StringUtils.isMatcher(obj.toString(), check.format())){
return getParaErrEnum(APIRespEnum.PARA_ERROR,entity.getFieldName(),msg);
}
}
if(!StringUtils.isNullOrEmpty(check.orNulls())){
List<Object> values=PropertUtil.getFieldValues(reqVO, check.orNulls());
if(!StringUtils.isAllNull(values)){
return getParaErrEnum(APIRespEnum.PARAS_IS_NULL,entity.getFieldName()+":"+check.orNulls().toString(),msg);
}
}
}
}
return null;
}
private APIRespEnum getParaErrEnum(APIRespEnum enm,String fieldName,String msg){
APIRespEnum currNum=enm;
if(!StringUtils.isNullOrEmpty(msg)){
currNum.setMsg(msg);
}
currNum.setMsg(currNum.getMsg()+":"+fieldName);
return currNum;
}
private void writeEnum(HttpServletResponse response,APIRespEnum msgEnum) {
String context = msgEnum.toJson();
writeMsg(response,context);
}
private void writeMsg(HttpServletResponse response,String context) {
try {
PrintWriter out = response.getWriter();
out.print(context);
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
}
@Override
public void destroy() {
}
}
JAVA技术交流群:218481849