User-Profile-Image
hankin
  • 5
  • Java
  • Kotlin
  • Spring
  • Web
  • SQL
  • MegaData
  • More
  • Experience
  • Enamiĝu al vi
  • 分类
    • Zuul
    • Zookeeper
    • XML
    • WebSocket
    • Web Notes
    • Web
    • Vue
    • Thymeleaf
    • SQL Server
    • SQL Notes
    • SQL
    • SpringSecurity
    • SpringMVC
    • SpringJPA
    • SpringCloud
    • SpringBoot
    • Spring Notes
    • Spring
    • Servlet
    • Ribbon
    • Redis
    • RabbitMQ
    • Python
    • PostgreSQL
    • OAuth2
    • NOSQL
    • Netty
    • MySQL
    • MyBatis
    • More
    • MinIO
    • MegaData
    • Maven
    • LoadBalancer
    • Kotlin Notes
    • Kotlin
    • Kafka
    • jQuery
    • JavaScript
    • Java Notes
    • Java
    • Hystrix
    • Git
    • Gateway
    • Freemarker
    • Feign
    • Eureka
    • ElasticSearch
    • Docker
    • Consul
    • Ajax
    • ActiveMQ
  • 页面
    • 归档
    • 摘要
    • 杂图
    • 问题随笔
  • 友链
    • Spring Cloud Alibaba
    • Spring Cloud Alibaba - 指南
    • Spring Cloud
    • Nacos
    • Docker
    • ElasticSearch
    • Kotlin中文版
    • Kotlin易百
    • KotlinWeb3
    • KotlinNhooo
    • 前端开源搜索
    • Ktorm ORM
    • Ktorm-KSP
    • Ebean ORM
    • Maven
    • 江南一点雨
    • 江南国际站
    • 设计模式
    • 熊猫大佬
    • java学习
    • kotlin函数查询
    • Istio 服务网格
    • istio
    • Ktor 异步 Web 框架
    • PostGis
    • kuangstudy
    • 源码地图
    • it教程吧
    • Arthas-JVM调优
    • Electron
    • bugstack虫洞栈
    • github大佬宝典
    • Sa-Token
    • 前端技术胖
    • bennyhuo-Kt大佬
    • Rickiyang博客
    • 李大辉大佬博客
    • KOIN
    • SQLDelight
    • Exposed-Kt-ORM
    • Javalin—Web 框架
    • http4k—HTTP包
    • 爱威尔大佬
    • 小土豆
    • 小胖哥安全框架
    • 负雪明烛刷题
    • Kotlin-FP-Arrow
    • Lua参考手册
    • 美团文章
    • Java 全栈知识体系
    • 尼恩架构师学习
    • 现代 JavaScript 教程
    • GO相关文档
    • Go学习导航
    • GoCN社区
    • GO极客兔兔-案例
    • 讯飞星火GPT
    • Hollis博客
    • PostgreSQL德哥
    • 优质博客推荐
    • 半兽人大佬
    • 系列教程
    • PostgreSQL文章
    • 云原生资料库
    • 并发博客大佬
Help?

Please contact us on our email for need any support

Support
    首页   ›   Spring   ›   Spring Notes   ›   正文
Spring Notes

Spring Data REST—两行代码搞定RESTFul(SpringBoot补充)

2020-03-25 02:11:54
1009  0 0
参考目录 隐藏
1) 什么是Spring Data REST
2) Spring Data REST本身是一个Spring MVC的应用
3) Spring MVC配置Spring Data REST
4) Spring Boot整合Spring Data REST
5) 基础配置
6) 自定义输出字段
7) 三、屏蔽自动化方法
8) 自定义查询方法
9) 模糊查询
10) 忽略大小写查询
11) 多条件查询
12) 排序

阅读完需:约 11 分钟

直接扔出中文官方文档:

https://www.springcloud.cc/spring-data-rest-zhcn.html#getting-started.boot

什么是Spring Data REST

Spring Data REST是基于Spring Data的repository之上,可以把 repository 自动输出为REST资源,目前支持Spring Data JPA、Spring Data MongoDB、Spring Data Neo4j、Spring Data GemFire、Spring Data Cassandra的 repository 自动转换成REST服务。注意是自动。简单点说,Spring Data REST把我们需要编写的大量REST模版接口做了自动化实现。

