56、springboot ------ RESTful服务及RESTful接口设计

★ RESTful服务

RESTful服务是"前后端分离"架构中的主要功能:

复制代码
后端应用对外暴露RESTful服务,前端应用则通过RESTful服务与后端应用交互。

后端应用  RESTful接口   <------------------> 前端

★ 基于JSON的RESTful服务

使用@RestController注解修饰控制器类,或使用@ResponseBody修饰处理方法即可。

@RestController和@Controller的区别就在于@RestController会自动为每个处理方法都添加@ResponseBody注解。

@RequestBody,用于修饰处理方法的参数,用于获取RESTful提交的请求数据。

复制代码
RESTful有一个约定,主要是对URL有约定

比如对于一个操作图书的RESTful接口:

GET  /books/{id} - (获取数据) 获取指定id的图书
GET  /books?参数  -(获取数据) 获取符合查询参数的图书
GET  /books        -(获取数据) 获取所有图书
POST /books        -(添加数据) 添加图书
PUT  /books/{id}    -(更新数据) 更新指定ID的图书
DELETE /books/{id}    -(删除数据) 删除指定ID的图书
DELETE /books?参数    -(删除数据) 删除符合指定参数的图书

Restful处理方法的返回值通常都应该使用HttpEntity或ResponseEntity。

复制代码
   HttpEntity    只能额外地指定响应头,不支持指定响应码。
       ↑
 ResponseEntity:  可额外指定响应的响应头、响应码(HttpStatus代表)

 ResponseEntity 继承 HttpEntity    

代码演示

总结:就只是前端用 get 、 post 、 put 、 delete 发起请求,

后端用

@GetMapping(前端获取数据)、PostMapping(前端推送数据)、

PutMapping(前端修改数据)、DeleteMapping(前端删除数据)

接收,就是 RESTful风格了。

基础数据:

1、Get 请求, 前段根据id查看图书

2、查看所有图书,前端用get请求

3、添加图书,前端用 post 请求

4、根据id更新图书信息,前端用 put 进行请求

5、根据id删除图书,前端用delete 发起请求

总结:

如图:三个方法的访问路径都是一样的,不同的只是请求的方式不同,一个是get,一个是put,一个是delete,这就是 restful 风格,项目会自动识别。

完整代码

Book

java 复制代码
@Data
public class Book
{
    private Integer id;
    private String name;
    private double price;
    private String author;

    public Book(Integer id, String name, double price, String author)
    {
        this.id = id;
        this.name = name;
        this.price = price;
        this.author = author;
    }
}

BookController

java 复制代码
package cn.ljh.app.controller;


import cn.ljh.app.domain.Book;
import cn.ljh.app.service.BookService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/*
 *     GET  /books/{id} - (获取数据) 获取指定id的图书
 *     GET  /books?参数  -(获取数据) 获取符合查询参数的图书
 *     GET  /books        -(获取数据) 获取所有图书
 *     POST /books        -(添加数据) 添加图书
 *     PUT  /books/{id}    -(更新数据) 更新指定ID的图书
 *     DELETE /books/{id}    -(删除数据) 删除指定ID的图书
 *     DELETE /books?参数    -(删除数据) 删除符合指定参数的图书
 *
 *  Restful处理方法的返回值通常都应该使用HttpEntity或ResponseEntity。
 *
 */

@RequestMapping("/books")
@RestController
public class BookController
{
    //有参构造器进行依赖注入
    private BookService bookService;

    public BookController(BookService bookService)
    {
        this.bookService = bookService;
    }


    //根据id查看图书
    @GetMapping("/{id}")
    public ResponseEntity<Book> viewBookById(@PathVariable Integer id)
    {
        Book book = bookService.getBookById(id);

        //参数1:响应数据体  参数2:需要添加的响应头,没有就给个null   参数3:响应码 , OK 代表 200
        return new ResponseEntity<>(book, null, HttpStatus.OK);
    }

    //查看所有图书
    @GetMapping("")
    public ResponseEntity<List<Book>> viewBooks()
    {
        List<Book> allBooks = bookService.getAllBooks();

        return new ResponseEntity<>(allBooks, null, HttpStatus.OK);
    }

    //添加图书
    @PostMapping("")
    public ResponseEntity<Book> addBook(@RequestBody Book book)
    {
        Book b = bookService.addOrUpdateBook(book);
        //HttpStatus.CREATED 代表返回的状态码为 201
        return new ResponseEntity<>(b, null, HttpStatus.CREATED);
    }

