★ 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;
}
}