03.Spring Cloud OpenFeign声明式服务调用

Spring Cloud OpenFeign声明式服务调用

一、体验demo

1.Eureka Server

新建一个Eureka Server工程,导入eureka-server依赖:

<dependency>
  	<groupId>org.springframework.cloud</groupId>
  	<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

新建启动类:

@SpringBootApplication
// 开启eureka server
@EnableEurekaServer
public class Server02App {

	public static void main(String[] args) {
		SpringApplication.run(Server02App.class, args);
	}
	
}

配置配置文件:

# 配置server sever端口
server:
  port: 9000
  
eureka:
  # eureka server 也是一个eureka client
  client:
    # 作为客户端不注册
    registerWithEureka: false
    # 不从注册中心获取注册信息
    fetchRegistry: false

2.新建客户端

导入依赖:

	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-web</artifactId>
  	</dependency>

同时要导入Spring Boot插件,使jar打包能正常运行(避免执行时报错XXX.jar中没有主清单属性):

<build>
  <plugins>
  	<plugin>
  		<groupId>org.springframework.boot</groupId>
 		<artifactId>spring-boot-maven-plugin</artifactId>
  	</plugin>
  </plugins>
 </build>

启动类:


@SpringBootApplication
@EnableDiscoveryClient
public class Client01App {

	public static void main(String[] args) {
		SpringApplication.run(Client01App.class, args);
	}
	
}

服务类(用户提供服务):

@RestController
public class ServiceController {

	@GetMapping("/hello/{name}")
	public String getHello(@PathVariable("name") String name) {
		return "hello " + name;
	}
	
}

配置文件:

server:
  port: 9010
  
eureka:
  client:
    serviceUrl:
      # 设置注册中心的地址
      defaultZone: http://localhost:9000/eureka
      
spring:
  # 设置项目名等
  application:
    name: client-service

3.新建消费服务客户端

导入依赖:

	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-web</artifactId>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework.cloud</groupId>
  		<artifactId>spring-cloud-starter-openfeign</artifactId>
  	</dependency>

启动类:

@SpringBootApplication
@EnableDiscoveryClient
// 开启OpenFeign支持
@EnableFeignClients
public class OpenFeignClientApp {

	public static void main(String[] args) {
		SpringApplication.run(OpenFeignClientApp.class, args);
	}
	
}

新建一个接口,用于调用服务:

// 指定这是feign客户端 name属性指明要调用的服务名
@FeignClient(name = "client-service")
public interface IServiceFeign {

	// 指定要调用的服务,要和调用的服务调用方式保持一致
	@GetMapping("/hello/{name}")
	public String getHello(@PathVariable("name") String name);
	
}

调用服务:

@RestController
public class ServiceController {

	// 注入IServiceFeign(feign的客户端,来调用服务)
	@Autowired
	private IServiceFeign iServiceFeign;
	
	@GetMapping("/consumer/{name}")
	public String consumer(@PathVariable("name") String name) {
		// 调用具体的服务
		return iServiceFeign.getHello(name);
	}
	
}

启动项目,访问接口@GetMapping("/consumer/{name}"),即可看到服务调用结果。

二、自定义配置

1.配置使用feign自带注解

上面的例子中,feign使用的完全是SpringMVC的注解,其实feign也提供了注解,如果需要使用feign的注解需要自己配置。
配置类不能被扫描,否则全局生效(不能作用于单个feign)

@Configuration
public class OpenFeignConfig {

	// 使用feign默认的配置
	@Bean
	public Contract feignContract() {
		return new feign.Contract.Default();
	}
	
}

修改接口配置:

// 指定这是feign客户端 name属性指明要调用的服务名,configuration指定要使用的配置类
@FeignClient(name = "client-service", configuration = OpenFeignConfig.class)
public interface IServiceFeign {

	// RequestLine指定请求方式和地址
	@RequestLine("GET /hello/{name}")
	public String getHello(@Param("name") String name);
	
}

启动项目,再次请求即可。

2.配置认证

修改服务提供者配置,添加Spring Security依赖:

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-security</artifactId>
	</dependency>

添加配置:

server:
  port: 9010
  
eureka:
  client:
    serviceUrl:
      # 设置注册中心的地址
      defaultZone: http://localhost:9000/eureka
      
      
      
spring:
  # 设置项目名等
  application:
    name: client-service
    # 配置security登录名和密码
  security:
    user:
      name: zhangsan
      password: 12345

编写配置类:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// 配置httpBasic认证,配置所有请求都要认证
		http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
	}
	
}

由于服务提供者配置了认证,所以再去调用(消费)服务就会报错:

feign.FeignException: status 401 reading IServiceFeign#getHello(String); content:
{"timestamp":"2018-12-21T05:58:15.318+0000","status":401,"error":"Unauthorized","message":"Unauthorized","path":"/hello/hah"}

所以添加消费者配置:

@Import(FeignClientsConfiguration.class)
@RestController
public class ServiceController {

	private IServiceFeign iServiceFeign;
	
	@Autowired
	public ServiceController(Decoder decoder, Encoder encoder, Client client, Contract contract) {
		
		this.iServiceFeign = Feign.builder().client(client).encoder(encoder).decoder(decoder).contract(contract)
				// 设置http-basic认证用户名及密码
			.requestInterceptor(new BasicAuthRequestInterceptor("zhangsan", "12345"))
			// 作用的feign和服务
			.target(IServiceFeign.class, "http://client-service/");
		
	}
	
	@GetMapping("/consumer/{name}")
	public String consumer(@PathVariable("name") String name) {
		// 调用具体的服务
		return iServiceFeign.getHello(name);
	}
	
}

// 指定这是feign客户端 name属性指明要调用的服务名
@FeignClient(name = "client-service", configuration = OpenFeignConfig.class)
public interface IServiceFeign {

	// 指定要调用的服务,要和调用的服务调用方式保持一致
	@GetMapping("/hello/{name}")
	public String getHello(@PathVariable("name") String name);
	
}

这里如果还是使用@RequestLine会出错。

猜你喜欢

转载自blog.csdn.net/qq122516902/article/details/85159228
今日推荐