举个例子,比如你写了如下代码:

@RepositoryRestResource(path="user")
public interface UserRepository extends JpaRepository<User, Long>{  
}

自定了一个接口UserRepository 继承了JpaRepository,其中泛型中的User是实体类,Long是主键类型,在类的头部加上了一个 @RepositoryRestResource注解,并添加了一个Path为user。

两行代码即可实现User实体类的RESTFul风格的所有接口,比如发送GET请求到127.0.0.1/api/user,返回JSON格式的数据集合(注:”api”为统一前缀),并且每个Item都提供了相应的Detail URI

简单分页查询127.0.0.1:8080/api/user?page=2&size=2 

这里简单的传入了页码也页数,Spring Data REST为我们自动做了分页功能,是不是很炫?还没完,注意下半部分红框圈住的内容,这里Spring Data REST 还为我们返回了上一页,下一页,以及最后一页的URI。然而到目前为止你只写了两行代码,而且Spring Data REST的功能还不止如此,这里只是简单展现下Spring Data REST的魅力而已。

Spring Data REST本身是一个Spring MVC的应用

<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>white.yu</groupId>
    <artifactId>spring-data-rest-demo</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-data-rest-demo Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-rest-webmvc</artifactId>
            <version>2.5.6.RELEASE</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>spring-data-rest-demo</finalName>
    </build>
</project>

可以看到在Maven项目中,我们加入了Spring Data REST,从引入的Jar可以看到其依赖于Spring和Spring MVC,还可以猜测出Spring Data REST提供的REST服务默认返回的JSON格式,并且默认是用的jackSon解析。

Spring MVC配置Spring Data REST

Spring Data REST的配置定义在RepositoryRestMvcConfiguration类中,其中定义了Spring Data REST的默认配置,在Spring MVC中可以采用继承或者使用@import导入的方式导入Spring Data REST的默认配置,如果需要自定义配置,则需要实现RepositoryRestConfigurer接口 或者继承 RepositoryRestConfigurerAdapter然后重写你自己所需要的方法即可

Spring Boot整合Spring Data REST

如果你还没用过请看这篇Spring Boot环境搭建,在Spring Boot项目中,我只需要引入spring-boot-starter-data-rest的依赖,无需任何配置即可使用

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

 <!-- 引入spring data rest -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
    </dependencies>

   等等等等等等等…………………………………………………………

具体的看这里:

SpringBoot —构建 RESTful 风格应用

基础配置 

Spring Data REST的基础配置定义在RepositoryRestConfiguration(org.springframework.data.rest.core.config.RepositoryRestConfiguration)类中。

如果使用的是Spring Boot,则可以在application.properties中直接进行配置。

spring.data.rest.basePath=/api
等等等等……………………………………

还可以通过java文件来配置:

@Configuration
class CustomRestMvcConfiguration {

  @Bean
  public RepositoryRestConfigurer repositoryRestConfigurer() {

    return new RepositoryRestConfigurerAdapter() {

      @Override
      public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        configuration.setBasePath("/api")
      }
    };
  }
}

自定义输出字段

1.隐藏某个字段

public class User {

    /**
     * 指定id为主键,并设置为自增长
     */
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @GenericGenerator(name = "increment", strategy = "increment")
    private long id;
    private String name;
    @JsonIgnore
    private String password;
    private int age;
    private boolean sex;
}

比如在实体对象User中,我们不希望password 序列化未JSON,在上篇博客中说到,Spring Data REST默认使用的是JackSon,则我们就可以使用在需要隐藏的字段添加@JsonIgnore即可 

2、@Projections

@Projection(name="list",types=User.class)
public interface ListUser {
    String getName();
    long getId();
}

也可以通过@Projection注解实现1中的效果, 
请求URL为:127.0.0.1:8080/user?projection=list 
返回数据:

