spring 远程调用时报错No substitution in url for:id

在使用GET请求时使用了rest风格方式,结果报错500

  • Feign客户端代码
  • 请求路由

服务端路由

使用postman 请求

报错信息

刚开始还以为路由写错了,最后发现是需要把路径上的id参数取出来传入调用的方法中,修改后代码

  • Feign客户端

package com.fengyun.medical.customersconsumerservice.openfeign;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import reactivefeign.spring.config.ReactiveFeignClient;
import reactor.core.publisher.Mono;

@ReactiveFeignClient(name="medical-product-service")
public interface HandBookFeignService {

    @GetMapping(value = "/echo/{string}")
    Mono<String> echo(@PathVariable String string);

    @GetMapping(value = "/city")
    Mono<String> getCity();

    @GetMapping(value = "/ethnic")
    Mono<String> getEthnic();

    @GetMapping(value = "/relational")
    Mono<String> getRelational();

    @GetMapping(value = "/title")
    Mono<String> getTitle();

    @PostMapping(value = "/doctors")
    Mono<String> register();

    @GetMapping(value = "/doctors/{id}")
    Mono<String> getDoctorById(@PathVariable Integer id);
}
  • Consumer端路由

package com.fengyun.medical.customersconsumerservice.routers;

import com.fengyun.medical.customersconsumerservice.openfeign.HandBookFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;

//@Configuration(proxyBeanMethods = false)
public class HandBookRouter {

    @Autowired
    HandBookFeignService feignService;

    @Value("${spring.application.name}")
    private String appName;

    @Bean
    public RouterFunction<ServerResponse> router(){
        return RouterFunctions.route()
                .GET("/echo/app-name", accept(MediaType.APPLICATION_JSON),
        request -> ServerResponse.ok().body(feignService.echo(appName), String.class))
                .GET("/city", accept(MediaType.APPLICATION_JSON),
                        request -> ServerResponse.ok().body(feignService.getCity(), String.class))
                .GET("/relational", accept(MediaType.APPLICATION_JSON),
                        request -> ServerResponse.ok().body(feignService.getRelational(), String.class))
                .GET("/ethnic", accept(MediaType.APPLICATION_JSON),
                        request -> ServerResponse.ok().body(feignService.getEthnic(), String.class))
                .GET("/title", accept(MediaType.APPLICATION_JSON),
                        request -> ServerResponse.ok().body(feignService.getTitle(), String.class))

                .build();

    }

    @Bean
    public RouterFunction<ServerResponse> doctorRouter() {
        return RouterFunctions.route()
                .GET("/doctor/{id}", accept(MediaType.APPLICATION_JSON),
                        request -> ServerResponse.ok()
                                .body(feignService.getDoctorById(Integer.valueOf(request.pathVariable("id"))), String.class))
//                .path("/doctors", b1 -> b1
//                        .nest(accept(MediaType.APPLICATION_JSON), b2 -> b2
//                                .GET("/{id}", request -> ServerResponse.ok()
//                                        .body(feignService.getDoctorById(), String.class))
//                        )
//                        .POST(request -> ServerResponse.ok().body(feignService.register(), String.class))
//                )
                .build();
    }

}
  • 浏览器发起请求:http://localhost:8090/doctor/57

  • 找到consumer端路由:"/doctor/{id}"

  • 调用Feign端提供的方法,这时需要把路径上的id取出来交给Feign

  • 接下来Feign根据@ReactiveFeignClient(name="medical-product-service")注解找到相应的服务,在注册中心找到服务所对应的url。

  • Feign再找到方法上的GetMapping提供的映射地址@GetMapping(value = "/doctors/{id}")

  • Feign 通过方法内传递过来的id值与映射地址上的占位符id进行替换,错误就发生在这一步,因为Feign没有接收到id的值,所以无法与点位符上的id进行替换。

  • 最后一步,Feign 把url与替换后的映射地址进行拼接,生成一个全新url: http://localhost:8810/doctors/57,Feign使用新的url发起远程调用。



来自为知笔记(Wiz)


posted on 2022-06-22 02:19  白衣风云  阅读(123)  评论(0编辑  收藏  举报

导航