【问题标题】:404 while using Spring cloud FeignClients使用 Spring Cloud Feign Client 时出现 404
【发布时间】:2015-10-12 17:25:09
【问题描述】:

这是我的设置:

使用 FeignClients API 和 Eureka 调用第二个服务(BaggageServiceApplication)的第一个服务(FlightIntegrationApplication)。

github上的项目:https://github.com/IdanFridman/BootNetflixExample

第一次服务:

@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
@ComponentScan("com.bootnetflix")
public class FlightIntegrationApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(FlightIntegrationApplication.class).run(args);
    }

}

在其中一个控制器中:

    @RequestMapping("/flights/baggage/list/{id}")
    public String getBaggageListByFlightId(@PathVariable("id") String id) {
        return flightIntegrationService.getBaggageListById(id);
    }

FlightIntegrationService:

    public String getBaggageListById(String id) {
        URI uri = registryService.getServiceUrl("baggage-service", "http://localhost:8081/baggage-service");
        String url = uri.toString() + "/baggage/list/" + id;
        LOG.info("GetBaggageList from URL: {}", url);

        ResponseEntity<String> resultStr = restTemplate.getForEntity(url, String.class);
        LOG.info("GetProduct http-status: {}", resultStr.getStatusCode());
        LOG.info("GetProduct body: {}", resultStr.getBody());
        return resultStr.getBody();

    }

注册服务:

@Named
public class RegistryService {

    private static final Logger LOG = LoggerFactory.getLogger(RegistryService.class);


    @Autowired
    LoadBalancerClient loadBalancer;

    public URI getServiceUrl(String serviceId, String fallbackUri) {
        URI uri;
        try {
            ServiceInstance instance = loadBalancer.choose(serviceId);
            uri = instance.getUri();
            LOG.debug("Resolved serviceId '{}' to URL '{}'.", serviceId, uri);

        } catch (RuntimeException e) {
            // Eureka not available, use fallback
            uri = URI.create(fallbackUri);
            LOG.error("Failed to resolve serviceId '{}'. Fallback to URL '{}'.", serviceId, uri);
        }

        return uri;
    }

}

这是第二个服务(baggage-service):

BaggageServiceApplication:

@Configuration
@ComponentScan("com.bootnetflix")
@EnableAutoConfiguration
@EnableEurekaClient
@EnableFeignClients
public class BaggageServiceApplication {


    public static void main(String[] args) {
        new SpringApplicationBuilder(BaggageServiceApplication.class).run(args);
    }

}

行李服务:

@FeignClient("baggage-service")
public interface BaggageService {

    @RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
    List<String> getBaggageListByFlightId(@PathVariable("flight_id") String flightId);


}

BaggageServiceImpl:

@Named
public class BaggageServiceImpl implements BaggageService{

....

    @Override
    public List<String> getBaggageListByFlightId(String flightId) {
        return Arrays.asList("2,3,4");
    }

}

调用飞行集成服务的其余控制器时,我得到:

2015-07-22 17:25:40.682  INFO 11308 --- [  XNIO-2 task-3] c.b.f.service.FlightIntegrationService   : GetBaggageList from URL: http://X230-Ext_IdanF:62007/baggage/list/4
2015-07-22 17:25:43.953 ERROR 11308 --- [  XNIO-2 task-3] io.undertow.request                      : UT005023: Exception handling request to /flights/baggage/list/4

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 404 Not Found
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978)

有什么想法吗?

谢谢, 射线。

【问题讨论】:

    标签: spring spring-boot spring-cloud netflix-eureka netflix-feign


    【解决方案1】:

    registryService.getServiceUrl("baggage-service", ... 替换为

    registryService.getServiceUrl("baggage-service")
    

    确保匹配正确的名称

    删除本地主机部分

    或仅使用http://local 部分

    仅当您在 eureka 仪表板中列出服务的名称时,它才对我们有用,而不是两者都列出

    【讨论】:

    • 我不明白。你写了同一行。
    • 本地主机只在 faillback-url 中提到,而不是在主目录中
    【解决方案2】:

    你的代码在我看来是向后看的。

    行李服务的 feign 客户端应该在航班服务中声明,并且行李服务应该有一个控制器来响应您在行李服务客户端中映射的 URL,您应该实现带有@FeignClient注解的界面。

    您现在的设置将不会有任何控制器在行李服务中监听 /baggage/list/{flightId} 并且在飞行服务中没有 Feign 客户端 - Feign 的全部意义在于调用接口上的方法而不是手动处理 URL,Spring Cloud 负责自动实例化接口实现并将使用 Eureka 进行发现。

    试试这个(或修改它以适合您的实际应用):

    飞行服务:

    FlightIntegrationService.java:

    @Component
    public class FlightIntegrationService {
    
        @Autowired
        BaggageService baggageService;
    
        public String getBaggageListById(String id) {
            return baggageService.getBaggageListByFlightId(id);
        }
    }
    

    BaggageService.java:

    @FeignClient("baggage-service")
    public interface BaggageService {
    
        @RequestMapping(method = RequestMethod.GET, value = "/baggage/list/{flight_id}")
        List<String> getBaggageListByFlightId(@PathVariable("flight_id") String flightId);   
    }
    

    行李服务:

    BaggageController.java:

    @RestController
    public class BaggageController {
    
        @RequestMapping("/baggage/list/{flightId}")
        public List<String> getBaggageListByFlightId(@PathVariable String flightId) {
            return Arrays.asList("2,3,4");
        }
    }
    

    从 Baggage Service 中删除 BaggageService.javaBaggageServiceImpl.java

    【讨论】:

    • 不应该BaggageController实现BaggageService吗?
    • 不一定——有时你想在控制器中获取请求或响应对象,或者用同一个控制器方法处理多个接口方法。一个很好的例子是查询参数,您可以在一个控制器方法中为缺少的参数设置默认值,但如果您想避免使用一堆 nulls 调用它,则需要多个接口方法。
    猜你喜欢
    • 1970-01-01
    • 2018-08-31
    • 2015-11-12
    • 2018-02-01
    • 2015-08-24
    • 2015-06-08
    • 1970-01-01
    • 2022-08-17
    • 2021-12-17
    相关资源
    最近更新 更多