文档章节

APP后端架构之Bean后端接口

Coody
 Coody
发布于 2017/02/17 13:57
字数 773
阅读 66
收藏 5

 

 

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

© 著作权归作者所有

共有 人打赏支持
Coody
粉丝 25
博文 17
码字总数 14905
作品 5
广州
架构师
私信 提问
app后端设计--总目录

做了3年app相关的系统架构,api设计,先后在3个创业公司中工作,经历过手机网页端,android客户端,iphone客户端,现就职于app云后端平台bmob(想了解bmob点击这里)。其中的乐与苦,得与失,...

云栖希望。
2017/12/04
0
0
一个O2O后端架构问题咨询

一个后端架构问题咨询 业务: O2O,采购方通过App向供应商申请供货,供应商审核通过后 , 采购方可在App上进入该供货商的店铺中进行下单。 后端 仅负责提供Rest Api,前端调用后端提供的接口来...

zgw06629
2015/11/01
178
1
互联网架构,为啥要前后端分离?

通用业务服务化之后,系统的典型后端结构如上: web-server通过RPC接口,从通用业务服务获取数据 biz-service通过RPC接口,从多个基础数据service获取数据 基础数据service通过DAO,从独立d...

xqtesting
2017/12/15
0
0
APP后端服务架构,接口安全

关于APP的后端服务器,接口安全应该具有哪些方面的考虑。 架构需要有哪些方面的考量 创业项目预备20人开发团队。JAVA后端。电商项目。 其实已有一些参考。但纯属我个人想知道大家是怎么做的...

码农的道途
2016/06/13
2.4K
9
互联网分层架构,为啥要前后端分离?

作者:58沈剑,来源:架构师之路 一,典型后端架构 通用业务服务化之后,系统的典型后端结构如上: web-server通过RPC接口,从通用业务服务获取数据 biz-service通过RPC接口,从多个基础数据...

bjweimengshu
2017/12/07
0
0

没有更多内容

加载失败,请刷新页面

加载更多

基于阿里云物联网平台实现的简易出入监控

本文通过一个简单实例,主要介绍了如何使用树莓派快速接入阿里云iot platform,并实现了一个简易的监控人员出入并拍照上送钉钉群的场景 场景 在公司大门入口处布点树莓派和红外感应,实现出入...

阿里云官方博客
3分钟前
0
0
基于阿里云物联网平台,我们这样实现简易出入监控

本文通过一个简单实例,主要介绍了如何使用树莓派快速接入阿里云iot platform,并实现了一个简易的监控人员出入并拍照上送钉钉群的场景 场景 在公司大门入口处布点树莓派和红外感应,实现出入...

阿里云云栖社区
8分钟前
1
0
fedora linux for 龙芯查看实时输出的tomcat日志

软件源带的tomcat版本较低,所以建议从官网下载最新版本。 解压后,执行./startup.sh文件。 查看实时输出的tomcat日志,请使用命令tail -f /usr/share/tomcat/logs/catalina.out。 “/usr/sh...

gugudu
9分钟前
0
0
为什么MySQL数据库要用B+树存储索引?

要回答好这个问题,首先我们要弄懂什么是索引?索引常见的数据结构有哪些?这些数据结构有何优缺点?只有弄懂这些,再去比较,才会知道为啥要用B+树作为MySQL数据库的存储索引了。 一、索引是...

Lienson
10分钟前
0
0
Java重点基础:反射机制

一、什么是反射? Java反射说的是在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性进行调用。我们把这种动态获取对象信...

一个程序员的成长
12分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部