前言:继上一篇博客的基础上在进行的编码
SpringCloud 的基本使用 nacos | SpringCloud 基本使用与 nacos_m0_58525944的博客-CSDN博客 |
一,Feign 远程调用 消费者(consumer) 生产者(provider)
1,定义远程调用接口 在生产者 建立pojo软件包,新建User实体类
package com.provider.nacos_provider.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author lgs
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class User {
private String account;
private String password;
}
2,提供接口用于消费者调用 在生产者中创建controller层
其中远程调用三种传参方式
①.@PathVariable 路径传参 ②.@RequestParam 请求参数传参
③.@RequestBody json传参
package com.provider.nacos_provider.controller;
import com.lgs.commons.dto.UserDto;
import com.provider.nacos_provider.pojo.User;
import javassist.runtime.DotClass;
import ma.glasnost.orika.MapperFactory;
import org.apache.logging.log4j.util.PerformanceSensitive;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* @author T440s
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
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(@RequestParam("account") String account, @RequestParam("password") String password){
System.out.println("account:"+account+"\tpassword:"+password);
return "provider say : yes";
}
// jxon格式
@RequestMapping("/pojo")
public String getByPojo(@RequestBody UserDto userDto){
User u = new User();
u.setAccount(userDto.getAccount()).setPassword(userDto.getPassword());
// 只适应属于一样的
// User u = factory.getMapperFacade().map(userDto,User.class);
// 属性不一样 生产者为name dto里面为account
// factory.classMap(UserDto.class,User.class)
// .field("name","account")
// .byDefault().register();
// User map = factory.getMapperFacade().map(userDto,User.class);
System.out.println("pojo:"+userDto);
return "provider say : yes";
}
// 所有格式
@RequestMapping("/more")
public String getByMore(@RequestBody Map<String,Object> map){
System.out.println("more:"+map);
return "provider say : yes";
}
}
3,在消费者模块中添加接口
注解@FeignClient("/nacos-provider")表示远程通信,括号内
package com.consumer.cloud_consumer.service;
import com.lgs.commons.dto.UserDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* @author lgs
*
* FeignClient 远程通信
*/
@FeignClient("nacos-provider")
@SuppressWarnings("all")
public interface FeignUserService {
// 路径传参
@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);
// jxon格式
@RequestMapping("/user/pojo")
public String getByPojo(@RequestBody UserDto user);
// 所有格式
@RequestMapping("/user/more")
public String getByMore(@RequestBody Map<String,Object> map);
}
4,在启动类中添加注解 开启远程通信
@EnableDiscoveryClient
5,测试时,我们需把生产者中的user类复制一份到消费者中
6,开始远程调用,在消费者创建controller层进行测试
package com.consumer.cloud_consumer.controller;
import com.consumer.cloud_consumer.service.FeignUserService;
import com.lgs.commons.dto.UserDto;
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 {
@Autowired
private FeignUserService 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 UserDto().setAccount(account).setPassword(password));
return "yes";
}
@RequestMapping("/test05")
public String test05(String account,String password){
Map<String,Object> map = new HashMap<>();
map.put("account",account);
map.put("password",password);
service.getByMore(map);
return "yes";
}
}
测试:
二,DTO 层的构建
消费者调用接口时,需要使用到user实体类,这就使得代码重复,为了使代码简介,我们采取dot层的构建
1,DTO封装介绍
1.VO(View Object):视图对象,用于展示层,前端将数据传到后台
2.DTO(Data Transfer Object):数据传输对象,用于后端服务互相传数据
3.DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。用于服务调用service层
4.PO(Persistent Object):持久化对象,用于service调用数据库
关系图:
消费者 远程调用 生产者 : 需要网络传输 , 使用 DTO 同一封装对象原理与 SpringBoot 启动类相同1. 将 DTO 对象封装到公共 DTO 模块2. 为需要的项目引入公共 DTO 模块注意点1. 不需要继承父模块 ( 重复引用问题 )2. 打包方式为 jar3. 不需要添加启动类的编译
2,在父项目中新建一个子项目,版本为2.4.1
3,在这个 commons 的 pom 文件中导入 lombok 依赖 如果有很多子项目要用,就放到父项目中
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
4,将dot模块变成jar包的形式,使得其他模块可导入pom文件添加依赖
5,父模块pom文件中添加dot依赖并进行单方面认亲
<dependency>
<groupId>com.lgs</groupId>
<artifactId>commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
然后消费者中的user类就可以删除,并在使用过user类的地方用userdto代替
在这里会产生一个问题:dto类的属性比user中的多,或者字段名不一样
有以下两种解决方式:
①拿到user类,然后去修改属性值,但字段过多就不适用了
User u = new User(); u.setAccount(userDto.getAccount()).setPassword(userDto.getPassword());
②orika 对象复制
生产者pom文件中添加依赖
<dependency> <groupId>ma.glasnost.orika</groupId> <artifactId>orika-core</artifactId> <version>1.4.6</version> </dependency>
在生产者的启动类中对MapperFactory属性进行spring注入
@Scope("prototype")表示原型链模式(为了使MapperFactory互不干涉)
@Bean @Scope("prototype") public MapperFactory mapperFactory(){ return new DefaultMapperFactory.Builder().build(); }
//只适应属于一样的 User u = factory.getMapperFacade().map(userDto,User.class); //属性不一样 生产者为name dto里面为account factory.classMap(UserDto.class,User.class) .field("name","account") .byDefault().register(); User map = factory.getMapperFacade().map(userDto,User.class);
OK!到这就结束了,希望能帮到你!!!