一、定义远程调用接口
1.生产者中新建实体类user
package com.lj.provider.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author My
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true) //链式编程
public class User {
private String accout;
private String pwassword;
}
2.在生产者中创建controller层
package com.lj.provider.controller;
import com.cloud02.code.dto.UserDto;
import com.lj.provider.pojo.User;
import ma.glasnost.orika.MapperFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* @author My
*/
@RestController
@RequestMapping("/user")
public class UserController {
private MapperFactory factory;
@Autowired
public UserController(MapperFactory factory) {
this.factory = factory;
}
@RequestMapping("/{account}")
/**
* @PathVariable 路径传参
*/
public String getByPath(@PathVariable String account) {
System.out.println("account:" + account);
return "provider say : yes";
}
@RequestMapping("/param")
/**
* @RequestParam 请求传参
*/
public String getByParam(@RequestParam("account") String account, @RequestParam("password") String password) {
System.out.println("account:" + account + "----password----:" + password);
return "provider say : yes";
}
@RequestMapping("/pojo")
/**
* 前台发送json数据 @RequestBody说明接收的是json
*/
public String getByPojo(@RequestBody UserDto dto) {
//dto中的属性可能比sshi实体类多
//需要拿到的是实体类 根据实体类d的属性去数据库查询数据
// User u = new User();
// u.setAccout(dto.getAccout());
// u.setPwassword(dto.getPwassword());
//在学习Struts2的时候 BeanUtils(将我的数据与实体类的数据匹配,然后将符合的数据放到实体类中)
// User u = factory.getMapperFacade().map(dto, User.class); //适用属性相同情况
//属性不同
factory.classMap(UserDto.class, User.class)
.field("name", "account")
.byDefault().register();
User u = factory.getMapperFacade().map(dto, User.class);
System.out.println("pojo" + dto);
return "provider say : yes";
}
@RequestMapping("/more")
/**
* 接收任意类型 map
*/
public String getByPojo(@RequestBody Map<String, Object> map) {
System.out.println("more" + map);
return "provider say : yes";
}
}
3.在消费者模块中添加接口
注解@FeignClient("nacos-provider")表示远程通信,括号内
package com.consumer.code.service;
import com.cloud02.code.dto.UserDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* @author My
*/
@FeignClient("nacos-provider")
public interface FeginUserService {
@RequestMapping("/user/{account}")//@PathVariable 路径传参
public String getByPath(@PathVariable("account") String account);
@RequestMapping("/user/param")//@RequestParam 请求传参
public String getByParam(@RequestParam("account") String account, @RequestParam("password") String password);
@RequestMapping("/user/pojo")//前台发送json数据 @RequestBody说明接收的是json
public String getByPojo(@RequestBody UserDto user);
@RequestMapping("/user/more")//接收任意类型 map
public String getByMore(@RequestBody Map<String,Object> map);
}
4.在启动类中添加注解@EnableFeignClients
表示开启远程通信功能
package com.consumer.code;
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;
/**
* @author My
*/
@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.远程调用三种传参方式:
①.@PathVariable 路径传参
②.@RequestParam 请求参数传参
③.@RequestBody json传参
二、远程调用
1.在消费者创建controller层进行测试,需要将pojo包复制过来
package com.consumer.code.controller;
import com.cloud02.code.dto.UserDto;
import com.consumer.code.service.FeginUserService;
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;
/**
* @author My
*/
@RestController
@RequestMapping("/user")
public class UserController {
private FeginUserService service;
@Autowired
public UserController(FeginUserService service) {
this.service = service;
}
@RequestMapping("/test01")
public String test01(String account){
service.getByPath(account);
return "yes";
}
@RequestMapping("/{account}")
public String test02(@PathVariable("account") 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().setName(account).setPwassword(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";
}
}
2.结果
三、DOT层的构建
由于消费者调用接口时,需要使用到user实体类,这就使得代码重复,为了使代码简介,我们采取dot层的构建
下面介绍以下对象命名分类
1.VO(View Object):视图对象,用于展示层,前端将数据传到后台
2.DTO(Data Transfer Object):数据传输对象,用于后端服务互相传数据
3.DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。用于服务调用service层
4.PO(Persistent Object):持久化对象,用于service调用数据库
关系图
dot层的构建:
目的:作为启动器,将实体类移到里面作为公共部分为其他模块所用
1.创建spring项目,版本号为2.4.1
2.将实体类移进来
3.在pom文件中导入lombok依赖
<?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.cloud02</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>
4.将dot模块变成jar包的形式,使得其他模块可导入pom文件添加依赖
5.父模块pom文件中添加dot依赖并进行单方面认亲
注意:dot模块不能继承父模块
然后消费者中的user类就可以删除,并在使用过user类的地方用userdto代替
在这里会产生一个问题:dto类的属性比user中的多,或者字段名不一样
有以下两种解决方式:
①拿到user类,然后去修改属性值
②orika 对象复制
①拿到user类,然后去修改属性值
②orika 对象复制
生产者pom文件中添加依赖
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.4.6</version>
</dependency>
在生产者的启动类中对MapperFactory属性进行spring注入
@Scope("prototype")表示原型链模式(为了使MapperFactory互不干涉)
//prototype原型链模式
@Bean
@Scope("prototype")
public MapperFactory mapperFactory(){
return new DefaultMapperFactory.Builder().build();
}
生产者controller