APP后端架构之Bean后端接口

 

 

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

转载于:https://my.oschina.net/hooker/blog/840766

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值