这次遇到一个问题,两个项目之间需要通信的问题。在一个服务上调用另外一个服务的接口。不能用nacos等注册中心,所以找到了spring实现的RestTemplate方式进行通讯。
1、首先在yaml文件里面添加另外一个服务的ip和端口。
#flowable配置
flowable:
activity-font-name: \u5B8B\u4F53
label-font-name: \u5B8B\u4F53
annotation-font-name: \u5B8B\u4F53
check-process-definitions: false
database-schema-update: true
# 访问服务设置
services:
contacts_path: contacts
contacts_port: 80
我这儿用的是映射,比如你如果将contacts这个服务跑在本机的话,那就需要在host文件里面配置映射。如下:
127.0.0.1 contacts
同样,如果你将自己服务跑在对应ip的服务器上,你只需要在你跑的当下服务的主机host配置服务器ip和contacts的映射。
2、覆盖原值
另外,也可以通过启动服务时候传输的环境变量里面进行设置。
如下:
image.png
当然也需要在spring启动类里面设置获取环境变量的值并且覆盖原来的值。
image.png
public class BladeApplication {
/**
* Create an application context
* java -jar app.jar --spring.profiles.active=prod --server.port=2333
*
* @param appName application name
* @param source The sources
* @return an application context created from the current state
*/
public static ConfigurableApplicationContext run(String appName, Class source, String... args) {
SpringApplicationBuilder builder = createSpringApplicationBuilder(appName, source, args);
return builder.run(args);
}
public static SpringApplicationBuilder createSpringApplicationBuilder(String appName, Class source, String... args) {
Assert.hasText(appName, "[appName]服务名不能为空");
// 读取环境变量,使用spring boot的规则
ConfigurableEnvironment environment = new StandardEnvironment();
MutablePropertySources propertySources = environment.getPropertySources();
propertySources.addFirst(new SimpleCommandLinePropertySource(args));
propertySources.addLast(new MapPropertySource(StandardEnvironment.SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, environment.getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, environment.getSystemEnvironment()));
// 获取配置的环境变量
String[] activeProfiles = environment.getActiveProfiles();
// 判断环境:dev、test、prod
List<String> profiles = Arrays.asList(activeProfiles);
// 预设的环境
List<String> presetProfiles = new ArrayList<>(Arrays.asList(AppConstant.DEV_CODE, AppConstant.TEST_CODE, AppConstant.PROD_CODE));
// 交集
presetProfiles.retainAll(profiles);
// 当前使用
List<String> activeProfileList = new ArrayList<>(profiles);
Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString;
SpringApplicationBuilder builder = new SpringApplicationBuilder(source);
String profile;
if (activeProfileList.isEmpty()) {
// 默认dev开发
profile = AppConstant.DEV_CODE;
activeProfileList.add(profile);
builder.profiles(profile);
} else if (activeProfileList.size() == 1) {
profile = activeProfileList.get(0);
} else {
// 同时存在dev、test、prod环境时
throw new RuntimeException("同时存在环境变量:[" + StringUtils.arrayToCommaDelimitedString(activeProfiles) + "]");
}
String startJarPath = BladeApplication.class.getResource("/").getPath().split("!")[0];
String activePros = joinFun.apply(activeProfileList.toArray());
System.out.printf("----启动中,读取到的环境变量:[%s],jar地址:[%s]----%n", activePros, startJarPath);
Properties props = System.getProperties();
props.setProperty("spring.application.name", appName);
props.setProperty("spring.profiles.active", profile);
props.setProperty("info.version", AppConstant.APPLICATION_VERSION);
props.setProperty("info.desc", appName);
props.setProperty("file.encoding", StandardCharsets.UTF_8.name());
props.setProperty("blade.env", profile);
props.setProperty("blade.name", appName);
props.setProperty("blade.is-local", String.valueOf(isLocalDev()));
props.setProperty("blade.dev-mode", profile.equals(AppConstant.PROD_CODE) ? "false" : "true");
props.setProperty("blade.service.version", AppConstant.APPLICATION_VERSION);
props.setProperty("spring.main.allow-bean-definition-overriding", "true");
props.setProperty("spring.sleuth.sampler.percentage", "1.0");
props.setProperty("spring.cloud.nacos.config.shared-dataids", NacosConstant.sharedDataIds(profile));
props.setProperty("spring.cloud.nacos.config.refreshable-dataids", NacosConstant.sharedDataIds(profile));
props.setProperty("spring.cloud.nacos.config.file-extension", NacosConstant.NACOS_CONFIG_FORMAT);
props.setProperty("spring.cloud.alibaba.seata.tx-service-group", appName.concat(NacosConstant.NACOS_GROUP_SUFFIX));
Map<String, Object> envMap = environment.getSystemEnvironment();
String dbUrl = "DB_URL";
String dbUsername = "DB_USERNAME";
String dbPassword = "DB_PASSWORD";
String redisHost = "REDIS_HOST";
String redisPort = "REDIS_PORT";
String redisPassword = "REDIS_PASSWORD";
String contactsPath = "CONTACTS_SERVER_PATH";
String contactSport = "CONTACTS_SERVER_PORT";
if (null != envMap.get(dbUrl)) {
props.setProperty("spring.datasource.url", envMap.get(dbUrl).toString());
}
if (null != envMap.get(dbUsername)) {
props.setProperty("spring.datasource.username", envMap.get(dbUsername).toString());
}
if (null != envMap.get(dbUsername)) {
props.setProperty("spring.datasource.password", envMap.get(dbPassword).toString());
}
if (null != envMap.get(redisHost)) {
props.setProperty("spring.redis.host", envMap.get(redisHost).toString());
}
if (null != envMap.get(redisPort)) {
props.setProperty("spring.redis.port", envMap.get(redisPort).toString());
}
if (null != envMap.get(redisPassword)) {
props.setProperty("spring.redis.password", envMap.get(redisPassword).toString());
}
if (null != envMap.get(contactsPath)) {
props.setProperty("services.contacts_path", envMap.get(contactsPath).toString());
}
if (null != envMap.get(contactSport)) {
props.setProperty("services.contacts_port", envMap.get(contactSport).toString());
}
// 加载自定义组件
List<LauncherService> launcherList = new ArrayList<>();
ServiceLoader.load(LauncherService.class).forEach(launcherList::add);
launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList())
.forEach(launcherService -> launcherService.launcher(builder, appName, profile, isLocalDev()));
return builder;
}
}
主要是这几句:
Map<String, Object> envMap = environment.getSystemEnvironment();
String contactsPath = "CONTACTS_SERVER_PATH";
String contactSport = "CONTACTS_SERVER_PORT";
if (null != envMap.get(contactsPath)) {
props.setProperty("services.contacts_path", envMap.get(contactsPath).toString());
}
if (null != envMap.get(contactSport)) {
props.setProperty("services.contacts_port", envMap.get(contactSport).toString());
}
这样就覆盖了yaml文件中services下的值。
3、调用RestTemplate
package org.springblade.modules.system.service.impl;
import com.alibaba.fastjson.JSONObject;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserVOService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
/**
* UserAccount achieved Class
*
* @author liupeng
* @date 2020-12-03
*/
@Service
public class UserVOServiceImpl implements IUserVOService {
@Value("${services.contacts_path}")
private String contacts_path;
@Value("${services.contacts_port}")
private String contacts_port;
User user = new User();
@Override
public User getUserById(String id) {
//复杂构造函数的使用
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(1000);
requestFactory.setReadTimeout(1000);
user.setId(id);
//利用复杂构造器可以实现超时设置,内部实际实现为 HttpClient
RestTemplate restTemplate = new RestTemplate(requestFactory);
String url = "http://" + contacts_path + ":"+ contacts_port + "/users/" + id;
//发送
ResponseEntity<JSONObject> entity = restTemplate.getForEntity(url, JSONObject.class);
if (Func.isNotEmpty(entity)) {
if (Func.isNotEmpty(entity.getBody())) {
user.setName((String) entity.getBody().get("name"));
}
}
return user;
}
}
3.1、首先是使用 @Value("${services.contacts_path}") 注解将yaml文件中的值注入到声明的字符串中,为了后面组装访问url
3.2、getUserById函数中先声明一个SimpleClientHttpRequestFactory 对象,构造RestTemplate对象用来访问contacts服务。
3.3、调用restTemplate对象的getForEntity方法来实现get请求,postForEntity()实现post请求,patchForObject()实现patch请求,put()实现put请求等等。
网友评论