当前位置:网站首页>Implementing declarative rest calls using feign
Implementing declarative rest calls using feign
2022-06-11 10:37:00 【chentian114】
Use Feign Implement declarative REST call
List of articles
Preface
In the foreword 《 Use Ribbon Achieve client load balancing 》https://mp.weixin.qq.com/s/YwwCsUKoUA1UsaarZWVMHw in , Inter service calls use RestTemplate:
User entity = restTemplate.getForObject("http://micro-provider-user/user/v1/"+id, User.class);
From the code , It is mainly constructed by splicing strings URL To make the call , This makes the code difficult to maintain .
Feign brief introduction
Feign yes Netflix Developed declarative 、 templated HTTP client ,Feign Can help us more convenient 、 Call... Gracefully HTTP API .
stay Spring Cloud in , Use Feign It's simple – Create an interface , And add some comments to the interface , The code is done . Feign Support for multiple annotation , for example Feign Own notes or JAX-RS Annotations etc. .
Spring Cloud Yes Feign Enhanced , send Feign Support SpringMVC annotation , And integrated Ribbon and Eureka , So that Feign It is more convenient to use .
Spring Cloud Feign In essence, it is a dynamic agent mechanism , You just give one RESTful API Corresponding Java Interface , It can dynamically assemble the strong type client of the corresponding interface at run time , The simplified structure of the assembled client and the process of request response , Here's the picture :

Although the services we developed are weakly typed RESTful Service for , But because of Spring Cloud Feign Support for , Let's simply give a strongly typed Java API Interface , You automatically get a strongly typed client .
For details of strong / weak type interfaces, see :《 How to base on Spring Cloud Feign Implement strongly typed interface calls RESTful service 》https://mp.weixin.qq.com/s/bYZXhf9BfAfL5aC3bSyiHQ
Integrate for service consumers Feign
Create project , Copy project micro-consumer-movie , take artifactId It is amended as follows micro-consumer-movie-feign .
add to Feign Dependence
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
- Create a Feign Interface , And add
@FeignClientannotation .
@FeignClient(name = "micro-provider-user")
public interface UserFeignClient {
@RequestMapping(value = "/user/v1/{id}", method = RequestMethod.GET)
User findById(@PathVariable("id") Long id);
}
@FeignClient In the annotations micro-provider-user Is an arbitrary client name , be used for Ribbon Load Balancer .
In this case , Due to the use of Eureka , therefore Ribbon Will be able to micro-provider-user It can be interpreted as Eureka Server Services in the service registry .
Of course , If you don't want to use it Eureka You can use service.ribbon.listOfServers Property to configure the server list .
You can also use url Property specifies the requested URL (URL It can be complete URL Or the Lord name ), for example @FeignClient(name = "micro-provider-user", url="http://localhost:8000/")".
- modify Controller Code , Let it call Feign Interface .
@RestController
@RequestMapping("/movie/v1")
public class MovieController {
@Resource
private UserFeignClient userFeignClient;
@GetMapping("/{id}")
public User findById(@PathVariable Long id){
User entity = userFeignClient.findById(id);
return entity;
}
}
- Modify the startup class , To add
@EnableFeignClientsannotation .
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class MicroConsumerMovieFeignApplication {
public static void main(String[] args) {
SpringApplication.run(MicroConsumerMovieFeignApplication.class, args);
}
}
- Start service test . start-up Eureka Server: micro-discovery-eureka 、 Service providers :micro-provider-user 、 Serving consumers :micro-consumer-movie-feign ; visit :http://localhost:8010/movie/v1/1 .
Manually create Feign
In some cases , You can use Feign Builder API Manually create Feign .
For example, the following scenario :
- The user microservice interface can only be called after logging in , And for the same API , Users in different roles have different behaviors .
- Let the movie micro service be the same Feign The interface uses different accounts to log in , And call the user microservice interface .
One 、 Modify the user microservice , Make it accessible only after login and authentication
Create project , Copy project micro-provider-user , take artifactId It is amended as follows micro-provider-user-with-auth .
Add dependencies to the project .
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- establish Spring Scurity Configuration class
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder(){
// Plaintext encoder .Spring Provide clear text testing
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// All requests , All need to go through HTTP basic authentication
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
@Component
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if("user".equalsIgnoreCase(username)){
return new SecurityUser("user", "password1", "user-role");
} else if("admin".equalsIgnoreCase(username)){
return new SecurityUser("admin", "password2", "admin-role");
} else {
return null;
}
}
}
public class SecurityUser implements UserDetails {
private Long id;
private String username;
private String password;
private String role;
public SecurityUser(String username, String password, String role){
super();
this.username = username;
this.password = password;
this.role = role;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Collection<GrantedAuthority> authorities = new ArrayList<>();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(this.role);
authorities.add(authority);
return authorities;
}
//...
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Simulated two accounts : user and admin , Their passwords are password1 and password2 , The roles are user-role and admin-role .
- modify Controller , Print the currently logged in user information in the log .
@RestController
@RequestMapping("/user/v1")
public class UserController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private UserRepository userRepository;
@GetMapping("/{id}")
public User findById(@PathVariable Long id){
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if(principal instanceof UserDetails){
UserDetails user = (UserDetails) principal;
Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
for(GrantedAuthority authority : authorities){
logger.info(" The current user is :{}, The role is :{}", user.getUsername(), authority.getAuthority());
}
}
User entity = userRepository.findOne(id);
return entity;
}
}
- Start service test , start-up Eureka Server: micro-discovery-eureka 、 Service providers :micro-provider-user-auth , Access address : http://localhost:8000/user/v1/1 .
Two 、 Modify the movie microservice , Make it possible to achieve the same Feign The interface uses different accounts to log in
Copy project micro-consumer-movie-feign , modify artifactId by micro-consumer-movie-feign-manual .
Get rid of Feign Interface UserFeignClient Of
@FeignClientannotation .Remove the on the startup class
@EnableFeignClientsannotation .modify Controller as follows :
@Import(FeignClientsConfiguration.class)
@RestController
@RequestMapping("/movie/v1")
public class MovieController {
private UserFeignClient userFeignClient;
private UserFeignClient adminFeignClient;
@Autowired
public MovieController(Decoder decoder, Encoder encoder, Client client, Contract contract){
this.userFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
.requestInterceptor(new BasicAuthRequestInterceptor("user", "password1"))
.target(UserFeignClient.class, "http://micro-provider-user");
this.adminFeignClient = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
.requestInterceptor(new BasicAuthRequestInterceptor("admin", "password2"))
.target(UserFeignClient.class, "http://micro-provider-user");
}
@GetMapping("/user-user/{id}")
public User findByIdUser(@PathVariable Long id){
User entity = userFeignClient.findById(id);
return entity;
}
@GetMapping("/user-admin/{id}")
public User findByIdAdmin(@PathVariable Long id){
User entity = adminFeignClient.findById(id);
return entity;
}
}
among ,@Import Imported FeignClientsConfiguration yes Spring Cloud by Feign The configuration class provided by default .
userFeignClient Login account user, adminFeignClient Login account admin , They use the same interface UserFeignClient .
- Start the test , start-up Eureka Server: micro-discovery-eureka 、 Service providers :micro-provider-user-auth 、 Serving consumers :micro-consumer-movie-feign-manual ; visit http://localhost:8010/movie/v1/user-user/1 and http://localhost:8010/movie/v1/user-admin/1 , see user Logs of services , You can see that different user accounts have been printed .
Code warehouse
https://gitee.com/chentian114/spring-cloud-practice
official account
Reference resources
《Spring Cloud And Docker Microservice architecture practice 》 Zhou Li
边栏推荐
- C语言课程设计题目
- Correct opening method of RPC | understand go native net/rpc package
- Finite cyclic group
- Explain the physical layer consistency test of 2.5g/5g/10g Base-T Ethernet interface in detail!
- C语言课程设计
- Use of JMeter (simulating high concurrency)
- 修复UICollectionView 没有到达底部安全区的问题
- NGUI,背包拖拽,以及随机克隆图片知识点
- What is the SOA or ASO of MOSFET?
- NGUI,地图放大缩小
猜你喜欢