{
  "_embedded": {
    "users": [
      {
        "name": "小白鱼",
        "id": 1,
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/1"
          },
          "user": {
            "href": "http://127.0.0.1:8080/user/1{?projection}",
            "templated": true
          }
        }
      },
      {
        "name": "小白",
        "id": 2,
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/2"
          },
          "user": {
            "href": "http://127.0.0.1:8080/user/2{?projection}",
            "templated": true
          }
        }
      },
      {
        "name": "小 鱼 ",
        "id": 3,
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/3"
          },
          "user": {
            "href": "http://127.0.0.1:8080/user/3{?projection}",
            "templated": true
          }
        }
      },
      {
        "name": "white yu",
        "id": 4,
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/4"
          },
          "user": {
            "href": "http://127.0.0.1:8080/user/4{?projection}",
            "templated": true
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://127.0.0.1:8080/user"
    },
    "profile": {
      "href": "http://127.0.0.1:8080/profile/user"
    }
  },
  "page": {
    "size": 20,
    "totalElements": 4,
    "totalPages": 1,
    "number": 0
  }
}

@Projection还可以用来建立虚拟列

@Projection(name="virtual",types=User.class)
public interface VirtualUser {

    @Value("#{target.name} #{target.age}") 
    String getFullInfo();

}

这里把User中的name和age合并成一列,这里需要注意String getFullInfo();方法名前面一定要加get,不然无法序列化为JSON数据 
url:http://127.0.0.1:8080/user?projection=virtual
返回数据:

