Spring Cloud Netflix Feign - 不支持错误 405 请求方法“POST”

Posted

技术标签:

【中文标题】Spring Cloud Netflix Feign - 不支持错误 405 请求方法“POST”【英文标题】:Spring Cloud Netflix Feign - Error 405 Request method 'POST' not supported 【发布时间】:2016-07-13 01:58:31 【问题描述】:

我正在尝试使用 Feign 为我的 Web 服务构建一个 REST 客户端。 Web 服务是使用 Spring 4 构建的,具有 xml beans 配置。

项目使用 Maven 构建并使用子模块构建

foo-api
--- foo-api-client
------ src/main/java/foo/client
--------- FooClientFactory.java
------ pom.xml
--- foo-api-shared
------ src/main/java/foo/shared
--------- FooClient.java
------ pom.xml
--- foo-api-service
------ src/main
--------- /java/foo/service
------------ /config
--------------- FeignConfiguration.java
------------ /controller
--------------- FooController.java
--------- /webapp/WEB-INF
------------ spring.xml
------------ web.xml
--- pom.xml

为了启用 Feign 客户端,我创建了一个在 Spring xml 配置中启用的带注释的类。

spring.xml

...

<context:component-scan base-package="foo.service"/>

<context:annotation-config/>

<bean class="foo.service.config.FeignConfiguration" />

...

FeignConfiguration.java

package foo.service.config;

import org.springframework.cloud.netflix.feign.EnableFeignClients;

@EnableFeignClients
public class FeignConfiguration 

然后我创建了一个 Feign 客户端并使用注解进行配置

FooClient.java

package foo.shared;

import feign.Headers;
import feign.RequestLine;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient("foo")
public interface FooClient 

    @RequestLine("GET /foo/v2/id")
    @Headers("Accept: " + MediaType.APPLICATION_JSON_VALUE)
    Object get(@PathVariable("id") String id);


API控制器实现Feign客户端如下

FooController.java

package foo.service.controller;

@Controller
@RequestMapping("/foo")
public class FooController implements FooClient 

    @Override
    @RequestMapping(value = "/v2/id", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public @ResponseBody Object get(@PathVariable("id") String id) 
        ...
    

    ...


foo-api-client 模块 jar 被外部客户端用作依赖项来联系 foo-api-service REST 服务。为了让这些客户端能够轻松使用 api,我们创建了一个工厂类来生成 FooClient 的实例。

FooClientFactory.java

package foo.client;

import foo.shared.FooClient;
import feign.Feign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

@Service
public class FooClientFactory 

    @Autowired
    private Environment env;

    public static final String SERVER_URL_PROPERTY = "foo.api.url";

    public FooClient build() 
        return Feign.builder()
                .encoder(new JacksonEncoder())
                .decoder(new JacksonDecoder())
                .target(FooClient.class, env.getProperty(SERVER_URL_PROPERTY));
    


问题 当外部客户端使用 FooClientFactory fooClientFactory.build().get("id"); 对 foo Web 服务执行请求时,会返回 405 错误。 这是客户端控制台上的响应日志:

ERROR [http-nio-8091-exec-1] --- [dispatcherServlet]: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.FeignException: status 405 reading FooClient#get(String); content:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 405 Request method &apos;POST&apos; not supported</title>
</head>
<body><h2>HTTP ERROR 405</h2>
<p>Problem accessing /foo/v2/id. Reason:
<pre>    Request method &apos;POST&apos; not supported</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.7.v20160115</a><hr/>

</body>
</html>
] with root cause
feign.FeignException: status 405 reading FooClient#getOrder(String); content:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 405 Request method &apos;POST&apos; not supported</title>
</head>
<body><h2>HTTP ERROR 405</h2>
<p>Problem accessing /foo/v2/id. Reason:
<pre>    Request method &apos;POST&apos; not supported</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.7.v20160115</a><hr/>

</body>
</html>

我在 *** 和其他博客上搜索了此类问题,但我无法理解整个设置有什么问题。

有什么想法吗?

谢谢, 安德烈亚

【问题讨论】:

要么使用带有 spring boot 的 spring Cloud,要么使用 vanilla Netflix feign。目前没有混搭。 查看除了@EnableFeignClients 之外的代码,您正在使用vanilla feign,因此spring MVC 注释将不起作用。 【参考方案1】:

我在路径中看到两个“foo”。

@FeignClient("foo")@RequestLine("GET /foo/v2/id")

这使得路径为/foo/foo/v2/id,但是您的呼叫应该是/foo/v2/id

请您尝试删除“/foo”

【讨论】:

以上是关于Spring Cloud Netflix Feign - 不支持错误 405 请求方法“POST”的主要内容,如果未能解决你的问题,请参考以下文章

Spring Cloud Netflix—使用EurekaClient

Spring Cloud Netflix(网飞)

`spring-cloud-starter-eureka-server`和`spring-cloud-starter-netflix-eureka-server`之间的区别

Netflix之后,如何用Spring Cloud 新组件构建微服务架构?

Spring Cloud / Netflix OSS 中的负载均衡

随手记录关于spring-cloud-starter-eureka-server 和 spring-cloud-starter-netflix-eureka-server