1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Feign报错Method Not Allowed 405 5种解决方案

Feign报错Method Not Allowed 405 5种解决方案

时间:2023-01-23 18:55:55

相关推荐

Feign报错Method Not Allowed 405 5种解决方案

一,问题产生背景

Feign发送Get请求时,采用POJO传递参数 Method Not Allowed 405

@FeignClient("microservice-provider-user")public interface UserFeignClient {@RequestMapping(value = "/user", method = RequestMethod.GET)public PageBean<User> get(User user);}

二,问题产生原因

.www.protocol.http;public class HttpURLConnection extends .HttpURLConnection {// 这里很简单:只要你doOutput = true了,你是get请求的话也会强制给你转为POST请求private synchronized OutputStream getOutputStream0() throws IOException {try {if (!this.doOutput) {throw new ProtocolException("cannot write to a URLConnection if doOutput=false - call setDoOutput(true)");} else {if (this.method.equals("GET")) {this.method = "POST";}}...}}

这段代码是在 HttpURLConnection 中发现的,jdk原生的http连接请求工具类,原来是因为Feign默认使用的连接工具实现类,所以里面发现只要你有body体对象,就会强制的把get请求转换成POST请求。

三,解决方案

1,方案一使用Map 接收参数

量大的话改的东西多

使用@Validated验证的时候不支持了,需要手动调用校验方法

@FeignClient("microservice-provider-user")public interface UserFeignClient {//@RequestParam不要指定参数@RequestMapping(value = "/user", method = RequestMethod.GET)public PageBean<User> get(@RequestParam Map<String,Object> param);}

2,方案二不用实体接收,改为单独的参数

量大的话改的东西多

@FeignClient("microservice-provider-user")public interface UserFeignClient {@RequestMapping(value = "/user", method = RequestMethod.GET)public PageBean<User> get(@RequestParam("name") String name,@RequestParam("age") int age);}

3,方案三修改feign的请求工具

默认的是jdk的,可以修改为okhttp 或者 httpclent

yml:

feign:httpclient:enabled: true

maven:

<!--httpClient--><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version></dependency><dependency><groupId>flix.feign</groupId><artifactId>feign-httpclient</artifactId><version>8.17.0</version></dependency>

四,方案四添加RequestInterceptor 拦截器

package com.mugua.demo.config;import com.fasterxml.jackson.databind.JsonNode;import com.fasterxml.jackson.databind.ObjectMapper;import feign.Request;import feign.RequestInterceptor;import feign.RequestTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.ponent;import org.springframework.util.StringUtils;import java.io.IOException;import java.util.*;/*** GET 405** @author liwenchao*/@Componentpublic class FeignRequestParamInterceptor implements RequestInterceptor {private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();@Overridepublic void apply(RequestTemplate template) {// feign 不支持 GET 方法传 POJO, json body转queryif ("GET".equals(template.method()) && template.requestBody() != null) {try {JsonNode jsonNode = OBJECT_MAPPER.readTree(template.requestBody().asBytes());template.body(Request.Body.empty());Map<String, Collection<String>> queries = new HashMap<>();buildQuery(jsonNode, "", queries);template.queries(queries);} catch (IOException e) {e.printStackTrace();}}}private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {// 叶子节点if (!jsonNode.isContainerNode()) {if (jsonNode.isNull()) {return;}Collection<String> values = puteIfAbsent(path, k -> new ArrayList<>());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);}}}}}

5,方案五重写SpringMvcContract

package com.mugua.demo.config;import feign.MethodMetadata;import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;import org.springframework.cloud.openfeign.support.SpringMvcContract;import org.springframework.core.convert.ConversionService;import org.ponent;import org.springframework.web.bind.annotation.RequestBody;import java.lang.annotation.Annotation;import java.util.List;/*** GET 405** @author lwc*/@Componentpublic class SpringMvcPojoObjectQueryContract extends SpringMvcContract {public SpringMvcPojoObjectQueryContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors, ConversionService conversionService) {super(annotatedParameterProcessors, conversionService);}@Overrideprotected boolean processAnnotationsOnParameter(MethodMetadata data, Annotation[] annotations, int paramIndex) {boolean httpAnnotation = super.processAnnotationsOnParameter(data, annotations, paramIndex);//在springMvc中如果是Get请求且参数中是对象 没有声明为@RequestBody 则默认为Paramif (!httpAnnotation && "GET".equalsIgnoreCase(data.template().method())) {for (Annotation parameterAnnotation : annotations) {if (!(parameterAnnotation instanceof RequestBody)) {return false;}}data.queryMapIndex(paramIndex);return true;}return httpAnnotation;}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。