Leetcode 1952. 三除数

国际多语言出海商城返佣产品自动匹配订单源码

金仓数据库KingbaseES UDP监控工具的使用

Circuit board made of real gold -- golden finger

Installing mysql5.7 for Linux

Install MySQL version 5.7 or above on windows (install in compressed package)

使用 Hystrix 实现微服务的容错处理

Leetcode 1961. Check whether the string is an array prefix

【GAMES101】作业2--三角形光栅化

详述用网络分析仪测量DC-DC和PDN
随机推荐
Data consistency
Jedislock redis distributed lock implementation
Leetcode 1952. Triple divisor
远程监控项目离线日志说明书
NFT将改变元宇宙中的数据所有权
Leetcode 1961. Check whether the string is an array prefix
地铁路线图云开发小程序源码和配置教程
MySQL基础篇常用约束总结上篇
Global pooling – pytoch
国际多语言出海商城返佣产品自动匹配订单源码
Ngui, floating blood
MOSFET的SOA或者ASO是什么?
[MySQL] use of stored procedures
用真金做的电路板——金手指
NGUI,背包拖拽,以及随机克隆图片知识点
Leetcode 1995. Statistics special quads (brute force enumeration)
Ngui, backpack drag and drop, and random cloning of picture knowledge points
Bcgcontrolbar Library Professional Edition, fully documented MFC extension class
利用PHP开发的一款万能、表白墙系统部分代码片段
基于C语言实现比赛评分系统