好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

解决Feign调用的GET参数传递的问题

需求

​ 在消费方服务通过GET方式,访问服务提供方的接口,需要传递多参数,拆分成多个参数的方式访问,不太适合用在该场景,需要改造成合适的方式调用服务方的接口

思考

拆分成多个参数时,若GET请求的参数超过3个及以上时,便不适用该种方式请求服务,因为这样传递参数过于臃肿,可读性也比较差;

若改造成POST请求的方式,虽然解决参数过多的问题,但是也带来了其他的开销,参数被放到了body里面,然后请求到服务方提供的接口,服务方的接口也改造成了POST方式,改变了原来的GET方式调用的初衷,不太友好;

​ 可以在消费方调用Feign接口时,参数封装到body中,在组装Feign接口请求时,将body里面的参数取出来,转换为GET方式请求的参数,请求body的参数,然后发起请求,实现了GET方式访问服务方提供的接口;

以下是这三种调用方式的具体实现,可以根据适合自己的业务场景去使用,选择不同的方式请求调用:

GET方式请求①

请求DTO对象:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

package com.springcloud.pojo; 

import java.util.Date;  

public class Requets01DTO { 

    private Date startTime; 

    private Date endTime; 

    private String message;

 

    @Override

    public String toString() {

        return "Requets01DTO{" +

                "startTime=" + startTime +

                ", endTime=" + endTime +

                ", message='" + message + '\ '' +

                '}' ;

    }

 

    public Date getStartTime() {

        return startTime;

    }

 

    public void setStartTime(Date startTime) {

        this .startTime = startTime;

    }

 

    public Date getEndTime() {

        return endTime;

    }

 

    public void setEndTime(Date endTime) {

        this .endTime = endTime;

    }

 

    public String getMessage() {

        return message;

    }

 

    public void setMessage(String message) {

        this .message = message;

    }

}

消费方的请求:

?

1

2

3

4

5

6

7

    @Autowired

    GetClient01 getClient01;

 

    @GetMapping ( "/request/get/01" )

    public String requestGetOne(Requets01DTO requets01DTO) {

        return getClient01.queryDataByGetRequest(requets01DTO.getStartTime(), requets01DTO.getEndTime(), requets01DTO.getMessage());

    }

Feign接口:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

package com.springcloud.service; 

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestParam; 

import java.util.Date;

 

@FeignClient (value = "provider-8762" , contextId = "GetClient01" )

public interface GetClient01 {

 

    /**

      * GET方式请求①

      *

      * @param startTime

      * @param endTime

      * @param message

      * @return

      */

    @GetMapping ( "/get/01" )

    String queryDataByGetRequest( @RequestParam ( "startTime" ) Date startTime, @RequestParam ( "endTime" ) Date endTime,

                                  @RequestParam ( "message" ) String message);

}

服务提供方:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

@RestController

public class RequestProviderController {

 

    @GetMapping ( "/get/01" )

    public String queryDataByGetRequest( @RequestParam ( "startTime" ) Date startTime, @RequestParam ( "endTime" ) Date endTime,

                                        @RequestParam ( "message" ) String message) {

        Requets01DTO requets01DTO = new Requets01DTO();

        requets01DTO.setStartTime(startTime);

        requets01DTO.setEndTime(endTime);

        requets01DTO.setMessage(message);

        return requets01DTO.toString();

    }

}

请求结果截图:

GET方式请求②

Feign调用的请求改为POST方式

消费方的请求:

?

1

2

3

4

5

6

7

    @Autowired

    GetClient02 getClient02;

 

    @GetMapping ( "/request/get/02" )

    public String requestGetTwo(Requets01DTO requets01DTO) {

        return getClient02.queryDataByGetRequest(requets01DTO);

    }

Feign接口:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

package com.springcloud.service; 

import com.springcloud.pojo.Requets01DTO;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.PostMapping;

 

@FeignClient (value = "provider-8762" , contextId = "GetClient02" )

public interface GetClient02 { 

 

    /**

      * GET方式请求②(Feign调用的请求改为POST方式)

      *

      * @param requets01DTO

      * @return

      */

    @PostMapping ( "/post/02" )

    String queryDataByGetRequest(Requets01DTO requets01DTO);

}

服务提供方:

?

1

2

3

4

    @PostMapping ( "/post/02" )

    public String queryDataByGetRequest( @RequestBody Requets01DTO requets01DTO) {

        return requets01DTO.toString();

    }

请求结果截图:

GET方式请求③

组装Feign接口请求时,将body里面的参数取出来,转换为GET方式请求的参数

添加Feign请求的配置类:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

package com.springcloud.config; 

import com.alibaba.fastjson.JSON;

import feign.Request;

import feign.RequestInterceptor;

import feign.RequestTemplate;

import org.springframework.context.annotation.Configuration;

import org.springframework.http.HttpMethod;

import org.springframework.web.context.request.RequestContextHolder;

import org.springframework.web.context.request.ServletRequestAttributes;

 

import javax.servlet.http.HttpServletRequest;

import java.lang.reflect.Field;

import java.util.*;

 

@Configuration

public class FeignConfiguration implements RequestInterceptor {

 

    @Override

    public void apply(RequestTemplate requestTemplate) {

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = attributes.getRequest();

 

        //填充get中的body数据转化成query数据

        if (requestTemplate.method().equals(HttpMethod.GET.name()) && Objects.nonNull(requestTemplate.body())) {

            String json = requestTemplate.requestBody().asString();

            Map<String, Object> map = JSON.parseObject(json);

            Set<String> set = map.keySet();

            Iterator<String> it = set.iterator();

            while (it.hasNext()) {

                String key = it.next();

                Object values = map.get(key);

                if (Objects.nonNull(values)) {

                    // 将body的参数写入queries

                    requestTemplate.query(key, values.toString());

                }

            }

 

            try {

                Class requestClass = requestTemplate.getClass();

                Field field = requestClass.getDeclaredField( "body" );

                field.setAccessible( true );

                //修改body为空。

                field.set(requestTemplate, Request.Body.empty());

            } catch (Exception ex) {

                System.out.println(ex.fillInStackTrace());

            } 

        }

 

        Enumeration<String> headerNames = request.getHeaderNames();

        if (headerNames != null ) {

            while (headerNames.hasMoreElements()) {

                String name = headerNames.nextElement();

                String values = request.getHeader(name);

                // 跳过 content-length

                if (name.equals( "content-length" )){

                    continue ;

                }

                requestTemplate.header(name, values);

            }

        } else {

            System.out.println(String.format( "feign interceptor error header:%s" , requestTemplate));

        }

    }

}

 添加fastJson的maven依赖:

?

1

2

3

4

5

6

<!-- JSON 解析器和生成器 -->

        < dependency >

            < groupId >com.alibaba</ groupId >

            < artifactId >fastjson</ artifactId >

            < version >1.2.74</ version >

        </ dependency >

消费方的请求:

?

1

2

3

4

5

6

7

    @Autowired

    GetClient03 getClient03;

 

    @GetMapping ( "/request/get/03" )

    public String requestGetThree(Requets01DTO requets01DTO) {

        return getClient03.queryDataByGetRequest(requets01DTO);

    }

Feign接口:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

package com.springcloud.service; 

import com.springcloud.config.FeignConfiguration;

import com.springcloud.pojo.Requets01DTO;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

 

@FeignClient (value = "provider-8762" , contextId = "GetClient03" , configuration = FeignConfiguration. class )

public interface GetClient03 {

 

    /**

      * GET方式请求③(组装Feign接口请求时,将body里面的参数取出来,转换为GET方式请求的参数)

      *

      * @param requets01DTO

      * @return

      */

    @GetMapping ( "/get/03" )

    String queryDataByGetRequest(Requets01DTO requets01DTO);

}

服务提供方:

?

1

2

3

4

    @GetMapping ( "/get/03" )

    public String queryDataByGetRequest03(Requets01DTO requets01DTO) {

        return requets01DTO.toString();

    }

请求结果截图:

 Feign调用传递的GET参数日期,要指定jsonFormat注解,body转GET参数时,日期参数会变为字符串,需要指定日期格式

?

1

2

3

4

5

6

7

@JsonFormat (pattern = "yyyy-MM-dd HH:mm:ss" )

@DateTimeFormat (pattern = "yyyy-MM-dd HH:mm:ss" )

private Date startTime;

 

@JsonFormat (pattern = "yyyy-MM-dd HH:mm:ss" )

@DateTimeFormat (pattern = "yyyy-MM-dd HH:mm:ss" )

private Date endTime;

**结果截图:**

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/weixin_41221717/article/details/120209007

查看更多关于解决Feign调用的GET参数传递的问题的详细内容...

  阅读:22次