Spring Boot RestController不返回JSON数据

时间:2017-04-08 09:32:11

标签: spring-boot groovy spring-restcontroller spring-boot-actuator

我有一个SSCCE,可以在my GitHub repo here完全重现此问题。要在本地运行它:

  1. 克隆
  2. ./gradlew clean build
  3. java -Dspring.config=. -jar build/libs/bootup.jar
  4. 打开浏览器至http://localhost:9200/cars/1
  5. 基本上我有一个Spring Boot应用程序(用Groovy编写),它有一个CarController

    @Slf4j
    @RestController
    @RequestMapping(value = "/cars")
    class CarController {
        // Mock for an actual DB
        static Map<Long,Car> carDb
        static {
            carDb = new HashMap<Long,Car>()
    
            carDb.put(1, new Car(
                1, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
                new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
                "Toyota", "Corolla")
            )
            carDb.put(2, new Car(
                2, UUID.fromString("45a148b9-a44b-41c2-8ad4-c3b5069f091a"),
                new CarType(11, UUID.fromString("b68148b9-a44b-41c2-8ad4-c3b5069f0922"), "Sport Utility Vehicle", "SUV"),
                "Honda", "CRV")
            )
            carDb.put(3, new Car(
                3, UUID.fromString("fe9ede26-886a-4bd9-9b09-535387fffe88"),
                new CarType(12, UUID.fromString("5a5ede26-886a-4bd9-9b09-535387fffe10"), "Truck", "TRUCK"),
                "Chevy", "Silverado")
            )
        }
    
        @RequestMapping(value = "/{carId}", method = RequestMethod.GET)
        Car getCarById(@PathVariable(value = "carId") Long carId) {
            carDb.get(carId)
        }
    
        @RequestMapping(method = RequestMethod.POST)
        void createCar(@RequestBody Car car) {
            log.info("Received a car: ${car}")
        }
    }
    

    CarCarType分别为:

    @Canonical
    abstract class BaseEntity {
        Long id
        UUID refId
    }
    
    @Canonical
    @TupleConstructor(includeSuperProperties = true)
    @ToString(includeSuperProperties = true)
    class Car extends BaseEntity {
        CarType type
        String make
        String model
    }
    
    @Canonical
    @TupleConstructor(includeSuperProperties = true)
    @ToString(includeSuperProperties = true)
    class CarType extends BaseEntity {
        String name
        String label
    }
    

    我使用的是Spring Boot Actuator,这里是我所依赖的依赖项:

    compile(
        'org.codehaus.groovy:groovy-all:2.4.6'
        ,'org.springframework.boot:spring-boot-starter-actuator'
        ,'org.springframework.boot:spring-boot-starter-jetty'
        //,'org.springframework.boot:spring-boot-starter-security'
    //        ,'org.springframework.boot:spring-boot-starter-thymeleaf'
        ,'org.apache.commons:commons-lang3:3.4'
        ,'ch.qos.logback:logback-parent:1.1.7'
    )
    compile('org.springframework.boot:spring-boot-starter-web') {
        exclude module: 'spring-boot-starter-tomcat'
    }
    
    dev('org.springframework.boot:spring-boot-devtools')
    

    当我运行它时(使用上面提到的步骤)它启动就好了。然后我将浏览器打开到http://localhost:9200/cars/1(希望以{J}有效负载的形式取回Car中的第一个carDb,但不返回任何内容。在日志中,当我搜索该请求时,我看到:

    2017-04-08 05:06:58.668 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/cars/1]
    2017-04-08 05:06:58.675 DEBUG 31573 --- [tp1164253047-17] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /cars/1
    2017-04-08 05:06:58.678 DEBUG 31573 --- [tp1164253047-17] s.w.s.m.m.a.RequestMappingHandlerMapping : Returning handler method [public hotmeatballsoup.bootup.model.Car hotmeatballsoup.bootup.controllers.CarController.getCarById(java.lang.Long)]
    2017-04-08 05:06:58.678 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/cars/1] is: -1
    2017-04-08 05:06:58.751 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
    2017-04-08 05:06:58.751 DEBUG 31573 --- [tp1164253047-17] o.s.web.servlet.DispatcherServlet        : Successfully completed request
    2017-04-08 05:06:58.774 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet        : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/favicon.ico]
    2017-04-08 05:06:58.774 DEBUG 31573 --- [tp1164253047-21] o.s.w.s.handler.SimpleUrlHandlerMapping  : Matching patterns for request [/favicon.ico] are [/**/favicon.ico]
    2017-04-08 05:06:58.775 DEBUG 31573 --- [tp1164253047-21] o.s.w.s.handler.SimpleUrlHandlerMapping  : URI Template variables for request [/favicon.ico] are {}
    2017-04-08 05:06:58.775 DEBUG 31573 --- [tp1164253047-21] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapping [/favicon.ico] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], class path resource []], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@592dfeae]]] and 1 interceptor
    2017-04-08 05:06:58.776 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet        : Last-Modified value for [/favicon.ico] is: -1
    2017-04-08 05:06:58.781 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet        : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
    2017-04-08 05:06:58.781 DEBUG 31573 --- [tp1164253047-21] o.s.web.servlet.DispatcherServlet        : Successfully completed request
    

    我不确定如何解释这些日志,但我觉得Spring Boot试图将此视为对HTML(网页)数据的请求,而不是基于JSON的REST数据。

    所以我问:我需要做什么才能向http://localhost:9200/cars/1发送一个GET请求返回JSON,可能是这样的:

    {
      "id" : 1,
      "refId" : "d3bdc4ea-4c62-4bd2-a751-681a531f34f4",
      "type" : {
        "id" : 10,
        "refId" : "ba4dc4ea-4c62-4bd2-a751-681a531f3487",
        "name" : "Sedan",
        "label" : "SEDAN"
      }
      "make" : "Toyota",
      "model" : "Corolla"
    }
    

    有什么想法吗?

