微服务分模块后怎么跨模块访问资源

如果我们使用微服务框架后,每个模块变的相互独立,有自己的端口,那两个模块之间如何相互通信。

方案一:

使用糊涂工具向指定地址发送请求

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);
        }
}
相关推荐
Flittly5 小时前
【AgentScope Java新手村系列】(16)从RAG到多路检索
java·spring boot·spring
小兔崽子去哪了5 小时前
Java 生成二维码解决方案
java·后端
人活一口气10 小时前
从JVM调优到MCP协议:Java全栈技术体系深度总结与企业级架构实践
java·spring boot
NE_STOP11 小时前
Vibe Coding -- 完整项目案例实操
java
荣码11 小时前
GraphRAG:普通RAG只能回答"点"的问题,我踩了4个坑才搞懂
java·python
SimonKing11 小时前
Google第三方授权登录
java·后端·程序员
明月光81812 小时前
从一行 @Builder 说起:重新拾起 Java 的 Lombok、注解与 Builder 模式
java
考虑考虑21 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯1 天前
GoF设计模式——中介者模式
java·后端·spring·设计模式
fanly111 天前
Surging AI Agent 完整产品介绍
微服务·microservice