REpresentational State Transfer
中文直译是“表征状态转移”。Restful就是一个资源定位、资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
资源与操作方式:
互联网所有的事物都可以被抽象为资源,资源操作分为POST、DELETE、PUT、GET四种方法,使用不同方法对资源进行操作(增、删、改、查)GET和POST两种http方法,如下图,无疑浪费了 HTTP 协议的潜力,而 REST 则充分利用了 HTTP 规范中的方法,达到接口描述的语义化
传统非Restful风格
rest风格中,url所代表的时一类资源,比如说学生资源,但实际开发中最常见的就是我们对一类资源做增删改查操作,传统接口写法伪代码如下
@RequestMapping(value = "insertStudent")
public void insertStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs)
@RequestMapping(value = "updateStudent")
public void updateStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs)
@RequestMapping(value = "queryStudent")
public void queryStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs)
@RequestMapping(value = "queryAllStudent")
public void queryAllStudent(HttpServletRequest request, HttpServletResponse response)
@RequestMapping(value = "deleteStudent")
public void deleteStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs)
@RequestMapping(value = "deleteAllStudent")
public void deleteStudent(HttpServletRequest request, HttpServletResponse response)
这种传统模式缺点很明显这url又长又多;但事实上,一个 URL 应该用来定位资源,而不应该掺入对操作行为的描述,如果说url即定位资源又区分操作那必然会使url又长数目又多
所以标准的规则应该是
- URL 中不应该出现任何表示操作的动词,链接只用于对应资源;
- URL 中应该单复数区分,推荐的实践是永远只用复数;比如GET /api/users表示获取用户的列表;如果获取单个资源,传入 ID,比如/api/users/123表示获取单个用户的信息;
- 按照资源的逻辑层级,对 URL 进行嵌套,比如一个用户属于某个团队,而这个团队也是众多团队之一;那么获取这个用户的接口可能是这样:GET /api/teams/123/members/234 表示获取 id 为 123 的小组下,id 为234 的成员信息。
@PostMapping(value = "/student/{id}")
public void insertStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs) //需要传参表示插入学生的信息
@PutMapping(value = "/student/{id}")
public void updateStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs) //需要传参表示修改学生的信息
@GettMapping(value = "/student/{id}")
public void queryStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs) //需要传参表示查询那个学生
@GetMapping(value = student")
public void queryAllStudent(HttpServletRequest request, HttpServletResponse response) //查询全部的学生(列表)
@deleteMapping(value = "student")
public void deleteStudent(HttpServletRequest request, HttpServletResponse response,Objects ...objs)
@RequestMapping(value = "student")
public void deleteStudent(HttpServletRequest request, HttpServletResponse response)//这个是通用的,处理各种类型的request请求
规范注意点:
- URI结尾不应包含(/)
- 正斜杠分隔符(/)必须用来指示层级关系
- 应使用连字符( - )来提高URI的可读性
- 不得在URI中使用下划线(_)
- URI路径中全都使用小写字母
总结
REST 规范可以简单粗暴抽象成以下两个规则:
- 请求 API 的 URL 表示用来定位资源;
- 请求的 METHOD表示对这个资源进行的操作;最常见的四种PUT,DELETE,UPDATE,GET分别代表着增删改查,接口调用注意分为前端js请求接口和接口请求接口,请求方法在请求接口时可指定
RestFul相关问题扩展
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class RestFulController {
//映射访问路径
@RequestMapping("/commit/{p1}/{p2}")
public ModelAndView index(@PathVariable int p1, @PathVariable int p2, ModelAndView mv){
int result = p1 + p2;
//实例化一个ModelAndView对象用于向视图中传值
mv.addObject("msg","结果:" + result);
//返回视图
mv.setViewName("test");
return mv;
}
}
正常请求
异常请求
异常原因:在SpringMVC中可以使用 @PathVariable,让方法参数的值对应绑定到一个URI模板变量上,而上述接口中已经为请求路径绑定了int类型的url,但我们传入了一个String类型的变量a,所以报错状态码400,请求信息错误,更准确的说是请求参数类型错误
情况二
//在RestFulController类中增加一个方法
//映射访问路径,必须是POST请求
@RequestMapping(value = "/hello",method = {RequestMethod.POST})
public String index2(Model model){
model.addAttribute("msg", "hello!");
return "test";
}
使用POST发送请求后
会报错405,即请求的方法服务器不支持,因为我们这里已经限定是需要使用POST类型的请求方法了,这里把GET请求类型改为POST即可