【问题标题】:Feign Client and Spring-data-rest (HAL): Howto navigate to linked (`_links`) resorces?Feign Client 和 Spring-data-rest (HAL):如何导航到链接的 (`_links`) 资源?
【发布时间】:2018-06-04 05:36:33
【问题描述】:

终于在大量堆栈溢出 ;-) 和调试之后,我让它工作了: 我的 Feign-client 可以在 Spring-Data-Rest 的 API 上发出请求,我得到一个 Resource<Something> 和填充的 links 返回。

到目前为止我的代码...

FeignClient:

@FeignClient(name = "serviceclient-hateoas",
    url = "${service.url}",
    decode404 = true,
    path = "${service.basepath:/api/v1}",
    configuration = MyFeignHateoasClientConfig.class)
public interface MyFeignHateoasClient {

    @RequestMapping(method = RequestMethod.GET, path = "/bookings/search/findByBookingUuid?bookingUuid={uuid}")
    Resource<Booking> getBookingByUuid(@PathVariable("uuid") String uuid);

}

客户端配置:

@Configuration
public class MyFeignHateoasClientConfig{

    @Value("${service.user.name:bla}")
    private String serviceUser;

    @Value("${service.user.password:blub}")
    private String servicePassword;

    @Bean
    public BasicAuthRequestInterceptor basicAuth() {
        return new BasicAuthRequestInterceptor(serviceUser, servicePassword);
    }

    @Bean
    public Decoder decoder() {
        return new JacksonDecoder(getObjectMapper());
    }

    @Bean
    public Encoder encoder() {
        return new JacksonEncoder(getObjectMapper());
    }

    public ObjectMapper getObjectMapper() {
        return new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
                .registerModule(new Jackson2HalModule());
    }

    @Bean
    public Logger logger() {
        return new Slf4jLogger(MyFeignHateoasClient.class);
    }

    @Bean
    public Logger.Level logLevel() {
        return Logger.Level.FULL;
    }
}

在应用程序中通过 jar 依赖使用客户端:

@SpringBootApplication
@EnableAutoConfiguration
@EnableFeignClients(basePackageClasses=MyFeignHateoasClient.class)
@EnableHypermediaSupport(type = EnableHypermediaSupport.HypermediaType.HAL)
@ComponentScan(excludeFilters = @Filter(type = ... ), basePackageClasses= {....class}, basePackages="...")
public class Application {
...

现在可以了:

@Autowired
private MyFeignHateoasClient serviceClient;
...
void test() {
    Resource<Booking> booking = serviceClient.getBookingByUuid(id);
    Link link = booking.getLink("relation-name");
}

现在我的问题:

我如何从这里继续,即导航到链接中的资源?

链接包含我要请求的资源的 URL。

  • 我真的必须从 URL 中解析出 ID 并向 FeignClient 添加一个方法,例如 getRelationById(id)
  • 是否至少有一种方法可以将完整的资源 URL 传递给 FeignClient 的方法?

我没有找到演示如何从这里开始的示例(尽管有 POST/修改)。任何提示表示赞赏!

谢谢

【问题讨论】:

    标签: spring-data-rest hateoas hal spring-cloud-feign feign


    【解决方案1】:

    我目前的解决方案:

    我在 Feign 客户端中添加了一个额外的请求,取整个资源路径:

    ...
    public interface MyFeignHateoasClient {
    ...
        @RequestMapping(method = RequestMethod.GET, path = "{resource}")
        Resource<MyLinkedEntity> getMyEntityByResource(@PathVariable("resource") String resource);
    }
    

    然后我实现了某种“HAL-Tool”:

    ...                                                                                                                                                                              
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    
    import org.springframework.hateoas.Link;
    
    import feign.Target;
    import lombok.SneakyThrows;
    
    public class HalTool {
    
        private Object feignClient;
    
        public static HalTool forClient( Object feignClient ) {
            return new HalTool(feignClient);
        }
    
        private HalTool( Object feignClient ) {
            this.feignClient = feignClient;
        }
    
        @SneakyThrows
        private String getUrl() {
            InvocationHandler invocationHandler = Proxy.getInvocationHandler(feignClient);
            Field target = invocationHandler.getClass().getDeclaredField("target");
            target.setAccessible(true);
            Target<?> value = (Target<?>) target.get(invocationHandler);
            return value.url();
        }
    
        public String toPath( Link link ) {
            String href = link.getHref();
            String url = getUrl();
            int idx = href.indexOf(url);
            if (idx >= 0 ) {
                idx += url.length();
            }
            return href.substring(idx);
        }
    }                                                                                                                                                                                         
    

    然后我可以请求这样的链接资源:

    Link link = booking.getLink("relation-name");
    Resource<MyLinkedEntity> entity = serviceClient.getMyEntityByResource(
        HalTool.forClient(serviceClient).toPath(link));
    

    【讨论】:

    • 与此同时,我删除了反射的东西,并在我注入 service.urlpath 的 feign 客户端周围构建了一个小包装器。这在测试方面具有优势。
    猜你喜欢
    • 2023-03-29
    • 2014-10-06
    • 1970-01-01
    • 2017-04-27
    • 1970-01-01
    • 2018-09-04
    • 2021-12-14
    • 2017-06-21
    • 1970-01-01
    相关资源
    最近更新 更多