SpringMVC RESTful API
# SpringMVC RESTful API
RESTful 表述性状态转移 , 是目前最流行的一种软件架构风格
REST指的是一组架构 约束条件/原则 . 不是一个标准 , 而是 设计理念/设计原则 , 使得代码 API更加简洁
# REST特性
资源(Resources) : 每个URI代表一个资源 ==PS: URI , 统一资源标志符 , 表示的是web上每一种可用的资源==
表现层(Representation) : 把资源具体呈现出来的形式 JSON/HTML
**状态转换(State Transfer) : ** 每发出一个请求 , 就代表了客户端和服务器的一次交互过程
# HTTP Method
使用 URL 表示资源时 , 每个资源都用一个独一无二的 URL 来表示 , 并使用 HTTP 方法表示操作 , 即准确描述服务器对资源的处理动作 (GET、POST、PUT、DELETE) , 实现资源的增删改查
类型 | 操作 | 返回值 | 特定返回 |
---|---|---|---|
GET | Read(获取资源) | 200(获取 列表/...) | 404(资源不存在) |
PSOT | Create(创建资源) | 201(提交/保存 ) | 404(未找到)/409(资源已存在) |
PUT | Update(更新资源) | 200(修改资源)/204(暂无内容) | 404(资源不存在)/405(禁止使用) |
PATCH | Update(更新部分资源) | 200(修改资源)/204(暂无内容) | 404(资源不存在) |
DELETE | Delete(删除资源) | 200(删除成功) | 404资源不存在/405(禁止使用) |
传统URL 与 REST风格 的URL区别
传统URL | REST风格URL | 资源操作方式 |
---|---|---|
http://localhost:8080/getUser.do?id=12 | GET : http://localhost:8080/user/12 | 获取用户信息 |
http://localhost:8080/saveUser.do | POST : http://localhost:8080/user | 新建用户信息 |
http://localhost:8080/updateUser.do?=12 | PUT : http://localhost:8080/user/12 | 更新用户信息 |
http://localhost:8080/deleteUser.do?=12 | DELETE : http://localhost:8080/user/12 | 删除用户信息 |
REST应用
**应用前提&注意 : **
- 添加 过滤器
org.springframework.web.filter.HiddenHttpMethodFilter
指定 请求 or 所有请求- PUT 和 DELETE 请求类型 需要以POST请求 添加
_method
属性 值为 指定的 请求类型
web.xml
配置过滤器 HiddenHttpMethodFilter
<!-- HiddenHttpMethodFilter过滤器可以将POST请求转化为put请求和delete请求! -->
<filter>
<filter-name>hiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
rest.jsp
页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<script src="/js/jquery-1.11.1.js"></script>
<html>
<head>
<title>REST风格</title>
</head>
<body>
<h1>REST风格 URL 测试</h1>
<h2>普通请求 测试</h2>
<h3>get请求</h3>
<a href="/rest/12">Get</a>
<h3>post请求</h3>
<form action="/rest/12" method="post">
<input type="submit" value="POST"/>
</form>
<h3>put请求</h3>
<form action="/rest/12" method="post">
<input type="hidden" name="_method" value="PUT" />
<input type="submit" value="PUT" />
</form>
<h3>delete请求</h3>
<input type="hidden" name="_method" value="DELETE"/>
<form action="/rest/12" method="post">
<input type="hidden" name="_method" value="DELETE" />
<input type="submit" value="DELETE" />
</form>
<h2>AJAX请求 测试</h2>
<form action="" id="myForm" method="post">
id: <input type="text" id="id"> <br>
name: <input type="text" id="name"> <br>
age: <input type="text" id="age"> <br>
<button type="button" id="getAjax">GET</button> <br>
<button type="button" id="postAjax">POST</button> <br>
<button type="button" id="putAjax">PUT</button> <br>
<button type="button" id="deleteAjax">DELETE</button> <br>
</form>
<script>
$(function(){
// get
$("#getAjax").click(function(){
$.ajax({
type: "GET",
url: "/rest/"+$("#id").val(),
data:"name="+$("#name").val()+"&age="+$("#age").val(),
dataType:"json",
success: function(){}
});
});
// post
$("#postAjax").click(function(){
$.ajax({
type: "POST",
url: "/rest/"+$("#id").val(),
data:{
"name":$("#name").val(),
"age":$("#age").val() },
dataType:"json",
success: function(){}
});
});
// put
$("#putAjax").click(function(){
$.ajax({
type: "POST",
url: "/rest/"+$("#id").val(),
data:{
"_method":"PUT",
"name":$("#name").val(),
"age":$("#age").val() },
dataType:"json",
success: function(){}
});
});
//delect
$("#deleteAjax").click(function(){
$.ajax({
type: "POST",
url: "/rest/"+$("#id").val(),
data:{
"_method":"DELETE",
"name":$("#name").val(),
"age":$("#age").val() },
dataType:"json",
success: function(){}
});
});
});
</script>
</body>
</html>
RestController
类 控制器
package com.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
@RequestMapping("rest")
public class RestController {
@RequestMapping("torest")
public String torest() {
return "jsp/rEST";
}
@RequestMapping(value = "{id}",method = RequestMethod.GET)
public String getTest(String name ,Integer age) {
System.out.println("get请求");
System.out.println("name : " + name);
System.out.println("age : " + age);
return "jsp/ok";
}
@RequestMapping(value = "{id}",method = RequestMethod.POST)
public String postTest(String name ,Integer age) {
System.out.println("post请求");
System.out.println("name : " + name);
System.out.println("age : " + age);
return "jsp/ok";
}
@RequestMapping(value = "{id}",method = RequestMethod.PUT)
public String putTest(String name ,Integer age) {
System.out.println("put请求");
System.out.println("name : " + name);
System.out.println("age : " + age);
return "jsp/ok";
}
@RequestMapping(value = "{id}",method = RequestMethod.DELETE)
public String deleteTest(String name ,Integer age) {
System.out.println("delete请求");
System.out.println("name : " + name);
System.out.println("age : " + age);
return "jsp/ok";
}
}
通过进入页面进行点
# HTTP 状态码
HTTP状态码是服务向用户返回状态码和提示信息 , 每次请求都会包含有 , HTTP状态码有40种 , 分为五大类 :
- 1xx : 信息 , 通信传输协议级信息
- 2xx : 成功 , 表示请求已接受
- 3xx : 重定向 , 表示执行其他操作完成其请求
- 4xx : 客户端错误 , 客户端自身问题
- 5xx : 服务器错误 , 服务器自身问题
详细了解自行百度即可
# Swagger 规范API
Swagger是个规范和完整的框架 , 用于 生成/描述/调用/可视化 API应用 , 流行的API表达工具
应用
pon.xml
<!-- Swagger API表达 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- swagger UI --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency>
添加 SwaggerConfig配置类
// Swagger 配置类 @Configuration @EnableSwagger2 // 启动Swagger2功能 public class SwaggerConfig { @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() // com包下所有API由Swagger2管理 .apis(RequestHandlerSelectors.basePackage("com")) .paths(PathSelectors.any()) .build(); } // API文档显示的信息 private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("API演示") .description("项目演示") .version("1.0") .build(); } }
Spring Boot 2.6.x版本后 与 Swagger版本冲突问题 , 需要 application.properties配置
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
Spring Boot 2.6.x版本后版本 , Swagger 版本也需要改为 3.0.0
运行访问 以下链接即可 http://localhost:8080/swagger-ui.html
Swagger常用注解
注解 | 作用范围 | 说明 |
---|---|---|
@Api | class | 控制整个类生成接口信息的内容 |
@ApiOperation | method | 对方法进行总体描述 |
@ApiParam | parameter | 对参数进行描述说明 |
@ApiImplicitParams /@ApilmplicitParam | method/@ApiImplicitParams | 对单个请求参数进行描述说明 |
@ApiResponses /@ApiResponse | method/@ApiResponse | 表示一个响应信息 , 一般用来描述错误信息 |
@ApiModel /@ApiModelProperty | property/@ApiModel | 描述一个 Model 的属性 |
# REST Q&A
# 避免多级URL
如果资源有多级分类 , 不建议写多级URL如 :
GET : /class/12/student/1002
建议=> GET : /class/12?student=1002
(查班级中指定学生)
# 传参问题
采用Restful风格 PUT 和 DELETE 请求传递参数无效 , 传递到后台的参数值为 null
封装请求说明 :
- 将请求中的数据封装成map
- request.getParameter(Key)会获取map中的值
- SpringMVC封装了POJO对象 , 但POJO会通过 request.getParameter(Key) 进行获取 , 因此 UPT 和 DELETE 请求时 request.getParameter(Key) 会拿不到
- Tomcat检测到 PUT、DELETE不会封装请求 数据map
解决方案
利用POST请求 添加 _method
属性 值为 指定的 请求类型 (PUT、DELETE、..) , 前提需要过滤器
web.xml
配置过滤器 HiddenHttpMethodFilter<!-- HiddenHttpMethodFilter过滤器可以将POST请求转化为put请求和delete请求! --> <filter> <filter-name>hiddenHttpMethodFilter</filter-name> <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class> </filter> <filter-mapping> <filter-name>hiddenHttpMethodFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
页面 请求
··· <!--form表单请求 添加隐藏 属性 _method 请求类型为 : PUT --> <form action="/rest/12" method="post"> <input type="hidden" name="_method" value="PUT" /> <input type="submit" value="PUT" /> </form> ··· <!--ajax请求 添加 属性 _method 请求类型为 : DELETE --> <button id="deleteAjax">DELETE请求</button> ··· <script> $(function(){ //delect $("#deleteAjax").click(function(){ $.ajax({ type: "POST", url: "/rest/12", data:{"_method":"DELETE"}, dataType:"json", success: function(){} }); }); }); </script>