当前位置:网站首页>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
边栏推荐
猜你喜欢

Summary of common constraints in MySQL foundation part I

Internet of things security in the era of remote work

用真金做的电路板——金手指

Leetcode 1952. 三除数

beginning一款非常优秀的emlog主题

MySQL foundation part common constraints summary part 2

MN梦奈宝塔主机系统V1.5版本发布

New Zealand is one of the best countries for road safety

Wechat applet ordering system with source code

iPhone 15 被迫用上 Type-C 接口
随机推荐
C+ daily exercises (15)
Circuit board made of real gold -- golden finger
使用bat向文件的第一行中写入内容
Fix the problem that uicollectionview does not reach the bottom security zone
金仓数据库KingbaseES UDP监控工具的使用
数字藏品系统开发源码搭建
Use of JMeter (simulating high concurrency)
NFT产品是有生命的
VMware install win7 virtual machine
PHP仿网易云原创音乐分享平台网站源码
Knowledge drop - personality analysis - four types of method
NGUI,地图放大缩小
安装MySQL ,出现由于找不到 MSVCR120.dll,无法继续执行代码解决方法”
NFT 2.0: the next generation of NFT will be lean and trustworthy
Some code fragments of a universal and confession wall system developed by PHP
NFT products are alive
[machine learning theory] true positive, true negative, false positive, false negative concept
Gamefi: everything you need to know about the "play and earn" game economy
C#入门系列(十一) -- 多维数组
详述用网络分析仪测量DC-DC和PDN