OpenFeign 快速入門
- OpenFeign 是什么,解決了什么問題?
- OpenFeign 插件列表
- OpenFeign Vs Spring RestTemplate
- OpenFeign Demo
OpenFeign是什么,它解決了什么問題?
OpenFeign是為了方便 HTTP、Restful調用而產生的,使用它,在訪問一個http 服務時,不需要寫了一大隊的代碼。使用它可以扔掉Webservic , jaxrs 等技術的客戶端了,可以不用直接使用 httpclient了。
OpenFeign 插件列表
支持的插件說明:
1) 可以與多種HttpClient配合使用:
+ Jdk HTTPURLConnction 默認
+ Apache HttpClient 4,5
+ OKHttp
+ google httpclient
2) 可以與多種JSON框架結合使用
+ Gson
+ Jackson
+ Easyjson (一個JSON庫的門面,類似的slf4j)
3) 支持SOAP、XML消息
4)可以與Ribbon結合,提供負載均衡功能
如果對feign-ribbon進行擴展,就能實現服務發現功能,動態路由功能。
5)可以與hystrix結合,提供熔斷功能
6)可以與dropwizard-metric 結合提供監控功能
7)提供了jaxrs插件,用於支持使用jaxrs規范的注解來替代默認的注解
OpenFeign Vs Spring RestTemplate?
OpenFeign Demo
網上很多都是 Spring Cloud下的demo,那么非 Spring Cloud環境下該如何使用呢?下面就給出這樣一個例子,所用技術:Spring Boot + Apache DBUtils + SqlHelper + EasyJson + OpenFeign + Jackson。
+ Spring Boot 快速開發環境。
+ Apache DBUtils 提供統一的數據庫訪問功能,數據庫用h2。
+ SqlHelper 提供統一的分頁功能
+ EasyJson 提供統一的 JSON 門面,Jackson 提供 JSON 轉換底層實現。
+ OpenFeign 提供 統一的 Http訪問門面, JDK HttpUrlConnection 提供http訪問底層實現。
+ Slf4j 提供 統一的 logger 門面,logback提供 日志訪問底層實現。
下面列出服務端代碼:

@RestController @RequestMapping("/users") public class UserController { @Autowired private QueryRunner queryRunner; @Autowired @Qualifier("sqlMap") private Map<String, String> sqlMap; @PostMapping() public void add(User user) throws Throwable { queryRunner.insert( sqlMap.get("user.insert"), new UpdatedRowsResultSetHandler(), user.getId(), user.getName(), user.getAge()); } @PutMapping("/{id}") public void update(String id, User user) throws Throwable { user.setId(id); User u = getById(id); if (u == null) { add(user); } else { queryRunner.update(sqlMap.get("user.updateById"), user.getId(), user.getName(), user.getAge(), user.getId() ); } } @DeleteMapping("/{id}") public void deleteById(@RequestParam("id") String id) throws Throwable { queryRunner.update(sqlMap.get("user.deleteById"), id); } @GetMapping("/_all") public List<User> all() throws Throwable { return queryRunner.query(sqlMap.get("user.selectAll"), new RowMapperResultSetHandler<User>(new BeanRowMapper<User>(User.class)) ); } @GetMapping() public PagingResult list_useApacheDBUtils( @RequestParam(name = "pageNo", required = false) Integer pageNo, @RequestParam(name = "pageSize", required = false) Integer pageSize, @RequestParam(name = "sort", required = false) String sort, @RequestParam(name = "testSubquery", required = false, defaultValue = "false") boolean testSubquery) throws SQLException { PagingRequest request = SqlPaginations.preparePagination(pageNo == null ? 1 : pageNo, pageSize == null ? -1 : pageSize, sort); if (testSubquery) { request.subqueryPaging(true); } StringBuilder sqlBuilder = testSubquery ? new StringBuilder("select * from ([PAGING_START]select ID, NAME, AGE from USER where 1=1 and age > ?[PAGING_END]) n where name like CONCAT(?,'%') ") : new StringBuilder("select ID, NAME, AGE from USER where 1=1 and age > ?"); List<Object> params = Collects.emptyArrayList(); params.add(10); if (testSubquery) { params.add("zhangsan"); } List<User> users = queryRunner.query(sqlBuilder.toString(), new RowMapperResultSetHandler<User>(new BeanRowMapper<User>(User.class)), Collects.toArray(params) ); String json = JSONBuilderProvider.simplest().toJson(users); System.out.println(json); return request.getResult(); } @GetMapping("/{id}") public User getById(@PathVariable("id") String id) throws Throwable { List<User> users = queryRunner.execute( sqlMap.get("user.selectById"), new SingleRecordRowMapperResultSetHandler<User>(new BeanRowMapper<User>(User.class)), id ); return Collects.findFirst(users, Functions.nonNullPredicate()); } }
下面列出 client代碼:
public interface UserClientService { @RequestLine("GET /users?pageSize=10&pageNo=1") public PagingResult<User> getUsers(); @RequestLine("GET /users?pageSize=10&pageNo={pageNo}}") public PagingResult<User> queryUsers(@Param("pageNo") int pageNo); @RequestLine("GET /users/{id}") public User getById(@Param("id") String id); @RequestLine("POST /users") public void add(User user); @RequestLine("PATCH /users") public void update(User user); } public class UserClientServiceTests { private static JSONFactory jsonFactory; private static Feign feign; private static UserClientService userClientService; private static JSON jsons; static { JSONBuilder jsonBuilder = JSONBuilderProvider.create().enableIgnoreAnnotation(); jsonFactory = JsonFactorys.getJSONFactory(jsonBuilder, JsonScope.SINGLETON); jsons = jsonFactory.get(); } @BeforeClass public static void init() { feign = Feign.builder() .decoder(new EasyjsonDecoder(jsonFactory)) .build(); Target<UserClientService> webTarget = new Target.HardCodedTarget(UserClientService.class, "userService", "http://localhost:8080/"); userClientService = feign.<UserClientService>newInstance(webTarget); } @Test public void testPagination() { System.out.println(jsons.toJson(userClientService.getUsers())); } @Test public void testGetById() { System.out.println(jsons.toJson(userClientService.getById("0001"))); } }
完整的測試用例:
https://github.com/fangjinuo/sqlhelper
sqlhelper-examples-service-apachedbutils提供 服務端
sqlhelper-examples-client-feign 提供客戶端