本篇文章只涉及到应用层面,没有涉及到什么底层原理之类的,我目前的实力还没有达到那个级别。如果是大神级别的人看到这篇文章,请跳过。

项目框架也已经是搭建好了的,springboot版本为1.5,数据库操作使用的是Mybatis,数据库使用的Oracle,前端使用VUE,Node.js打包之类的。由于

实际需要,要在多个项目之间相互调用,其中一种方式是访问一个固定的项目,只有一台服务器;还有一种方式是调用一个项目,该项目部署了多台服

务器。

调用方式一

通过一个项目调用另外一个项目,调用地址固定,调用方式为通过  RestTemplate 这个类来进行调用,由spring提供。这样调用的原因是当前这个

项目中有不同的数据源,除了Oracle的还有其他的数据库,可是其他的数据库连接资源有限,除了我们负责的子项目在调用外,其他人也在进行调用。

所以最后就将被调用方做成了一个单独的服务,让其他系统之间可以直接调用。大致的实现方式为拿到传递的参数,通过反射的方式拿到对应的service

实现类,然后通过serviceImpl调用Mapper.java中的方法执行增、删、改、查操作,最后将返回的结果返回给调用方。请求时参数的传递方式为通过

Map传输,被调用方通过Map可以直接获取到参数信息。然后通过自定义的JSON工具类来解析数据,分为单个对象

数据、列表数据、分页数据。经过反复的调试,最终很好的实现了需求,解决了当前项目中存在的问题。

解析返回参数的工具类为//

@Slf4j

@Component

@Scope(value = "singleton")//显示单例

