上一篇文章介绍了Spring Data REST的功能及特征,以及演示了如何在项目中引入Spring Data REST并简单地启动演示了Spring Data REST项目。在本文中,我们将深入了解Spring Data REST的特性,以此来满足我们日常api开发工作的要求。

如果仅仅是上一篇文章中对Spring Data REST的使用,那无法做到在日常开发中使用Spring Data REST,所以在上一篇文章中,我们列出了日常api开发中的一些必要功能:

需要满足的一些要求:

1.针对字段级别,方法级别,类级别进行限制(禁止某些字段,方法,接口的对外映射)。

2.对数据增删改查的限制(禁止某些请求方法的访问)。

3.能个性化定义请求的路径。

4.对所传参数进行值校验。

5.响应统一处理。

6.异常处理。

7.数据处理的切面。

➡️本文,将演示这些要求中的前三个要求。


针对接口级别,方法级别,字段级别进行访问限制

所谓的访问限制,这里我们的目的是指定某些资源不对外暴露,Spring Data REST使用注解来实现各级别的访问限制。

接口级别的访问限制:

@RepositoryRestResource(exported = false)
public interface TenantRepository extends CrudRepository<Tenant, Long> {
Page<Tenant> findAllByNameContaining(String name, Pageable page); Page<Tenant> findAllByIdCardContaining(String idCard, Pageable page); Tenant findFirstByMobile(String mobile); Tenant findFirstByIdCard(String idCard);
}

Spring Data REST中我们在接口级别增加@RepositoryRestResource(exported = false)来实现接口及接口中的所有方法不对外暴露,从而限制访问。

方法级别的访问限制:

public interface TenantRepository extends CrudRepository<Tenant, Long> {
Page<Tenant> findAllByNameContaining(String name, Pageable page); Page<Tenant> findAllByIdCardContaining(String idCard, Pageable page); Tenant findFirstByMobile(String mobile); @RestResource(exported = false)
Tenant findFirstByIdCard(String idCard);
}

上述代码中,我们使用@RestResource(exported = false)注解在指定的方法上,从而实现该方法不对外暴露。

字段级别的访问限制

@Entity
@Data
@Accessors(chain = true)
public class Tenant {
@Id
@GeneratedValue
private Long id; private String name; //隐私信息不需要暴露
@JsonIgnore
private String idCard; private String mobile; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime rentDateTime; @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
private House house; public Tenant() {
} public Tenant(String name, String idCard, String mobile, LocalDateTime rentDateTime, House hous) {
this.name = name;
this.idCard = idCard;
this.mobile = mobile;
this.rentDateTime = rentDateTime;
this.house = hous;
}
}

在上述代码中,我们在idCard字段上增加了@JsonIgnore注解,从而实现该字段不对外暴露。

如上图,我们在HAL Browser中看到,输出的租客数据中不再包含idCard字段。

使用Projections和Excerpts来实现访问限制

@Projection(name = "mobileAndName", types = {Tenant.class})
public interface TenantProjection {
String getName(); String getMobile();
}

如上,首先我们声明一个投影(Projection),在上面的投影中,我们使用指定字段的get方法来对外暴露需要暴露的字段name,mobile。

此时,我们访问HAL Browser

可以看到Spring Data REST此时提供了一个投影的链接。

此时我们查询指定租客类的投影http://localhost:8080/tenants/1?projection=mobileAndName

{
"name": "王一",
"mobile": "186****3331",
"_links": {
"self": {
"href": "http://localhost:8080/tenants/1"
},
"tenant": {
"href": "http://localhost:8080/tenants/1{?projection}",
"templated": true
}
}
}

可以看到只显示了我们投影的字段。

⚠️:我们声明的投影接口需要和数据类在同一个包中。

⚠️:否则,我们需要增加配置类,来告诉Spring Data REST投影接口的位置,如下图

@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.getProjectionConfiguration().addProjection(TenantProjection.class);
}

数据内联

有时候,我们可能需要单独对House类进行数据操作,所以我们会声明一个HouseRepository

public interface HouseRepository extends CrudRepository<House, Long> {
}

