Feign GET 多参数传递

版权声明: https://blog.csdn.net/wo18237095579/article/details/83378819

  Spring MVC 是支持 GET/POST 多参数传递的,但是 Feign 并没有实现所有的 Spring MVC 的功能,暂时是不支持 GET 的 POJO 传递方法。一般的解决办法有一下三种:

  • 把 POJO 拆散成一个一个单独的属性放在方法参数里。
  • 把方法参数变成 Map 传递。
  • 使用 GET 传递 @Requestbody,但此方式违反 RESTFul 规范。

  以上三种方法都是可以的,这里要使用的方法是 Feign 的 RequestInterceptor 进行统一的处理,当检测到请求方法为 GET 时,把请求体里面的内容重新拼装成请求参数的形式。

  1. 消费者的 Controller
/**
 * @Author:大漠知秋
 * @Description:测试 FeignGetInterceptor 的 Controller
 * @CreateDate:2:38 PM 2018/10/25
 */
@RestController
@RequestMapping("/feignGet")
public class FeignGetInterceptorController {

    @Resource
    private FeignGetInterceptorFeign feignGetInterceptorFeign;

    @RequestMapping(
            value = "/addUser",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    ResponseEntity<byte[]> addUser(User user) {
        return feignGetInterceptorFeign.addUser(user);
    }

    @RequestMapping(
            value = "/updateUser",
            method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    ResponseEntity<byte[]> updateUser(@RequestBody User user) {
        return feignGetInterceptorFeign.updateUser(user);
    }

}
  1. 消费者的 Feign
@FeignClient(name = "demo-goods")
public interface FeignGetInterceptorFeign {

    @RequestMapping(
            value = "/feignGet/addUser",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    ResponseEntity<byte[]> addUser(User user);

    @RequestMapping(
            value = "/feignGet/updateUser",
            method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    ResponseEntity<byte[]> updateUser(@RequestBody User user);

}
  1. 提供者的 Controller
/**
 * @Author:大漠知秋
 * @Description:测试 FeignGetInterceptor 的 Controller
 * @CreateDate:2:38 PM 2018/10/25
 */
@RestController
@RequestMapping("/feignGet")
public class FeignGetInterceptorController {

    @RequestMapping(
            value = "/addUser",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    User addUser(User user) {
        user.setAge(user.getAge() + 1);
        user.setUsername(user.getUsername() + "1");
        user.setBirthday(new Date());
        return user;
    }

    @RequestMapping(
            value = "/updateUser",
            method = RequestMethod.POST,
            produces = MediaType.APPLICATION_JSON_UTF8_VALUE
    )
    User updateUser(@RequestBody User user) {
        user.setAge(user.getAge() + 1);
        user.setUsername(user.getUsername() + "1");
        user.setBirthday(new Date());
        return user;
    }

}

  没有加拦截器之前,请求 GET 方式,会报如下错误:

报错

  1. 增加 Feign 拦截器
/**
 * @Author:大漠知秋
 * @Description:拦截使用 Get 请求,并且使用的时 POJO 请求方式的 Feign 请求
 * @CreateDate:2:24 PM 2018/10/25
 */
@Component
@Slf4j
public class FeignRequestInterceptor implements RequestInterceptor {

    @Resource
    private ObjectMapper objectMapper;

    @Override
    public void apply(RequestTemplate template) {
        if (HttpMethod.GET.name().equals(template.method())
                && null != template.body()) {
            try {
                JsonNode jsonNode = objectMapper.readTree(template.body());
                template.body(null);

                Map<String, Collection<String>> queries = new HashMap<>();
                buildQuery(jsonNode, "", queries);
                template.queries(queries);
            } catch (IOException e) {
                log.error("【拦截GET请求POJO方式】-出错了:{}", ExceptionUtils.getStackFrames(e));
                throw new RuntimeException();
            }
        }
    }

    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
        // 叶子节点
        if (!jsonNode.isContainerNode()) {
            if (jsonNode.isNull()) {
                return;
            }
            Collection<String> values = queries.get(path);
            if (null == values) {
                values = new ArrayList<>();
                queries.put(path, values);
            }
            values.add(jsonNode.asText());
            return;
        }
        // 数组节点
        if (jsonNode.isArray()) {
            Iterator<JsonNode> it = jsonNode.elements();
            while (it.hasNext()) {
                buildQuery(it.next(), path, queries);
            }
        } else {
            Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
            while (it.hasNext()) {
                Map.Entry<String, JsonNode> entry = it.next();
                if (StringUtils.hasText(path)) {
                    buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
                } else {  // 根节点
                    buildQuery(entry.getValue(), entry.getKey(), queries);
                }
            }
        }
    }

}
  1. Model
@Data
public class User {

    private String username;

    private Integer age;

    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date birthday;

}
  1. 结果:

GET 请求

POST 请求

源码:https://github.com/SlowSlicing/demo-spring-cloud-finchley/tree/FeignGETRequestMoreParameter

猜你喜欢

转载自blog.csdn.net/wo18237095579/article/details/83378819