基本介绍
rest的全称是Representational State Transfer。翻译过来就是表现层状态转移,是现在比较流行的一种请求方式。
在HTTP协议里面,拥有4个表示操作方式的动词。GET,POST,DELETE,PUT,这也就对应了传统的crud操作,get就是获取,post就是保存,delete就是删除,put就是更新。
快速入门
在传统中,我们要更新一个资源,往往请求格式是 /xxx/xxx/update?id=1,通过这样的方式传递过去,而使用rest风格的请求方式,就是 /xxx/xxx/1的方式来进行,要进行的操作通过method来进行说明。
下面通过一个案例来进行说明
创建BookController
@Controller
@RequestMapping("/book")
public class BookController {
@GetMapping("/{id}")
public ModelAndView get(@PathVariable("id") Integer id) {
System.out.println("get方法---id=" + id);
return success();
}
@PostMapping("/{id}")
public ModelAndView post(@PathVariable("id") Integer id) {
System.out.println("post方法---id=" + id);
return success();
}
@DeleteMapping("/{id}")
public ModelAndView delete(@PathVariable("id") Integer id) {
System.out.println("delete方法---id=" + id);
return success();
}
@PutMapping("/{id}")
public ModelAndView put(@PathVariable("id") Integer id) {
System.out.println("put方法---id=" + id);
return success();
}
public ModelAndView success() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("/WEB-INF/pages/success.jsp");
return modelAndView;
}
}
上面就是对应的4种请求方式,下面我们来以rest方式进行请求,使用postman来测试
GET方式
POST方式
可以发现get和post请求都没有问题,但是,如果我们用put或者delte请求就会出现问题
put请求
后台也拿到了数据,但是请求转发页面时报了405的错误,405解释如下
翻译过来就是目标资源不支持该请求方法
解决405错误
这个错误的原因就是jsp只支持get,post,head方式请求。所以,解决方法就简单了,直接重定向即可。我们的思路就是写一个中间handler,这个方法转发到success页面,而put和delete请求重定向到该方法即可
@DeleteMapping("/{id}")
public String delete(@PathVariable("id") Integer id, HttpServletRequest request) {
System.out.println("delete方法---id=" + id);
return "redirect:/book/temp";
}
@PutMapping("/{id}")
public String put(@PathVariable("id") Integer id, HttpServletRequest request, HttpServletResponse response) {
System.out.println("put方法---id=" + id);
return "redirect:/book/temp";
}
@RequestMapping("/temp")
public ModelAndView temp() {
return success();
}
再去使用delete的方式请求,没有问题
解决ajax不支持delete和put
我们要解决该问题可以使用spring提供的HiddenHttpMethodFilter来对post请求进行转换,将其转换为put和delte
在web.xml配置过滤器
<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>
注意:配置了这个之后还要查看我们在spring配置文件中是否开启了注解驱动
<!--开启注解驱动,支持JSR303校验,动态映射等-->
<mvc:annotation-driven/>
<!--springmvc不能处理的交由tomcat处理-->
<mvc:default-servlet-handler/>
使用_method解决put和delete问题
我们不再使用put和delete请求,而是使用post请求,携带一个_method参数,这个参数指定是put请求还是delete请求。
源码分析
下面展示部分核心代码
可以发现,post方法就是在这个过滤器这里进行了转换,看springmvc是否支持我们在_method中配置的方法
if (ALLOWED_METHODS.contains(method)) {
requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
}
ALLOWED_METHODS这个是一个成员属性,是一个集合,我们debug可以看见该集合的内容
说明支持的方法有3个,put,delete,patch。如果_method的值是这3个之一,那么就会进行转换,原理就是这样的。
总结
在这篇文章中,讲解了rest请求风格,并且解决了405的问题,通过重定向来进行解决。我们在前端使用ajax的时候,由于不支持put和delete,我们需要使用_method隐藏域来解决,同时还需要配置一个HiddenHttpMethodFilter过滤器来进行处理。