    //根据id更新图书信息
    @PutMapping("/{id}")
    public ResponseEntity<Book> updateBookById(@PathVariable Integer id, @RequestBody Book book)
    {
        book.setId(id);
        Book b = bookService.addOrUpdateBook(book);

        return new ResponseEntity<>(b, null, HttpStatus.OK);
    }

    //根据id删除图书
    @DeleteMapping("/{id}")
    public ResponseEntity<Book> deleteBookById(@PathVariable Integer id)
    {
        Book book = bookService.deleteBookById(id);
        return new ResponseEntity<>(book, null, HttpStatus.OK);
    }

}

BookService

java 复制代码
package cn.ljh.app.service;

import cn.ljh.app.domain.Book;

import java.util.List;

public interface BookService
{
    //根据id查看图书
    Book getBookById(Integer id);

    //查看所有图书
    List<Book> getAllBooks();

    //添加/修改图书
    Book addOrUpdateBook(Book book);

    //根据id删除图书
    Book deleteBookById(Integer id);

}

BookServiceImpl

java 复制代码
package cn.ljh.app.service.impl;

import cn.ljh.app.domain.Book;
import cn.ljh.app.service.BookService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


@Service
public class BookServiceImpl implements BookService
{
    //创建一个线程安全的map集合存数据,假设为数据库
    static Map<Integer, Book> bookDB = new ConcurrentHashMap<>();
    static int nextId = 1;

    //初始化数据库的数据
    static
    {
        bookDB.put(nextId, new Book(nextId++, "火影忍者", 120, "岸本"));
        bookDB.put(nextId, new Book(nextId++, "七龙珠", 121, "鸟山明"));
    }


    //根据id查看图书
    @Override
    public Book getBookById(Integer id)
    {
        if (id != null)
        {
            Book book = bookDB.get(id);
            if (book!=null){
                return book;
            }
        }
        throw new RuntimeException("根据id查看图书失败!");
    }

    //查看所有图书
    @Override
    public List<Book> getAllBooks()
    {
        //获取map中的所有数据
        Collection<Book> mapBooks = bookDB.values();
        //强转
        List<Book> books = new ArrayList<>(mapBooks);
        return books;
    }

    //添加/修改图书
    @Override
    public Book addOrUpdateBook(Book book)
    {
        if (book.getId() != null){
            //修改
            //map的key是唯一的,所以map里面有这个key的话,直接把原来的value覆盖掉
            bookDB.put(book.getId(),book);
            return book;
        }else {
            //新增
            //为新增的图书设置id
            book.setId(nextId);
            //book添加完之后,这个id才会自增
            bookDB.put(nextId++,book);
            return book;
        }
    }

    //根据id删除图书
    @Override
    public Book deleteBookById(Integer id)
    {
        Book book = bookDB.remove(id);
        return book;
    }
}
相关推荐
程序员阿黄22 分钟前
基于 Django 与 Vue 3 的智能实验室预约系统设计与实现
后端·python·mysql·django·vue·毕设
光影少年29 分钟前
Koa 为什么使用洋葱模型
后端·node.js·koa
用户2986985301434 分钟前
Python 如何实现 Word 与 RTF 文档互转
后端·python·api
打工仔折腾 AI38 分钟前
用 Shell 脚本自动部署 mysqld_exporter 并接入 Prometheus 远程抓取
人工智能·后端·python·性能优化·ai agent 实战
毅炼38 分钟前
不写多语言 SDK,怎么让 Python、Go、Node 服务接入注册中心?
java·后端·系统架构·gateway
Methy1 小时前
IoTHub半个月崩了五次?都是裸rethrow惹的祸
服务器·c++·后端
我不会起名字3221 小时前
一天一道力扣Hot100(36):深度优先算法---组合总和
数据结构·c++·后端·python·算法·go
回家路上绕了弯1 小时前
AI 编程助手为什么反复读取同一份上下文?如何减少无效重复
后端
Lost of 程序猿1 小时前
用 Quartz.NET 优雅地处理 .NET 定时任务:从选型到 Docker 部署全记录
后端·c#·asp.net
名字还没想好☜1 小时前
Spring Boot 优雅停机实战:等在途请求处理完再退出,配合 K8s preStop 别丢请求
java·后端·spring