SpringCloud远程消费

目录

一、SpringCloud核心组件——Feign

二、SpringCloud远程消费接口定义以及组件Feign使用

        1、在provider新建实体类User与controller层

        2、在消费者consumer中建立实体类和实现生产者方法的接口类

        3、实现接口中的方法

        4、在消费者启动类中加上启动远程通信注解

        5、进行测试

三、优化远程消费(DTO封装)

        1、介绍DTO封装:

        2、步骤:

                 1、创建一个commons类,将相同部分取出来

                 2、进行打包,在父类进行引用此依赖

                 3、将之前的user类进行删除,改成dto进行测试


一、SpringCloud核心组件——Feign

如何从订单服务跟其他服务建立网络连接,接着发送请求过去。

Feign组件就是进行个服务之间的通信

二、SpringCloud远程消费接口定义以及组件Feign使用

        1、在provider新建实体类User与controller层

package com.zj.provider.pojo;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@NoArgsConstructor
@AllArgsConstructor
@Data
@Accessors(chain = true)
public class User {

    private String account;
    private String password;



}

controller层:

package com.zj.provider.controller;


import ch.qos.logback.core.net.SyslogOutputStream;
import com.zj.provider.pojo.User;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.server.PathParam;
import java.util.Map;

@RestController
@RequestMapping("/user")
public class UserController {


    //以路径的方式访问

    @RequestMapping("/{account}")
    public String getByPath(@PathVariable  String account){
        System.out.println("account:"+account);
        return  "provider say : yes";
    }

    //以请求的方式访问
    @RequestMapping("/param")
    public String getByParam(@PathParam("account") String account, @PathParam("account") String password){
        System.out.println("account:"+account);
        return  "provider say : yes";
    }

    @RequestMapping("/pojo")
    public String getByPojo(@RequestBody User user){
        System.out.println("pojo"+user);
        return  "provider say : yes";
    }

    @RequestMapping("/more")
    public String getByMore(@RequestBody Map<String,Object> map){
        System.out.println("more"+map);
        return  "provider say : yes";
    }






}

        2、在消费者consumer中建立实体类和实现生产者方法的接口类

实体类中的内容和生产者中内容一样

接口FeignService:

package com.zj.consumer.service;


import com.zj.consumer.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.websocket.server.PathParam;
import java.util.Map;

@FeignClient("provider")
@SuppressWarnings("all")
public interface FeignService {


    //以路径的方式访问
    @RequestMapping("/user/{account}")
    public String getByPath(@PathVariable(value = "account") String account);

    //以请求的方式访问
    @RequestMapping("/user/param")
    public String getByParam(@RequestParam("account") String account, @RequestParam ("password") String password);

    @RequestMapping("/user/pojo")
    public String getByPojo(@RequestBody User user);

    @RequestMapping("/user/more")
    public String getByMore(@RequestBody Map<String, Object> map);


}

注意:

@PathVariable中必须含有value()

@FeignClient("provider")消费者要与生产者进行通信,provider应为服务名

三种传参方式:

①.@PathVariable 路径传参

②.@RequestParam 请求参数传参

③.@RequestBody   json传参

        3、实现接口中的方法

package com.zj.consumer.controller;


import com.zj.consumer.pojo.User;
import com.zj.consumer.service.FeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;


@RestController
@RequestMapping("/user")
public class UserController {


    private FeignService service;

    @Autowired
    public UserController(FeignService service) {
        this.service = service;
    }

    @RequestMapping("/test01")
    public String test01(String account) {
        service.getByPath(account);
        return "yes";
    }


    @RequestMapping("/{account}")
    public String test02(@PathVariable String account) {
        service.getByPath(account);
        return "yes";
    }


    @RequestMapping("/test03")
    public String test03(String account, String password) {
        service.getByParam(account, password);
        return "yes";
    }


    @RequestMapping("/test04")
    public String test04(String account, String password) {
        service.getByPojo(new User().setAccount(account).setPassword(password));
        return "yes";
    }

