Feign Client和Spring-data-rest(HAL):如何导航到链接(`_links`)resorces?

时间:2017-12-21 14:08:01

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

最后经过大量的堆栈溢出;-)和调试我使它工作: 我的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);

}

client-config:

@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。

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

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

THX

1 个答案:

答案 0 :(得分:0)

我目前的解决方案:

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

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

然后我实施了某种&#34; HAL-Tool&#34;:

...                                                                                                                                                                              
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));