SpringCloud远程消费

一、SpringCloud核心组件——Feign

①、实体类

首先,写一个用户实体类

建立pojo软件包,新建User实体类

user.java

package com.provider.code.pojo;

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

@AllArgsConstructor
@NoArgsConstructor
@Data
//链式编程
@Accessors(chain = true)
public class User {

    private String account;
    private String password;

}

②、提供接口让别人来操纵用户实体类

使用UserController来构建一些有参数的东西

(1)UserController:

package com.provider.code.controller;

import com.provider.code.pojo.User;
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.consumer.service;

import com.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 javax.websocket.server.PathParam;
import java.util.Map;

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

    //被接受传过来的账号
    @RequestMapping("/user/{account}")
    public String getByPath(@PathVariable String account);

    //以请求的方式访问
    @RequestMapping("/user/param")
    public String getByParam(@PathParam("account") String account, @PathParam("account") 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.consumer.controller;

import com.consumer.pojo.User;
import com.consumer.service.FeignUserService;
import org.springframework.beans.factory.annotation.Autowired;
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 FeignUserService service;

    @Autowired
    public UserController(FeignUserService 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";
    }

}

 二、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.不需要添加启动类的编译

消费者调用生产者接口的时候还需要调用相关实体类,因此生产者和消费者的实体类一模一样,如果实体类过多,就会出现代码大量重复,因此,解决这一问题

把这些重复的类放到一个公共模块中,做成类似与启动器(web启动器:把某些功能封装在里面,要的时候就调用)的,在导入到这个类中

消费者(consumer)调用生产者(provider)的接口,生产者(provider)的接口需要一个user对象,消费者(consumer)在进行远程调用的时候需要把user对象传过去,服务之间互相调用使用DTO

所以,写一个公共模块,把所有的DTO封装起来

1、新建启动器
父项目上新建

2、修改pom.xml

①、不要继承父项目

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.hmf</groupId>
    <artifactId>code</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>commons</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.4.1</spring-boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </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>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

3、新建dto软件包

 把所有的实体类移上来

package com.hmf.code.dto;

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

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

    private String account;
    private String password;
}

4、引用Commons

因为provider和consumer都要引用Commons

①、将Commons导成jar

 ②、父项目中进行依赖引入

pom.xml

<dependency>
  <groupId>com.hmf</groupId>
  <artifactId>code</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>

 现在代码中实体类只需要写一次了,

生产者是要去数据库那数据的所有实体类不能删除,而消费者是与生产者进行远程通信的,因而删除

将消费者(consumer)中的pojo软件包删除

package com.consumer.service;

import com.hmf.code.dto.UserDto;
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 javax.websocket.server.PathParam;
import java.util.Map;

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

    //被接受传过来的账号
    @RequestMapping("/user/{account}")
    public String getByPath(@PathVariable String account);

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

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

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

}
FeignUserService中的User改为UserDto

两个实体类并不一致,但是并没有报错,因为是json接收,所以说前台与后台数据库并不一定保持一致

但是,我们的DTO并不完善,假如有一天DTO变了,因为Dto不可能只有账号密码这两个属性,假如增加了属性,User与DtoUser就会不匹配,所有修改生产者类的User改为UserDto

生产者类(provider)的User改为UserDto:

5、Orika
Orika:Orika对象复制教程(完美笔记) - 付宗乐 - 博客园

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

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

我们现在需要做的是,将UserDto填到User中去,

②、生产(provider)的启动类增加方法

由于每次使用MapperFactory都需要new出来,所有增加到启动类中去,

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

 ③、生产者(provider)的UserController类进行注入

将UserDto填到User中去,将dto转成user对象

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

package com.provider.code.controller;

import com.hmf.code.dto.UserDto;
import com.provider.code.pojo.User;
import ma.glasnost.orika.MapperFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 {


    private MapperFactory factory;

    //被接受传过来的账号
    @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 UserDto dto){
//        User u=new User();
        //需要拿到的是实体类 根据实体类到数据库查询
//        u.setAccount(dto.getAccount()).setPassword(dto.getPassword());
        User u = factory.getMapperFacade().map(dto, User.class);
        System.out.println("pojo"+dto);
        return  "provider say : yes";
    }

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

    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值