【SpringBoot】| 接口架构风格—RESTful
目录
一:接口架构风格—RESTful
1. 认识RESTful
(1)接口
①接口: API(Application Programming Interface,应用程序接口)是一些预先定义的接口(如函数、HTTP接口),或指软件系统不同组成部分衔接的约定。 用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问源码,或理解内部工作机制的细节。
②接口(API):可以指访问servlet, controller的url, 调用其他程序的函数。
(2)架构风格
指API的组织方式(长什么样子),就是一个传统的风格:http://localhost:9002/mytrans/addStudent?name=lisi&age=26
在地址上提供了 访问的资源名称addStudent, 在其后使用了get方式传递参数。
(3)REST架构风格
REST : 是一种接口的架构风格和设计的理念,不是标准。(英文: Representational State Transfer , 中文: 表现层状态转移)
①表现层状态转移:
表现层:就是视图层, 显示资源的, 例如:jsp等显示操作资源的结果。
状态: 表示资源的变化。
转移: 资源可以变化的;资源能创建(new状态)、资源创建后可以查询资源(能看到资源的内容)、资源内容可以被修改(修改后资源 和之前的不一样)。
②REST中的要素:用REST表示资源和对资源的操作
资源使用URL表示,通过名词表示资源:
在url中,使用名词表示资源, 以及访问资源的信息,在url中,使用“ / " 分隔对资源的信息,例如: http://localhost:8080/myboot/student/1001
查询资源: 通过url找到资源。
创建资源: 添加资源。
更新资源:更新资源 ,编辑。
删除资源: 去除。
使用http中的动作(请求方式), 表示对资源的操作(CURD):
GET: 查询资源 ---> sql select
处理单个资源: 用他的单数方式
http://localhost:8080/myboot/student/1001
http://localhost:8080/myboot/student/1002
处理多个资源:使用复数形式
POST: 创建资源 ---> sql insert
http://localhost:8080/myboot/student
在post请求中传递数据
<form action="http://localhost:8080/myboot/student" method="post">
姓名:<input type="text" name="name" />
年龄:<input type="text" name="age" />
</form>
PUT:更新资源 ---> sql update
浏览器不能直接支持put,所以先成post;然后使用一个隐藏域,把post请求变成真实的put
<form action="http://localhost:8080/myboot/student/1" method="post">
姓名:<input type="text" name="name" />
年龄:<input type="text" name="age" />
<input type="hidden" name="_method" value="PUT" />
</form>
DELETE: 删除资源 ---> sql delete
<a href="http://localhost:8080/myboot/student/1">删除1的数据</a>
总结:使用url表示资源 ,使用http动作操作资源!
(4)分页
如果需要分页、排序等参数,依然是通过?的形式放在url的后面, 例如:
(5)优点
①轻量:直接基于 http,不再需要任何别的诸如消息协议。
②面向资源:一目了然,具有自解释性。
③数据描述简单:一般以 xml,json做数据交换。
④无状态:在调用一个接口(访问、操作资源)的时候,可以不用考虑上下文,不用考虑当前状态, 极大的降低了复杂度。
⑤简单、低耦合
2. RESTful 的注解
①@PathVariable,用来获取url中的数据;该注解是实现RESTFul最主要的一个注解!
②@GetMapping,接收get方式的请求;等同于@RequestMapping( method=RequestMethod.GET)。
③@PostMapping,接收和处理Post方式的请求;等同于@RequestMapping( method=RequestMethod.POST) 。
④@PutMapping,接收put方式的请求;等同于 @RequestMapping( method=RequestMethod.PUT)。
⑤@DeleteMapping,接收delete方式的请求;等同于 @RequestMapping( method=RequestMethod.DELETE)。
⑥@RestController复合注解, 是@Controller 和@ResponseBody组合;在类的上面使用@RestController , 表示当前类者的所有方法都加入了 @ResponseBody。
案例:@PathVariable注解和@GetMapping注解的联合使用(查询资源)
①在类上使用@RestController复合注解,作用时把当前类交给Spring容器管理,并且在该类下面的每个方法都默认加上@ResponseBody。
②使用GetMapping注解发送get请求,我们知道Restful风格的请求路径中是没有变量的,所以要先使用{变量名}定义路径变量,在使用路径变量@PathVariable注解引用路径变量;例如:queryStudent(@PathVariable(value = "stuId") Integer stuId),表示把路径变量传过来的值赋给stuId变量。
package com.zl.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyRestController {
@GetMapping("/student/{stuId}")
public String queryStudent(@PathVariable(value = "stuId") Integer stuId){
return "Studnet的id是:"+stuId;
}
}
执行结果:
根据url传过来的值,赋值给路径变量,路径变量在通过@PathVariable注解让我们拿到数据,进行展示。
案例:@PathVariable注解和@PostMapping注解的联合使用(创建资源)
addStudent.html表单页面(属于静态资源放到static目录下),在post请求中传递数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>添加学生</h3>
<form action="student/zhangsan/18" method="post">
<input type="submit" value="注册学生">
</form>
</body>
</html>
接收数据
// 创建资源
@PostMapping("/student/{name}/{age}")
public String createStudent(@PathVariable("name") String name,
@PathVariable("age") Integer age){
return "创建资源Student"+name+"="+age;
}
执行结果:
案例:对于Post、Put、Delete都需要编写一个表单页面,比较麻烦,并且对于put和delete请求浏览器是不支持的;可以借助一个Postman工具
注:当路径变量名和形参名保持一致,@PathVariable中的value可以省略。
Postman测试工具:可以测试 get ,post , put ,delete 等请求
// 更新资源
@PutMapping("/student/{id}/{age}")
public String modifyStudent(@PathVariable Integer id,
@PathVariable Integer age){
return "更新资源Student:"+id+"="+age;
}
// 删除资源
@DeleteMapping("/student/{id}")
public String removeStudentById(@PathVariable Integer id){
return "删除资源Student:"+id;
}
执行结果:省去写表单页面了
案例:使用HiddenHttpMethodFilter过滤器,将post请求转为put ,delete
在SpringMVC中 有一个过滤器org.springframework.web.filter.HiddenHttpMethodFilter。
作用: 把请求中的post请求转为 put , delete。
第一步:在application.properties(yml) : 开启使用HiddenHttpMethodFilter过滤器
源码分析发现在SpringBoot中默认是把这个组件已经配置好的,但是默认是关闭的,要想生效必须手动设置生效。
package org.springframework.boot.autoconfigure.web.servlet;
public class WebMvcAutoConfiguration {
@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled")
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
return new OrderedHiddenHttpMethodFilter();
}
}
设置为true
#启用过滤器
spring.mvc.hiddenmethod.filter.enabled=true
第二步:在请求页面中,发出post请求;type类型使用隐藏域hidden,name参数是 _method, value对应着我们真正的请求方式put、delete
form表单页面,实际上真正发出的是put请求!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="student/test" method="post" >
<!--指定真正的请求方式-->
<input type="hidden" name="_method" value="put">
<input type="submit" value="测试" />
</form>
</body>
</html>
扩展:当前也可以把_method参数设置为自定义参数
通过前面的源码分析,如果没有自定义HiddenHttpMethodFilter,容器会帮我们自定义一个纳入容器管理,此时使用的默认参数就是_method!
所以就可以自己创建一个HiddenHttpMethodFilter,调用setMethodParam方法自己定义
package com.zl.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.HiddenHttpMethodFilter;
@Configuration(proxyBeanMethods = false)
public class MyConfig {
// 自定义Filter,纳入容器管理
@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter(){
HiddenHttpMethodFilter methodFilter = new HiddenHttpMethodFilter();
// 设置method参数为_m
methodFilter.setMethodParam("_m");
return methodFilter;
}
}
问题:请求路径冲突
例如:以下两个请求,使用get请求,资源名也相同,携带的数据类型也相同;我们直接进行访问:http://localhost:8081/student/1;此时就会有路径冲突,导致访问失败!
解决:设计路径,必须唯一, 路径uri和请求方式必须唯一!
@GetMapping("/student/{id}")
@GetMapping("/student/{age}")