文档章节

APP后端架构之Bean后端接口

Coody
 Coody
发布于 2017/02/17 13:57
字数 773
阅读 56
收藏 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
粉丝 21
博文 15
码字总数 14134
作品 5
广州
架构师
一个O2O后端架构问题咨询

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

zgw06629
2015/11/01
152
1
app后端设计--总目录

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

云栖希望。
2017/12/04
0
0
互联网架构,为啥要前后端分离?

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

xqtesting
2017/12/15
0
0
互联网分层架构,为啥要前后端分离?

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

bjweimengshu
2017/12/07
0
0
互联网分层架构系列之四:前后端为什么要分离

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

wqhlmark64
04/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

设计模式:简单工厂模式(静态共产方法模式)

简单工厂的构成包括三个角色: 1)抽象产品类 2)具体产品类(继承抽闲产品类) 3)工厂类(生产具体产品) 具体代码实现 1、抽象产品类 /** * 抽象类 */public abstract class Car ...

京一
6分钟前
0
0
Lombok使用

1 介绍 Lombok是一个简单的Java库,改工具可以通过注解自动地提供一些方法,简化开发。比如编写POJO时需要为每个属性提供getter()方法和setter()方法,这就可以使用Lombok实现。 2 配置 Lomb...

SuperHeroes
15分钟前
0
0
Confluence 6 删除垃圾内容

属性(profile)垃圾 属性垃圾的定义为,一个垃圾用户在 Confluence 创建了用户,但是这个用户在自己的属性页面中添加了垃圾 URL。 如果你有很多垃圾用户在你的系统中创建了属性,你可以使用...

honeymose
17分钟前
0
0
java虚拟机之内存模型

1. 概述 对于从事 C、C++ 程序开发的人员来说,在内存管理领域,他们既是拥有最高权力的「皇帝」又是从事基础工作的「劳动人民」 --- 既拥有每个对象的「所有权」,又担负着每一个对象生命开...

firepation
19分钟前
0
0
解决linux的-bash: ./xx: Permission denied

解决linux的-bash: ./xx: Permission denied 在linux下执行sh文件时提示下面信息: -bash: ./xx.sh: Permission denied解决:chmod 777 xx.sh 1 2 3 4 Linux chmod +755和chmod +777 ......

DemonsI
30分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部