周立 --- 《Spring Cloud與Docker微服務架構與實戰》
1. 回顧web
前文的示例中是使用RestTemplate實現REST API調用的,代碼大體以下:
spring
@GetMapping("/user/{id}") public User findById(@PathVariable Long id) { return this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class); }
由代碼剋制,咱們是使用拼接字符串的方式構造URL的,該URL只有一個參數。sql
然而在現實中,URL每每有多個參數。若是這時還使用這種方式構造URL,那麼就會變得很低效,而且難以維護。服務器
2. Feign簡介架構
Feign是Netflix開發的聲明式、模板化的HTTP客戶端,其靈感來自Retrofit、JAXRS-2.0以及WebSocket。Feign可幫助咱們更加便捷、優雅地調用HTTP API。app
在Spring Cloud中,使用Feign很是簡單——建立一個接口,並在接口上添加一些註解,代碼就完成了。Feign支持多種註解,例如Feign自帶的註解或者負載均衡
JAX-RS註解等。ide
Spring Cloud對Feign進行了加強,使Feign支持了Spring MVC註解,並整合了Ribbon和Eureka,從而讓Feign的使用更加方便。微服務
3. 爲服務消費者整合Feignpost
> 複製項目 microservice-consumer-movie,將ArtifactId修改成 microservice-consumer-movie-feign
> 添加Feign的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
> 建立一個Feign接口,並添加@FeignClient註解
package com.itmuch.cloud.microserviceconsumermoviefeign.feign; import com.itmuch.cloud.microserviceconsumermoviefeign.pojo.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(name = "microservice-provider-user") public interface UserFeignClient { @GetMapping(value = "/{id}") User findById(@PathVariable("id") Long id); }
@FeignClient註解中的microservice-provider-user是一個任意的客戶端名稱,用於建立Ribbon負載均衡器。在本例中,因爲使用了Eureka,
因此Ribbon會把microservice-provider-user解析成Eureka Server服務註冊表中的服務。
若是不想使用Eureka,也可以使用service.ribbon.listOfServers屬性配置服務器列表
也可以使用url屬性指定請求的URL(URL能夠是完整的URL或主機名),例如
@FeignClient(name = "microservice-provider-user", url = "http://localhost:8000/")
> 修改Controller代碼,讓其調用Feign接口
package com.itmuch.cloud.microserviceconsumermoviefeign.controller; import com.itmuch.cloud.microserviceconsumermoviefeign.feign.UserFeignClient; import com.itmuch.cloud.microserviceconsumermoviefeign.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class MovieController { @Autowired private UserFeignClient userFeignClient; @GetMapping("/user/{id}") public User findById(@PathVariable Long id) { return this.userFeignClient.findById(id); } }
> 修改啓動類,添加@EnableFeignClients註解
package com.itmuch.cloud.microserviceconsumermoviefeign; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class MicroserviceConsumerMovieFeignApplication { public static void main(String[] args) { SpringApplication.run(MicroserviceConsumerMovieFeignApplication.class, args); } @Bean public RestTemplate restTemplate() { return new RestTemplate(); } }
> 啓動 microservice-discovery-eureka
> 啓動兩個以上的 microservice-provider-user 實例
> 啓動 microservice-consumer-movie-feign
> 屢次訪問 http://localhost:8010/user/1,在各個實例的控制檯下均可看見相似日誌
Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=?
2018-03-27 17:48:19.468 TRACE 14160 --- [nio-8001-exec-2] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1] 2018-03-27 17:48:19.480 TRACE 14160 --- [nio-8001-exec-2] o.h.type.descriptor.sql.BasicExtractor : extracted value ([age2_0_0_] : [INTEGER]) - [20] 2018-03-27 17:48:19.481 TRACE 14160 --- [nio-8001-exec-2] o.h.type.descriptor.sql.BasicExtractor : extracted value ([balance3_0_0_] : [NUMERIC]) - [100.00] 2018-03-27 17:48:19.481 TRACE 14160 --- [nio-8001-exec-2] o.h.type.descriptor.sql.BasicExtractor : extracted value ([name4_0_0_] : [VARCHAR]) - [張三] 2018-03-27 17:48:19.481 TRACE 14160 --- [nio-8001-exec-2] o.h.type.descriptor.sql.BasicExtractor : extracted value ([username5_0_0_] : [VARCHAR]) - [account1]
4. 總結
以上結果說明,本文實現了聲明式的REST API調用,同時還實現了客戶端側的負載均衡。
下文將講解自定義Feign配置,敬請期待~~~
5. 參考
周立 --- 《Spring Cloud與Docker微服務架構與實戰》