您好,登錄后才能下訂單哦!
這篇文章主要介紹“Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法”,在日常操作中,相信很多人在Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Feign是Netflix公司開源的輕量級rest客戶端,使用Feign可以非常方便的實現(xiàn)Http 客戶端。Spring Cloud引入Feign并且集成了Ribbon實現(xiàn)客戶端負載均衡調(diào)用。
feign: httpclient: enabled: true
<!-- 配置feign 發(fā)送請求使用 httpclient,而不是java原生 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> </dependency> <!-- 此處不使用Apache HttpClient 的httpclient依賴,一定要使用下面這個依賴,因為我們要返回的是POJO類--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> <version>10.1.0</version> </dependency>
此處注意
此處依賴為什么使用io.github.openfeign的httpclient,而不使用Apache 的HttpClient替換Feign原生httpclient。
看了很多文章,都是說引用這個依賴:
<!-- 使用Apache HttpClient替換Feign原生httpclient--> <!-- <dependency>--> <!-- <groupId>com.netflix.feign</groupId>--> <!-- <artifactId>feign-httpclient</artifactId>--> <!-- <version>8.16.1</version>--> <!-- </dependency>-->
但是不知道哪里的問題,在獲取返回結(jié)果時一直報錯:
Caused by: java.lang.NoSuchMethodError: feign.Response.create(ILjava/lang/String;Ljava/util/Map;Lfeign/Response$Body;)Lfeign/Response;
查看源碼得知,openfeign在接受返回值時調(diào)用的不是httpclient的feign-core包的代碼而是調(diào)用的本身的feign-core的代碼,而本身的feign-core包中的Response類沒有create方法。兩個feign-core包中的Retryer接口不一致導致的,openfeign的feign-core版本為10.1.0 httpclient的版本為8.16.1。
找了半天問題,最后就把httpclient的依賴換成代碼塊中的依賴就OK了。
此處使用POST請求,第6步有解釋。
@Slf4j @RequestMapping("/list") @RestController public class WebQueryListController { @Autowired private TourismListService listService; @PostMapping("/ad/allByQuery") public ApiResult<Page<TourismAd>> allByQuery(@RequestBody TourismAdQuery adQuery){ ApiResult<Page<TourismAd>> pageApiResult = listService.selectAllAdByQuery(adQuery); return pageApiResult; }
我的TourismAdQuery類繼承了Page類(似乎沒有影響)
@Data public class TourismAdQuery extends Page<TourismAd> { /** * 標題 */ private String title; 。。。。。。。 }
此處@PostMapping地址為服務(wù)端提供的api接口地址
@FeignClient(name = "fisher-back-service", fallback = TourismListFallback.class, configuration = FeignConfig.class) public interface TourismListService { /** * 分頁查詢廣告根據(jù)查詢條件 * @param adQuery * @return */ @PostMapping(value = "/ad/get/allByQuery") ApiResult<Page<TourismAd>> selectAllAdByQuery(TourismAdQuery adQuery);
@Slf4j @Service public class TourismListFallback implements TourismListService { /** * 分頁查詢廣告根據(jù)查詢條件 * * @param adQuery * @return */ @Override public ApiResult<Page<TourismAd>> selectAllAdByQuery(TourismAdQuery adQuery) { log.error("調(diào)用 selectAllAdByQuery 方法異常,參數(shù):{}", adQuery); return null; }
此處傳進來的參數(shù)是一個POJO類,如果不使用@RequestBody注解 的話,feign遠程調(diào)用時參數(shù)是無法被接收到的。
雖然獲取數(shù)據(jù)時,大多數(shù)使用 Get請求方法,但是GET方法無法接收@RequestBody參數(shù)體。
所以只好改GET請求為POST請求。
@RestController @RequestMapping("/ad") public class TourismAdController extends BaseController<TourismAdService, TourismAd, Integer> { @Autowired private TourismAdService adService; @ApiOperation(value = "分頁查詢廣告根據(jù)查詢條件", notes = "分頁查詢廣告根據(jù)查詢條件", httpMethod = "POST") @PostMapping("/get/allByQuery") public ApiResult<Page<TourismAd>> allByQuery(@RequestBody TourismAdQuery adQuery){ return adService.selectAllByQuery(adQuery); }
調(diào)用接口http://localhost:9009/list/ad/allByQuery 傳遞json格式參數(shù)即可:
{ "address": "", "title": "廣告位1", "size": 6 }
成功分頁獲取數(shù)據(jù) 自定義的返回類型數(shù)據(jù):
{ "data": { "records": [ { "id": 1, "title": "廣告位1", "description": "招商", "sort": 0, "datetime": "2019-09-26 17:46:50", "updatetime": "2019-09-26 17:46:50", "peopleid": 0, "display": 0, "content": "04004", "file": "444//44.jpg", "leaseperson": "找找", "address": "杭州市", "idcard": "1154465656656", "phone": "131654799" } ], "total": 1, "size": 6, "current": 1, "searchCount": true, "pages": 1 }, "code": 200, "message": "分頁獲取成功" }
接口定義:
@ApiOperation(value = "分頁查詢會話") @PostMapping(Routes.SESSIONS_QUERY) JsonResult<Pagination<SessionInfo>> querySessions(@RequestBody @Valid SessionsQo qo, @PageableDefault(size = 20, sort = "id", direction = Sort.Direction.DESC) Pageable pageable);
服務(wù)消費方調(diào)用報錯:
Method has too many Body parameters: public abstract com.xingren.common.data.JsonResult com.xingren.xxx.yyy.contract.api.controller.ISessionController.querySessions(com.xingren.xxx.yyy.contract.qo.SessionsQo,org.springframework.data.domain.Pageable)
通過搜索、調(diào)研,目前有三種解決方法:
1、將分頁屬性直接通過入?yún)鬟f,接口定義如下:
@ApiOperation(value = "分頁查詢會話") @PostMapping(Routes.SESSIONS_QUERY) JsonResult<Pagination<SessionInfo>> querySessions(@RequestBody @Valid SessionsQo qo, @RequestParam("page") Integer page, @RequestParam("size") Integer size, @RequestParam("sort") Sort sort);
2、將分頁對象冗余在Qo中(通過繼承實現(xiàn)):
@Data @NoArgsConstructor @ApiModel(value = "查詢會話") public class SessionsQo extends PageableParam { @ApiParam(value = "會話id列表") private List<Long> sessionIdIn = Lists.newArrayList(); ... }
3、通過注解傳遞(參考:Issue):
服務(wù)提供方定義注解:
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface PageableParam { }
服務(wù)提供方定義接口:
@ApiOperation(value = "分頁查詢會話") @PostMapping(Routes.SESSIONS_QUERY) JsonResult<Pagination<SessionInfo>> querySessions(@RequestBody @Valid SessionsQo qo, @PageableParam @SpringQueryMap Pageable pageable);
服務(wù)消費方定義processor:
@Bean public PageableParamProcessor pageableParamProcessor() { return new PageableParamProcessor(); } public static class PageableParamProcessor implements AnnotatedParameterProcessor { private static final Class<PageableParam> ANNOTATION = PageableParam.class; @Override public Class<? extends Annotation> getAnnotationType() { return ANNOTATION; } @Override public boolean processArgument(AnnotatedParameterContext context, Annotation annotation, Method method) { int parameterIndex = context.getParameterIndex(); MethodMetadata data = context.getMethodMetadata(); data.queryMapIndex(parameterIndex); return true; } }
服務(wù)消費方自定義PageableUtil:
public class PageableUtil extends PageRequest implements Map<String, Object> { public static final String PAGE = "page"; public static final String SIZE = "size"; public static final String SORT = "sort"; @Delegate protected Map<String, Object> delegate = Maps.newHashMap(); public PageableUtil(int page, int size, Sort sort) { super(page, size, sort); delegate.put(PAGE, page); delegate.put(SIZE, size); if (Objects.nonNull(sort)) { delegate.put(SORT, sort.toString().replace(": ", ",")); } } public PageableUtil(int page, int size) { super(page, size); delegate.put(PAGE, page); delegate.put(SIZE, size); } }
定義PageableUtil原因:主要是因為Feign對QueryMap類型參數(shù)的序列化和反序列化的言七墨方式與Sort.Order的不兼容,導致排序失效。
服務(wù)消費方調(diào)用方式:
SessionsQo qo = SessionsQo.builder().sessionIdIn(Collections.singletonList(20L)).build(); JsonResult<Pagination<SessionInfo>> pageInfo = sessionContract.querySessions(qo, new PageableUtil(0, 5, new Sort(Sort.Direction.DESC,
到此,關(guān)于“Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法”的學習就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。