RESTful

140 阅读5分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

RESTful相关介绍、RESTful在Springboot中应用、SpringData REST的使用

URI 、URN 、URL三者之间的关系是什么 ? 

URI 

统一资源标识符,服务器上每一种资源,比如文档、图像、视频片段、程序都由

一个通用资源标识符(Uniform Resource Identifier 简称URI )进行定位。

REST 产生的背景 

近年来移动互联网的发展,前端设备层出不穷(手机、平板、桌面电脑、其他专用设备)因此必须有一种统一的机制,方便不同的前端设备与后端进行通信,于是RESY诞生了,它可以通过一套统一的接口为Web、 IOS 、 Android提供服务。

什么是REST?

REST(Representational State Transfer 表述性状态转移)一词是由Roy Thomas Fielding在他2000年博士论文中提出的,定义了他对互联网软件的架构原则,所以我们可以说REST是一种架构风格。

REST的原则

  • 网络上的所有事物都被抽象为资源
  • 每个资源都有一个唯一的资源标识符
  • 同一个资源具有多种表现形式(xml json等)
  • 对资源的各种操作不会改变资源标识符
  • 所有的操作都是无状态的

什么是RESTful?

  • 遵循了rest原则的web服务,rest式的web服务是一种ROA(The Resource-Oriented Architecture :面向资源的架构),RESTful架构一个核心概念是“资源” (Resource)
  • 互联网中,客户端和服务端之间的互动传递的就只是资源的表述,我们上网的过程,就是调用资源的URI,获取它不同表现形式的过程。这种互动只能使用无状态协议HTTP,也就是说,服务端必须保存所有的状态,客户端可以使用HTTP的几个基本操作,包括GET(获取)、POST(创建)、PUT(更新) 、DELETE(删除) 使得服务端上的资源发生“状态转化” (State Transfer),也就是所谓的 “表述性状态转移”

举例

方法

URL

功能

GET

/uesrs

获取用户列表

GET

/uesrs/1

获取id为1的用户

POST

/uesrs

创建一个用户

PUT

/uesrs/1

替换id为1的用户

PATCH

/uesrs/1

修改id为1的用户

DELETE

/uesrs/1

删除id为1的用户

RESTful 的运用 

  • SpringBoot 全面支持开发RESTful程序 通过不同的注解来支持前端的请
    @GetMapping ,处理Get请求
    @PostMapping, 处理Post请求
    @PutMapping ,用于更新资源
    @DeleteMapping ,处理删除请求
    @PatchMapping ,用于更新部分资源

  • Controller中的映射注解
    @PathVariable ,用于接收url路径上的参数
    @ModelAttribute, 用于直接接受url?后面的参数 ,如url?id = 123& name = 456 ,然后直接转为Pojo

SpringBoot下进行RESTful 的开发流程图

提前准备

  • 开启热部署详见 juejin.cn/post/702400…

  • pom依赖引入

  • properties配置

    server.port=8088

    #关闭thymeleaf的缓存,避免开发过程中修改页面不生效的情况,在部署的时候可以取消 spring.thymeleaf.cache=false

    #mysql数据库连接信息 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/nicole?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true spring.datasource.username=nicole spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

    #自动生成开启,让表数据都会自动跟随entity的变化而变化 spring.jpa.properties.hibernate.hbm2ddl.auto =update #方言选择mysql spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect #开启sql打印 spring.jpa.show-sql=true #开启sql格式化 spring.jpa.properties.hibernat.format_sql=true

  • UserController.java

    //只返回数据不跳页面所以用这个注解 @RestController public class UserController { @Autowired private UsersRepository usersRepository;

    @RequestMapping(value="users",method = RequestMethod.GET)
    public List<Users> findAll(){
       return usersRepository.findAll();
    }
    @RequestMapping(value="users/{id}",method = RequestMethod.GET)
    public Users findById(@PathVariable Integer id){
        return usersRepository.findById(id).get();
    }
    @RequestMapping(value="users" ,method = RequestMethod.POST)
    public Users saveUsers(@ModelAttribute Users users){
        return usersRepository.save(users);
    }
    @RequestMapping(value="users" ,method = RequestMethod.PUT)
    public Users updateUsers(@ModelAttribute Users users){
        return usersRepository.saveAndFlush(users);
    }
    @RequestMapping(value="users/{id}",method = RequestMethod.DELETE)
    public void deleteById(@PathVariable Integer id){
         usersRepository.deleteById(id);
    }
    

    }

  • UserRepositry.java

    public interface UsersRepository extends JpaRepository<Users,Integer> { }

  • User.java   

    @Entity public class Users { private Integer id; private String username; private String password; private String name;

    @Id
    @Column(name = "id")
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    @Basic
    @Column(name = "username")
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    @Basic
    @Column(name = "password")
    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    @Basic
    @Column(name = "name")
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Users users = (Users) o;
        return Objects.equals(id, users.id) && Objects.equals(username, users.username) && Objects.equals(password, users.password) && Objects.equals(name, users.name);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(id, username, password, name);
    }
    

    }

实体的生成,用到了JPA的Persistence工具

  • 接口调用验证,这里就不一一截图啦,举个GET调用的例子 

Spring Data REST 的介绍

  • Spring Data REST 作为Spring Data 项目的子集 ,开发者只需使用注解@RepositoryRestResource标记,就可以吧整个Repository转换为HAL风格的REST资源,目前已支持Spring Data JPA、Spring Data MongoDB、Spring Data Neo4j 等等。

  • 简单点说,Spring Data REST把我们需要编写的大量REST模板接口做了自动化实现,并符合HAL的规范。

  • HAL (Hypertxt Application Language)是一个被广泛采用的超文本表达的规范。

  • 官方文档:www.springcloud.cc/spring-data…

HAL规范示例

目前github提供的api就是这种风格。在返回结果中添加额外的信息(链接)之后,服务器端提供的表达可以帮助客户端更好的发现服务器端所支持的动作。

Spring Data REST的开发流程图

REST里的常用请求

  1. GET:查询所有,根据id查询,分页查询,排序分页查询,条件查询
  2. POST:新增、修改,全局,传的参数修改,没传的置为空
  3. PUT:修改、传的参数修改,没传的置为空
  4. PATCH:修改 ,局部修改传什么改什么。
  5. DELETE:  删除

Spring Data REST的开发流程

用Spring Data REST的方式,Controller的内容不用写啦,直接在Repository上增加@RepositoryRestResource注解指定路径即可。

  • UserRepositry.java

    @RepositoryRestResource(path="users") public interface UsersRepositoryPlus extends JpaRepository<Users,Integer> { }

  • IDEA里的REST接口调用测试 

UsersRepository.java

@RepositoryRestResource(path="users")
public interface UsersRepository extends JpaRepository<Users,Integer> {
    Users findByUsername(@Param("username") String username);
}
  • 举个新增数据的例子

    Send POST request with json body

    POST http://127.0.0.1:8088/users Content-Type: application/json;charset=UTF-8

    { "id": 999, "name": "九儿", "username": "nine", "password": "123" }