前言:我们知道SpringCloud中服务调用可以用Fegin本地客户端和RestTemplate模板的方式,如果是Dubbo则是分布式的RPC则轻松搞定,这里介绍的是Cloud模板的方式。性能不是很好,为什么大家可以思考一下!
背景:各服务都注册在Eureka上,彼此独立部署(注意不是独立部署,用模板就没那么多讲究了),现需要在一个服务调用另一个服务的接口,原因是视图改造,以往的开发人员服务间沟通居然采用视图的形式,视图这种东西基本被时代淘汰了。
在config类配置一下模板,@Bean注入进容器:
/**
* resttemplate客户端
*
* @return
*/
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public HystrixCommandAspect hystrixCommandAspect() {
return new HystrixCommandAspect();
}
@Service
public class RestTemplateService {
private ZSmartLogger zsmartLogger = ZSmartLogger.getLogger(this.getClass(), LogCodeUtil.getModule(this.getClass()));
/**
* 注入门户服务名,默认不需要配置,值为COMMON-SYSTEM
*/
@Value("${comsystem.service.name:COMMON-SYSTEM}")
private String comsystemServiceName;
/**
* post方式请求,当前用户请求安全服务,仅限用注册中心的时候可以调用
* @param postObject 请求参数
* @param module 模块名称
* @param header 请求头
* @param
* @return
*/
public T postSmartSafePortalService(Object postObject, String module, Map header) {
List headers = Lists.newArrayList();
Map safeHeader = Maps.newHashMap();
safeHeader.put("signature-sessionid", header.get("signature-sessionid"));
safeHeader.put("Content-Type", "application/json");
Iterator> iterator = safeHeader.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
if (Objects.nonNull(entry.getValue())) {
BasicHeader basicHeader = new BasicHeader(entry.getKey(), entry.getValue());
headers.add(basicHeader);
}
}
zsmartLogger.info(LogCodeUtil.getTranId(KeyValues.MODULE_NAME), "postSmartSafePortalService-postObject:{}", JsonUtil.toJson(postObject));
String url = "http://" + smartSafePortalServiceName.trim() + "/smartsafe/" + module;
return this.postJsonByObject(headers, postObject, url);
}
/**
* 模拟HTTP请求,不对外暴露
*
* @param headers 请求头
* @param postObject 请求参数
* @param url 请示服务路径
* @return 返回参数
*/
private T postJsonByObject(List headers, Object postObject, String url) {
HttpHeaders httpHeaders = new HttpHeaders();
for (Header header : headers) {
httpHeaders.add(header.getName(), header.getValue());
}
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
httpHeaders.setContentType(type);
httpHeaders.add("Accept", MediaType.APPLICATION_JSON.toString());
HttpEntity formEntity = new HttpEntity(new Gson().toJson(postObject), httpHeaders);
ResponseEntity postForEntity = this.restTemplate.postForEntity(url, formEntity, String.class);
String responseBody = postForEntity.getBody();
return (T) JSON.parseObject(responseBody);
}
@Service
public class SmartSafePortalService {
@Autowired
private RestTemplateService restTemplateService;
private ZSmartLogger zsmartLogger = ZSmartLogger.getLogger(this.getClass(), LogCodeUtil.getModule(this.getClass()));
/**
* 敏感字段查询
* @param params
* @param header
* @return
*/
public Result> getListAllSafeSensitiveField(Map params, Map header) {
// 别的服务的路径
String module = "SafeSensitiveFieldController/xxxxx";
zsmartLogger.info(LogCodeUtil.getTranId(KeyValues.MODULE_NAME), "getListAllSafeSensitiveField-params:{}", params);
Map resultMap = restTemplateService.postSmartSafePortalService(params, module, header);
String resultCode = MapParamUtil.getStringValue(resultMap, "resultCode");
String resultMsg = MapParamUtil.getStringValue(resultMap, "resultMsg");
Map resultObject = (Map) resultMap.get("resultObject");
zsmartLogger.info(LogCodeUtil.getTranId(KeyValues.MODULE_NAME), "resultObject:{}", resultObject);
if (null == resultObject) {
return Result.fail(resultMsg);
}
Map pageMap = (Map) resultObject.get("pageInfo");
PageInfo pageInfo = new PageInfo();
pageInfo.setPageCount((Integer) pageMap.get("pageCount"));
pageInfo.setTotal((Integer) pageMap.get("total"));
pageInfo.setPageIndex((Integer) pageMap.get("pageIndex"));
pageInfo.setPageSize((Integer) pageMap.get("pageSize"));
Integer records = MapParamUtil.getIntValue(resultObject, "records");
List
到这里就实现了从本服务调用别的服务的具体接口拿到该接口的数据了,我们在本服务只需要拿到别的方服务的返回值结构,实体,就可以自己封装成一个取数接口,供本服务调用。本服务需要调用安全服务的该接口,直接调用该方法即可。同理调用安全服务的其他方法也可以这样写
1、
(1)配置hosts
位置:C:\Windows\System32\drivers\etc
例如我要配置167的IP:
(2)配置端口注册到注册中心
为区别已经注册上注册中心的端口号,端口号要修改一下
例如原来本地localhost调试的:
smartservice.port=9280 smartweb.port=9284 center.port=8900 gateway.port=9286
改成:
smartservice.port=9281 smartweb.port=9285 center.port=8900 gateway.port=9287
(3)配置注册中心地址
原来的是:
eureka.instance.hostname=localhost
改成远程的注册中心,比如我要在167开发环境的测试:
eureka.instance.hostname=172.21.72.167
(4)改服务名,避免冲突:
例如,原来smartservice的服务名可以改成:
spring.application.name=smartservice2
其他几个 例如smartweb、center、gateway的类似
(5)改serviceId和postman的请求path(可选)
例如原来的:
zuul.routes.smartservice.path=/smartweb/smartservice/** zuul.routes.smartservice.serviceId=smartservice zuul.routes.smartweb.path=/** zuul.routes.smartweb.serviceId=smartweb
可以改成:
zuul.routes.smartservice.path=/smartweb2/smartservice2/** zuul.routes.smartservice.serviceId=smartservice2 zuul.routes.smartweb.path=/** zuul.routes.smartweb.serviceId=smartweb2
2、
eureka.instance.hostname=localhost
eureka.client.serviceUrl.defaultZone=http://localhost:8901/eureka/
改成:
eureka.instance.hostname=具体环境IP
eureka.client.serviceUrl.defaultZone=http://具体环境IP:8900/eureka/
此外端口号和服务名也可以修改
postman直接localhost:端口号/controller路径 访问即可