RESTful基本使用方法
传统Web应用的问题
REST与RESTful
- REST-表现层状态转换(理念),资源在网络中以某种表现形式进行状态转移(在web环境下获取img,html,js就需要以URL的形式进行展现)
- RESTful是基于REST理念的一套开发风格,是具体的开发规则(服务器端只返回数据,返回数据要求不包含于展现相关的内容)
RESTful传输数据
RESTful开发风格
- 使用URL作为用户交互入口
- 明确的语义规范(GET|POST|PUT|DELETE)(查询|新增|更新|删除)
- 只返回数据(JSON|XML),不包含任何展现
RESTful命名要求
| URI | 说明 | 修改建议 |
|---|---|---|
| GET /articles?au=lily | 正确用法 | |
| GET /a/1 | URI必须具有语义 | GET /student/1 |
| POST /createArticle/1 | URI必须使用名词 | POST /article/1 |
| GET /articles/author/1 | URI扁平化,不超两级 | GET /articles/author?id=1 |
| DELETE /articles/1 | URI名词区分单复数 | GET /articles?au=lily&DELETE /article/1 |
开发RESTful Web应用
@Controller
@RequestMapping("/restful")
public class RestfunConroller {
@GetMapping("/request")
@ResponseBody
public String doGetRequest(){
return "{\"message\":\"返回查询结果\"}";
}
@PostMapping("/request")
@ResponseBody
public String doPostRequest(){
return "{\"message\":\"数据新建成功\"}";
}
@PutMapping("/request")
@ResponseBody
public String doPutRequest(){
return "{\"message\":\"数据更新成功\"}";
}
@DeleteMapping("/request")
@ResponseBody
public String doDeleteRequest(){
return "{\"message\":\"数据删除成功\"}";
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>RESTful实验室</title>
<script src="https://afterglow.fun/jquery/jquery-3.4.1.min.js"></script>
<script>
$(function () {
$("#btnGet").click(function () {
$.ajax({
url: "/restful/request",
type: "get",
dataType: "json",
success : function (json) {
$("#messages").add(json.message);
$("#message").text(json.message);
}
})
})
})
$(function () {
$("#btnPost").click(function () {
$.ajax({
url: "/restful/request",
type: "post",
dataType: "json",
success : function (json) {
$("#messages").add(json.message);
$("#message").text(json.message);
}
})
})
})
$(function () {
$("#btnPut").click(function () {
$.ajax({
url: "/restful/request",
type: "put",
dataType: "json",
success : function (json) {
$("#messages").add(json.message);
$("#message").text(json.message);
}
})
})
})
$(function () {
$("#btnDelete").click(function () {
$.ajax({
url: "/restful/request",
type: "delete",
dataType: "json",
success : function (json) {
$("#messages").add(json.message);
$("#message").text(json.message);
}
})
})
})
</script>
</head>
<body>
<input type="button" id="btnGet" value="发送Get请求">
<input type="button" id="btnPost" value="发送Post请求">
<input type="button" id="btnPut" value="发送Put请求">
<input type="button" id="btnDelete" value="发送Delete请求">
<h1 id="message"></h1>
<h1 id="messages"></h1>
</body>
</html>
RestController注解与路径变量
// POST /restful/1
// POST /restful/100
@PostMapping("/request/{rid}")
// @ResponseBody
public String doPostRequest(@PathVariable("rid") Integer requestId){
return "{\"message\":\"数据新建成功\",\"id\":"+requestId+"}";
}
简单请求与非简单请求
- 简单请求是指标准结构的HTTP请求,对应GET/POST请求
- 非简单请求是复杂要求的HTTP请求,指PUT/DELETE、扩展标准请求
- 两者最大区别是非简单请求发送前需要发送预检请求
非简单请求
需要在web.xml中配置参数过滤器
<filter>
<filter-name>formContentFilter</filter-name>
<filter-class>org.springframework.web.filter.FormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>formContentFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
//put型复合请求
@GetMapping("/persons")
public List<Person> findByPerson(){
List list = new ArrayList();
Person person1 = new Person();
person1.setName("张三");
person1.setAge(100);
person1.setBirthady(new Date());
Person person2 = new Person();
person2.setName("李四");
person2.setAge(101);
person2.setBirthady(new Date());
list.add(person1);
list.add(person2);
return list;
}
public class Person {
private String name;
private Integer age;
//对时间进行格式化操作,调整时区
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
private Date birthady;
JSON序列化
//在pom.xml配置文件中配置jackson的相关依赖,版本一定要选择2.9以后的,在使用过程中,springmvc会自动将实体类对象转换为json数据格式返回
<dependency>
//核心包
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
//数据绑定
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
//json注解
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.9</version>
</dependency>
跨域问题
浏览器的同源策略
- 同源策略阻止从一个域加载的脚本去获取另一个域上的资源(ajax只能获取同网站、同域名下的资源,不能访问跨域名下的资源)
- 只要协议、域名、端口有任何一个不同, 都被当作是不同的域
- 浏览器Console看到Access-Control-Allow-Origin就代表跨域了
| 源URL | 目标URL | 直接访问? |
|---|---|---|
| imooc.com | xxx.com:8080/test | 不能 |
| imooc.com | imooc.com | 不能 |
| imooc.com | abc.imooc.com | 不能 |
| imooc.com | imooc.com:8080 | 不能 |
| http://localhost | http://127.0.0.1 | 不能 |
| imooc.com | imooc.com/user/test | 可以 |
HTML中允许跨域的标签
< img> - 显示远程图片 < script> - 加载远程js < link> - 加载远程csss
CORS跨域资源访问
- CORS是一-种机制使用额外的HTTP头通知浏览器可以访问其他域
- URL响应头包含Access-Control-*指明请求允许跨域
Spring MVC解决跨域访问
- @CrossOrigin - Controller跨域注解(局部注解,只在当前Controller中生效)
- mvc:cors - Spring MVC全局跨域配置
//@CrossOrigin(origins={"http://localhost:8080", "http://wWw.afterglow.fun"})
@CrossOrigin(origins = "*",maxAge = 3600)
CORS全局配置
- 在applicationContext.xml中配置
<mvc:cors>
<!-- 对应当前应用的URI地址 -->
<!-- path="/restful/**":只要是远程域名访问到了restful为前缀的URI上都会对这个策略管理 -->
<mvc:mapping path="/restful/**" allowed-origins="http://localhost:8080,http://afterglow.fun" max-age="3600"/>
</mvc:cors>