溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法

發(fā)布時間:2022-03-17 17:12:11 來源:億速云 閱讀:451 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法”,在日常操作中,相信很多人在Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Feign遠程調(diào)用傳遞對象參數(shù)并返回自定義分頁數(shù)據(jù)的方法”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Feign介紹

Feign是Netflix公司開源的輕量級rest客戶端,使用Feign可以非常方便的實現(xiàn)Http 客戶端。Spring Cloud引入Feign并且集成了Ribbon實現(xiàn)客戶端負載均衡調(diào)用。

Feign測試

1.在yml文件里面增加了配置信息

feign:
  httpclient:
    enabled: true

2.在客戶端pom.xml文件中引入的依賴(消費者端)

<!-- 配置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了。

3.服務(wù)調(diào)用端接口為

此處使用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;
     。。。。。。。
}

4.服務(wù)調(diào)用端Service代碼

此處@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);

5.服務(wù)調(diào)用端Fallback為

@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;
    }

6.服務(wù)提供端代碼為

此處傳進來的參數(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);
    }

7.測試

調(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": "分頁獲取成功"
}

Feign調(diào)用分頁接口報錯:Method has too many Body parameters

接口定義:

@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>

向AI問一下細節(jié)

免責聲明:本站發(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)容。

AI