ZetCode

Spring Boot @RestController

最后修改于 2023 年 7 月 18 日

Spring Boot @RestController 教程展示了如何在 Spring 应用程序中使用 @RestController 注解来构建一个 Restful 控制器。

Spring 是一个流行的 Java 应用程序框架,而 Spring Boot 是 Spring 的一个演进,它有助于轻松创建独立的、生产级的基于 Spring 的应用程序。

Spring MVC

Spring MVC 是基于 Servlet API 构建的主要 Web 框架。它是基于流行的 MVC 设计模式构建的。MVC (Model-View-Controller) 是一种软件架构模式,它将应用程序分为三个区域:模型、视图和控制器。模型表示一个携带数据的 Java 对象。视图表示模型包含的数据的可视化。控制器控制数据流到模型对象中,并在数据更改时更新视图。它分离了视图和模型。

Spring Framework 5.0 引入了一个并行的响应式栈 Web 框架,名为 Spring WebFlux

@RestController

@RestController 是用于创建 Restful 控制器的便捷注解。它是 @Component 的一个特例,并通过类路径扫描自动检测。它添加了 @Controller@ResponseBody 注解。它将响应转换为 JSON 或 XML。它不适用于视图技术,因此方法不能返回 ModelAndView。它通常与基于 @RequestMapping 注解的注解处理程序方法结合使用。

ResponseEntity 类表示一个 HTTP 响应,包括标头、主体和状态。它用于返回数据。

@Controller 注解与视图技术一起使用。

Restful 应用程序

一个 RESTFul 应用程序 遵循 REST 架构风格,该风格用于设计网络应用程序。RESTful 应用程序生成 HTTP 请求,对资源执行 CRUD(创建/读取/更新/删除)操作。RESTFul 应用程序通常以 JSON 或 XML 格式返回数据。

Spring Boot @RestController 示例

在以下应用程序中,我们演示了 @RestController 的用法。该应用程序以 JSON 数据的形式返回城市列表。

build.gradle
...
src
├── main
│   ├── java
│   │   └── com
│   │       └── zetcode
│   │           ├── Application.java
│   │           ├── controller
│   │           │   └── MyController.java
│   │           ├── model
│   │           │   └── City.java
│   │           └── service
│   │               ├── CityService.java
│   │               └── ICityService.java
│   └── resources
│       └── application.properties
└── test

这是项目结构。

build.gradle
plugins {
    id 'org.springframework.boot' version '3.1.1'
    id 'io.spring.dependency-management' version '1.1.0'
    id 'java'
}

group = 'com.zetcode'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

这是 Gradle 构建文件。spring-boot-starter-web 是用于构建 Web 应用程序(包括 RESTful 应用程序)的启动器,使用 Spring MVC。

resources/application.properties
spring.main.banner-mode=off

这是主属性文件。

com/zetcode/model/City.java
package com.zetcode.model;

public record City(Long id, String name, Integer population) {}

这是一个 City bean。它具有 idnamepopulation 属性。

com/zetcode/controller/MyController.java
package com.zetcode.controller;

import com.zetcode.model.City;
import com.zetcode.service.ICityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class MyController {

    private final ICityService cityService;

    @Autowired
    public MyController(ICityService cityService) {
        this.cityService = cityService;
    }

    @GetMapping(value = "/cities")
    public ResponseEntity<List<City>> getCities() {

        return cityService.findAll();
    }

    @GetMapping(value = "/cities/{id}")
    public ResponseEntity<City> getCity(@PathVariable("id") int id) {

        return cityService.findById(id);
    }
}

这是 MyController。它以 JSON 格式返回城市列表。

@RestController
public class MyController {

MyController 使用 @RestController 注解进行注解。

private final ICityService cityService;

@Autowired
public MyController(ICityService cityService) {
    this.cityService = cityService;
}

我们将 CityService 注入到 cityService 字段中。

@GetMapping(value = "/cities")
public ResponseEntity<List<City>> getCities() {

    return cityService.findAll();
}

getCities 方法映射到 /cities URL 模式;它返回一个城市列表,该列表由消息转换器转换为 JSON。

@GetMapping(value = "/cities/{id}")
public ResponseEntity<City> getCity(@PathVariable("id") int id) {

    return cityService.findById(id);
}

getCity 方法返回单个城市。

com/zetcode/service/ICityService.java
package com.zetcode.service;

import java.util.List;

import com.zetcode.model.City;

import org.springframework.http.ResponseEntity;

public interface ICityService {

    ResponseEntity<List<City>> findAll();
    ResponseEntity<City> findById(int id);
}

ICityService 包含 findAllfindById 契约方法。

com/zetcode/service/CityService.java
package com.zetcode.service;

import com.zetcode.model.City;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class CityService implements ICityService {

    private final List<City> cities = new ArrayList<>();

    public CityService() {

        cities.add(new City(1L, "Bratislava", 432000));
        cities.add(new City(2L, "Budapest", 1759000));
        cities.add(new City(3L, "Prague", 1280000));
        cities.add(new City(4L, "Warsaw", 1748000));
        cities.add(new City(5L, "Los Angeles", 3971000));
        cities.add(new City(6L, "New York", 8550000));
        cities.add(new City(7L, "Edinburgh", 464000));
        cities.add(new City(8L, "Berlin", 3671000));
    }

    @Override
    public ResponseEntity<List<City>> findAll() {

        return ResponseEntity.ok(cities);
    }

    public ResponseEntity<City> findById(int id) {

        if (id < 0 || id >= cities.size()) {
            return ResponseEntity.notFound().build();
        }

        return ResponseEntity.ok(cities.get(id));
    }
}

CityService 包含 findAllfindById 方法的实现。

com/zetcode/Application.java
package com.zetcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application  {
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Application 是设置 Spring Boot 应用程序的入口点。

$ ./gradlew bootRun

我们运行应用程序。

$ curl localhost:8080/cities/2 -i
HTTP/1.1 200
Content-Type: application/json
Transfer-Encoding: chunked
Date: Wed, 19 Jul 2023 14:25:22 GMT

{"id":3,"name":"Prague","population":1280000}
$ curl localhost:8080/cities
[{"id":1,"name":"Bratislava","population":432000},{"id":2,"name":"Budapest","population":1759000},
{"id":3,"name":"Prague","population":1280000},{"id":4,"name":"Warsaw","population":1748000},
{"id":5,"name":"Los Angeles","population":3971000},{"id":6,"name":"New York","population":8550000},
{"id":7,"name":"Edinburgh","population":464000},{"id":8,"name":"Berlin","population":3671000}]
$ curl localhost:8080/cities/26 -i
HTTP/1.1 404
Content-Length: 0
Date: Wed, 19 Jul 2023 14:26:24 GMT

作者

我叫 Jan Bodnar,是一位充满激情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我撰写了 1400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出 所有 Spring Boot 教程