3 个答案:

答案 0 :(得分:4)

问题是@Component @ExportMetricWriter public class MyMetricWriter implements MetricWriter, Closeable { private static final Log logger = LogFactory.getLog(MyMetricWriter.class); @Override public void increment(Delta<?> delta) { // record increment to log } @Override public void set(Metric<?> value) { // record set metric to log } @Override public void reset(String name) { // Not implemented } @Override public void close() { /// ... } } 返回null。尝试以下

car.get(carId )

像这样开始你的地图,你的原始代码就可以了

@RequestMapping(value = "/{carId}", method = RequestMethod.GET)
Car getCarById(@PathVariable(value = "carId") Long carId) {
    println 'car >> ' + carDb.get(carId)
    return new Car(
        1, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
        new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
        "Toyota", "Corolla")
}

答案 1 :(得分:1)

您的控制器方法没有返回任何内容

body{
  text-align: center;
}

span{
  background-color: white;
  z-index: 2;
}

div{
  border-top: 1px solid;
  position: absolute;
  width: 100%;
  margin-top: -8px;
  z-index: 1;
}

此方法甚至不会编译,因为您指定它返回Car,但不返回任何内容。 可能是您发布了错误的代码,或者您使用的方法看起来不同。你需要做的是在那里返回一个Car实例,而不是它应该工作。

答案 2 :(得分:1)

问题是你的地图。您将其定义为<Long,Car>,但在添加初始数据时,您会为汽车使用Integer

carDb.put(1, new Car(
        1L, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
        new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
        "Toyota", "Corolla")
    )

因此,如果你问你的地图键1L(长)是否是地图的一部分,你什么也得不到。但是1(作为整数)是地图的一部分并且会返回一辆汽车。由于您的get方法获取Long值,但您的所有键都是整数,因此您在HashMap中找不到汽车。您需要使用如下长值来初始化地图:

static {
    carDb = new HashMap<Long,Car>()

    carDb.put(1L, new Car(
        1, UUID.fromString("d3bdc4ea-4c62-4bd2-a751-681a531f34f4"),
        new CarType(10, UUID.fromString("ba4dc4ea-4c62-4bd2-a751-681a531f3487"), "Sedan", "SEDAN"),
        "Toyota", "Corolla")
    )
    carDb.put(2L, new Car(
        2, UUID.fromString("45a148b9-a44b-41c2-8ad4-c3b5069f091a"),
        new CarType(11, UUID.fromString("b68148b9-a44b-41c2-8ad4-c3b5069f0922"), "Sport Utility Vehicle", "SUV"),
        "Honda", "CRV")
    )
    carDb.put(3L, new Car(
        3, UUID.fromString("fe9ede26-886a-4bd9-9b09-535387fffe88"),
        new CarType(12, UUID.fromString("5a5ede26-886a-4bd9-9b09-535387fffe10"), "Truck", "TRUCK"),
        "Chevy", "Silverado")
    )
}