此时,我们访问某一租客数据(http://localhost:8080/tenants/1)时,

此时,house的数据就不会内联在Tenant里面。但是我们并不想要这种效果,我们希望house还是内联在Tenant中的。我们可以使用Projection来解决此问题。

@Projection(name = "NameAndHouse", types = {Tenant.class})
public interface OnlyNameProjection {
String getName(); House getHouse();
}

如上,我们声明了一个NameAndHouse投影。然后我们使用@RepositoryRestResource(excerptProjection = OnlyNameProjection.class)注解放在TenantRepository接口上。

@RepositoryRestResource(excerptProjection = OnlyNameProjection.class)
public interface TenantRepository extends CrudRepository<Tenant, Long> {
...
}

此时,我们访问NameAndHouse投影(http://localhost:8080/tenants/1?projection=NameAndHouse)

{
"name": "王一",
"house": {
"houseNumber": "1101",
"owner": "张三",
"idCard": "330521******1"
},
"_links": {
"self": {
"href": "http://localhost:8080/tenants/1"
},
"tenant": {
"href": "http://localhost:8080/tenants/1{?projection}",
"templated": true
},
"house": {
"href": "http://localhost:8080/tenants/1/house"
}
}
}

可以看到,House已经被内联进Tenant中。


对数据增删改查的限制

Spring Data REST提供了对资源请求的限制,比如对特定请求方法的限制,对特定资源访问的限制。

Repository对外暴露限制

有时候我们希望,我们在Repository中定义的某些数据操作方法不对外暴露。Spring Data REST提供了了四个级别的资源限制级别:

  • ALL:公开所有Spring Data存储库,无论其Java可见性或注释配置如何。
  • DEFAULT:公开公共Spring数据存储库或使用@RepositoryRestResource显式注释的存储库,并且其导出属性未设置为false。
  • VISIBILITY:无论注释配置如何,仅公开公共Spring Data存储库。
  • ANNOTATED:仅公开使用@RepositoryRestResource显式注释的Spring Data存储库,并且其导出属性未设置为false。

如下代码实现了ANNOTATED级别的限制:

@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) { config.setRepositoryDetectionStrategy(RepositoryDetectionStrategy.RepositoryDetectionStrategies.ANNOTATED);
}
}

增删改查限制

在RESTful中定义:

GET(GET方法返回单个实体)

PUT(PUT方法用提供的请求主体替换目标资源的状态(存在则修改,不存在则新建)。)

PATCH(PATCH方法类似于PUT方法,但是部分更新资源状态。)

DELETE(删除信息)

所以所谓的对增删改查的限制实际上就是对请求方法的限制。

如下,我们对Tenant类进行了两个操作

  1. PUT操作禁止新增,但可以修改。
  2. DELETE限制,也就是限制了删除操作。
@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
ExposureConfiguration exposureConfiguration = config.getExposureConfiguration();
exposureConfiguration.forDomainType(Tenant.class)
.disablePutForCreation()
.withItemExposure((metadata, httpMethods) -> httpMethods.disable(HttpMethod.DELETE));
}
}

如下为请求测试:

1.禁止DELETE请求

2.禁止PUT的新增操作

3.允许PUT的修改操作


个性化定义请求的路径

Spring Data REST提供了个性化请求路径的功能

自定义项目资源URI

默认情况下,项目资源的URI包含用于集合资源的路径段,并附加了数据库标识符。这样一来,您就可以使用存储库的findOne(…)方法来查找实体实例。从Spring Data REST 2.5开始,可以通过使用RepositoryRestConfiguration上的配置API(在Java 8上首选)或通过将EntityLookup的实现注册为应用程序中的Spring bean来自定义此属性。 Spring Data REST会选择它们并根据其实现来调整URI生成。

@Component
public class SpringDataRestCustomization implements RepositoryRestConfigurer {
@Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.withEntityLookup()
.forRepository(TenantRepository.class)
.withIdMapping(Tenant::getMobile)
.withLookup(TenantRepository::findFirstByMobile);
}
}

如上,我们个性化地指定了Tenant的标识符为mobile字段,此时我们可以通过HAL Browser来看到路径中的标识符变成了mobile字段。

配置REST URL路径

我们使用@RepositoryRestResource@RestResource注解直接指定资源在路径中的名字。

如下:

@RepositoryRestResource(path = "tenantPath")
public interface TenantRepository extends CrudRepository<Tenant, Long> {
@RestResource(path = "mobile")
Tenant findFirstByMobile(String mobile);
}

此时我们通过HAL Browser访问此资源:

可以看到,被我们注解的findFirstByMobile对应的资源路径已经被定制化。

另外我们看到"links"中的属性名还是findFirstByMobile,我们可以通过@RestResource(path = "mobile",rel = "mobile")来个性化指定其名字,例如此注解中,我们指定了"links"中的findFirstByMobile属性名为mobile。


总结

本文列出了接口开发常用的7个功能,并且演示如何实现针对接口级别,方法级别,字段级别进行访问限制,我们使用@RepositoryRestResource@RestResource@JsonIgnore分别实现接口,方法,字段级别的访问限制,并且我们利用了Projections和Excerpts来实现自定义数据格式。我们还是实现了对数据增删改查的限制,我们通过RepositoryDetectionStrategy的四个级别来控制数据接口的对外暴露,使用ExposureConfiguration来限制某些资源对特定请求方式的限制。最后我们使用RepositoryRestConfiguration以及@RepositoryRestResource@RestResource注解实现了个性化定义请求的路径

本文代码示例:https://gitee.com/jeker8chen/spring-data-rest-in-practice.git


关注笔者公众号,推送各类原创/优质技术文章 ⬇️

