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

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

方案一:

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

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);
        }
}
相关推荐
橙露5 小时前
Spring Boot 核心原理:自动配置机制与自定义 Starter 开发
java·数据库·spring boot
小程故事多_805 小时前
Agent Infra核心技术解析:Sandbox sandbox技术原理、选型逻辑与主流方案全景
java·开发语言·人工智能·aigc
冰暮流星5 小时前
sql语言之分组语句group by
java·数据库·sql
望舒5135 小时前
代码随想录day25,回溯算法part4
java·数据结构·算法·leetcode
黎雁·泠崖5 小时前
【魔法森林冒险】3/14 Allen类(一):主角核心属性与初始化
java·开发语言
黎雁·泠崖5 小时前
【魔法森林冒险】1/14 项目总览:用Java打造你的第一个回合制冒险游戏
java·开发语言
NuageL5 小时前
原始Json字符串转化为Java对象列表/把中文键名变成英文键名
java·spring boot·json
222you6 小时前
Redis的主从复制和哨兵机制
java·开发语言
江湖有缘6 小时前
零基础入门:使用 Docker 快速部署 Organizr 个人主页
java·服务器·docker
chilavert3186 小时前
技术演进中的开发沉思-357:重排序(下)
java·后端