REST(Representainal State Transfer)是一种 Web 软件架构风格,它是一种风格,而不是标准,匹配或兼容这种框架风格的网络服务称为 REST 服务器。REST 服务简洁并且有层次,REST 通常基于 HTTP、URI 和 XML 以及 HTML 折现现有的广泛流行的协议和标准。
在 REST 中,资源是有 URI 来指定的,对资源的增删改查操作可以通过 HTTP 协议提供的 GET、POST、PUT、DELETE 等方法实现。使用 REST 可以更高效地利用缓存来提高响应速度,同时 REST 中的通信会话状态由客户端来维护,这可以让不同的服务器来处理一系列请求中的不同请求,进而提高服务器的扩展性,在前后端分离项目中,一个设计良好的 Web 软件架构必然要满足 REST 风格。
在 Spring MVC 框架中,开发者可以通过 @RestController 注解开发一个 RESTful 服务,不过,Spring Boot 对此提供了自动化配置方案,开发者只需要添加相关依赖就能快速构建一个 RESTful 服务。
在 Spring Boot 中,使用 Spring Data JPA 和 Spring Data Rest 可以快速开发出一个 RESTful 应用。
创建 Spring Boot 项目,添加以下依赖。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-restartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.9version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
在 application.properties 中配置基本的数据库连接信息
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/jparestful
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database=mysql
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
spring.jpa.show-sql=true
@Entity(name = "t_book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String author;
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", author='" + author + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
public interface BookRepository extends JpaRepository<Book, Integer> {
}
继承 JpaRepository , JpaRepository 中默认提供了一些基本的操作方法,源码如下
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort sort);
List<T> findAllById(Iterable<ID> ids);
<S extends T> List<S> saveAll(Iterable<S> entities);
void flush();
<S extends T> S saveAndFlush(S entity);
<S extends T> List<S> saveAllAndFlush(Iterable<S> entities);
/** @deprecated */
@Deprecated
default void deleteInBatch(Iterable<T> entities) {
this.deleteAllInBatch(entities);
}
void deleteAllInBatch(Iterable<T> entities);
void deleteAllByIdInBatch(Iterable<ID> ids);
void deleteAllInBatch();
/** @deprecated */
@Deprecated
T getOne(ID id);
/** @deprecated */
@Deprecated
T getById(ID id);
T getReferenceById(ID id);
<S extends T> List<S> findAll(Example<S> example);
<S extends T> List<S> findAll(Example<S> example, Sort sort);
}
由这段源码可以看到,基本的增删改查、分页查询方法 JpaRepository 都提供了
经过如上几部,一个 RESTful 服务就构建完成了。明明什么都没写,或许这就是 Spring Boot 的魅力所在。
RESTful 的测试首先需要一个测试工具,可以直接使用浏览器中的插件,例如 Firefox 中的 RESTClient ,或者直接使用 Postman 等工具。
RESTful 服务构建成功后,默认的请求路径是实体类名小写加上后缀。
此时向数据库添加一条数据非常容易,发起一个 post 请求,请求地址为 http://localhost:8080/books

当添加成功后,服务端会返回刚刚添加成功的数据的基本信息以及浏览地址。
查询是 get 请求,http://localhost:8080/books,分页查询请求默认每页记录数是 20 条,页数为 0 (页码从 0 开始计),如果想修改请求页码和每页记录数,只需要在请求地址中携带相关参数即可,如查询第二页且一页10天记录:http://localhost:8080/books?page=1&size=10。另外默认还支持排序,例如想查询第二页数据,每页记录数为5,并且按照 id 倒序排列:http://localhost:8080/books?page=1&size=5&sort=id,desc

如果按照 id 查询,只需要在路径后追加 id 即可 http://localhost:8080/books/1

发送 PUT 请求可实现对数据的修改,对数据的修改是通过 id 进行的,因此请求路径中要有 id ,修改 id 为 1 的记录如下,http://localhost:8080/books/1

PUT 请求的返回结果就是被修改之后的记录
发送 DELETE 请求可以实现对数据的删除操作,删除id 为 1 的数据 :http://localhost:8080/books/1

DELETE 请求没有返回值,请求发送成功后 id 为 1 的数据就被删除掉了
默认情况下,请求路径都是实体类名小写加 s ,如果开发者想对请求路径进行重定义,只需要在 BookRepository 类上添加 @RepositoryRestResource 注解即可
@RepositoryRestResource(path = "bs",collectionResourceRel = "bs",itemResourceRel = "b")
public interface BookRepository extends JpaRepository<Book, Integer> {
}
@RepositoryRestResource 注解的 path 属性表示将所有请求路径中的 books 都改为 bs ,如 http://localhost:8080/bs;collectionResourceRel 属性表示将返回的 JSON 集合中 book 集合的 key 参数改为 bs;itemResourceRel 表示将返回的 JSON 集合中的单个 book 的 key 修改为 b

