控制器 class 级别上的路径变量不起作用 Spring Restful

Pathvariable on Controller class level does not work Spring Restful

我有一个控制器,其中控制器级别映射为“/subjects/{subjectId}/lessons”,由于某些原因,这是必需的

@RestController
@RequestMapping( value = "/subjects/{subjectId}/lessons",produces = { MediaType.APPLICATION_JSON_VALUE } )
public class LessonController {
    .......
    @RequestMapping( method = RequestMethod.GET )
    public ResponseEntity<Resources<Resource<Lesson>>> getAllSjubject(@PathVariable(value = "subjectId") int subjectId){        

        List<Lesson> lessonList = lessonService.getAllLessons(subjectId);
        Resources<Resource<Lesson>> resource = this.lessonResourceAssembler.toLessonResourceList(lessonList);
        return new ResponseEntity<Resources<Resource<Lesson>>>(resource, HttpStatus.OK);
    }
}

发出请求时抛出异常

java.lang.IllegalArgumentException: Not enough variable values available to expand 'subjectId'
    at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:327)
    at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:230)
    at org.springframework.web.util.HierarchicalUriComponents$FullPathComponent.expand(HierarchicalUriComponents.java:685)
    at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:328)
    at org.springframework.web.util.HierarchicalUriComponents.expandInternal(HierarchicalUriComponents.java:47)
    at org.springframework.web.util.UriComponents.expand(UriComponents.java:163)
    at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:89)
    at org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo(ControllerLinkBuilder.java:69)
    at com.khaino.springrest.assembler.LessonResourceAssembler.toLessonResource(LessonResourceAssembler.java:31)
    at com.khaino.springrest.assembler.LessonResourceAssembler.toLessonResourceList(LessonResourceAssembler.java:44)
    at com.khaino.springrest.controller.LessonController.getAllSjubject(LessonController.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:111)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:806)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:729)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Unknown Source)

但是当我将路径变量移动到下面的方法级别时,它工作正常。

@RequestMapping( value = "/subjects",produces = { MediaType.APPLICATION_JSON_VALUE } )
public class LessonController {

    ......

    @RequestMapping( value = "/{subjectId}/lessons", method = RequestMethod.GET )
    public ResponseEntity<Resources<Resource<Lesson>>> getAllSjubject(@PathVariable("subjectId") int subjectId){        

        List<Lesson> lessonList = lessonService.getAllLessons(subjectId);
        Resources<Resource<Lesson>> resource = this.lessonResourceAssembler.toLessonResourceList(lessonList);
        return new ResponseEntity<Resources<Resource<Lesson>>>(resource, HttpStatus.OK);
    }

    ....
}

我的代码有问题吗?可能是什么原因和解决方法?

http://localhost:8080/springexample/subjects/3/lessons 使用代码为我工作:

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/subjects/{subjectId}/lessons", produces = { MediaType.APPLICATION_JSON_VALUE })
public class LessonController {
    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity getAllSjubject(
            @PathVariable(value = "subjectId") int subjectId) {
        System.out.println(subjectId);
        return new ResponseEntity(HttpStatus.OK);
    }
}

Spring Dependencypom.xml中定义为:<spring.version>4.1.4.RELEASE</spring.version>

你的映射在这两种情况下都有效,但根据你的堆栈跟踪,以下部分是问题的根源:

this.lessonResourceAssembler.toLessonResourceList(lessonList)

您正在创建一些 Hypermedia Links,其中包含一些未展开的 Template Variables

已更新:使用此方法创建link:

linkTo(methodOn(LessonController.class).getAllSjubject(42))
                .withRel(REL_SELF)

mehtodOnorg.springframework.hateoas.mvc.ControllerLinkBuilder 包中,确保你有正确的静态导入。