目录
3、PUT (HiddenHttpMethodFilter ) ★
四、@PathParam 与 @PathVariable的区别?
@PathVariable("xxx") 映射 URL 绑定的占位符('/'),绑定到xxx传参中
一般与 @GetMapping(/abc/{xxx}) 一起使用
一、Restful风格交互方式
RESTful架构,是目前非常流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,正得到越来越多网站的采用。
REST这个词,是Roy Thomas Fielding在他2000年的博士论文中提出的。他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。
REST,即Representational State Transfer的缩写,可以翻译我为“表示性的状态转移”,“表现层资源的状态转移”
Rest架构的主要原则
- 网络上的所有事物都被抽象为资源
- 每个资源都有一个唯一的资源标识符
- 同一个资源具有多种表现形式(xml,json等)
- 对资源的各种操作不会改变资源标识符
- 所有的操作都是无状态的
如果一个架构符合REST原则,就称它为RESTful架构。
含蓄、安全;风格统一;无状态;严谨、规范;简洁,优雅。
二、REST 规范的内涵
①资源
REST的名称"表现层状态转化"中,省略了主语。"表现层"其实指的是"资源"(Resources)的"表现层"。
所谓"资源",就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。你可以用一个URI(统一资源定位符)指向它,每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以,因此URI就成了每一个资源的地址或独一无二的识别符。
所谓"上网",就是与互联网上一系列的"资源"互动,调用它的URI。
②表现层(Representation)
资源是一种信息实体,它可以有多种外在表现形式。我们把"资源"具体呈现出来的形式,叫做它的"表现层"(Representation)。
比如,文本可以用txt格式表现,也可以用HTML格式、XML格式、JSON格式表现,甚至可以采用二进制格式;图片可以用JPG格式表现,也可以用PNG格式表现。
③状态转移
互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"(State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"。
客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源,PUT用来更新资源,DELETE用来删除资源。
四种请求方式对应四种常见操作 ★
操作 | 传统风格 | REST 风格 |
---|---|---|
保存 | /CRUD/saveEmp | URI 地址:/CRUD/emp 请求方式:POST |
删除 | /CRUD/removeEmp?empId=2 | URI 地址:/CRUD/emp/2 请求方式:DELETE |
更新 | /CRUD/updateEmp | URI 地址:/CRUD/emp 请求方式:PUT |
查询(表单回显) | /CRUD/findEmpById?empId=2 | URI 地址:/CRUD/emp/2 请求方式:GET |
目前主要使用HTTP协议(就是REST思想提出者Roy Thomas Fielding设计的)来实现REST思想,网络上有人从实践的角度,一句话总结REST:URI定位资源,用HTTP动词(GET,POST,DELETE,DETC) 描述操作。
三、幂等性和安全性
幂等性: 一个方法多次调用返回的效果(形式)一致,客户端可以重复调用并且期望同样的结果。 一次调用和多次调用产生的效果是一致的,都是对一个变量进行赋值。
安全性:仅指该方法的多次调用不会产生副作用,不涉及传统意义上的“安全”,这里的副作用是指资源状态。 即,安全的方法不会修改资源状态,尽管多次调用的返回值可能不一样(被其他非安全方法修改过)。
HTTP操作 | 资源操作 | 幂等性 | 安全性 |
---|---|---|---|
GET | SELECT | 是 | 是 |
POST | INSERT / SAVE | 否 | 否 |
PUT | UPDATE / EDIT | 是 | 否 |
DELETE | DELETE / REMOVE | 是 | 否 |
四、Restful请求方式映射
1、GET @PathVariable
@PathVariable("xxx") 映射 URL 绑定的占位符,绑定到xxx传参中。
一般与 @GetMapping(/abc/{xxx}) 一起使用
<h3>Restful请求映射:Get</h3>
<a th:href="@{/emp}">查询所有员工</a><br>
<a th:href="@{/emp/1}">查询指定编号的员工1</a><br>
<a th:href="@{/emp/2}">查询指定编号的员工2</a><br>
<a th:href="@{/emp/zh/300}">按照姓名和工资查询员工1</a><br>
<a th:href="@{/emp/zh/500}">按照姓名和工资查询员工2</a><br>
@Slf4j
@Controller
@RequestMapping("/emp")
public class EmployeeController {
//@RequestMapping()
@GetMapping
public String findAll(){
log.info("-- findAll --");
return "result";
}
//<a th:href="@{/emp/?}">查询指定编号的员工</a><br>
@GetMapping("/{empId}")
public String findById(@PathVariable("empId") Integer empId){
log.info("-- findById empId = "+ empId +" --");
return "result";
}
//<a th:href="@{/emp/zh/?}">按照姓名和工资查询员工</a><br>
@GetMapping("/{empName}/{sal}")
public String findEmp(@PathVariable("empName") String empName,
@PathVariable("sal") Double salary){
log.info("-- findEmp empName="+ empName +",sal="+salary+" --");
return "result";
}
2、POST
<h3>Restful请求映射:POST</h3>
<form th:action="@{/emp}" method="post">
员工姓名:<input type="text" name="empName"><br/>
员工年龄:<input type="text" name="empAge" /><br/>
员工薪资:<input type="text" name="empSalary" /><br/>
<button type="submit">保存</button>
</form>
//Pust
@PostMapping //请求路径都是/emp,但是请求方式不同,所以不会冲突
public String saveEmp(Employee employee){
log.info("-- saveEmp employee:"+employee+" --");
return "result";
}
3、PUT (HiddenHttpMethodFilter ) ★
- 要点1:原请求方式必须是 post
- 要点2:新的请求方式名称通过请求参数发送
- 要点3:请求参数名称必须是 _method (底层定义)
- 要点4:请求参数的值就是要改成的请求方式(put、delete)
- 要点5:web.xml 配置 HiddenHttpMethodFilter 过滤器 (在字符过滤器之后配置)
<h3>Restful请求映射:PUT</h3>
<form th:action="@{/emp}" method="post">
<!--重要,添加隐藏标签,指明方法-->
<input type="hidden" name="_method" value="put">
员工姓名:<input type="text" name="empName" value="zhangsan疯"><br/>
员工年龄:<input type="text" name="empAge" value="18"/><br/>
员工薪资:<input type="text" name="empSalary" value="543.21"/><br/>
<button type="submit">保存</button>
</form>
web.xml
<!-字符编码过滤器-->
...
<!--将POST请求转换为PUT、DELETE请求的过滤器
(注意写在编码过滤下面,因为内部已经开始传递表单数据,而过滤器是按照标签声明顺序执行)-->
<filter>
<filter-name>hiddenHttpMethodFiltern</filter-name><!--注意别选异步的-->
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<!--映射过滤路径-->
<filter-mapping>
<filter-name>hiddenHttpMethodFiltern</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@PutMapping
public String updateEmp(Employee employee){
log.info("-- updateEmp employee:"+employee+" --");
return "result";
}
底层:
HiddenHttpMethodFilter 必须写在 CharacterEncodingFilter 后面。已经完成数据传递,再改变原始数据没有意义。
4、DELETE ★
1、需要使用vue,通过单击事件,在一个表单中进行请求类型转换
导入Vue
<script type="text/javascript" th:src="@{/js/vue.js}"></script>
<h3>Restful请求映射:DELETE</h3>
<div id="app">
<a th:href="@{/emp/1}" @click="deleteEmp">删除编号为1的员工</a>
<a th:href="@{/emp/2}" @click.prevent="confirmDeleteEmp">删除编号为2的员工</a>
</div>
2.临时表单 (重要)
将当前超链接的 href 属性赋值给表单的action属性,表单添加_method标签进行请求类型转换,然后在vue事件内进行提交。
备用表单
<form id="form1" method="post">
<input type="hidden" name="_method" value="delete">
</form>
不需要写在vue 的el元素中
3.Vue代码
<script>
new Vue({
el:"#app",
data:{
} ,
methods:{
deleteEmp:function(event){
//获取通用表单
var formElem = document.getElementById("form1");
//修改通用表单的action为超链接的href
formElem.action = event.target.href;
//提交表单
formElem.submit();
//阻止超链接的默认行为(请求href的资源)
//event.preventDefault();
},
confirmDeleteEmp:function(event){
var flag = window.confirm("您确认要删除该员工信息吗");
if(flag){
//获取通用表单
var formElem = document.getElementById("form1");
//修改通用表单的action为超链接的href
formElem.action = event.target.href;
//提交表单
formElem.submit();
//阻止超链接的默认行为(请求href的资源)
//event.preventDefault();
}
}
}
});
</script>
4.controller控制层
@DeleteMapping("/{empId}")
public String deleteEmp(@PathVariable("empId") Integer empId,HttpServletRequest request){ // findById?empId=1
log.info("request:"+request);
log.info("method:"+ request.getMethod());//不是POST,是DELETE
log.info("-----EmployeeController deleteEmp empId:"+empId+" ------");
return "result";
}
四、@PathParam 与 @PathVariable的区别?
一般来讲的话是以两种方式为主,分别为Post和Get,这两种方式都是向一个url传参,而Get方式体现到了地址栏里,Post方式则将内容放在了 body 里面。
@PathParam 和 @PathVariable 注解是用于从 request 中接收请求的,两个都可以接收参数,关键点不同的是@PathParam 是从 request 里面拿取值,而 @PathVariable 是从一个url模板里面来填充(绑定 URL 占位符到功能处理方法的参数上,主要实现RESTFULL风格的请求),也就是从地址栏中取值(以键值对形式)。
@PathVariable
它是以“/”方式来获取参数值。
也是RSET风格的springmvc取值。
@PathVariable是获取url上数据的
@RequestParam获取请求参数的(包括post表单提交)
如果加上@ResponseBody注解???,就不会走视图解析器,不会返回页面,目前返回的json数据
如果不加@ResponseBody,就走视图解析器,返回页面