如果我们使用微服务框架后,每个模块变的相互独立,有自己的端口,那两个模块之间如何相互通信。
方案一:
使用糊涂工具向指定地址发送请求
java
public void testGetByParam() {
//可以单独传入http参数,这样参数会自动做URL编码,拼接在URL中
HashMap<String, Object> paramMap = new HashMap<>();
paramMap.put("pageNum", 1);
paramMap.put("pageSize", 10);
String result = HttpUtil.get("http://localhost:9995/nursing_project", paramMap);//直接发送get
System.out.println(result);
}
方案二:
使用spring框架集成的RestTemplate
①注册bean
java
@Configuration
public class RemoteCallConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
②直接注入使用
java
import org.springframework.web.client.RestTemplate;
@Service
public class CartServiceImpl {
private final RestTemplate restTemplate;
private void handleCartItems(List<CartVO> vos) {
// 1.获取商品id
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
// 2.查询商品,因为已经划分了模块,itemService并不在此模块中,所以这种调用方式已经不行了
//List<ItemDTO> items = itemService.queryItemByIds(itemIds);
//处理一下字符串
StringBuilder ids= new StringBuilder();
for (Long itemId : itemIds) {
ids.append(itemId).append(",");
}
//去掉最后一个逗号
ids = new StringBuilder(ids.substring(0, ids.length() - 1));
//使用RestTemplate发生请求并接收数据
String forObject = restTemplate.getForObject("http://localhost:8081/items?ids=" + ids, String.class);
//json字符串转集合
List<ItemDTO> items = JSONUtil.toList(forObject, ItemDTO.class);
}
}
方案三:
使用DiscoveryClient,因为我们在配置文件里给每个模块都起了名字,所以我们可以不用输很长的地址,直接使用模块名称访问
java
spring:
application:
name: hm-cart
java
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
@Service
@RequiredArgsConstructor
public class CartServiceImpl{
private final DiscoveryClient discoveryClient;
private void handleCartItems(List<CartVO> vos) {
// 1.获取商品id
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
// 2.查询商品
//List<ItemDTO> items = itemService.queryItemByIds(itemIds);
//处理一下字符串
String ids = itemIds.stream().map(String::valueOf).collect(Collectors.joining(","));
//手动负载均衡
List<ServiceInstance> instances = discoveryClient.getInstances("hm-item");//使用名称拿到所有的这个模块的实例
ServiceInstance serviceInstance = instances.get(RandomUtil.randomInt(instances.size()));//随机挑一个端口
// 获取服务的地址
String url = serviceInstance.getUri().toString();
String json = restTemplate.getForObject(url + "/items?ids=" + ids, String.class);
List<ItemDTO> items = JSONUtil.toList(forObject, ItemDTO.class);
}
方案四(推荐):
使用OpenFeign创建相应模块的客户端与loadBalancer进行负载均衡默认为轮循
①引入依赖
XML
<!--openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!--nacos 服务注册发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
②写客户端
java
//加入容器
@FeignClient("hm-item")//模块名
public interface ItemClient {
@GetMapping("/items")//请求接口
List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);//与模块此接口的控制层的方法声明一样;
}
③启动类增加注解@EnableFeignClients
java
@EnableFeignClients
@SpringBootApplication
@MapperScan("com.hmall.cart.mapper")
public class HmCartApplication {
public static void main(String[] args) {
SpringApplication.run(HmCartApplication.class, args);
}
}
④注入使用
java
@Service
@RequiredArgsConstructor
public class CartServiceImpl{
private final ItemClient itemClient;
private void handleCartItems(List<CartVO> vos) {
// 1.获取商品id
Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
//跨模块查询
List<ItemDTO> items = itemClient.queryItemByIds(itemIds);
}
}