public class AnalysisGBaseDataUtils implements InitializingBean {

//私有化构造方法

private AnalysisGBaseDataUtils(){}

private static RestTemplate restTemplate = new RestTemplate();

private static String gbaseApi;

@Value("${gbase.api.prefix}")

private String getGbaseApi;

@Override

public void afterPropertiesSet() throws Exception {

AnalysisGBaseDataUtils.gbaseApi = this.getGbaseApi;

}

/**

* @Description: 方法参数校验

* @author: 1

* @date: 2020-9-5 10:13:10

* @param: @param

* @param: @param dataMap

* @param: @param e

* @param: @return

* @return: String

*/

private static String paramValidate(Map dataMap, E e) {

if(Objects.equal(dataMap, null)) {

throw new BaseException(MessageConstant.A000001, "dataMap参数错误");

}

if(Objects.equal(e, null)) {

throw new BaseException(MessageConstant.A000001, "E类型参数错误");

}

if(Objects.equal(dataMap.get("methodName"), null)) {

throw new BaseException(MessageConstant.A000001, "dataMap中methodName参数不能为null!");

}

if(Objects.equal(dataMap.get("serviceId"), null)) {

throw new BaseException(MessageConstant.A000001, "dataMap中serviceId参数不能为null!");

}

String methodName = (String)dataMap.get("methodName");

String serviceId = (String)dataMap.get("serviceId");

if(StringUtils.isBlank(methodName)) {

throw new BaseException(MessageConstant.A000001, "dataMap中methodName参数错误!");

}

if(StringUtils.isBlank(serviceId)) {

throw new BaseException(MessageConstant.A000001, "dataMap中serviceId参数错误!");

}

return methodName;

}

/**

* @Description: 抽取列表数据解析方法

* @author: 1

* @date: 2020-9-5 10:13:30

* @param: @param

* @param: @param methodName

* @param: @param resultStr

* @param: @param e

* @param: @return

* @return: List extends Object>

*/

private static List extends Object> analysisData(String methodName, String resultStr, E e) {

List extends Object> parseArray = JsonUtils.parseArray(resultStr,"data", e.getClass());

return parseArray;

}

/**

* @Description: 解析分页数据:新方法,使用更方便(直接传入 class 对象),备用

* @author: 1

* @date: 2020-9-21 21:41:03

* @param: @param

* @param: @param dataMap

* @param: @param clazz

* @param: @return

* @return: Page

*/

public static final Page getPageData(Map dataMap, final Class clazz) {

E e = AnalysisGBaseDataUtils.getInstance(clazz);

String methodName = AnalysisGBaseDataUtils.paramValidate(dataMap, e);

Page pages = null;

String resultStr = AnalysisGBaseDataUtils.sendRequest(dataMap, methodName);

try {

pages = new Page();

String pageData = JsonUtils.getSubJson(resultStr, "data");

pages.setCount(true);

if(Objects.equal("[]", pageData)) {

//未获取到数据

pages.setPageNum(1);

pages.setPageSize(10);

pages.setTotal(0);

pages.setPages(0);

}else {

pages.setPageNum(JsonUtils.parse(pageData, "pageNum"));

pages.setPageSize(JsonUtils.parse(pageData, "pageSize"));

Integer total = JsonUtils.parse(pageData, "total");

pages.setTotal(total);

pages.setPages(JsonUtils.parse(pageData, "pages"));

List extends Object> parseArray = AnalysisGBaseDataUtils.analysisData(methodName, pageData, e);

if(!Objects.equal(parseArray, null)) {

for (Object obj : parseArray) {

pages.add((E) obj);

}

}

}

}catch(Exception error) {

AnalysisGBaseDataUtils.log.error(methodName + "-方法-getPageData(clazz)-数据解析错误: " + error.getMessage(), error);

throw new BaseException(MessageConstant.A000001, methodName + "-方法-getPageData(clazz)-数据解析错误");

}

return pages;

}

/**

* @Description: 解析列表数据:新方法,使用更方便(直接传入 class 对象),备用

* @author: 1

* @date: 2020-9-22 14:18:22

* @param: @param

* @param: @param dataMap

* @param: @param clazz

* @param: @return

* @return: List

* @throws IllegalAccessException

* @throws InstantiationException

*/

public static final List getListData(Map dataMap, final Class clazz) {

List resultList = new ArrayList();

E e = AnalysisGBaseDataUtils.getInstance(clazz);

String methodName = AnalysisGBaseDataUtils.paramValidate(dataMap, e);

String resultStr = AnalysisGBaseDataUtils.sendRequest(dataMap, methodName);

try {

List extends Object> parseArray = AnalysisGBaseDataUtils.analysisData(methodName, resultStr, e);

if(!Objects.equal(parseArray, null)) {

for (Object object : parseArray) {

resultList.add((E) object);

}

}

}catch(Exception error) {

AnalysisGBaseDataUtils.log.error(methodName + "-方法getListData(clazz)数据解析错误: " + error.getMessage(), error);

throw new BaseException(MessageConstant.A000001, methodName + "-方法getListData(clazz)数据解析错误");

}

return resultList;

}

/**

* @Description: 解析单条数据:新方法,使用更方便(直接传入 class 对象),备用

* @author: 1

* @date: 2020-9-5 10:12:04

* @param: @param

* @param: @param dataMap

* @param: @param e

* @param: @return

* @return: E

*/

public static final E getBeanData(Map dataMap, final Class clazz) {

E e = AnalysisGBaseDataUtils.getInstance(clazz);

String methodName = AnalysisGBaseDataUtils.paramValidate(dataMap, e);

String resultStr = AnalysisGBaseDataUtils.sendRequest(dataMap, methodName);

try {

e = (E) JsonUtils.parse(resultStr, "data", clazz);

}catch(Exception error) {

AnalysisGBaseDataUtils.log.error(methodName + "-方法-getBeanData(clazz)-数据解析错误: " + error.getMessage(), error);

throw new BaseException(MessageConstant.A000001, methodName + "-方法-getBeanData(clazz)-数据解析错误");

}

return e;

}

/**

* @Description: 抽取发送请求的方法

* @author: 1

* @date: 2020-9-28 13:55:24

* @param: @param dataMap

* @param: @param methodName

* @param: @return

* @return: String

*/

private static String sendRequest(Map dataMap, String methodName) {

String resultStr = AnalysisGBaseDataUtils.restTemplate.postForObject(AnalysisGBaseDataUtils.gbaseApi, dataMap, String.class);

Integer code = JsonUtils.parse(resultStr, "code");

if(!Objects.equal(code, 20000)) {

String msg = JsonUtils.parse(resultStr, "msg", String.class);

AnalysisGBaseDataUtils.log.error(methodName + "-方法-sendRequest-操作错误: {}",msg );

throw new BaseException(MessageConstant.A000001, methodName + "-方法-sendRequest-操作错误: " + msg);

}

return resultStr;

}

/**

* @Description: 抽取获取实例的方法

* @author: 1

* @date: 2020-9-28 14:04:42

* @param: @param

* @param: @param clazz

* @param: @return

* @return: E

*/

private static final E getInstance(final Class clazz) {

E e = null;

try {

e = (E) clazz.newInstance();

} catch (InstantiationException | IllegalAccessException error) {

AnalysisGBaseDataUtils.log.error(clazz.toString() + "-方法-getInstance-获取实例错误: " + error.getMessage(), error);

throw new BaseException(MessageConstant.A000001, clazz.toString() + "-方法-getInstance-获取实例错误");

}

return e;

}

}