默认 的查询方法支持分页查询、排序查询以及按照 id 查询,如果开发者想按照某个属性查询,只需要在 BookRepository 类中定义相关方法并暴露出去即可
@RepositoryRestResource(path = "bs",collectionResourceRel = "bs",itemResourceRel = "b")
public interface BookRepository extends JpaRepository<Book, Integer> {
@RestResource(path = "author",rel = "author")
List<Book> findByAuthorContains(@Param("author") String author);
@RestResource(path = "name",rel = "name")
Book findByNameEquals(@Param("name") String name);
}
代码解释:

默认情况下,凡是继承了 Repository 接口(或者 Repository 的子类)的类都会被暴露出来,即开发者可执行基本的增删改查方法。以上面的 BookRepository 为例,如果开发者提供了 BookRepository 继承自 Repository ,就能执行对 Book 的基本操作,如果开发者继承了 Repository 但是又不想暴露相关操作,可做如下配置
@RepositoryRestResource(path = "bs",collectionResourceRel = "bs",itemResourceRel = "b")
public interface BookRepository extends JpaRepository<Book, Integer> {
@Override
@RestResource(exported = false)
void deleteById(Integer integer);
@RestResource(path = "author",rel = "author")
List<Book> findByAuthorContains(@Param("author") String author);
@RestResource(path = "name",rel = "name")
Book findByNameEquals(@Param("name") String name);
}
@RestResource 注解的 exported 属性默认为 true ,改为 false 即可。
默认的 RESTful 工程不需要开发者自己提供 Controller,因此添加在 Controller 的方法上的注解可以直接写在 BookRepository 上,如下
@CrossOrigin
@RepositoryRestResource(path = "bs",collectionResourceRel = "bs",itemResourceRel = "b")
public interface BookRepository extends JpaRepository<Book, Integer> {
@Override
@RestResource(exported = false)
void deleteById(Integer integer);
@RestResource(path = "author",rel = "author")
List<Book> findByAuthorContains(@Param("author") String author);
@RestResource(path = "name",rel = "name")
Book findByNameEquals(@Param("name") String name);
}
此时,BookRepository 中所有的方法都支持跨域。如果只需要某一个方法支持跨域,那么将 @CrossOrigin 添加到某一个方法上即可(关于 @CrossOrigin 注解的详细用法可以参照本专栏的《四、Spring Boot 整合 Web 开发》)
开发者也可以在 application.properties 中配置一些常用属性,如下
# 每页默认记录数,默认为20
spring.data.rest.default-page-size=10
# 分页查询也慢参数名,默认为page
spring.data.rest.page-param-name=page
# 分页查询记录数参数名,默认值为size
spring.data.rest.limit-param-name=size
# 分页查询排序参数名,默认值为sort
spring.data.rest.sort-param-name=sort
# 给所有请求路径都加上前缀
spring.data.rest.base-path=/api
# 添加成功时是否返回添加内容
spring.data.rest.return-body-on-create=true
# 更新成功时是否返回更新内容
spring.data.rest.return-body-on-update=true
当然,这些 XML 配置也可以配置在 Java 代码中,且代码中配置的优先级高于 application.properties 的优先级
@Configuration
public class RestConfig extends RepositoryRestConfigurerAdapter {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.setDefaultPageSize(2)
.setPageParamName("page")
.setLimitParamName("size")
.setSortParamName("sort")
.setBasePath("/api")
.setReturnBodyOnCreate(true)
.setReturnBodyOnUpdate(true);
}
}
Spring Boot 也可以结合 Spring Data MongoDB 实现快速构建 RESTful 服务
创建 Spring Boot 项目,依赖如下
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-restartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
然后在 application.properties 中配置 MongoDB 的基本连接信息
spring.data.mongodb.authentication-database=admin
spring.data.mongodb.database=test
spring.data.mongodb.username=root1
spring.data.mongodb.password=root1
spring.data.mongodb.host=ip地址
spring.data.mongodb.port=27017
public class Book {
private Integer id;
private String name;
private String author;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
public interface BookRepository extends MongoRepository<Book,Integer> {
}
如此,一个 RESTful 服务就搭建成功了。在启动项目前,记得要先启动 MongoDB 。Spring Boot 项目启动成功后,接下来的测试环节与 7.2.1 小节的第 5~8 步一致。另外,7.2.2~7.2.6 小节介绍的 Spring Data Rest 配置在这里一样适用。