Feign是一個聲明式的Web Service客戶端,比Ribbon好用,默認也是輪巡。我們只需要使用Feign創建一個接口,並用注解就好了。如果你基於spring cloud發布一個接口,實際上就是支持http協議的,對外發布的就是一個最普通的mvc的http接口。我們使用feign注解,實際上它會對這個接口生成動態代理,從eureka的readonly中拿到其他服務信息、進行http請求調用。
feign案例編寫:
1. 導包
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> </parent> <!-- springcloud依賴 --> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Dalston.SR3</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- eureka客戶端依賴 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <!-- feign客戶端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-feign</artifactId> </dependency> </dependencies>
2. 配置application.yml文件
# 項目訪問路徑前綴
server:
context-path: /feign
port: 8085
# 設置服務名稱,服務會以這個名字注冊到eureka服務器上
spring:
application:
name: feign
# 設置eureka服務器的注冊地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
#ribbon的超時時間, 防止feign調用超時
ribbon:
ReadTimeout: 15000
ConnectTimeout: 15000
MaxAutoRetries: 1 #同一台實例最大重試次數,不包括首次調用
MaxAutoRetriesNextServer: 1 #重試負載均衡其他的實例最大重試次數,不包括首次調用
OkToRetryOnAllOperations: false #是否所有操作都重試
3. 主函數入口開啟eureka和feign客戶端
@SpringBootApplication @EnableEurekaClient//開啟eureka @EnableFeignClients//開啟feign public class FeignMain { public static void main(String[] args) { new SpringApplicationBuilder(FeignMain.class).web(true).run(args); } }
4. 調用接口
@RestController public class UserController { @Autowired private UserService userService; @RequestMapping("/test") public Map test() { return userService.test("張三"); } @RequestMapping("/testObj") public User testObj() { return userService.testObj(new User()); } }
5. 編寫feign調用的服務層。
import java.util.Map; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import com.model.User; //name 目標的服務名 目標的url前綴 @FeignClient(name ="demo",path="/demo") public interface UserService { // 調用police服務的testOut接口 @RequestMapping("/testOut") public Map test(@RequestParam("name") String name); // 調用police服務的testOutObj接口 @RequestMapping("/testOutObj") public User testObj(@RequestBody User user); }
feign客戶端就開發完成了; 我們來看看提供服務的另一個項目的接口。
@RestController public class MyController { @RequestMapping("/testOut") public Map test(@RequestParam("name") String name,HttpServletRequest req) { Map m = new HashMap<>(); m.put("url", req.getRequestURL().toString()); m.put("name", name); try { Thread.sleep(16000); } catch (InterruptedException e) { } return m; } @RequestMapping("/testOutObj") public User testObj(@RequestBody() User user,HttpServletRequest req) { user.setUrl(req.getRequestURL().toString()); try { Thread.sleep(14000); } catch (InterruptedException e) { } return user; } }
測試: 由於超時時間設置的15s, 而兩個接口分別阻塞14s ,16s ,所以第二個接口會超時報錯。