REST简介
REST(Representational State Transfer)是一种Web软件架构风格,它是一种风格,而不是标准,匹配或兼容这种架构风格的网络服务称为REST服务。REST服务简洁并且有层次,REST通常基于HTTP、URI和XML以及HTML这些现有的广泛流行的协议和标准。
在REST中,资源是由URI来指定的,对资源的增删改查操作可以通过HTTP协议提供的GET、POST、PUT、DELETE等方法实现。使用REST可以更高效地利用缓存来提高响应速度,同时REST中的通信会话状态由客户端来维护,这可以让不同的服务器处理一系列请求中的不同请求,进而提高服务器的扩展性。在前后端分离项目中,一个设计良好的Web软件架构必然要满足REST风格。
在SpringMVC框架中,开发者可以通过@RestController注解开发一个RESTful服务,不过,SpringBoot对此提供了自动化配置方案,开发者只需要添加相关依赖就能快速构建一个RESTful服务。
JPA实现REST
1. 创建项目,添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
在application.yml配置:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: 123456
url: jdbc:mysql:///springboot
jpa:
hibernate:
ddl-auto: update
database: mysql
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL57Dialect
show-sql: true
2. 创建实体类:
@Entity(name = "t_book")
public class Book implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String author;
//省略getter和setter
}
3. 创建BookRepository:
继承JpaRepository,JpaRepository中默认提供了一些基本的操作方法:
public interface BookRepository extends JpaRepository<Book, Integer> {
}
4. 测试:
使用Postman工具进行测试:
- 添加数据
RESTful服务构建成功后,默认的请求路径是实体类名小写再加上后缀。
添加一条数据:发起一个post请求,请求地址为http://localhost:8080/books
当添加成功后,服务端会返回刚刚添加成功的数据的基本信息以及浏览器地址。
- 查询数据
查询是GET请求,分页查询请求路径为/books,请求url如下:
http://localhost:8080/books
分页查询请求默认每页记录是20条,页数为0(从0开始计算):
如果想要修改请求页码和每页记录数,只需要在请求地址中携带上相关参数即可,例如查询第2页数据并且每页记录数为3:
http://localhost:8080/books?page=1&size=3
如果想要排序,例如想查询第2页数据,每页记录数为3,并且按照id倒序排列,请求url如下:
http://localhost:8080/books?page=1&size=3&sort-id,desc
如果按照id查询,只需要在/books后面追加上id即可,例如查询id为1的book,如下图:
- 修改数据
发送PUT请求可以实现对数据的修改,对数据的修改是通过id进行的,因此请求路径中要有id。
例如如下请求路径表示修改id为2的记录,具体的修改内容在请求体中:
http://localhost:8080/books/2
- 删除数据
发送DELETE请求可以实现对数据的删除操作,例如删除id为1的记录,请求URL如下:
http://localhost:8080/books/1
DELETE请求没有返回值,上面这个请求发送成功后,id为1的记录就被删除了。
自定义请求路径
默认情况下,请求路径都是实体类名小写加s,如果开发者想对请求路径进行重定义,通过@RepositoryRestResource注解即可实现,下面的案例只需在BookRepository上面添加@RepositoryRestResource注解即可:
- @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> {
/*
如果不添加2RestResource 调用路径为 http://localhost:8080/bs/search/findByAuthorContains?author=鲁迅
如果需要对查询路径自定义,则加上@RestResource注解,下面的访问路径就是:http://localhost:8080/bs/search/author?author=鲁迅
*/
@RestResource(path = "author", rel = "author")
List<Book> findByAuthorContains(@Param("author") String author);
@RestResource(path = "name", rel = "name")
Book findByNameEquals(@Param("name") String name);
}
- 自定义查询只需要在BookRepository中定义相关查询方法即可,方法定义好之后可以不添加@RestResource注解,默认路径就是方法名。
- 可以直接访问http://localhost:8080/bs/search路径查看该实体类暴露出来哪些查询方法,默认情况下,在查询方法展示时使用的路径是方法名,通过@RestResource注解中的rel属性可以对这里的路径进行重定义:
隐藏方法
默认情况下,凡事继承了Repository接口的类都会被暴露出来,即开发者可执行基本的增删改查方法。
如果开发这继承了Repository但是又不想暴露相关操作,做如下配置即可:
@RepositoryRestResource(exported = false)
public interface BookRepository extends JpaRepository<Book, Integer> {}
将@RepositoryRestResource注解中的exported属性置为false之后,则上面定义的增删改查接口都会失效,BookRepository类中定义的相关方法也会失效。
若只是单纯地不想暴露某个方法,则在方法上进行配置即可,例如如果想屏蔽DELETE接口,做如下配置即可:
@RepositoryRestResource(path = "bs", collectionResourceRel = "bs", itemResourceRel = "b")
public interface BookRepository extends JpaRepository<Book, Integer> {
@Override
@RestResource(exported = false)
void deleteById(Integer integer);
}
//@RestResource注解的exported属性默认为true,将之置为false即可。
配置CORS
两种方式:
- 全局配置
- @CrossOrigin注解
全局配置在这里依然生效,但是默认的RESTful工程不需要我们自己提供Controller,所以添加在Controller的方法上的注解可以直接写在BookRepository上:
@CrossOrigin
@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);
}
此时,BookRepository中的所有方法都支持跨域。如果只需要某一个方法支持跨域,那么将@CrossOrigin注解添加到某一个方法上即可。
配置文件
可以在application.properties中配置一些常用属性:
#每页默认记录数,默认值为20
spring.data.rest.default-page-size=2
#分页查询页码参数名,默认值为page
spring.data.rest.page-param-name=page
#分页查询记录数参数名,默认值为size
spring.data.rest.limit-param-name=size
#分页查询排序参数名,默认值为sort
spring.data.rest.sort-param-name=sort
#base-path表示给所有请求路径都加上前缀
spring.data.rest.base-path=/api
#添加成功时是否返回添加内容
spring.data.rest.return-body-on-create-true
#更新成功时是否返回更新内容
spring.data.rest.return-body-on-update=true
配置类
配置类的优先级高于配置文件:
@Configuration
public class RestConfig implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.setDefaultPageSize(2)
.setPageParamName("page")
.setLimitParamName("size")
.setSortParamName("sort")
.setBasePath("/api")
.setReturnBodyOnCreate(true)
.setReturnBodyOnUpdate(true);
}
}