Restful API 学习
2. API
- A程序需要B程序部分,可以将B打包,给A用。日历Jar包。这种API称为API
- A需要B的部分功能,只需要B提供访问入口或者路径,则A程序按照约定就可以访问。例如 http 协议请求,这种称为应用接口
3. Web发展史
- 静态内容阶段
- CGI程序阶段
- 脚本语言阶段,JSP、PHP、ASP等。现在基本只剩PHP了。
- 瘦客户端应用阶段。MVC模式。前端后端分开的分清除
- RIA应用阶段。富客户端阶段,页面内容更丰富
- 移动Web应用阶段。
4. 前后分离
1)传统开发模式
- 一旦后端换语言了,前端也需要开发
- 前端后端严重耦合
2)前后端分离 front-end and back-end separation
separation
最大的优点是,一个后端服务器,然后前端可以随便写不同的形式 都可以进行交互
5 RESTful风格了解
前端可能是PC、小程序、IOS、安卓。要统一风格,则要遵循RESTful规范。设计接口要遵循RESTful风格。简单、易读、易用
6 RESTful 风格
1)传统代码设计风格
@Controller public class Tradition { @RequestMapping("/employee/list") public String list(Model model) { model.addAsttribute("list", employyService.list()); return "employee/list" } }
- 请求路径---见名思意
- 请求方式---传统模式会忽略
- 请求参数---按照需求决定
- 请求相应---模板路径 由需求决定
2)RESTful 风格接口设计
@Controller public class RESTful { @RequestMapping(value = "employees", method = RequestMethod.GET) @ResponseBody public List<Employee> list(Model model) { return employeeService.list(); } }
- 请求路径---以当前接口操作的资源决定,一般以资源复数形式。(每一个资源都有一个唯一资源定位符(URL))。RESTful眼中,一切皆为资源。路径就是实体对象的复数。
- 请求方式---由当前接口对资源的操作,增 POST,删 DELETE,改 PUT,查GET
GET(SELECT) , 查询
POST (CREATE), 添加
PUT (UPDATE), 所有属性更新,一般都用这个
PATCH (UPDATE), 部分
DELETE (DELETE) 删除
例如:
GET/zoos
POST/zoos
GET / zoos {id}
PUT / zoos {id}
PATCH / zoos {id}
DELETE / zoos {id}
GET / zoos {id}
- 请求参数---由需求决定
- 请求响应---一般JSON格式,也可以根据公司来设计
10. 其他
1)HTTP相应状态码
- 200 OK - [GET] :服务器成功返回请求的数据
- 201 CREATED - [Post / Put / Patch] : 用户新建或修改数据成功
- 202 Accepted - [] :表示一个请求已经进入后台排队 (异步任务)
- 204 NO CONTENT - [Delete] : 用户删除数据成功
- 400 Invalid Request - [Post / Put / Patch] : 用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的
- 401 Unauthorized- [] : 用户没有权限
- 403 Forbidden -[] : 用户有权限,但是访问被禁止
- 404 Not Found -[] : 用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的
- 406 Not Acceptable - [Get] :用户请求的资源被永久删除,且不会再得到的
- 410 Gone - [Get] :用户请求的资源被永久删除,且不会再得到的
- 422 Unprocesable entity - [Post / Put / Patch] 当创建一个对象时,发生一个验证错误
- 500 Internal Server Error - [*] 服务器错误,无法判断是否成功
2) 资源表现形式
文本可以用txt格式表现,也可以用HTML 格式,XML格式,Json 格式表现,甚至可以采用二进制格式,图片可以用JPG格式表现,也可以用Png格式表现。
具体表现形式,在请求头用Accept 和 Content -Type 字段指定,这两个字段才是对“表现”的描述
accept:application / json
content-type : application / json
Accept 与Content-Type的区别
Accept属于请求头代表希望接收的数据类型,Content-Type属于实体头,代表实际接收的数据类型
11 代码设计
在浏览器发起的请求都是GET方式
1) 获取所有员工信息
package com.wn.rest.controller; import com.wn.rest.domain.Employee; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 1) 路径 employees * 2) 方法 GET * 3) 请求参数 无 * 4)请求响应 List<Employee> json格式数据 */ @Controller public class EmployeeController { @RequestMapping(value = "/employees", method = RequestMethod.GET) @ResponseBody public List<Employee> list(){ // 查询数据库已经完成 List<Employee> res = Arrays.asList(new Employee(1, "A", 10), new Employee(2, "B", 20)); return res; } }
2) 查询单个 也可以直接把参数换成类
@RequestMapping(value = "/employees/{eid}", method = RequestMethod.GET) @ResponseBody public Employee detail(@PathVariable("eid") Long id) { // 查询数据库已经完成 return new Employee(id, "dafei", 10); }
真实开发混用参数的不同形式。核心数据用标准url写,不重要的参数用变量写。
package com.wn.rest.controller; import com.wn.rest.domain.Employee; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @Controller public class EmployeeController { /** * 1) 路径 employees * 2) 方法 GET * 3) 请求参数 无 * 4)请求响应 List<Employee> json格式数据 */ @RequestMapping(value = "/employees", method = RequestMethod.GET) @ResponseBody public List<Employee> list() { // 查询数据库已经完成 List<Employee> res = Arrays.asList(new Employee(1, "A", 10), new Employee(2, "B", 20)); return res; } @RequestMapping(value = "/employees/{eid}", method = RequestMethod.GET) @ResponseBody public Employee detail(@PathVariable("eid") Long id) { // 查询数据库已经完成 return new Employee(id, "dafei", 10); } @RequestMapping(value = "/employees", method = RequestMethod.POST) @ResponseBody public Employee save(Employee employee) { // 查询数据库已经完成 employee.setId(2); return employee; } @RequestMapping(value = "/employees", method = RequestMethod.PUT) @ResponseBody public Employee put(Employee employee) { // 查询数据库已经完成 employee.setId(3); return employee; } }
package com.wn.rest.domain; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Getter @Setter @AllArgsConstructor @NoArgsConstructor public class Employee { private long id; private String name; private int age; }
package com.wn.rest; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lagou.edu</groupId> <artifactId>com.learn.restful</artifactId> <packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>com.learn.restful Maven Webapp</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.3</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> <scope>provided</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>com.learn.restful</finalName> </build> </project>
20.页面让问restful接口
需求,页面有5个按钮,当按不同的接口,则发起不同请求
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Title</title> <script src="jquery/jquery.js"></script> <script> $(function () { $("#btn1").click(function () { $.get("/employees/1", function (data) { console.log(data) }) }) }) $(function () { $("#btn2").click(function () { $.get("/employees", function (data) { console.log(data) }) }) }) $(function () { $("#btn3").click(function () { $.ajax({ url: "/employees", type: "POST", data: {id: 1, name: "wn", age: 18}, success: function (data) { console.log(data); } }) }) }) $(function () { $("#btn4").click(function () { $.ajax({ url: "/employees", type: "PUT", data: {id: 1, name: "wn", age: 18}, success: function (data) { console.log(data); } }) }) }) </script> </head> <body> <button id="btn1">查单个</button> <button id="btn2">查多个</button> <button id="btn3">添加</button> <button id="btn4">更新</button> </body> </html>
谢谢!