JSONUtils工具类为//

public class JsonUtils {

/**

*

* 对象转化为json字符串

*

* @param obj 待转化对象

* @return 代表该对象的Json字符串

*/

public static final String toJson(final Object obj) {

return JSON.toJSONString(obj);

// return gson.toJson(obj);

}

/**

*

* 对象转化为json字符串

*

* @param obj 待转化对象

* @return 代表该对象的Json字符串

*/

public static final String toJson(final Object obj, SerializerFeature... features) {

return JSON.toJSONString(obj, features);

// return gson.toJson(obj);

}

/**

* 对象转化为json字符串并格式化

*

* @param obj

* @param format 是否要格式化

* @return

*/

public static final String toJson(final Object obj, final boolean format) {

return JSON.toJSONString(obj, format);

}

/**

* 对象对指定字段进行过滤处理,生成json字符串

*

* @param obj

* @param fields 过滤处理字段

* @param ignore true做忽略处理,false做包含处理

* @param features json特征,为null忽略

* @return

*/

public static final String toJson(final Object obj, final String[] fields, final boolean ignore,

SerializerFeature... features) {

if (fields == null || fields.length < 1) {

return toJson(obj);

}

if (features == null)

features = new SerializerFeature[] { SerializerFeature.QuoteFieldNames };

return JSON.toJSONString(obj, new PropertyFilter() {

@Override

public boolean apply(Object object, String name, Object value) {

for (int i = 0; i < fields.length; i++) {

if (name.equals(fields[i])) {

return !ignore;

}

}

return ignore;

}

}, features);

}

/**

*

* 解析json字符串中某路径的值

*

* @param json

* @param path

* @return

*/

@SuppressWarnings("unchecked")

public static final E parse(final String json, final String path) {

String[] keys = path.split(",");

JSONObject obj = JSON.parseObject(json);

for (int i = 0; i < keys.length - 1; i++) {

obj = obj.getJSONObject(keys[i]);

}

return (E) obj.get(keys[keys.length - 1]);

}

/**

*

* json字符串解析为对象

*

* @param json 代表一个对象的Json字符串

* @param clazz 指定目标对象的类型,即返回对象的类型

* @return 从json字符串解析出来的对象

*/

public static final T parse(final String json, final Class clazz) {

return JSON.parseObject(json, clazz);

}

/**

*

* json字符串解析为对象

*

* @param json json字符串

* @param path 逗号分隔的json层次结构

* @param clazz 目标类

*/

public static final T parse(final String json, final String path, final Class clazz) {

String[] keys = path.split(",");

JSONObject obj = JSON.parseObject(json);

for (int i = 0; i < keys.length - 1; i++) {

obj = obj.getJSONObject(keys[i]);

}

String inner = obj.getString(keys[keys.length - 1]);

return parse(inner, clazz);

}

/**

* 将制定的对象经过字段过滤处理后,解析成为json集合

*

* @param obj

* @param fields

* @param ignore

* @param clazz

* @param features

* @return

*/

public static final List parseArray(final Object obj, final String[] fields, boolean ignore,

final Class clazz, final SerializerFeature... features) {

String json = toJson(obj, fields, ignore, features);

return parseArray(json, clazz);

}

/**

*

* 从json字符串中解析出一个对象的集合,被解析字符串要求是合法的集合类型

* (形如:["k1":"v1","k2":"v2",..."kn":"vn"])

*

* @param json - [key-value-pair...]

* @param clazz

* @return

*/

public static final List parseArray(final String json, final Class clazz) {

return JSON.parseArray(json, clazz);

}

/**

*

* 从json字符串中按照路径寻找,并解析出一个对象的集合,例如:

* 类Person有一个属性name,要从以下json中解析出其集合:

* {

* "page_info":{

* "items":{

* "item":[{"name":"KelvinZ"},{"name":"Jobs"},...{"name":"Gates"}]

* }

* }

* 使用方法:parseArray(json, "page_info,items,item", Person.class),

* 将根据指定路径,正确的解析出所需集合,排除外层干扰

*

* @param json json字符串

* @param path 逗号分隔的json层次结构

* @param clazz 目标类

* @return

*/

public static final List parseArray(final String json, final String path, final Class clazz) {

String[] keys = path.split(",");

JSONObject obj = JSON.parseObject(json);

for (int i = 0; i < keys.length - 1; i++) {

obj = obj.getJSONObject(keys[i]);

}

String inner = obj.getString(keys[keys.length - 1]);

List ret = parseArray(inner, clazz);

return ret;

}

/**

*

* 有些json的常见格式错误这里可以处理,以便给后续的方法处理

* 常见错误:使用了\" 或者 "{ 或者 }",腾讯的页面中常见这种格式

*

* @param invalidJson 包含非法格式的json字符串

* @return

*/

public static final String correctJson(final String invalidJson) {

String content = invalidJson.replace("\\\"", "\"").replace("\"{", "{").replace("}\"", "}");

return content;

}

/**

* 格式化Json

*

* @param json

* @return

*/

public static final String formatJson(String json) {

Map, ?> map = (Map, ?>) JSON.parse(json);

return JSON.toJSONString(map, true);

}

/**

* 获取json串中的子json

*

* @param json

* @param path

* @return

*/

public static final String getSubJson(String json, String path) {

String[] keys = path.split(",");

JSONObject obj = JSON.parseObject(json);

for (int i = 0; i < keys.length - 1; i++) {

obj = obj.getJSONObject(keys[i]);

System.out.println(obj.toJSONString());

}

return obj != null ? obj.getString(keys[keys.length - 1]) : null;

}

}