{
  "_embedded": {
    "users": [
      {
        "fullUser": "小白鱼 25",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/1"
          },
          "user": {
            "href": "http://127.0.0.1:8080/user/1{?projection}",
            "templated": true
          }
        }
      },
      {
        "fullUser": "小白鱼 25",
        "_links": {
          "self": {
            "href": "http://127.0.0.1:8080/user/2"
          },
          "user": {
            "href": "http://127.0.0.1:8080/user/2{?projection}",
            "templated": true
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://127.0.0.1:8080/user"
    },
    "profile": {
      "href": "http://127.0.0.1:8080/profile/user"
    }
  },
  "page": {
    "size": 20,
    "totalElements": 2,
    "totalPages": 1,
    "number": 0
  }
}

@Projection定义的数据格式还可以直接配置到Repository之上,就像下面代码中的这样

@RepositoryRestResource(path="user",excerptProjection=ListUser.class)
public interface UserRepository extends JpaRepository<User, Long>{

}

配置之后返回的JSON数据会按照ListUser定义的数据格式进行输出

三、屏蔽自动化方法

在实际生产环境中,不会轻易的删除用户数据,此时我们不希望DELETE的提交方式生效,可以添加@RestResource注解,并设置exported=false,即可屏蔽Spring Data REST的自动化方法
比如我们不想轻易的暴露按主键删除的方法,只需要写如下代码

@RepositoryRestResource(path="user",excerptProjection=ListUser.class)
public interface UserRepository extends JpaRepository<User, Long>{

    @RestResource(exported = false)
    @Override
    public void delete(Long id);
}

自定义查询方法 

通常会有这样的需求,根据给定的字段查找相应表中的数据对象。比如在前几篇博客中定义的User实体来,需要一个按照name值查到与之对应的数据对象返回,只需要在UserRopository中定义如下代码:

 /**
     * 根据用户名称查找用户
     */
    @RestResource(path="name",rel="name")
    public User findByName(@Param("name") String name);

一行非常简单的代码的代码,满足了我们的需求。我们并没有做任何实现,只是声明了一个findByName的方法而已,方法签名已经告诉Spring Data Jpa足够的信息来创建这个方法的实现了。
请求URL:http://127.0.0.1:8080/user/search/name?name=小白鱼
返回数据:

{
  "name" : "小白鱼",
  "age" : 25,
  "sex" : false,
  "_links" : {
    "self" : {
      "href" : "http://127.0.0.1:8080/user/1"
    },
    "user" : {
      "href" : "http://127.0.0.1:8080/user/1{?projection}",
      "templated" : true
    }
  }
}

当创建Repository实现的时候,Spring Data会检查Repository接口的所有方法,解析方法的名称,并基于被持久化的对象来试图推测方法的目的。本质上,Spring Data定义了一组小型的领域特定语言(domain-specific language ,DSL),在这里,持久化的细节都是通过Repository方法的签名来描述的。
Spring Data能够知道这个方法是要查找User的,因为我们使用User对JpaRepository进行了参数化。方法名findByName确定该方法需要根据name属性相匹配来查找User,而name是作为参数传递到方法中来的。

findByName()方法非常简单,但是Spring Data也能处理更加有意思的方法名称。Repository方法是由一个动词、一个可选的主题(Subject)、关键词By以及一个断言所组成。在findByName()这个样例中,动词是find,断言是name,主题并没有指定,暗含的主题是User。


Spring Data允许在方法名中使用四种动词:get、read、find和count。其中,动词get、read和find是同义的,这三个动词对应的Repository方法都会查询数据并返回对象。而动词count则会返回匹配对象的数量,而不是对象本身。
在断言中,会有一个或多个限制结果的条件。每个条件必须引用一个属性,并且还可以指定一种比较操作。如果省略比较操作符的话,那么这暗指是一种相等比较操作。不过,我们也可以选择其他的比较操作,包括如下的种类:

IsAfter、After、IsGreaterThan、GreaterThan 
IsGreaterThanEqual、GreaterThanEqual 
IsBefore、Before、IsLessThan、LessThan 
IsLessThanEqual、LessThanEqual 
IsBetween、Between 
IsNull、Null 
IsNotNull、NotNull 
IsIn、In 
IsNotIn、NotIn 
IsStartingWith、StartingWith、StartsWith 
IsEndingWith、EndingWith、EndsWith 
IsContaining、Containing、Contains 
IsLike、Like 
IsNotLike、NotLike 
IsTrue、True 
IsFalse、False 
Is、Equals 
IsNot、Not 
要对比的属性值就是方法的参数。

模糊查询

@RestResource(path="nameStartsWith",rel="nameStartsWith")
    public List<User> findByNameStartsWith(@Param("name") String name);

需求查询以name为white开始的用户,则 
查询URL为:http://127.0.0.1:8080/user/search/nameStartsWith?name=white

忽略大小写查询

要处理String类型的属性时,如果需要忽略大小写则可以在方法签名中加入IgnoringCase,这样在 
执行对比的时候就会不再考虑字符是大写还是小写。例如,要在name属性上忽略大小写,那么可以将方法签名改成如下的形式:

@RestResource(path="nameStartsWith",rel="nameStartsWith")
    public List<User> findByNameStartsWithIgnoringCase(@Param("name") String name);

多条件查询

如果需要匹配多个添加则用And和Or连接,比如:

 @RestResource(path="nameAndAge",rel="nameAndAge")
    public List<User> findByNameAndAge(@Param("name")String name ,@Param("age")int age);

排序

可以在方法名称的结尾处添加OrderBy,实现结果集排序。比如可以按照User的Age降序排列

  @RestResource(path="nameStartsWith",rel="nameStartsWith")
    public List<User> findByNameStartsWithOrderByAgeDesc(@Param("name") String name);

这里只是初步体验了所能声明的方法种类,Spring Data JPA会为我们实现这些方法。现在,我们只需知道通过使用属性名和关键字构建Repository方法签名,就能让Spring Data JPA生成方法实现,完成几乎所有能够想象到的查询。不过,Spring Data这个小型的DSL依旧有其局限性,有时候通过方法名称表达预期的查询很烦琐,甚至无法实现。如果遇到这种情形的话,Spring Data能够让我们通过@Query注解来解决问题。

如本文“对您有用”,欢迎随意打赏作者,让我们坚持创作!

0 打赏
Enamiĝu al vi
不要为明天忧虑.因为明天自有明天的忧虑.一天的难处一天当就够了。
543文章 68评论 294点赞 593811浏览

随机文章
Java8—新特性之CompletableFuture(构建异步应用)
5年前
Mybatis—手写脱敏插件
5年前
Java—Future、FutureTask、CompletionService、CompletableFuture多线程并发中归集问题的效率对比
5年前
Ajax简介和发送异步请求(四步操作)
5年前
Kotlin-类型进阶—内部类(二十三)
4年前
博客统计
  • 日志总数:543 篇
  • 评论数目:68 条
  • 建站日期:2020-03-06
  • 运行天数:1927 天
  • 标签总数:23 个
  • 最后更新:2024-12-20
Copyright © 2025 网站备案号: 浙ICP备20017730号 身体没有灵魂是死的,信心没有行为也是死的。
主页
页面
  • 归档
  • 摘要
  • 杂图
  • 问题随笔
博主
Enamiĝu al vi
Enamiĝu al vi 管理员
To be, or not to be
543 文章 68 评论 593811 浏览
测试
测试
看板娘
赞赏作者

请通过微信、支付宝 APP 扫一扫

感谢您对作者的支持!

 支付宝 微信支付