SpringCload搭建(二):使用Feign远程调用和参数,公共模块:传输对象dto,0X orika方便赋值

在上篇文章中,我们使用了@LoadBalanced //开启负载均衡大大简化了远程调用时的代码:

String  forEntity = restTemplate.getForObject("http://provider/test/hello", String.class);

1.简介

Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做

 

2.consumer层使用feign替代RestTemplate去远程调用provider的流程

  2.1 建立一个feign接口类(放需要远程调用的接口)

    

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* @Author: LJX
* @DateTime: 2022/3/12 15:06
* @Description: TODO
*/
@Service
@FeignClient("provider")
public interface HelloFeign {

/**
* 这里配置生产者的接口
* @return
*/
@RequestMapping("/test/hello")
String hello();

}

    2.2consumer去调用

  

@Resource
private HelloFeign helloFeign;

@RequestMapping("/hello")
public String hello(){
System.out.println("消费者");
//调用生产者,url + 返回类型
// String forEntity = restTemplate.getForObject("http://provider/test/hello", String.class);
String hello = helloFeign.hello();
return hello;
}

    2.3调用生产者成功:消费者的启动类添加注解@EnableFeignClients

 

 

 

3.公共模块(maven项目,不需要启动类和继承父类):传输对象dto

3.1 为何公共模块可以跨模块调用:

因为在父类的pom文件中引入了依赖

<!-- 公共Vo模块-->
<dependency>
<groupId>com.xiu</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

3.2 消费者通过feign调用生产者,如果insert(Book book),那么消费者中也要有Book去传参,可是feign只是远程调用接口,那么实体类怎么跨模块呢?

  传参形式:http://localhost:6101/book/insert?bookId=1&bookName=hhh&price=1.1&desc=这是啥书,到了消费者可以接收到值,但是消费者 -->生产者

  {bookid: 1,bookName=hhh...},这种形式给生产者,生产者是识别不出来的,所以要加上注解:

@RequestBody

Feign综合示例
1~N个参数
@RequestParam Long bookId
1个复杂对象DTO
生产者接受参数时要添加@RequestBody
将DTO对象定义到公共模块

附录一:远程调用的相关注解
@PathVariable
--
@RequestMapping("show5/{id}/{name}")
public ModelAndView test5(@PathVariable("id") Long ids ,@PathVariable("name") String names){
ModelAndView mv = new ModelAndView();
mv.addObject("msg","占位符映射:id:"+ids+";name:"+names);
mv.setViewName("hello2");
return mv;
}

@RequestParam
@RequestBody

@RequestMapping
注解RequestMapping中produces属性可以设置返回数据的类型以及编码,可以是json或者xml:
@RequestMapping(value="/xxx",produces = {"application/json;charset=UTF-8"})
@RequestMapping(value="/xxx",produces = {"application/xml;charset=UTF-8"})

4.0X orika 方便dto对象赋值给po对象
1.从消费者到生产者传值方法:set

 

2.从消费者到生产者传值方法:直接使用dto对象传到service层
3.使用orika进行dto对po对象的赋值
  3.
1.导入依赖

<!-- https://mvnrepository.com/artifact/ma.glasnost.orika/orika-core -->
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
<version>1.5.4</version>
</dependency>

3.2 下配置
package com.xiu.provider.config;

import com.xiu.common.dto.BookDto;
import com.xiu.provider.model.Book;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.impl.DefaultMapperFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Author: LJX
* @DateTime: 2022/3/13 21:07
* @Description: TODO
*/
@Configuration
public class OrikaConfig {

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

@Autowired//作用在方法上有参数,那么该参数注入到spring上下文中的时候调用此方法
public void mapper(MapperFactory mapperFactory) {
mapperFactory.classMap(BookDto.class, Book.class)
// .field("bookName","bname")//如果属性名不一样时需要
.byDefault()
.register();

//如果还有别的类继续往下面加

}
}
3.3使用方法,只需要两句
/**
* @Author: LJX
* @DateTime: 2022/3/12 22:03
* @Description: TODO
*/
@RestController
@RequestMapping("/book")
public class BookController {

@Resource
private IBookService ibookService;

//注入的时候会自动都要@Autoride配置方法
@Resource
private MapperFactory mapperFactory;

@PostMapping("/insert")
public Map<String ,Object> insert(@RequestBody BookDto bookDto){
System.out.println("这是生产者的insert方法");
MapperFacade mapperFacade = mapperFactory.getMapperFacade();
Book book = mapperFacade.map(bookDto,Book.class);
System.out.println("生产者BookDto"+bookDto);
Map map = new HashMap();
// book.setBookId(bookDto.getBookId());
// book.setBookName(bookDto.getBookName());
int insert = ibookService.insert(book);
map.put("msg","书本添加成功");
map.put("book",bookDto);
return map;
}
}
效果
orika番外篇

附录一:MapperFactory公共配置Bean映射DTO
@Configuration
public class ServerConfig {


@Autowired
public void config(MapperFactory mapperFactory) {
mapperFactory.getConverterFactory().registerConverter("orderStatusConvert", new OrderStatusConvert());


//添加一个Bean和Dto的映射就使用classMap,只要程序当中使用到的classMap包含的
//两个类进行转换,就会自动跳到该转换器来。
//classMap第一个参数是需要转换的参数实体
//classMap第二个参数是转换对应的参数实体
//field表示实体名称的字段不太一样,添加映射关系
//fieldMap表示字段值不一样,添加自定义转换器
//orderStatusConvert表示被mapperFactory注册过的id值,
//一个orderStatusConvert对应一个类,可以在当前类简建立一个内部类,当做自定义转换器

mapperFactory.classMap(Order.class, OrderDto.class)
.field("finallyTime", "lastTime")
.field("orderItems", "orderItemList")
.field("userAddrOrder", "orderAddress")
.fieldMap("status", "status").converter("orderStatusConvert")
.add()
.byDefault()
.register();


mapperFactory.classMap(MyOrderDto.class, OrderDto.class)
.field("orderItemDtos", "orderItemList")
.fieldMap("status", "status").converter("orderStatusConvert")
.add()
.byDefault()
.register();


mapperFactory.classMap(OrderParam.class, Order.class)

.fieldMap("status", "status").converter("orderStatusConvert")
.add()
.byDefault()
.register();

mapperFactory.classMap(NewOrderParam.class, Order.class)
.fieldMap("status", "status").converter("orderStatusConvert")
.add()
.byDefault()
.register();

// mapperFactory.classMap(String.class, Date.class);

}

 

posted @ 2022-03-12 22:44  创嗨  阅读(729)  评论(0编辑  收藏  举报