# Spring Boot RESTFul 应用

> 原文： [http://zetcode.com/articles/springbootrestsimple/](http://zetcode.com/articles/springbootrestsimple/)

在本教程中，我们将创建一个简单的 Spring Boot RESTful 应用。 我们的应用将部署在嵌入式 Tomcat 服务器上。

我们展示了如何从 Web 服务中以 JSON 和 XML 格式返回数据。

## Spring Boot

Spring 是用于创建企业应用的流行 Java 应用框架。 Spring Boot 是一种以最少的精力创建独立的，基于生产级别的基于 Spring 的应用的方法。

## RESTFul 应用

RESTFul 应用创建遵循 REST 体系结构样式的系统（API），该系统用于设计联网应用。 RESTful 应用使用 HTTP 请求对资源执行 CRUD（创建/读取/更新/删除）操作。

## Spring Boot RESTFul 简单示例

以下代码示例创建一个 Web 服务，该服务从 CSV 文件读取数据并将其以 JSON 格式返回给客户端。

```java
$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── Application.java
    │   │           ├── bean
    │   │           │   └── Country.java
    │   │           ├── controller
    │   │           │   └── MyController.java
    │   │           └── service
    │   │               ├── CountryService.java
    │   │               └── ICountryService.java
    │   └── resources
    │       ├── application.yml
    │       └── countries.csv
    └── test
        └── java

```

这是项目结构。

`pom.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>SpringBootRest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>SpringBootRest</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>         
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.3.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.opencsv</groupId>
            <artifactId>opencsv</artifactId>
            <version>3.8</version>
        </dependency>         
    </dependencies>    

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>            
        </plugins>
    </build>

</project>

```

这是 Maven 构建文件。 `opencsv`用于处理 CSV 数据。 `spring-boot-starter-web`是用于构建 Web 和 RESTful 应用的入门工具。 该应用打包到可执行的 JAR 文件中。 可执行 JAR 是使用`spring-boot-maven-plugin`创建的。

`application.yml`

```java
server:
  port: 8086
  contextPath: /rest

```

`application.yml`文件包含 Spring Boot 应用的各种配置设置。 我们具有服务器端口和上下文路径（应用名称）的映射。 该文件位于`src/main/resources`目录中。

`countries.csv`

```java
Country, Population
Slovakia,5429000
Norway,5271000
Croatia,4225000
Russia,143439000
Mexico,122273000
Vietnam,95261000
Sweden,9967000
Iceland,337600
Israel,8622000
Hungary,9830000
Germany,82175700
Japan,126650000

```

`src/main/resources`目录中的`countries.csv`包含我们的应用中使用的数据。

`Country.java`

```java
package com.zetcode.bean;

public class Country {

    private String name;
    private int population;

    public Country() {
    }

    public Country(String name, int population) {

        this.name = name;
        this.population = population;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }
}

```

`countries.csv`文件中的字段映射到`Country`类。

`ICountryService.java`

```java
package com.zetcode.service;

import com.zetcode.bean.Country;
import java.util.ArrayList;

public interface ICountryService {

    public ArrayList<Country> findAll();
}

```

这是`ICountryService`接口。 它包含一种称为`findAll()`的方法。

`CountryService.java`

```java
package com.zetcode.service;

import com.opencsv.CSVReader;
import com.zetcode.bean.Country;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.springframework.stereotype.Service;

@Service
public class CountryService implements ICountryService {

    private final ArrayList<Country> countries;

    public CountryService() {

        countries = new ArrayList();
    }

    @Override
    public ArrayList<Country> findAll() {

        FileInputStream fis = null;

        try {

            String fileName = "src/main/resources/countries.csv";

            fis = new FileInputStream(new File(fileName));
            CSVReader reader = new CSVReader(new InputStreamReader(fis));
            String[] nextLine;
            reader.readNext();

            while ((nextLine = reader.readNext()) != null) {

                Country newCountry = new Country(nextLine[0],
                        Integer.valueOf(nextLine[1]));
                countries.add(newCountry);
            }

        } catch (FileNotFoundException ex) {
            Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                if (fis != null) {
                    fis.close();
                }
            } catch (IOException ex) {
                Logger.getLogger(CountryService.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        return countries;
    }
}

```

这是`ICountryService`契约的执行。 它包含`findAll()`方法，该方法从`countries.csv`文件中读取数据并返回`Country`对象的列表。

`MyController.java`

```java
package com.zetcode.controller;

import com.zetcode.bean.Country;
import com.zetcode.service.ICountryService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private ICountryService countryService;

    @RequestMapping("/countries")
    public List<Country> listCountries() {

        return countryService.findAll();
    }
}

```

这是 Spring Boot RESTful 应用的控制器类。 `@RestController`注解创建一个 RESTful 控制器。 传统的 MVC 控制器使用`ModelAndView`，而 RESTful 控制器仅返回对象，并且对象数据以 JSON 或 XML 格式直接写入 HTTP 响应。

```java
@Autowired
private ICountryService countryService;

```

我们将`CountryService`注入`countryService`变量中。

```java
@RequestMapping("/countries")
public List<Country> listCountries() {

    return countryService.findAll();
}

```

`@RequestMapping`注解用于将 Web 请求映射到 Spring 控制器方法。 在这里，我们将具有`/countries`路径的请求映射到控制器的`listCountries()`方法。 默认请求是 GET 请求。

我们不需要手动将`Country`域对象转换为 JSON。 因为 Jackson 2 在类路径上，所以 Spring 自动选择`MappingJackson2HttpMessageConverter`将`Country`实例转换为 JSON。

`Application.java`

```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 应用。 `@SpringBootApplication`启用自动配置和组件扫描。

```java
$ mvn package

```

使用`mvn package`命令，构建应用。

```java
$ mvn spring-boot:run

```

使用`mvn spring-boot:run`命令，运行应用。 该应用部署在嵌入式 Tomcat 服务器上。

```java
$ curl localhost:8086/rest/countries
[{"name":"Slovakia","population":5429000},{"name":"Norway","population":5271000},
{"name":"Croatia","population":4225000},{"name":"Russia","population":143439000},
{"name":"Mexico","population":122273000},{"name":"Vietnam","population":95261000},
{"name":"Sweden","population":9967000},{"name":"Iceland","population":337600},
{"name":"Israel","population":8622000},{"name":"Hungary","population":9830000},
{"name":"Germany","population":82175700},{"name":"Japan","population":126650000}]

```

使用`curl`命令，测试应用。

## 返回 XML 数据

要返回 XML 数据而不是 JSON，我们需要添加一个依赖项并修改控制器。

```java
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>      

```

我们将`jackson-dataformat-xml`添加到依赖项。

`MyController.java`

```java
package com.zetcode.controller;

import com.zetcode.bean.Country;
import com.zetcode.service.ICountryService;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MyController {

    @Autowired
    private ICountryService countryService;

    @RequestMapping(value="/countries", method=RequestMethod.GET, 
            produces=MediaType.APPLICATION_XML_VALUE)
    public List<Country> listCountries() {

        return countryService.findAll();
    }
}

```

我们选择`MediaType.APPLICATION_XML_VALUE`类型来告诉控制器返回 XML 数据。

在本教程中，我们创建了一个 Spring Boot RESTful 应用，该应用以 JSON 和 XML 返回数据。 您可能也对相关教程感兴趣： [Spring Boot H2 REST 教程](/articles/springbootresth2/)， [Spring Web 应用简介](/articles/springwebfirst/)，[独立的 Spring 应用](/articles/standalonespring/)， [OpenCSV 教程](/articles/opencsv/) ，[在经典的 Spring 应用中使用 HikariCP 连接池](/articles/hikaricp/)，[`JdbcTemplate`](/articles/springjdbctemplate/)。