# 系列文3:前后端彻底解耦!统一入参解析,前端只发JSON,后端随意
系列文3前后端彻底解耦统一入参解析前端只发JSON后端随意非科班野生程序员深耕政务信息化20年这套自研Java Web框架支撑过省级新农保、全国跨省医保结算等核心民生系统18年稳定运行至今。本系列拆解10个核心架构决策全是政务场景踩坑后的实用解法不求优雅但求落地愿同赛道朋友少走弯路也欢迎懂行大佬轻拍指正。最后感谢豆包、智谱、OpenCode决策是我做的代码是我搓的文字是他们总结的。背景前端只有一种通信方式POST JSON。但后端方法签名各不相同——有的要DataCenter有的要HttpServletRequest有的要自定义Dao对象有的要ListDao。能不能让框架根据方法签名自动把 JSON 转换成对应的参数类型比如// 方法1要 DataCenter requestpublicDataCentersave(DataCenterdc,HttpServletRequestreq){...}// 方法2要一个 UserDao 对象publicvoidupdate(UserDaouser){...}// 方法3要一个 ListpublicvoidbatchSave(ListUserDaousers){...}前端不管后端方法签名是什么统一 POST JSON 就行。框架根据方法的参数类型列表自动做类型转换。我的方案在route.java里写了一个praserInParameter()方法根据方法签名自动做参数转换。下面是完整的真实源码praserInParameter() 方法publicstaticObject[]praserInParameter(HttpServletRequestrequest,HttpServletResponseresponse,MethodMapmothodmap)throwsTypeException,IOException{Object[]paramValuesnull;Stringdc;intparameterCountmothodmap.getParametertypeList().size();booleanisreadfalse;if(parameterCount0){paramValuesnewObject[parameterCount];for(inti0;iparameterCount;i){Objecttempnull;SuppressWarnings(rawtypes)Classclsmothodmap.getParametertypeList().get(i);if(clsHttpServletRequest.class){temprequest;}elseif(clsHttpServletResponse.class){tempresponse;}elseif(clsHashMap.class){tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(request);}elseif(clsList.class){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc,mothodmap.getParameterGenerictList().get(i));}elseif(clsnewDataStore.class){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc,mothodmap.getParameterNameList().get(i),mothodmap.getParameterGenerictList().get(i));}else{if(clsDataCenter.class){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc);}elseif(cls.getName().startsWith(com.browise)){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc,cls);}else{temprequest.getParameter(mothodmap.getParameterNameList().get(i));tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(temp);}}paramValues[i]temp;}}returnparamValues;}逻辑拆解这段代码的核心就是遍历方法的参数类型列表对每个参数做不同的处理1. HttpServletRequest / HttpServletResponse直接透传不转换if(clsHttpServletRequest.class){temprequest;}elseif(clsHttpServletResponse.class){tempresponse;}方法里需要 request/response 的直接给你。2. HashMap文件上传elseif(clsHashMap.class){tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(request);}如果参数类型是 HashMap走文件上传的处理逻辑。3. List 类型elseif(clsList.class){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc,mothodmap.getParameterGenerictList().get(i));}List 类型比较特殊——需要知道泛型类型List 里装的是什么所以额外传了parameterGenerictList。泛型信息是在BeanFactory启动时通过getMethodGenericInfo()方法解析的。4. newDataStore 类型elseif(clsnewDataStore.class){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc,mothodmap.getParameterNameList().get(i),mothodmap.getParameterGenerictList().get(i));}这是框架特有的数据结构需要参数名和泛型信息来定位 JSON 中的对应数据块。5. DataCenter 类型if(clsDataCenter.class){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc);}DataCenter是框架的核心数据结构相当于一个增强版的 Map。JSON 反序列化成 DataCenter框架自动处理。6. com.browise 包下的自定义 Daoelseif(cls.getName().startsWith(com.browise)){if(!isread){dcreadDc(request);isreadtrue;}tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(dc,cls);}如果参数是自定义的 Dao 类如 UserDao、OrderDao框架会把 JSON 自动反序列化成对应的 Dao 对象。业务代码直接拿到就是 Java 对象不需要手动解析。7. 普通类型String、int等else{temprequest.getParameter(mothodmap.getParameterNameList().get(i));tempTypeHandlerFactory.newInstance().getTypeHandler(cls).parse(temp);}普通类型从 URL 参数里取值然后通过TypeHandlerFactory做类型转换String→int、String→Date 等。这里的parameterNameList就是系列文5 ASM 读取到的参数名。isread 标志注意一个细节isread标志。因为readDc(request)只能调用一次request 的输入流只能读一次所以用一个布尔变量确保只读一次 JSON后面需要的地方复用dc变量。效果前端永远只管发 JSON后端方法签名随意定义// 方式1通用数据容器 requestresponseMapping(key/save)publicDataCentersave(DataCenterdc,HttpServletRequestreq){...}// 方式2自动反序列化为 DaoresponseMapping(key/update)publicvoidupdate(UserDaouser){...}// 方式3支持泛型列表responseMapping(key/batchSave)publicvoidbatchSave(ListUserDaousers){...}不管方法要什么类型的参数框架自动根据签名做转换。前端完全不需要知道后端方法签名是什么。为什么这样做在这个决策之前每个业务方法都要自己解析参数——从 request 里取值、类型转换、拼装对象。这些重复代码占了每个方法的前几行而且容易出错。有了praserInParameter()之后参数解析变成了框架的事。业务方法直接拿到想要的类型只关注业务逻辑。决策原则前端不关心后端方法签名后端不关心数据是怎么来的。前后端彻底解耦。这个原则也贯穿了整个框架的设计——框架做中间的翻译层前端和后端各自用自己最舒服的方式工作。你觉得前后端参数自动转换这种方式怎么样有没有什么潜在的问题欢迎评论区讨论。系列导航- 上一篇[系列文2新老代码共存的终极解法——注解路由参数路由平滑迁移]- 下一篇[系列文4轻量AOP落地CGLIB代理责任链搞定事务日志监控]作者许彰午| 非科班野生程序员深耕政务信息化20年标签#Java #参数解析 #前后端解耦 #JSON #反射 #类型转换 #政务信息化 #技术复盘
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2501891.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!