ApiServiceSMOImpl.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. package com.java110.api.smo.impl;
  2. import com.alibaba.fastjson.JSONArray;
  3. import com.alibaba.fastjson.JSONObject;
  4. import com.java110.api.smo.IApiServiceSMO;
  5. import com.java110.common.cache.AppRouteCache;
  6. import com.java110.common.cache.MappingCache;
  7. import com.java110.common.constant.*;
  8. import com.java110.common.exception.*;
  9. import com.java110.common.kafka.KafkaFactory;
  10. import com.java110.common.log.LoggerEngine;
  11. import com.java110.common.util.DateUtil;
  12. import com.java110.common.util.StringUtil;
  13. import com.java110.core.context.ApiDataFlow;
  14. import com.java110.core.context.DataFlow;
  15. import com.java110.core.factory.AuthenticationFactory;
  16. import com.java110.core.factory.DataFlowFactory;
  17. import com.java110.core.factory.GenerateCodeFactory;
  18. import com.java110.entity.center.AppRoute;
  19. import com.java110.entity.center.AppService;
  20. import com.java110.entity.center.DataFlowLinksCost;
  21. import com.java110.event.service.api.ServiceDataFlowEventPublishing;
  22. import com.java110.service.smo.IQueryServiceSMO;
  23. import org.apache.commons.lang3.math.NumberUtils;
  24. import org.springframework.beans.factory.annotation.Autowired;
  25. import org.springframework.http.HttpStatus;
  26. import org.springframework.http.ResponseEntity;
  27. import org.springframework.stereotype.Service;
  28. import org.springframework.web.client.RestTemplate;
  29. import java.util.Date;
  30. import java.util.List;
  31. import java.util.Map;
  32. /**
  33. * 中心服务处理类
  34. * Created by wuxw on 2018/4/13.
  35. */
  36. @Service("apiServiceSMOImpl")
  37. //@Transactional
  38. public class ApiServiceSMOImpl extends LoggerEngine implements IApiServiceSMO {
  39. @Autowired
  40. private RestTemplate restTemplate;
  41. @Autowired
  42. private RestTemplate restTemplateNoLoadBalanced;
  43. @Autowired
  44. private IQueryServiceSMO queryServiceSMOImpl;
  45. /**
  46. * 服务调度
  47. * @param reqJson 请求报文json
  48. * @param headers
  49. * @return
  50. * @throws SMOException
  51. */
  52. @Override
  53. public ResponseEntity<String> service(String reqJson, Map<String, String> headers) throws SMOException{
  54. ApiDataFlow dataFlow = null;
  55. //JSONObject responseJson = null;
  56. ResponseEntity<String> responseEntity = null;
  57. String resJson = "";
  58. try {
  59. //在post和 put 时才存在报文加密的情况
  60. if("POST,PUT".contains(headers.get(CommonConstant.HTTP_METHOD))){
  61. reqJson = decrypt(reqJson,headers);
  62. }
  63. //1.0 创建数据流
  64. dataFlow = DataFlowFactory.newInstance(ApiDataFlow.class).builder(reqJson,headers);
  65. //2.0 加载配置信息
  66. initConfigData(dataFlow);
  67. //3.0 校验 APPID是否有权限操作serviceCode
  68. judgeAuthority(dataFlow);
  69. //6.0 调用下游系统
  70. invokeBusinessSystem(dataFlow);
  71. responseEntity = dataFlow.getResponseEntity();
  72. } catch (DecryptException e){ //解密异常
  73. responseEntity = new ResponseEntity<String>("解密异常:"+e.getMessage(), HttpStatus.NON_AUTHORITATIVE_INFORMATION);
  74. }catch (BusinessException e) {
  75. responseEntity = new ResponseEntity<String>("业务处理异常:"+e.getMessage(), HttpStatus.BAD_REQUEST);
  76. } catch (NoAuthorityException e) {
  77. responseEntity = new ResponseEntity<String>("鉴权失败:"+e.getMessage(), HttpStatus.UNAUTHORIZED);
  78. } catch (InitConfigDataException e){
  79. responseEntity = new ResponseEntity<String>("初始化失败:"+e.getMessage(), HttpStatus.BAD_REQUEST);
  80. }catch (Exception e) {
  81. logger.error("内部异常:",e);
  82. responseEntity = new ResponseEntity<String>("内部异常:"+e.getMessage()+e.getLocalizedMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
  83. } finally {
  84. if(dataFlow != null) {
  85. //这里记录日志
  86. Date endDate = DateUtil.getCurrentDate();
  87. dataFlow.setEndDate(endDate);
  88. //添加耗时
  89. //DataFlowFactory.addCostTime(dataFlow, "service", "业务处理总耗时", dataFlow.getStartDate(), dataFlow.getEndDate());
  90. //保存耗时
  91. //saveCostTimeLogMessage(dataFlow);
  92. //处理返回报文鉴权
  93. //AuthenticationFactory.putSign(dataFlow);
  94. }
  95. if (responseEntity == null){
  96. //resJson = encrypt(responseJson.toJSONString(),headers);
  97. responseEntity = new ResponseEntity<String>(resJson, HttpStatus.OK);
  98. }
  99. //这里保存耗时,以及日志
  100. return responseEntity;
  101. }
  102. }
  103. /**
  104. * 抒写返回头信息
  105. * @param dataFlow
  106. */
  107. private void putResponseHeader(DataFlow dataFlow,Map<String,String> headers) {
  108. headers.put("responseTime", DateUtil.getDefaultFormateTimeString(new Date()));
  109. headers.put("transactionId",dataFlow.getTransactionId());
  110. }
  111. /**
  112. * 解密
  113. * @param reqJson
  114. * @return
  115. */
  116. private String decrypt(String reqJson,Map<String,String> headers) throws DecryptException{
  117. try {
  118. if (MappingConstant.VALUE_ON.equals(headers.get(CommonConstant.ENCRYPT))) {
  119. logger.debug("解密前字符:" + reqJson);
  120. reqJson = new String(AuthenticationFactory.decrypt(reqJson.getBytes("UTF-8"), AuthenticationFactory.loadPrivateKey(MappingConstant.KEY_PRIVATE_STRING)
  121. , NumberUtils.isNumber(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) ? Integer.parseInt(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) :
  122. Integer.parseInt(MappingCache.getValue(MappingConstant.KEY_DEFAULT_DECRYPT_KEY_SIZE))),"UTF-8");
  123. logger.debug("解密后字符:" + reqJson);
  124. }
  125. }catch (Exception e){
  126. throw new DecryptException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR,"解密失败");
  127. }
  128. return reqJson;
  129. }
  130. /**
  131. * 加密
  132. * @param resJson
  133. * @param headers
  134. * @return
  135. */
  136. private String encrypt(String resJson,Map<String,String> headers){
  137. try {
  138. if (MappingConstant.VALUE_ON.equals(headers.get(CommonConstant.ENCRYPT))) {
  139. logger.debug("加密前字符:" + resJson);
  140. resJson = new String(AuthenticationFactory.encrypt(resJson.getBytes("UTF-8"), AuthenticationFactory.loadPubKey(MappingConstant.KEY_PUBLIC_STRING)
  141. , NumberUtils.isNumber(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) ? Integer.parseInt(headers.get(CommonConstant.ENCRYPT_KEY_SIZE)) :
  142. Integer.parseInt(MappingCache.getValue(MappingConstant.KEY_DEFAULT_DECRYPT_KEY_SIZE))),"UTF-8");
  143. logger.debug("加密后字符:" + resJson);
  144. }
  145. }catch (Exception e){
  146. logger.error("加密失败:",e);
  147. }
  148. return resJson;
  149. }
  150. /**
  151. * 2.0初始化配置信息
  152. *
  153. * @param dataFlow
  154. */
  155. private void initConfigData(ApiDataFlow dataFlow) {
  156. Date startDate = DateUtil.getCurrentDate();
  157. //查询配置信息,并将配置信息封装到 dataFlow 对象中
  158. List<AppRoute> appRoutes = AppRouteCache.getAppRoute(dataFlow.getAppId());
  159. if (appRoutes == null) {
  160. //添加耗时
  161. DataFlowFactory.addCostTime(dataFlow, "initConfigData", "加载配置耗时", startDate);
  162. throw new InitConfigDataException(ResponseConstant.RESULT_CODE_INNER_ERROR,"当前没有获取到AppId对应的信息,appId = "+dataFlow.getAppId());
  163. }
  164. for(AppRoute appRoute: appRoutes) {
  165. dataFlow.addAppRoutes(appRoute);
  166. }
  167. //
  168. if("-1".equals(dataFlow.getDataFlowId()) || StringUtil.isNullOrNone(dataFlow.getDataFlowId())){
  169. dataFlow.setDataFlowId(GenerateCodeFactory.getDataFlowId());
  170. }
  171. //添加耗时
  172. DataFlowFactory.addCostTime(dataFlow, "initConfigData", "加载配置耗时", startDate);
  173. }
  174. /**
  175. * 3.0判断 AppId 是否 有serviceCode权限
  176. *
  177. * @param dataFlow
  178. * @throws RuntimeException
  179. */
  180. private void judgeAuthority(ApiDataFlow dataFlow) throws NoAuthorityException {
  181. Date startDate = DateUtil.getCurrentDate();
  182. if (StringUtil.isNullOrNone(dataFlow.getAppId()) || dataFlow.getAppRoutes().size() == 0 ) {
  183. //添加耗时
  184. DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
  185. throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "APP_ID 为空或不正确");
  186. }
  187. if (StringUtil.isNullOrNone(dataFlow.getTransactionId())) {
  188. //添加耗时
  189. DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
  190. throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "TRANSACTION_ID 不能为空");
  191. }
  192. if(!StringUtil.isNullOrNone(dataFlow.getAppRoutes().get(0).getSecurityCode())){
  193. String sign = AuthenticationFactory.apiDataFlowMd5(dataFlow);
  194. if(!sign.equals(dataFlow.getReqSign().toLowerCase())){
  195. throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "签名失败");
  196. }
  197. }
  198. if (StringUtil.isNullOrNone(dataFlow.getRequestTime()) || !DateUtil.judgeDate(dataFlow.getRequestTime(), DateUtil.DATE_FORMATE_STRING_DEFAULT)) {
  199. //添加耗时
  200. DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
  201. throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "requestTime 格式不对,遵循yyyyMMddHHmmss格式");
  202. }
  203. //判断 AppId 是否有权限操作相应的服务
  204. AppService appService = DataFlowFactory.getService(dataFlow, dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
  205. //这里调用缓存 查询缓存信息
  206. if (appService == null || !CommonConstant.HTTP_SERVICE_API.equals(appService.getBusinessTypeCd())) {
  207. //添加耗时
  208. DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
  209. throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "AppId 没有权限访问 serviceCode = " + dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
  210. }
  211. //检验白名单
  212. List<String> whileListIp = dataFlow.getAppRoutes().get(0).getWhileListIp();
  213. if (whileListIp != null && whileListIp.size() > 0 && !whileListIp.contains(dataFlow.getIp())) {
  214. //添加耗时
  215. DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
  216. throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "当前IP被限制不能访问服务");
  217. }
  218. //检查黑名单
  219. List<String> backListIp = dataFlow.getAppRoutes().get(0).getBackListIp();
  220. if (backListIp != null && backListIp.size() > 0&& backListIp.contains(dataFlow.getIp())) {
  221. //添加耗时
  222. DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
  223. throw new NoAuthorityException(ResponseConstant.RESULT_CODE_NO_AUTHORITY_ERROR, "当前IP被限制不能访问服务");
  224. }
  225. //添加耗时
  226. DataFlowFactory.addCostTime(dataFlow, "judgeAuthority", "鉴权耗时", startDate);
  227. }
  228. /**
  229. * 6.0 调用下游系统
  230. *
  231. * @param dataFlow
  232. * @throws BusinessException
  233. */
  234. private void invokeBusinessSystem(ApiDataFlow dataFlow) throws BusinessException {
  235. Date startDate = DateUtil.getCurrentDate();
  236. //拿到当前服务
  237. AppService appService = DataFlowFactory.getService(dataFlow, dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
  238. //这里对透传类处理
  239. if("NT".equals(appService.getIsInstance())){
  240. //如果是透传类 请求方式必须与接口提供方调用方式一致
  241. String httpMethod = dataFlow.getRequestCurrentHeaders().get(CommonConstant.HTTP_METHOD);
  242. if(!appService.getMethod().equals(httpMethod)) {
  243. throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR,
  244. "服务【" + appService.getServiceCode() + "】调用方式不对请检查,当前请求方式为:"+httpMethod);
  245. }
  246. dataFlow.setApiCurrentService(ServiceCodeConstant.SERVICE_CODE_DO_SERVICE_TRANSFER);
  247. }else{
  248. dataFlow.setApiCurrentService(dataFlow.getRequestHeaders().get(CommonConstant.HTTP_SERVICE));
  249. }
  250. ServiceDataFlowEventPublishing.multicastEvent(dataFlow,appService);
  251. DataFlowFactory.addCostTime(dataFlow, "invokeBusinessSystem", "调用下游系统耗时", startDate);
  252. }
  253. /**
  254. * 保存日志信息
  255. * @param requestJson
  256. */
  257. private void saveLogMessage(String requestJson,String responseJson){
  258. try{
  259. if(MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.KEY_LOG_ON_OFF))){
  260. JSONObject log = new JSONObject();
  261. log.put("request",requestJson);
  262. log.put("response",responseJson);
  263. KafkaFactory.sendKafkaMessage(KafkaConstant.TOPIC_LOG_NAME,"",log.toJSONString());
  264. }
  265. }catch (Exception e){
  266. logger.error("报错日志出错了,",e);
  267. }
  268. }
  269. /**
  270. * 保存耗时信息
  271. * @param dataFlow
  272. */
  273. private void saveCostTimeLogMessage(DataFlow dataFlow){
  274. try{
  275. if(MappingConstant.VALUE_ON.equals(MappingCache.getValue(MappingConstant.KEY_COST_TIME_ON_OFF))){
  276. List<DataFlowLinksCost> dataFlowLinksCosts = dataFlow.getLinksCostDates();
  277. JSONObject costDate = new JSONObject();
  278. JSONArray costDates = new JSONArray();
  279. JSONObject newObj = null;
  280. for(DataFlowLinksCost dataFlowLinksCost : dataFlowLinksCosts){
  281. newObj = JSONObject.parseObject(JSONObject.toJSONString(dataFlowLinksCost));
  282. newObj.put("dataFlowId",dataFlow.getDataFlowId());
  283. newObj.put("transactionId",dataFlow.getTransactionId());
  284. costDates.add(newObj);
  285. }
  286. costDate.put("costDates",costDates);
  287. KafkaFactory.sendKafkaMessage(KafkaConstant.TOPIC_COST_TIME_LOG_NAME,"",costDate.toJSONString());
  288. }
  289. }catch (Exception e){
  290. logger.error("报错日志出错了,",e);
  291. }
  292. }
  293. public RestTemplate getRestTemplate() {
  294. return restTemplate;
  295. }
  296. public void setRestTemplate(RestTemplate restTemplate) {
  297. this.restTemplate = restTemplate;
  298. }
  299. public IQueryServiceSMO getQueryServiceSMOImpl() {
  300. return queryServiceSMOImpl;
  301. }
  302. public void setQueryServiceSMOImpl(IQueryServiceSMO queryServiceSMOImpl) {
  303. this.queryServiceSMOImpl = queryServiceSMOImpl;
  304. }
  305. public RestTemplate getRestTemplateNoLoadBalanced() {
  306. return restTemplateNoLoadBalanced;
  307. }
  308. public void setRestTemplateNoLoadBalanced(RestTemplate restTemplateNoLoadBalanced) {
  309. this.restTemplateNoLoadBalanced = restTemplateNoLoadBalanced;
  310. }
  311. }