Feign的使用和POST,GET请求问题

因为最近学习spring cloud组件问题,所以需要使用feign的接口调用方式,而Feign的http调用和RPC调用以及原生Ribbon的RestTemplate请求问题不再称述。
首先加入feign依赖

<!-- feign依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

服务提供者(生产者)

	//GET请求
	//查询全部用户
//    @PreAuthorize("hasAnyRole('employee')")
    @RequestMapping("/api/findAll")
    @ResponseBody
    public Object findAllUser(HttpServletResponse response) {
        //设置响应头方法,解决ajax跨域问题
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Methods", "*");
        List<User> userList = userService.findAllUser();
        Map<String, Object> jsonMap = new HashMap<String, Object>();
        if (userList != null) {
            //如果查询数据为空
            if (userList.size() == 0) {
                return Result.failure(ResultCode.RESULT_EMPTY, userList);//直接用静态方法返回
            }
            //如果查询数据不为空
            return Result.success(ResultCode.SUCCESS, userList);
        }else {
            return Result.failure(ResultCode.FAIL);
        }
    }
	//Post请求
	//新增用户
	@PostMapping("/api/insUser")
    @ResponseBody
    public Object insUser(@RequestBody User user) {//其中@RequstBody注解必不可少
        User alreadyUser = userService.selUserByUsername(user.getUserName());
        //如果用户已经存在
        if (alreadyUser != null) {
            return Result.failure(ResultCode.USER_HAS_EXISTED);
        }
        //记录状态
        int data = -1;
        if ((data = userService.insUser(user)) > 0) {
            return Result.success(ResultCode.SUCCESS, data);
        }else
            return Result.failure(ResultCode.FAIL, data);
    }    

@RequestBody:请求以对象的形式传输
@RequestParam:请求以基本数据类型传输
@PathVariable:以Rest请求方式传输基本数据类型
如:

@GetMapping("/api/delete/{id}")
    @ResponseBody
    public Object delUserById(@PathVariable("id") Integer id) {
    /**/
    }

Feign客户端

@Service
@FeignClient(value = "resource-server", configuration = {FeignConfiguration.class})//添加配置类名
public interface UserClientService {

    @RequestMapping("/api/findAll")
    @ResponseBody
    public Object findAllUser();

    @GetMapping("/api/delete/{id}")
    @ResponseBody
    Object delUserById(@PathVariable("id") Integer id);

    @PostMapping(value = "/api/insUser")
    @ResponseBody
    Object insUser(@RequestBody User user);

    @PostMapping(value = "/api/updUser")
    @ResponseBody
    Object updUserById(@RequestBody User user);
}

因为需要在请求头中附加token信息,而feign又是以接口方式调用,而不是直接用地址发送请求,所以需要一个feign的配置类,将请求需要携带的token加入到请求头中。

@Configuration
public class FeignConfiguration {

    private static String token = "";

    @Bean
    public RequestInterceptor requestInterceptor(){
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate requestTemplate) {
                //获取请求信息
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                assert attributes != null;
                HttpServletRequest request = attributes.getRequest();
                //获取在session中的token信息
                token = (String) request.getSession().getAttribute("token");
                System.out.println("RequestTemplateToken-->" + token);


                //输出请求中已经存在的请求信息
                Map<String,Object> map = new HashMap<String,Object>();
                Enumeration paramNames = request.getParameterNames();
                while (paramNames.hasMoreElements()) {
                    String paramName = (String) paramNames.nextElement();

                    String[] paramValues = request.getParameterValues(paramName);
                    if (paramValues.length >0) {
                        String paramValue = paramValues[0];
                        if (paramValue.length() != 0) {
                            map.put(paramName, paramValue);
                        }
                    }
                }
                //迭代
                // 输出 key 和 value
                for (String i : map.keySet()) {
                    System.out.println("key: " + i + " value: " + map.get(i));
                }
                // 返回所有 value 值
                for(Object value: map.values()) {
                    // 输出每一个value
                    System.out.print(value + ", ");
                }
                System.out.println();


                //在请求头中添加token信息
                List<String> accessToken = Lists.newArrayList("Bearer " + token);
//                List<String> contentTypeList = Lists.newArrayList("application/x-www-form-urlencoded");
                List<String> contentTypeList = Lists.newArrayList("application/json");
//                System.out.println("accessToken-->" + accessToken);
                Map<String, Collection<String>> headers = ImmutableMap.of("Authorization", accessToken,"Content-Type", contentTypeList);
//                Map<String, Collection<String>> headers = ImmutableMap.of("Authorization", accessToken);
//                Map<String, Collection<String>> headers = ImmutableMap.of("Content-Type", contentTypeList);
                requestTemplate.headers(headers);
            }
        };
    }
}

