《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
org.springframework.cloud
spring-cloud-starter-feign
org.springframework.boot
spring-boot-starter-web
2.在主类上使用@EnableFeignClients注解开启SpringCloudFeign的支持功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class FeignApplication {
public static void main(String[] args) {
SpringApplication.run(FeignApplication.class, args);
}
}
3.接口定义:我们这里调用USER-SERVICE服务,在该服务中创建一个查询所有用户的接口,然后在feign-consumer中定义。
USER-SERVICE
@RestController
public class UserFeignController {
@Autowired
private UserRepository userRepository;
@GetMapping(“/feign/user/list”)
public List findAllUser(){
return userRepository.findAll();
}
}
feign-consumer
@FeignClient(value = “USER-SERVICE”)
public interface UserService {
@GetMapping(“/feign/user/list”)
List findAll();
}
使用@FeignClient注解指定服务名来绑定服务,如果不指定服务名,启动项目将会报错。然后创建一个接口与调用普通的service一样调用UserService。
@RestController
public class FeignConsumerController {
@Autowired
private UserService userService;
@GetMapping(value = “/feign/find”)
public List findAllUser(){
return userService.findAll();
}
}
最后修改配置文件
spring:
application:
name: feign-consumer
server:
port: 50000
eureka:
client:
service-url:
defaultZone: http://localhost:8888/eureka/
这里使用的User对象与前面ARTICLE-SERVICE的User对象一样。依次启动服务注册中心、服务提供方、服务消费方。然后调用/feign/find接口,可以正常返回数据。
参数绑定
在实际开发中,像上面那种不带参数的接口可能少之又少。Feign提供了多种参数绑定的方式。
在服务提供的UserFeignController中添加以下三个接口:
/**
- 根据id查询用户,将参数包含在Request参数
*/
@GetMapping(“/feign/userById”)
public User finUserById(@RequestParam Long id){
logger.info(“>>>>>>>>>>>id:{}<<<<<<<<<<<<<”,id);
return userRepository.findOne(id);
}
/**
-
带有Header信息的请求,需要注意的是,使用请求头传递参数,如果参数是中文会出现乱码
-
所以需要使用 URLEncoder.encode(name,“UTF-8”) 先编码
-
后解码 URLDecoder.decode(name,“UTF-8”);
*/
@GetMapping(“/feign/header/user”)
public User findUserHeader(@RequestHeader String name,@RequestHeader Long id,@RequestHeader Integer age) throws UnsupportedEncodingException {
User user = new User();
user.setId(id);
user.setUsername( URLDecoder.decode(name,“UTF-8”));
user.setAge(age);
logger.info(“>>>>>>>>>>>findUserHeader{}<<<<<<<<<<<<<”,user);
return user;
}
/***
- 带有RequestBody以及请求相应体是一个对象的请求
*/
@PostMapping(“/feign/insert”)
public User insertUser(@RequestBody User user){
userRepository.save(user);
return userRepository.findOne(user.getId());
}
直接将上面添加的接口复制到消费方的Service接口中,删除方法体。需要注意的是:在SpringMVC中@RequestParam和@RequestHeader注解,如果我们不指定value,则默认采用参数的名字作为其value,但是在Feign中,这个value必须明确指定,否则会报错。
/**
- 根据id查询用户,将参数包含在Request参数
*/
@GetMapping(“/feign/userById”)
User finUserById(@RequestParam(“id”) Long id);
/**
- 带有Header信息的请求
*/
@GetMapping(“/feign/header/user”)
User findUserHeader(@RequestHeader(“name”) String name, @RequestHeader(“id”) Long id,@RequestHeader(“age”) Integer age);
/**
- 带有RequestBody以及请求相应体是一个对象的请求
*/
@PostMapping(“/feign/insert”)
User insertUser(@RequestBody User user);
测试接口:
@GetMapping(“/testFeign”)
public void testFeign() throws UnsupportedEncodingException {
User user = userService.finUserById(2L);
logger.info(“>>>>>>>>>>>>Request参数:{}>>>>>>>>>>>>>”,user);
User user2 = userService.findUserHeader(URLEncoder.encode(“呜呜呜呜”,“UTF-8”), 3L,1000);
logger.info(“>>>>>>>>>>>>Header:{}>>>>>>>>>>>>>”,user2);
User save_user = new User(5L,“嘻嘻嘻”,56);
User users = userService.insertUser(save_user);
logger.info(“>>>>>>>>>>>>RequestBody:{}>>>>>>>>>>>>>”,users);
}
继承特性
在上面的例子中,在服务消费方声明接口时都是将服务提供方的Controller复制过来。这么做会出现很多重复代码。在SpringCloudFeign中提供了继承特性来帮助我们解决这些复制操作。
1. 创建建一个基础的Maven工程,命名service-api,以复用DTO与接口定义。这里需要用到SpringMVC的注解,所以需要引入依赖:
org.springframework.boot
spring-boot-starter-web
将上面的User对象复制到api中,并创建UserService
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements Serializable {
private Long id;
private String username;
private int age;
}
@RequestMapping(“/rafactor”)
public interface UserService {
@GetMapping(“/feign/user/list”)
List findAll();
/**
- 根据id查询用户,将参数包含在Request参数
*/
@GetMapping(“/feign/userById”)
User finUserById(@RequestParam(“id”) Long id);
/**
- 带有Header信息的请求
*/
@GetMapping(“/feign/header/user”)
User findUserHeader(@RequestHeader(“name”) String name, @RequestHeader(“id”) Long id, @RequestHeader(“age”) Integer age);
/**
- 带有RequestBody以及请求相应体是一个对象的请求
*/
@PostMapping(“/feign/insert”)
User insertUser(@RequestBody User user);
}
重构USER-SERVICE,在pom文件中新增service-api;并创建UserRafactorController类实现service-api的UserService类;
com.wqh
sevice-api
0.0.1-SNAPSHOT
@RestController
public class UserRafactorController implements UserService{
private final Logger logger = LoggerFactory.getLogger(UserRafactorController.class);
@Autowired
private UserRepository userRepository;
@Override
public List findAll() {
return null;
}
@Override
public User finUserById(Long id) {
logger.info(“>>>>>>>>>>>Rafactor id:{}<<<<<<<<<<<<<”,id);
com.wqh.user.entity.User one = userRepository.findOne(id);
User user = new User(one.getId(),one.getUsername(),one.getAge());
return user;
}
@Override
public User findUserHeader(@RequestHeader(“name”)String name, @RequestHeader(“id”)Long id,@RequestHeader(“age”) Integer age) {
User user = new User();
user.setId(id);
try {
user.setUsername( URLDecoder.decode(name,“UTF-8”));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
user.setAge(age);
logger.info(“>>>>>>>>>>>Rafactor findUserHeader{}<<<<<<<<<<<<<”,user);
return user;
}
@Override
public User insertUser(@RequestBody User user) {
logger.info(“>>>>>>>>>>>Rafactor RequestBody{}<<<<<<<<<<<<<”,user);
return user;
}
}
该类不需要使用@RequestMapping注解来定义请求映射,参数注解需要添加,并且在类上添加@RestController注解。
4. 重构feign-consumer,添加service-api的依赖
com.wqh
sevice-api
0.0.1-SNAPSHOT
创建UserRafactorService接口继承UserService接口
@FeignClient(value = “USER-SERVICE”)
public interface UserRafactorService extends UserService {
}
测试接口
@GetMapping(“/testRafactorService”)
public void testRafactorService() throws UnsupportedEncodingException {
com.wqh.api.dto.User user = userRafactorService.finUserById(2L);
logger.info(“>>>>>>>>>>>>Rafactor Request参数:{}>>>>>>>>>>>>>”,user);
com.wqh.api.dto.User user2 = userRafactorService.findUserHeader(URLEncoder.encode(“呜呜呜呜”,“UTF-8”), 3L,1000);
logger.info(“>>>>>>>>>>>>Rafactor Header:{}>>>>>>>>>>>>>”,user2);
com.wqh.api.dto.User save_user = new com.wqh.api.dto.User(5L,“嘻嘻嘻”,56);
com.wqh.api.dto.User users = userRafactorService.insertUser(save_user);
logger.info(“>>>>>>>>>>>>Rafactor RequestBody:{}>>>>>>>>>>>>>”,users);
}
注意:这里对于对象之间的处理是存在问题,就不详细的修改了,主要是为了Feign的继承特性。
Feign配置详解
Ribbon配置
在Feign中配置Ribbon非常简单,直接在application.properties中配置即可,如:
设置连接超时时间
ribbon.ConnectTimeout=500
设置读取超时时间
ribbon.ReadTimeout=5000
对所有操作请求都进行重试
ribbon.OkToRetryOnAllOperations=true
切换实例的重试次数
ribbon.MaxAutoRetriesNextServer=2
对当前实例的重试次数
ribbon.MaxAutoRetries=1
同样也可以指定服务配置,直接在application.properties中采用.ribbon.key=value的格式进行配置,如下:
设置针对user-service服务的连接超时时间
user-service.ribbon.ConnectTimeout=600
设置针对user-service服务的读取超时时间
user-service.ribbon.ReadTimeout=6000
设置针对user-service服务所有操作请求都进行重试
最后
金三银四到了,送上一个小福利!
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!
OkToRetryOnAllOperations=true
切换实例的重试次数
ribbon.MaxAutoRetriesNextServer=2
对当前实例的重试次数
ribbon.MaxAutoRetries=1
同样也可以指定服务配置,直接在application.properties中采用.ribbon.key=value的格式进行配置,如下:
设置针对user-service服务的连接超时时间
user-service.ribbon.ConnectTimeout=600
设置针对user-service服务的读取超时时间
user-service.ribbon.ReadTimeout=6000
设置针对user-service服务所有操作请求都进行重试
最后
金三银四到了,送上一个小福利!
[外链图片转存中…(img-oox2ZknS-1714761027946)]
[外链图片转存中…(img-MlBlzmIg-1714761027947)]
[外链图片转存中…(img-HeZ2gmV5-1714761027947)]
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门,即可获取!