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

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

方案一:

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

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);
        }
}
相关推荐
步行cgn2 小时前
Spring c 命名空间注入详解
java·后端·spring
明月_清风2 小时前
Maven 到底是什么?一篇文章搞懂 Java 项目构建与依赖管理
java·后端·maven
aramae2 小时前
MySQL复合查询(8)
java·c语言·开发语言·后端·算法
Rain的Java大神之路3 小时前
如何快速上传10G文件
java·spring boot·redis·后端·mysql·spring cloud·面试
Wang's Blog3 小时前
Java 接入Redis: 通用命令与键管理
java·服务器·redis
Wang's Blog3 小时前
Java 接入Redis: 列表集合与有序集合操作命令
java·服务器·redis
Ivanqhz4 小时前
SVD++算法
java·服务器·网络·深度学习·神经网络
qq_2518364575 小时前
springboot vue3 开发实现 拼豆管理系统
java·开发语言·ai编程
liangshanbo12155 小时前
Redux 的中间件(Middleware)的工作机制
中间件·react·redux
caoerzhong5 小时前
JeeWMS 开源仓库管理系统全景解读:一套 Java WMS 如何把 WMS/OMS/BMS/TMS 装进同一个系统
java·开源