feign集成了Ribbon负载均衡:

@Configuration
public class MyConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }



    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

客户端(消费者)

    @GetMapping(value = "/findAll")
    @ResponseBody
    public Object findAllUsers(HttpServletRequest request, HttpServletResponse response) {
        Object result = userClientService.findAllUser();
        if (result.equals("")) {
            return Result.failure(ResultCode.FAIL);
        }
        return Result.success(ResultCode.SUCCESS, result);
    }


	@PostMapping("/updUser")
    @ResponseBody
//    @Headers("Content-Type=application/json")
    public Object updUser(User user, HttpServletRequest request, Authentication authentication) {
        UserInfo userInfo = (UserInfo) authentication.getPrincipal();
        if (userInfo.getUsername() == null) {
            //没有获取到当前用户信息
            return Result.failure(ResultCode.USER_INFO_ERROR);
        }
        user.setUserId(Integer.parseInt(request.getParameter("userId")));
        user.setUserName(request.getParameter("userName"));
        user.setUserPwd(request.getParameter("userPwd"));
        user.setUserRole(request.getParameter("userRole"));
        Object result = userClientService.updUserById(user);
        return Result.success(ResultCode.SUCCESS, result);
    }
  • 这里三个微服务最好是请求类型都写一样,要么都是PostMapping,要么都是RequestMapping等
  • 我在客户端的User对象传递时没有使用@RequestBody是因为我在前端是以form表单形式传递,即application/x-www-form-urlencoded格式传输,如果加了RequestBody注解的话会报415传递类型不支持错误,所以干脆不加注解。而在feigin调用中是不能以form表单形式传递,只能以json格式传递,所以要加@RequestBody注解转为json格式。
    如果请求体较大,会出现超时错误,需要添加配置:
# 配置 feign 默认请求时间仅几秒钟,配置请求时间长一些(毫秒)
feign:
  client:
    config:
      default:
        connectTimeout: 10000
        readTimeout: 600000

结果

GET查询:
在这里插入图片描述
POST查询:
在这里插入图片描述

### Feign GET 请求发送对象参数 当使用 Feign 客户端发送 GET 请求并传递对象作为参数时,由于 HTTP 协议本身的限制,GET 请求通常不允许在请求体中携带数据。因此,在这种情况下,需要将对象中的各个字段转换成 URL 查询参数来实现。 对于 Feign Client 来说,如果要发送的对象包含多个属性,则可以通过定义接口的方法签名,并利用 `@RequestParam` 注解指定如何映射这些属性到查询字符串上[^1]。需要注意的是,Feign 不支持直接将整个 Java 对象序列化为 JSON 并放在 GET 请求体内传输;相反,应该手动构建查询参数或者借助库函数自动完成此过程。 下面是一个简单的例子展示如何配置 Feign Client 以发送带有复杂对象的 GET 请求: ```java // 假设有一个名为 QueryParamObject 的类表示我们要传递的对象结构 public class QueryParamObject { private String param1; private Integer param2; // Getters and setters... } // 接口声明部分 @FeignClient(name = "exampleService", url = "${service.url}") public interface ExampleClient { @GetMapping("/api/resource") ResponseEntity<String> getResource(@ModelAttribute QueryParamObject query); } ``` 在这个例子中,`@ModelAttribute` 可用于指示 Spring MVC 将请求参数绑定到命令对象或表单对象上。不过请注意,这可能不是最标准的做法,因为严格意义上讲这是针对 HTML 表单提交设计的功能。更推荐的方式是显式地标记每一个参数: ```java @GetMapping("/api/resource") ResponseEntity<String> getResource( @RequestParam(value="param1") String param1, @RequestParam(value="param2") Integer param2); ``` 另外值得注意的一点是在某些版本的 Feign 中确实存在一种行为模式,即无论是什么样的 HTTP 方法(包括 GET),只要检测到了对象类型的参数就会尝试将其视为 POST 请求处理[^2]。但这并不是官方文档所提倡的最佳实践,而且可能会带来兼容性安全性方面的问题。所以建议按照上述方法正确设置 GET 请求及其参数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值