通过这种方式很好的解决了当前项目中需要相互调用的问题,而且也非常适合当前项目的实际情况。

这中间遇到一个比较棘手的问题是,在数据返回时,分页数据不能直接使用,需要转换一次才能使用。

转换方法也很简单,如下,

由于该项目的访问量不是太大,因此这种方式完全符合要求,解决了项目中存在的问题。

调用方式二

第二种调用方式和第一种有些区别,第二种调用方式的项目部署了多台服务器,如果仍然通过第一种方式来调用则不能满足要求。

第一种调用方式只适合有一台服务器的情况,第二种就只能通过feign来调用了。这种调用方式的作用在于通过调用来实现数据的同步。

先看一下当前项目中的一种实现方式,先定义feign调用的接口,然后定义一个feign接口的实现类,然后在写一个具体的调用接口和实现

类。在具体的实现类中,将feign接口当做成员变量,然后调用feign接口种的方法实现调用。最后实际调用时,是通过callFixDataService

实现调用的。

CallBigDataFeign

CallBigDataFeignFallBack

CallFixDataService

CallFixDataServiceImpl

最终调用方式,通过fastJson包下面的JSONObject和JSONOArray来进行调用。

配置方式为,地址可以配置多个,中间使用逗号分隔。

最终通过测试,这种方式完全符合业务要求,实现了一个项目调用另外一个部署在多台服务器上的项目。