Spring Data REST不完全指南(二)的更多相关文章

  1. ElasticSearch(十二):Spring Data ElasticSearch 的使用(二)

    在前一篇博文中,创建了Spring Data Elasticsearch工程,并且进行了简单的测试,此处对Spring Data Elasticsearch进行增删改查的操作. 1.增加 在之前工程的 ...

  2. 一步步学习 Spring Data 系列之JPA(二)

    继上一篇文章对Spring Data JPA更深( )一步剖析. 上一篇只是简单的介绍了Spring Data JPA的简单使用,而往往在项目中这一点功能并不能满足我们的需求.这是当然的,在业务中查询 ...

  3. Spring Data REST不完全指南(一)

    简介 Spring Data REST是Spring Data项目的一部分,可轻松在Spring Data存储库上构建超媒体驱动的REST Web服务. Spring Data REST 构建在 Sp ...

  4. Spring Data REST不完全指南(三)

    上一篇我们介绍了使用Spring Data REST时的一些高级特性,以及使用代码演示了如何使用这些高级的特性.本文将继续讲解前面我们列出来的七个高级特性中的后四个.至此,这些特性能满足我们大部分的接 ...

  5. Spring Data 开发环境搭建(二)

    首先咱们先创建一个maven工程 在pom.xml加入以下 依赖 <!--Mysql 驱动包--> <dependency> <groupId>mysql</ ...

  6. Spring Data Elasticsearch 用户指南

    https://www.jianshu.com/p/27e1d583aafb 翻译自官方文档英文版,有删减. BioMed Central Development Team version 2.1.3 ...

  7. Spring Data(二)查询

    Spring Data(二)查询 接着上一篇,我们继续讲解Spring Data查询的策略. 查询的生成 查询的构建机制对于Spring Data的基础是非常有用的.构建的机制将截断前缀find-By ...

  8. Spring Data MongoDB 五:进阶文档查询(分页、Morphia)(二)

    Spring Data MongoDB 三:基本文档查询(Query.BasicQuery)(一) 学习MongoDB 六: MongoDB查询(游标操作.游标信息)(三) 一.简单介绍 Spring ...

  9. Spring Boot入门系列(二十六)超级简单!Spring Data JPA 的使用!

    之前介绍了Mybatis数据库ORM框架,也介绍了使用Spring Boot 的jdbcTemplate 操作数据库.其实Spring Boot 还有一个非常实用的数据操作框架:Spring Data ...

随机推荐

  1. 北邮OJ-257- 最近公共祖先-软件14 java

    思路分析:思路应该比较简单也很容易想的来,就是比较两个节点的最近的祖先节点,要对每个节点依次记录下他的所有祖先节点,包括其自己,因为自己也算自己的祖先节点,这一点题目中没有明确指出 所以比较坑. 我们 ...

  2. BFS与DFS常考算法整理

    BFS与DFS常考算法整理 Preface BFS(Breath-First Search,广度优先搜索)与DFS(Depth-First Search,深度优先搜索)是两种针对树与图数据结构的遍历或 ...

  3. K折-交叉验证

    k-折交叉验证(k-fold crossValidation):在机器学习中,将数据集A分为训练集(training set)B和测试集(test set)C,在样本量不充足的情况下,为了充分利用数据 ...

  4. OpenCV-Python 改变颜色空间 | 十三

    目标 在本教程中,你将学习如何将图像从一个色彩空间转换到另一个,像BGR↔灰色,BGR↔HSV等 除此之外,我们还将创建一个应用程序,以提取视频中的彩色对象 你将学习以下功能:cv.cvtColor, ...

  5. 全屏banner及全屏轮播

    一.全屏banner 1.设置网页图片全屏banner <!DOCTYPE html> <html lang="en"> <head> < ...

  6. 骑士cms-通读全文-代码审计

    版本号:3.5.1 下载地址:http://103.45.101.75:66/2/201412/74cms.rar 1.审计方法 通读审计 1.1查看文件结构 首先需要看看有哪些文件和文件夹,寻找名称 ...

  7. 服务器上安装.NET Framework 3.5 sp1

    操作系统是Windows Server 2008 R2 或 Windows Server 2012 或 Windows Server 2012 R2,可以直接进入“服务器管理器”添加“功能”.

  8. 汇编学习二-VB(常见函数分析)

    VB代码如下所示 push ebp 00401FF1 . 8BEC mov ebp,esp 00401FF3 . 83EC 0C sub esp,0xC push <jmp.&MSVBV ...

  9. JSP+Struts2+JDBC+Mysql实现的校园宿舍管理系统

    项目简介 项目来源于:https://gitee.com/passenger134/javaweb-sushe 本系统基于JSP+Struts2+JDBC+Mysql的校园宿舍管理系统.该系统没有使用 ...

  10. Centos下载新版内核

                                                                                              下载新版内核的安装文 ...