Spring Boot RestController不返回JSON数据

问题描述 投票:3回答:3

我有一个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

基本上我有一个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(希望在Car中取回第一个carDb作为JSON有效载荷)但没有返回任何内容。在日志中,当我搜索该请求时,我看到:

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"
}

有任何想法吗?

spring-boot groovy spring-restcontroller spring-boot-actuator
3个回答
4
投票

问题是car.get(carId )返回null。尝试以下方法

@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")
}

像这样初始化您的地图,您的原始代码将起作用

  static Map<Long,Car> carDb = [(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"),
        (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"),
        (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")
    ]

1
投票

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

@RequestMapping(value = "/{carId}", method = RequestMethod.GET)
Car getCarById(@PathVariable(value = "carId") Long carId) {
    carDb.get(carId)
}

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


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值,但你的所有键都是Integers,你在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")
    )
}
© www.soinside.com 2019 - 2024. All rights reserved.