一、主要特征
以资源为基础 :Rest是web服务的一种设计思想和风格,只要符合REST原则,即为RESTful。URL只指定资源,以HTTP方法动词进行不同的操作。
统一接口: 对资源的操作包括获取、创建、修改和删除,这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。换言而知,使用RESTful风格的接口但从接口上你可能只能定位其资源,但是无法知晓它具体进行了什么操作,需要具体了解其发生了什么操作动作要从其HTTP请求方法类型上进行判断。具体的HTTP方法和方法含义如下:
- GET(SELECT):从服务器取出资源(一项或多项)。
- POST(CREATE):在服务器新建一个资源。
- PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。
- PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。
- DELETE(DELETE):从服务器删除资源。
URI指向资源:URI = Universal Resource Identifier 统一资源标志符,用来标识抽象或物理资源的一个紧凑字符串。URI包括URL和URN,在这里更多时候可能代指URL(统一资源定位符)。RESTful是面向资源的,每种资源可能由一个或多个URI对应,但一个URI只指向一种资源。
无状态:服务器不能保存客户端的信息, 每一次从客户端发送的请求中,要包含所有必须的状态信息,会话信息由客户端保存, 服务器端根据这些状态信息来处理请求。 当客户端可以切换到一个新状态的时候发送请求信息, 当一个或者多个请求被发送之后, 客户端就处于一个状态变迁过程中。 每一个应用的状态描述可以被客户端用来初始化下一次的状态变迁。
二、RESTful URL设计规范
URL为统一资源定位器 ,接口属于服务端资源,首先要通过URL这个定位到资源才能去访问,而通常一个完整的URL组成由以下几个部分构成:
URI = scheme "://" host ":" port "/" path [ "?" query ][ "#" fragment ]
scheme: 指底层用的协议,如http、https、ftp
host: 服务器的IP地址或者域名
port: 端口,http默认为80端口
path: 访问资源的路径,就是各种web 框架中定义的route路由
query: 查询字符串,为发送给服务器的参数,在这里更多发送数据分页、排序等参数。
fragment: 锚点,定位到页面的资源
从大体样式了解URL路径组成之后,对于RESTful API的URL具体设计的规范如下:
- 不用大写字母,所有单词使用英文且小写。
- 连字符用中杠
"-"
而不用下杠"_"
- 正确使用
"/"
表示层级关系,URL的层级不要过深,并且越靠前的层级应该相对越稳定 - 结尾不要包含正斜杠分隔符
"/"
- URL中不出现动词,用请求方式表示动作
- 资源表示用复数不要用单数
- 不要使用文件扩展名
三、案例
对应的Mapper文件为:
package com.restfuldemo.mapper;
import com.restfuldemo.pojo.Dog;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface DogMapper {
@Select("select * from dog")
List<Dog> getAllDog();
@Select("select * from dog where id=#{id}")
Dog getDogById(@Param("id") int id);
@Insert("insert into dog (name,age) values (#{name},#{age})")
boolean addDog(Dog dog);
@Update("update dog set name=#{name},age=#{age} where id=#{id}")
boolean updateDog(Dog dog);
@Delete("delete from dog where id=#{id}")
boolean deleteDogById(int id);
}
对应controller文件为:
package com.restfuldemo.controller;
import com.restfuldemo.mapper.DogMapper;
import com.restfuldemo.pojo.Dog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RestController
public class TestController {
@Autowired(required = false)
DogMapper dogMapper;
@GetMapping("dogs")
public List<Dog> getDogs()
{
return dogMapper.getAllDog();
}
@GetMapping("dogs/{id}")
public Dog getDogById(@PathVariable("id") int id)
{
Dog dog=dogMapper.getDogById(id);
return dog;
}
@PostMapping("dogs")
public boolean addDog(Dog dog)
{
return dogMapper.addDog(dog);
}
@PutMapping("dogs/{id}")
public boolean updateDog(@PathVariable("id")int id,@RequestParam("name")String name,@RequestParam("age")int age)
{
Dog dog=dogMapper.getDogById(id);
dog.setName(name);
dog.setAge(age);
return dogMapper.updateDog(dog);
}
@DeleteMapping("dogs/{id}")
public boolean deleteDog(@PathVariable("id") int id)
{
return dogMapper.deleteDogById(id);
}
}
@RestController = @Controller + @ResponseBody
使用@Controller 注解,在对应的方法上,视图解析器可以解析return 的jsp,html页面,并且跳转到相应页面。
若返回json等内容到页面,则需要加@ResponseBody注解。
使用@RestController这个注解,返回json,视图解析器无法解析jsp,html页面。
@PathVariable(路径变量)
总结
RESTful风格的API 固然很好很规范,但大多数互联网公司并没有按照或者完全按照其规则来设计,因为REST是一种风格,而不是一种约束或规则,过于理想的RESTful API 会付出太多的成本。
比如RESTful API也有一些缺点
- 比如操作方式繁琐,RESTful API通常根据GET、POST、PUT、DELETE 来区分操作资源的动作,而HTTP Method 本身不可直接见,是隐藏的,而如果将动作放到URL的path上反而清晰可见,更利于团队的理解和交流。
- 并且有些浏览器对GET,POST之外的请求支持不太友好,还需要特殊额外的处理。
- 过分强调资源,而实际业务API可能有各种需求比较复杂,单单使用资源的增删改查可能并不能有效满足使用需求,强行使用RESTful风格API只会增加开发难度和成本。
所以,当你或你们的技术团队在设计API的时候,如果使用场景和REST风格很匹配,那么你们可以采用RESTful 风格API。但是如果业务需求和RESTful风格API不太匹配或者很麻烦,那也可以不用RESTful风格API或者可以借鉴一下,毕竟无论那种风格的API都是为了方便团队开发、协商以及管理,不能墨守成规。