spring-hateoas如何在期望对象而不是原始性的方法中构造链接

时间:2019-06-24 18:40:07

标签: spring-boot spring-hateoas

当控制器方法需要对象而不是原始性时,如何在spring-hateoas中构造链接。

例如。

我有类似的方法

@GetMapping(value = "/{environmentId}/stores/{id}")
    public Resource<Store> getById(@PathVariable("id") Optional<Store> storeOptional) {

        return storeOptional
            .map(store -> {
                Resource<Store> resource = new Resource<>(store);
                val link = linkTo(methodOn(OsmosisStoreController.class).getById(storeOptional)).withSelfRel();
                resource.add(link);
                return resource;
            }).orElseThrow(ResourceNotFoundException::new);
    }

它会抛出

java.lang.IllegalArgumentException: Source to convert from must be an instance of [@org.springframework.web.bind.annotation.PathVariable com.tux.osmosis.domain.Store]; instead it was a [java.util.Optional]
        at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:187)
        at org.springframework.hateoas.mvc.AnnotatedParametersParameterAccessor$BoundMethodParameter.asString(AnnotatedParametersParameterAccessor.java:196)
        at org.springframework.hateoas.mvc.ControllerLinkBuilderFactory.linkTo(ControllerLinkBuilderFactory.java:150)
        at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:195)
        at com.tux.osmosis.api.controller.OsmosisStoreController.lambda$getById$0(OsmosisStoreController.java:89)
        at java.util.Optional.map(Optional.java:215)
        at com.tux.osmosis.api.controller.OsmosisStoreController.getById(OsmosisStoreController.java:87)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
        at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
        at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at com.tux.PingFilter.doFilter(PingFilter.java:44)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at com.tux.osmosis.api.filter.FeatureFlagFilter.doFilterInternal(FeatureFlagFilter.java:76)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at com.tux.PathSanitizingFilter.doFilter(PathSanitizingFilter.java:61)
        at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
        at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:182)
        at com.tux.osmosis.api.controller.OsmosisStoreControllerIT.testGetByIdWhenFound(OsmosisStoreControllerIT.java:98)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
        at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
        at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
        at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
        at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:74)
        at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:84)
        at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
        at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
        at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)

我知道我可以将方法参数Optional storeOptional更改为字符串storeId。我只是很好奇,有没有比使用原始性变量更好的方法。

我正在使用spring-boot 2.1.4和spring-hateoas 0.25.1

谢谢。

0 个答案:

没有答案