java 多个项目间事物_Java-web-多个独立项目之间相互调用实践相关推荐

  1. WinCC项目函数之间相互调用

    采用WinCC作为上位机框架进行开发工业控制界面,全局脚本中C-Editor进行开发工业控制模型. 我们用C#或者C++时,方法之间调用.类调用等等,比较灵活.其实WinCC和C#或者C++一样. 项 ...

  2. java web网上书店_java web简易网上书店项目系列,使用MVC模式(servlet+jstl+dbutils),开篇...

    一. 针对很多java web初学者入门困难的问题,笔者利用一个小型web项目,一步一步的展示java web开发方法,每一个章节引入一些java web开发的重点知识,让同学们可以将java web ...

  3. java输出的汉字变成乱码_Java Web项目中解决中文乱码方法总结

    一.了解常识: 1.UTF-8国际编码,GBK中文编码.GBK包含GB2312,即如果通过GB2312编码后可以通过GBK解码,反之可能不成立; 2.web tomcat:默认是ISO8859-1,不 ...

  4. java移动端开发教程视频_Java Web开发-项目部分(中国移动科技综合管理系统)视频教程 - JavaWeb - Java - 私塾在线 - 只做精品视频课程服务...

    第01节课:进行整体课程概览:参看其他项目,总结需要实现的功能:讲解本次项目练习要实现的功能:基本的业务功能介绍 第02节课:页面布局:框架使用:页面上菜单的使用:项目基本的数据字典:构建包结构和划分 ...

  5. java 业务层业务接口层_Java web五层架构

    DAO层: 1.DAO层--[面向表]: 持久层.数据访问层,主要与数据库进行交互 介绍: DAO层只是封装增删改查,比较底层,比较基础的操作,具体到对于某个表.某个实体的增删改查.至于增删查改如何去 ...

  6. web项目答辩总结_java web 答辩总结

    今天我们组答辩.在昨天前三个组答辩之后,整理了一些试题. 在这个项目的答辩准备:首先把这个java web这本书大概的看了一遍:对整理的那些试题也把答案整理出来了:针对老师提问频率较高的试题:针对自己 ...

  7. java接口注入对象的意义_Java Web系列:Spring依赖注入基础

    一.Spring简介 1.Spring简化Java开发 Spring Framework是一个应用框架,框架一般是半成品,我们在框架的基础上可以不用每个项目自己实现架构.基础设施和常用功能性组件,而是 ...

  8. java 反正多次重复提交_java web开发时防止刷新后的重复提交

    在java web开发过程中大家经常都会遇到页面刷新后重复提交导致数据库数据重复的情况出现. 那么,如何避免重复提交数据的情况出现呢?如下代码,是在jsp中解决重复提交的一种方式. //此段代码用于防 ...

  9. java 新窗口跳转页面_Java web开发中页面跳转小技巧——跳转后新页面在新窗口打开...

    最近学习Java web,在学习过程中想实现一个需求,就是在jsp页面跳转的时候,希望跳转后的新页面在新窗口中打开, 而不是覆盖原来的页面,这个需求使我困惑了好长时间,后来通过大海捞针似的在网上寻找方 ...

最新文章

  1. html应用缓存,HTML5应用缓存
  2. 几个关于money处理的函数
  3. 计算机英语基础课程论文,计算机专业英语课程教学论文
  4. 如何得到别人的上网帐号和密码
  5. js获取一个月份最大天数和获取月的最后一天
  6. OC中property的有关属性
  7. Ext this.getView(...).saveDocumentAs is not a function
  8. 正则表达式 - C语言
  9. Go编程笔记(28)
  10. mysql的初始化语句是_MySQL入门之预处理语句的使用
  11. 惠普笔记本电脑驱动BIOS下载中心,战66驱动下载
  12. java实现socket长连接_java如何实现Socket的长连接和短连接
  13. java 开发工具eli_二进制开发ELI5 –第1部分
  14. 过年了,想窝在家里把这些黑客电影都看完(附剧情简介和评分)
  15. Either health or status endpoint must be enabled,
  16. 超融合的网络bond和bridge模式。kvm+bond+bridge
  17. 10万弹幕大军带你一起看芒果热播综艺《披荆斩棘的哥哥》
  18. Unix/Linux中中文图像输出乱码问题。
  19. UML图:活动图详细介绍
  20. 获取一个月中第几个周的第几天的具体日期

热门文章

  1. 【论文写作】SSM房屋租赁系统如何写设计总结
  2. 我对象说陪我过七夕,象说没时间,我一怒给女神做了一个某音上很火的3D旋转相册
  3. 判断相等_C语言判断字符串是否为回文
  4. Python+OpenCV:理解k近邻(kNN)算法(k-Nearest Neighbour (kNN) algorithm)
  5. 基于机器视觉的电容表面字符检测
  6. Halcon:标准标定板的自制方法
  7. Vue项目中的RSA加解密
  8. 2018 我所了解的 Vue 知识大全(一)
  9. MyBatis参数为Integer型并赋值为0时判断失误的问题解决
  10. Python-语句结构