Rest-优雅的url 请求风格
Rest-基本介绍
- 1、REST:即Representational State Transfer。(资源)表现层状态转化。是目前流行的请求方式。它结构清晰, 很多网站采用
- 2、HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。
它们分别对应四种基本操作:
GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE 用来删除资源。
- 3、实例
传统的请求方法:
getBook?id=1 GET
delete?id=1 GET
update POST
add POST
- 4、说明: 传统的url 是通过参数来说明crud 的类型,rest 是通过get/post/put/delete 来说明crud 的类型.
REST 的核心过滤器
当前的浏览器只支持post/get 请求,因此为了得到put/delete 的请求方式需要使用Spring提供的HiddenHttpMethodFilter 过滤器进行转换.
1HiddenHttpMethodFilter:浏览器form 表单只支持GET 与POST 请求,而DELETE、PUT等method 并不支持,
Spring 添加了一个过滤器,可以将这些请求转换为标准的http 方法,使得支持GET、POST、PUT 与DELETE 请求。
2HiddenHttpMethodFilter 能对post 请求方式进行转换,因此我们需要特别的注意这一点。
3这个过滤器需要在web.xml 中配置。
Rest 风格的url-完成增删改查
Rest 应用案例-代码实现
修改web.xml 添加HiddenHttpMethodFilter
<!--配置HiddenHttpMethodFilter 1. 把 以post方式提交的delete和put请求进行转换 2. 配置url-pattern 是 /* 表示所有请求都经过 hiddenHttpMethodFilter过滤 3. 后面可以debug源码,看的很清楚 --> <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>
修改springDispatcherServlet-servlet.xml
<!-- 加入两个常规配置--> <!-- 能支持SpringMVC 高级功能,比如JSR303 校验,映射动态请求--> <mvc:annotation-driven></mvc:annotation-driven> <!-- 将SpringMVC 不能处理的请求交给Tomcat, 比如请求css,js 等--> <mvc:default-servlet-handler/>
创建springmvc\web\rest.jsp, 注意需要引入jquery, 测试的时候查询/添加/删除/修改一个一个来.
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>rest </title> <%-- 引入jquery--%> <script type="text/javascript" src="script/jquery-3.6.0.min.js"></script> <script type="text/javascript"> $(function () { //当页面加载完成后,就执行 //给删除超链接绑定一个点击事件 $("#deleteBook").click(function (){ //我们自己定义给提交的行为 $("#hiddenForm").attr("action", this.href); $(":hidden").val("DELETE"); $("#hiddenForm").submit();//这里就是提交删除请求了 //这里必须返回false,否则会提交两次 return false; //改变点击超链接的行为, 不在提交 }) }) </script> </head> <body> <h3>Rest风格的crud操作案例</h3> <br><hr> <h3>rest风格的url 查询书籍[get]</h3> <a href="user/book/200">点击查询书籍</a> <br><hr> <h3>rest风格的url 添加书籍[post]</h3> <form action="user/book" method="post"> name:<input name="bookName" type="text"><br> <input type="submit" value="添加书籍"> </form> <br><hr> <h3>rest风格的url, 删除一本书</h3> <%-- 1. 默认情况下 <a href="user/book/600">删除指定id的书</a> 是get 2. 怎么样将 get 请求转成 springmvc 可以识别的 delete 就要考虑HiddenHttpMethodFilter机制 public static final String DEFAULT_METHOD_PARAM = "_method"; --------------------------------------------------- private static final List<String> ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name())); --------------------------------------------------- if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) { String paramValue = request.getParameter(this.methodParam); if (StringUtils.hasLength(paramValue)) { String method = paramValue.toUpperCase(Locale.ENGLISH); if (ALLOWED_METHODS.contains(method)) { requestToUse = new HttpMethodRequestWrapper(request, method); } } } 3. 上面代码可以看到 HiddenHttpMethodFilter 过滤器可以对以Post方式提交的delete,put,patch进行转换,成springmvc 识别的 RequestMethod.DELETE / RequestMethod.PUT /... 4. 我们需要将 get <a href="user/book/600">删除指定id的书</a> 以post方式提交给后端handler, 这样过滤器才会生效 5. 我们可以用jquery来处理-引入jquery --%> <a href="user/book/600" id="deleteBook">删除指定id的书</a> <form action="" method="post" id="hiddenForm"> <input type="hidden" name="_method"/> </form> <br><hr> <h3>rest风格的url 修改书籍[put]~</h3> <form action="user/book/666" method="post"> <input type="hidden" name="_method" value="PUT"> <input type="submit" value="修改书籍~"> </form> </body> </html>
创建com\web\rest\BookHandler.java , 处理rest 风格的请求 ```java @RequestMapping("/user") @Controller public class BookHandler { //查询[GET] @RequestMapping(value = "/book/{id}", method = RequestMethod.GET) public String getBook(@PathVariable("id") String id) { System.out.println("查询书籍 id=" + id); return "success"; } //添加[POST] @PostMapping(value = "/book") public String addBook(String bookName) { System.out.println("添加书籍 bookName== " + bookName); return "success"; } //删除[DELETE] @RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE) public String delBook(@PathVariable("id") String id) { System.out.println("删除书籍 id= " + id); //return "success"; //[如果这样返回会报错 JSPs only permit GET POST or HEAD] //1. redirect:/user/success重定向 //2. 会被解析成 /springmvc/user/success return "redirect:/user/success"; } //如果请求是 /user/success , 就转发到 success.jsp //successGenecal对应的url http://ip:port/springmvc/user/success @RequestMapping(value = "/success") public String successGenecal() { return "success"; //由该方法 转发到success.jsp页面 } //修改[PUT] @PutMapping(value = "/book/{id}") public String updateBook(@PathVariable("id") String id) { System.out.println("修改书籍 id=" + id); return "redirect:/user/success"; } }
注意事项和细节说明
1HiddenHttpMethodFilter 在将post 转成delete / put 请求时,是按_method 参数名来读取的。
2如果web 项目是运行在Tomcat 8 及以上,会发现被过滤成DELETE 和PUT 请求,到达控制器时能顺利执行,
但是返回时(forward)会报HTTP 405 的错误提示:消息JSP 只允许GET、POST 或HEAD。
解决方式1: 使用Tomcat7
解决方式2: 将请求转发(forward)改为请求重定向(redirect):重定向到一个Handler,由Handler 转发到页面
- 3页面测试时, 如果出现点击修改书籍,仍然走的是删除url ,是因为浏览器原因(缓存等原因), 换成chrome 即可