🥳🥳Welcome Huihui's Code World ! !🥳🥳
接下来看看由辉辉所写的关于SpringCloud的相关操作吧
目录
[🥳🥳Welcome Huihui's Code World ! !🥳🥳](#🥳🥳Welcome Huihui's Code World ! !🥳🥳)
[一. 远程消费组件是什么](#一. 远程消费组件是什么)
[二. 远程消费组件的详解](#二. 远程消费组件的详解)
一. 远程消费组件是什么
声明式HTTP客户端组件是一种用于简化HTTP请求的编程工具。它通过提供一种声明式的方式来发送HTTP请求,而无需编写繁琐的手动请求代码 。声明式HTTP客户端组件通常与特定的编程框架或库一起使用,可以根据预定义的配置和注解来自动生成HTTP请求的代码。这种方式可以提高开发效率,减少错误,并使代码更具可维护性。通过声明式HTTP客户端组件,开发者可以将精力集中在业务逻辑上,而无需过多关注底层的HTTP请求细节。
二. 远程消费组件的详解
场景模拟
当你使用一个电子商务应用程序下订单 时,应用程序需要与后端的服务器进行通信以处理你的请求。在这种情况下,声明式HTTP客户端组件可以被用来简化和优化与服务器的通信。
假设你正在使用一个购物应用程序,你想要下一份外卖订单。你打开应用程序,并选择你所喜欢的餐厅和菜单项。当你点击"下订单" 按钮时,应用程序会使用声明式HTTP客户端组件来发送HTTP请求到后端的服务器。
声明式HTTP客户端组件通过一种声明性的方式来定义和描述HTTP请求的结构和行为。在这个例子中,它会将你的订单信息(如餐厅ID、菜单项ID、送货地址等)转换为一个符合API规范的HTTP请求,并发送给服务器。
服务器收到请求后,会根据请求的内容来处理订单。它可能会验证订单信息、计算价格、生成订单号等。一旦服务器完成订单处理,它会将响应发送回给声明式HTTP客户端组件。
声明式HTTP客户端组件会解析服务器的响应并将其转换为应用程序可以理解的格式。例如,它可能会将响应转换为一个订单确认页面,显示订单的详细信息和预计送达时间。
通过使用声明式HTTP客户端组件,应用程序可以更轻松地与后端服务器进行通信,而无需手动构建和解析HTTP请求和响应。这使得应用程序的开发更加高效和简洁,并提供更好的用户体验。
代码实操
上面的就是一个场景模拟,现在话不多说,我们直接上代码
这里我们使用的是feign这个组件,所以需要导入相应的pom依赖
Feign: Feign是Spring Cloud提供的声明式、模板化的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可
XML<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
这里使用的例子还是生产者于消费者的例子,谁需要调用远程的服务,那么对应的那个项目的启动类中就需要添加一个注解--**@EnableFeignClients 【**主要是为开启feign接口扫描】
1.生产者
生产者主要是负责提供接口,其中可以使用以下几个注解接收远程调用的参数值
这里也有一个注意点:只要参数是复杂对象,即使指定了是GET方法,feign依然会以POST方法进行发送请求,同时生产者必 须支持POST请求并给参数添加@RequestBody注解
java@PathVariable 路径传参 @RequestParam 多个参数中,指定接收的参数名 @RequestBody 接收复杂的参数类型(比如对象)
javapackage com.provider.main; import com.provider.main.model.User; import com.wh.common.dto.UserDto; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import java.util.Map; @RestController @RequestMapping("/user") @Slf4j public class UserController { @RequestMapping("/{name}") public String pathparam(@PathVariable("name")String name) { log.info("name{}",name); return "么么哒"; } @RequestMapping("/manyparam") public String manyparam(@RequestParam("name") String name, @RequestParam("pwd") String pwd) { log.info("name{},pwd{}",name,pwd); return "么么哒"; } @RequestMapping("/objectparam") public String objectparam(@RequestBody UserDto userDto) { log.info("user{}",userDto); return "么么哒"; } @RequestMapping("/copyproperties") public String copyproperties(@RequestBody User user){ log.info("user{}",user); return "么么哒"; } @RequestMapping("/mapparam") public String mapparam(@RequestBody Map<String, Object> map) { log.info("getByMore: more:" + map); return "provider say : yes"; } }
2.消费者
消费者需要开启Feign功能,创建service,并使用Feign表示其需要远程对接的服务名称,
并使用@RequestMapping表示其映射的路径
在这个feign组件的接口中编写代码时,还需要注意一些点:
- FeignClient接口,不能使用@GettingMapping之类的组合注解
- FeignClient接口中,如果使用到@PathVariable必须指定其value
- 当使用feign传参数的时候,需要加上@RequestParam注解,否则对方服务无法识别参数
javapackage com.consumer.main.service; import com.consumer.main.model.User; import com.wh.common.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 org.springframework.web.bind.annotation.RequestParam; import java.util.Map; /** * @author是辉辉啦 * @create 2024-01-06-22:18 * 负责连接生产者的controller */ @FeignClient("provider") public interface FeignUserServise { /** * 路径传参 * @param name * @return */ @RequestMapping("user/{name}") String pathparam(@PathVariable("name") String name); /** * 多个参数【指定参数接收名】 * @param name * @param pwd * @return */ @RequestMapping("user/manyparam") String manyparam(@RequestParam("name") String name, @RequestParam("pwd") String pwd); /** * 参数是一个对象 * @param userDto * @return */ @RequestMapping("user/objectparam") public String objectparam(@RequestBody UserDto userDto); /** * 参数是一个对象--属性复制 * @param user * @return */ @RequestMapping("user/copyproperties") public String copyproperties(@RequestBody User user); /** * 参数是一个map集合 * @param map * @return */ @RequestMapping("user/mapparam") public String mapparam(@RequestBody Map<String, Object> map); }
3.复杂参数的处理
前面也说到了复杂参数必须使用post请求发送,但这里还有一个点需要注意,我们在写代码时,可能会出现这样的情况:用户的信息需要被多个服务所调用。如果服务少还好说,我们可以直接在相应的服务中编写一个实体类,其中存放我们需要的字段就行了。
DTO
但要是服务多了呢,如果还是这样做的话,好像会很麻烦,所以我们可以直接写一个dto的类,这个dto的类很多模块都可能需要用到,所以我们可以创建一个公共的maven项目,将dto的类写在那个项目中就好了。
然后再将这个项目引入到对应需要使用的项目中便可
DTO:
DTO(Data Transfer Object):数据传输对象 ,这个概念来源于J2EE的设计模式,原来的目的是 为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的 性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象
消费者远程调用生产者 : 需要网络传输,这样就可以使用DTO同一封装对象,就不需要在两个项目中都把用户这个实体类复制过来了
java/** * 参数是一个对象 * @param userDto * @return */ @RequestMapping("user/objectparam") public String objectparam(@RequestBody UserDto userDto);
属性赋值
使用了dto拿到值了,也需要将其中的值赋给相应的user对象,这里的话我们可以使用到一个映射框架--Orika
Orika:
Orika是java Bean映射框架,可以实现从一个对象递归拷贝数据至另一个对象。 在开发多层应用程序中非常有用。在这些层之间交换数据时,通常为了适应不同API需要转换一个实例至 另一个实例。
使用它也需要引入相应的依赖
XML<dependency> <groupId>ma.glasnost.orika</groupId> <artifactId>orika-core</artifactId> <version>1.4.6</version> </dependency>
然后调用相应方法之前就可以做一个复制属性的操作了
java@RequestMapping("/test03") public String test03() { UserDto userDto = new UserDto(); userDto.setPwd("root123"); userDto.setName("root"); userDto.setId(1L); DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); User u = mapperFactory.getMapperFacade().map(userDto, User.class); return feignUserServise.copyproperties(u); }
上面我们说的是属性一致的情况,那可能也会有属性不一样的时候
java@RequestMapping("/test03") public String test03() { UserDto userDto = new UserDto(); userDto.setPwd("root123"); userDto.setName("root"); userDto.setId(2L); DefaultMapperFactory mapperFactory = new DefaultMapperFactory.Builder().build(); mapperFactory.classMap(UserDto.class, User.class) .field("name", "account") .byDefault().register(); User u = mapperFactory.getMapperFacade().map(userDto, User.class); return feignUserServise.copyproperties(u); }
好啦,今天的分享就到这了,希望能够帮到你呢!😊😊