文章目录
1、 RESTful概述
1.1、 什么是REST
作者:
REST 仅仅是一种架构的风格,并不是真正的架构,也不是一个软件,而是一种思想。
我们可以基于现有的HTTP、URI、XML、等现有技术来实现REST的风格。而不用去学习任何新的技术。
而学习REST的关键,不是任何的API或者实现方式,而是这种思想。
- 全新的界面设计 ,将会带来全新的写作体验;
- 在创作中心设置你喜爱的代码高亮样式,Markdown 将代码片显示选择的高亮样式 进行展示;
- 增加了 图片拖拽 功能,你可以将本地的图片直接拖拽到编辑区域直接展示;
- 全新的 KaTeX数学公式 语法;
- 增加了支持甘特图的mermaid语法1 功能;
- 增加了 多屏幕编辑 Markdown文章功能;
- 增加了 焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置 等功能,功能按钮位于编辑区域与预览区域中间;
- 增加了 检查列表 功能。
1.2、 什么是RESTful
1.3、 REST标准规范
在REST提出后,到了2008年,Java才具有了完善的官方REST式的WEB服务标准规范:JAX-RS标准:
Jersey是Java的JAX-RS标准的一种实现框架,就是一种RESTful 的框架,基于Jersey开发的WEB应用自然就是Restful的WEB服务
SpringMVC天生也是支持REST标准的。
1.3.1、 REST风格的WEB设计原则
从上面的定义中,我们可以发现REST其实是一种组织Web服务的架构风格,而并不是我们想象的那样是实现Web服务的一种新的技术,更没有要求一定要使用HTTP。其目标是为了创建具有良好扩展性的分布式系统。它提出了一系列架构级约束。这些约束有:
-
使用客户/服务器模型
客户和服务器之间通过一个统一的接口来互相通讯。 -
层次化的系统
在一个REST系统中,客户端并不会固定地与一个服务器打交道。 -
无状态
在一个REST系统中,服务端并不会保存有关客户的任何状态。也就是说,客户端自身负责用户状态的维持,并在每次发送请求时都需要提供足够的信息。
Http协议本身就是无状态的协议。 -
可缓存
REST系统需要能够恰当地缓存请求,以尽量减少服务端和客户端之间的信息传输,以提高性能。 -
统一接口
一个REST系统需要使用一个统一的接口来完成子系统之间以及服务与用户之间的交互。这使得REST系统中的各个子系统可以独自完成演化。
如果一个系统满足了上面所列出的五条约束,那么该系统就被称为是RESTful的
1.3.2、 如何统一接口规则
要实现统一接口,必须满足一下条件:
- 每个资源都拥有一个资源标识。每个资源的资源标识可以用来唯一地标明该资源REST是围绕资源为核心的,任何接口的设计都是围绕着资源进行,而不再是围绕着业务功能
- 消息的自描性
在REST系统中所传递的消息需要能够提供自身如何被处理的足够信息。例如该消息所使用的MIME类型,是否可以被缓存,返回结果包含哪些字段等 - 资源操作动作
不使用动词来描述要对资源进行的操作,那么REST中该如何表示CRUD呢?
一般我们会借助于HTTP协议中的请求方法来表明对资源的操作:
举例:
以前非REST时,我们的URI
查询用户: http://localhost/user/query?id=1 - GET
添加用户: http://localhost/user/insert - POST
修改用户: http://localhost/user/update - POST
删除用户: http://localhost/user/delete?id=1 - GET
遵循REST规范的URI定义:
查询用户: http://localhost/user/{id} - GET
添加用户: http://localhost/user - POST
修改用户: http://localhost/user - PUT
删除用户: http://localhost/user/{id} - DELETE
2、 REST最佳实践
2.1、 接口设计
REST中的最佳实践:
2.2、 响应设计
2.2.1、 响应规则
示例:
2.2.2、 响应字段
2.2.3、 响应状态码
3、 REST实现用户CRUD
3.1、 根据ID查询用户
根据REST的原则,我们查询后需要根据结果返回不同的状态码: 资源存在:200
资源不存在:404
内部异常:500 这里通过ResponseEntity来封装响应的结果,包含两部分内容:数据和状态码
- 定义Service
@Service
@Transactional
public class UserService {
@Resource
private UserMapper userMapper;
public User queryById(Long id){
return this.userMapper.selectByPrimaryKey(id);
}
}
- 定义Controller
@RestController
@RequestMapping("/hello")
public class HelloController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public ResponseEntity<User> queryById(@PathVariable("id") Long id){
try {
User user = userService.queryById(id);
return ResponseEntity.ok(user);
} catch (Exception e) {
e.printStackTrace();
// 出现异常,返回500
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
- 测试
3.2、 查询所有用户
- 定义Service
public List<User> queryAll(){
return this.userMapper.selectAll();
}
- 定义Controller
@GetMapping
public ResponseEntity<List<User>> queryAll(){
try {
List<User> userList = userService.queryAll();
return ResponseEntity.ok(userList);
} catch (Exception e) {
e.printStackTrace();
// 出现异常,返回500
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 测试
3.3、 新增用户
在原来的新增用户功能中,我们返回的结果包含了status,也就是状态,这不符合REST风格。响应状态应该包含在header中
并且新增成功,应返回201状态码
- 定义Service中的方法
public void addUser(User user){
this.userMapper.insert(user);
}
- 定义Controller中的方法
@PostMapping
public ResponseEntity<Void> addUser(@RequestBody User user){
try {
userService.addUser(user);
return new ResponseEntity<Void>(HttpStatus.CREATED);
} catch (Exception e) {
e.printStackTrace();
// 出现异常,返回500
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 测试
3.4、 修改用户
修改成功,但是没有结果返回,根据REST原则,返回204:
- 定义Service中的方法
public void updateUser(User user){
this.userMapper.updateByPrimaryKey(user);
}
- 定义Controller中的方法
@PutMapping
public ResponseEntity<Void> modifyUser(User user){
try {
userService.updateUser(user);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
// 出现异常,返回500
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 测试
3.5、 删除用户
删除成功,但是没有结果返回,根据REST原则,返回204
- 定义Service中的方法
public void deleteById(Long id){
this.userMapper.deleteByPrimaryKey(id);
}
- 定义Controller中的方法
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id){
try {
userService.deleteById(id);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
// 出现异常,返回500
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
- 测试: