zoukankan      html  css  js  c++  java
  • Spring Data REST

    1.REST(Representational State Transfer)

    用来规范应用如何在 HTTP 层与 API 提供方进行数据交互

    REST约束

    1.客户端-服务器结构
    2.无状态
    3.可缓存
    4.分层的系统
    5.按需代码(可选)
    6.统一接口。
      该约束是 REST 服务的基础,是客户端和服务器之间的桥梁。该约束又包含下面
    4个子约束:     资源标识符。每个资源都有各自的标识符。客户端在请求时需要指定该标识符。在 REST 服务中,该标识符通常是 URI。客户端所获取的是资源的表达(representation),通常使用 XML 或 JSON 格式。     通过资源的表达来操纵资源。客户端根据所得到的资源的表达中包含的信息来了解如何操纵资源,比如对资源进行修改或删除。     自描述的消息。每条消息都包含足够的信息来描述如何处理该消息。     超媒体作为应用状态的引擎(HATEOAS)。客户端通过服务器提供的超媒体内容中动态提供的动作来进行状态转换。

    2.HATEOAS(The Hypermedia As The Engine Of Application Statue)

    是REST架构的主要约束

    REST成熟的模型

    第一个层次(Level 0)的 Web 服务只是使用 HTTP 作为传输方式,实际上只是远程方法调用(RPC)的一种具体形式。SOAP 和 XML-RPC 都属于此类。
    第二个层次(Level 1)的 Web 服务引入了资源的概念。每个资源有对应的标识符和表达。
    第三个层次(Level 2)的 Web 服务使用不同的 HTTP 方法来进行不同的操作,并且使用 HTTP 状态码来表示不同的结果。如 HTTP GET 方法来获取资源,HTTP DELETE 方法来删除资源。
    第四个层次(Level 3)的 Web 服务使用 HATEOAS。在资源的表达中包含了链接信息。客户端可以根据链接来发现可以执行的动作。

    根据REST 成熟度模型中可以看到,使用 HATEOAS 的 REST 服务是成熟度最高的,也是推荐的做法

    RESTful API最好做到Hypermedia,或HATEOAS,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么

    eg:

    { 
        "links": { 
         "self": { "href": "http://api.com/items" }, 
         "item": [ 
          { "href": "http://api.com/items/1" }, 
          { "href": "http://api.com/items/2" } 
         ] 
        "data": [ 
          {"itemName":"a"}, 
          {"itemName":"b"} 
        ] 
    } 

    3.HAL(Hypertext Application Language)

    HAL是一种简单的格式,为 API 中的资源提供简单一致的链接

    HAL可以用来实现HATEOAS

    HAL 模型包括:

    链接

    内嵌资源

    状态

     HAL专为构建API而设计,在这些API中,客户端通过以下链接在客户端中浏览资源

    4.spring-boot-starter-data-rest使用Spring Boot构建RESTful API

    Spring Data REST是基于Spring Data的repository之上,可以把 repository 自动输出为REST资源

    Spring Data REST把我们需要编写的大量REST模版接口做了自动化实现,并符合HAL的规范
    (1)添加依赖

    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-rest</artifactId>
    </dependency>

    (2)示例

    实体类User

    package com.example.demo.model;
    
    import lombok.*;
    import org.hibernate.annotations.CreationTimestamp;
    
    import javax.persistence.*;
    import java.util.Date;
    
    @Entity
    @Table(name = "users")
    @Data
    @Builder
    @ToString(callSuper = true)
    @NoArgsConstructor
    @AllArgsConstructor
    public class Users {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private int id;
        private String name;
        @Column(updatable = false)
        @CreationTimestamp
        private Date createTime;
    }
    View Code

    UsersRepository

    package com.example.demo.repository;
    
    import com.example.demo.model.Users;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @Repository
    public interface UsersRepository extends JpaRepository<Users,Integer> {
    }
    View Code

    这样就已经提供了一个关于user的rest api,简单的增、删、改、查都有了。不用写Controller,spring已经实现了

    启动项目

    GET  http://127.0.0.1:8080

    {
      "_links": {
        "userses": {
          "href": "http://127.0.0.1:8080/userses{?page,size,sort}",
          "templated": true
        },
        "profile": {
          "href": "http://127.0.0.1:8080/profile"
        }
      }
    }

    分页+排序查询

    GET  http://127.0.0.1:8080/userses?page=1&size=2&sort=createTime

    {
      "_embedded": {
        "userses": [
          {
            "name": "Nana",
            "createTime": "2020-04-07T02:10:12.469+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/userses/5"
              },
              "users": {
                "href": "http://127.0.0.1:8080/userses/5"
              }
            }
          },
          {
            "name": "xyz",
            "createTime": "2020-04-07T02:10:12.469+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/userses/3"
              },
              "users": {
                "href": "http://127.0.0.1:8080/userses/3"
              }
            }
          }
        ]
      },
      "_links": {
        "first": {
          "href": "http://127.0.0.1:8080/userses?page=0&size=2&sort=createTime,asc"
        },
        "prev": {
          "href": "http://127.0.0.1:8080/userses?page=0&size=2&sort=createTime,asc"
        },
        "self": {
          "href": "http://127.0.0.1:8080/userses"
        },
        "next": {
          "href": "http://127.0.0.1:8080/userses?page=2&size=2&sort=createTime,asc"
        },
        "last": {
          "href": "http://127.0.0.1:8080/userses?page=2&size=2&sort=createTime,asc"
        },
        "profile": {
          "href": "http://127.0.0.1:8080/profile/userses"
        }
      },
      "page": {
        "size": 2,
        "totalElements": 5,
        "totalPages": 3,
        "number": 1
      }
    }

    查询某一个

    GET  http://127.0.0.1:8080/userses/5

    {
      "name": "Nana",
      "createTime": "2020-04-07T02:10:12.469+0000",
      "_links": {
        "self": {
          "href": "http://127.0.0.1:8080/userses/5"
        },
        "users": {
          "href": "http://127.0.0.1:8080/userses/5"
        }
      }
    }

    新增

    POST  http://127.0.0.1:8080/userses

     修改

    PUT  http://127.0.0.1:8080/userses/481

     删除

    DELETE   http://127.0.0.1:8080/userses/481

    (3)其他

    注解 @RepositoryRestResource指定切入点

    eg:

      映射到 /user上

      添加自定义查询

        findByName

        findByNameContaining

    package com.example.demo.repository;
    
    import com.example.demo.model.Users;
    import org.springframework.data.jpa.repository.JpaRepository;
    import org.springframework.data.repository.query.Param;
    import org.springframework.data.rest.core.annotation.RepositoryRestResource;
    import org.springframework.stereotype.Repository;
    
    import java.util.List;
    
    @RepositoryRestResource(collectionResourceRel = "user", path = "user")
    public interface UsersRepository extends JpaRepository<Users,Integer> {
        List<Users> findByName(@Param("name") String name);
        List<Users> findByNameContaining(@Param("name") String name);
    }

    注:

      方法的定义,参数要有 @Param 注解

    重新启动项目

    GET  http://127.0.0.1:8080/user

    {
      "_embedded": {
        "user": [
          {
            "name": "Lili",
            "createTime": "2020-04-07T02:50:27.501+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/user/1"
              },
              "users": {
                "href": "http://127.0.0.1:8080/user/1"
              }
            }
          },
          {
            "name": "Fiona",
            "createTime": "2020-04-07T02:50:27.508+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/user/2"
              },
              "users": {
                "href": "http://127.0.0.1:8080/user/2"
              }
            }
          },
          {
            "name": "xyz",
            "createTime": "2020-04-07T02:50:27.508+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/user/3"
              },
              "users": {
                "href": "http://127.0.0.1:8080/user/3"
              }
            }
          }
          }
        ]
      },
      "_links": {
        "self": {
          "href": "http://127.0.0.1:8080/user{?page,size,sort}",
          "templated": true
        },
        "profile": {
          "href": "http://127.0.0.1:8080/profile/user"
        },
        "search": {
          "href": "http://127.0.0.1:8080/user/search"
        }
      },
      "page": {
        "size": 20,
        "totalElements": 5,
        "totalPages": 1,
        "number": 0
      }
    }

    GET  http://127.0.0.1:8080/user/search

    {
      "_links": {
        "findByNameContaining": {
          "href": "http://127.0.0.1:8080/user/search/findByNameContaining{?name}",
          "templated": true
        },
        "findByName": {
          "href": "http://127.0.0.1:8080/user/search/findByName{?name}",
          "templated": true
        },
        "self": {
          "href": "http://127.0.0.1:8080/user/search"
        }
      }
    }

    查询 name=xyz

    GET http://127.0.0.1:8080/user/search/findByName?name=xyz

    {
      "_embedded": {
        "user": [
          {
            "name": "xyz",
            "createTime": "2020-04-07T03:14:11.921+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/user/3"
              },
              "users": {
                "href": "http://127.0.0.1:8080/user/3"
              }
            }
          }
        ]
      },
      "_links": {
        "self": {
          "href": "http://127.0.0.1:8080/user/search/findByName?name=xyz"
        }
      }
    }

    查询 name 包含i的

    GET http://127.0.0.1:8080/user/search/findByNameContaining?name=i

    {
      "_embedded": {
        "user": [
          {
            "name": "Lili",
            "createTime": "2020-04-07T03:14:11.913+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/user/1"
              },
              "users": {
                "href": "http://127.0.0.1:8080/user/1"
              }
            }
          },
          {
            "name": "Fiona",
            "createTime": "2020-04-07T03:14:11.920+0000",
            "_links": {
              "self": {
                "href": "http://127.0.0.1:8080/user/2"
              },
              "users": {
                "href": "http://127.0.0.1:8080/user/2"
              }
            }
          }
        ]
      },
      "_links": {
        "self": {
          "href": "http://127.0.0.1:8080/user/search/findByNameContaining?name=i"
        }
      }
    }

    配置

    在application.properties 中配置

    给所有的接口添加统一的前缀

    spring.data.rest.base-path=/rest

    添加/更新成功时是否返回添加/更新记录

    spring.data.rest.return-body-on-create=true
    spring.data.rest.return-body-on-update=true

    注:

      如果为false,则返回空白

  • 相关阅读:
    Python Scrapy 爬虫入门
    Python Requests 高级用法
    Python Requests库快速入门
    linux 高并发事件触发处理 — epoll
    初识Python爬妹子图片
    android 使用gradle实现资源自动拷贝
    Android Studio Cmake使用 (附带demo)
    JNI 学习笔记
    Cmake 常见命令说明
    mybatis逆向工程生成代码
  • 原文地址:https://www.cnblogs.com/baby123/p/12652389.html
Copyright © 2011-2022 走看看