    @RequestMapping("/test05")
    public String test05(String account, String password) {
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("account",account);
        map.put("password",password);
        service.getByMore(map);
        return "yes";
    }

}

        4、在消费者启动类中加上启动远程通信注解

package com.zj.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }


    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

        5、进行测试

在消费者实现方法进行测试,当运行方法后,生产者会出现对应的结果: 

 测试成功

三、优化远程消费(DTO封装)

由于两者之间可能存在许多冗余的代码,那么要将相同的部分提取出来,成为公共的部分,

        1、介绍DTO封装:

VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。
DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的
性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。
DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。
PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

消费者 远程调用 生产者 : 需要网络传输,使用DTO同一封装对象
原理与SpringBoot启动类相同
1.将DTO对象封装到公共DTO模块
2.为需要的项目引入公共DTO模块     
  

 注意点:

1.不需要继承父模块(重复引用问题)
2.打包方式为jar
3.不需要添加启动类的编译

        2、步骤:

                 1、创建一个commons类,将相同部分取出来

package com.zj.commons.dto;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@NoArgsConstructor
@AllArgsConstructor
@Data
@Accessors(chain = true)
public class UserDto {

    private String account;
    private String password;



}

                 2、进行打包,在父类进行引用此依赖

        <dependency>
            <groupId>com.ZJ</groupId>
            <artifactId>commons</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>org.zj</groupId>
    <artifactId>cloud02</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>cloud02 Maven Webapp</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

  <modules>
      <module>provider</module>
      <module>consumer</module>
      <module>commons</module>
  </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
        <spring-boot.version>2.4.1</spring-boot.version>
        <spring-cloud.version>2020.0.0</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.ZJ</groupId>
            <artifactId>commons</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <dependencyManagement>

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <finalName>cloud02</finalName>
    </build>
</project>

并且在父类将commons加入到modules中

注意:但是在commos不要继承父类依赖

原因:在父类实现了commons的依赖供给给消费者和生产者使用,以及认了commons作为儿子,如果还在commons中加入父类依赖,就会继承自己的依赖,导致重复依赖,就会你报错

                 3、将之前的user类进行删除,改成dto进行测试

但是这里就会产生一个问题,如果实体类和我数据库中的字段数量或者字段名不一样,那该怎么解决?

这里将会用orika框架

orika的网址:Orika对象复制教程(完美笔记) - 付宗乐 - 博客园

Orika是java Bean映射框架,可以实现从一个对象递归拷贝数据至另一个对象。
在开发多层应用程序中非常有用。在这些层之间交换数据时,通常为了适应不同API需要转换一个实例至另一个实例。

 在生产者中导入以下依赖:

<dependency>
  <groupId>ma.glasnost.orika</groupId>
  <artifactId>orika-core</artifactId>
  <version>1.4.6</version>
</dependency>

在生产者启动类中实例出mapper工厂

@Bean
@Scope("prototype")
public MapperFactory mapperFactory(){
    return  new DefaultMapperFactory.Builder().build();
}

对于以上问题的两种情况:

1、如果字段属性一致:

User u = mapperFactory.getMapperFacade().map(dto, User.class);

2、如果字段属性不一致:

    @RequestMapping("/pojo")
    public String getByPojo(@RequestBody UserDto dto) {
//         User u = mapperFactory.getMapperFacade().map(dto, User.class);
        mapperFactory.classMap(UserDto.class, User.class)
                .field("name", "account")
                .byDefault().register();
        User map = mapperFactory.getMapperFacade().map(dto, User.class);
        System.out.println("pojo" + dto);
        return "provider say : yes";
    }
mapperFactory.classMap(User.class, UserVo.class)
.field("name", "userName")
.field("age", "ageOne")
.byDefault().register();
List<UserVo> userVos = mapperFactory.getMapperFacade().mapAsList(A, UserVo.class);

今天的知识就分享到这了,希望能够帮助到你!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值