Spring MVC 中使用 RESTFul 编程风格

圆咕噜咕噜  金牌会员 | 2024-7-4 21:23:02 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 903|帖子 903|积分 2709

1. Spring MVC 中使用  RESTFul 编程风格

@
目录

2. RESTFul 编程风格

2.1 RESTFul 是什么

RESTFul 是 web 服务器接口 的一种计划风格。
RESTFul 定义了一组束缚条件和规范,可以让 web服务器接口 更加简洁,易于理解,易于扩展,安全可靠。
RESTFUl 对一个 web 服务器接口 都规定了哪些东西 ?

  • 对请求的 URL 格式有束缚和规范
  • 对 HTTP 的请求方式有束缚和规范
  • 对请求和响应的数据格式有束缚和规范
  • 对 HTTP 状态码有束缚和规范
  • 等......
REST 对请求方式的束缚是如许的:

  • 查询必须发送 GET 请求
  • 新增必须发送 POST 请求
  • 修改必须发送 PUT 请求
  • 删除必须发送 DELETE 请求
REST对 URL 的束缚时如许的:

  • 传统的 URL : get 请求,/springmvc/getUserById?id=1
  • REST风格的 URL:get 请求,/springmvc/user/1
  • 传统的URL :get 请求,/springmvc/deleteUserById?id=1
  • REST风格的URL:delete 请求,/springmvc/user/1
RESTFul 对 URL 的束缚和规范的焦点时:通过采用 :不同的请求方式   + URL 来确定 web 服务中的资源。
RESTFul 的英文全称时:Representational State Transfer(表述性状态转移),简称 REST。
表述性(Representational) 是:URL + 请求方式。
状态(State) 是 :服务器端的数据。
转移(Transfer) 是:变化。
表述性转移是指:通过 URL + 请求方式来控制服务器端数据的变化。
2.2 RESTFul风格与传统方式对比

统的 URL 与 RESTful URL 的区别是传统的 URL 是基于方法名举行资源访问和操纵,而 RESTful URL 是基于资源的结构和状态举行操纵的。下面是一张表格,展示两者之间的具体区别:
传统的 URLRESTful URLGET /getUserById?id=1GET /user/1GET /getAllUserGET /userPOST /addUserPOST /userPOST /modifyUserPUT /userGET /deleteUserById?id=1DELETE /user/1从上表中我们可以看出,传统的 URL是基于动作的,而 RESTful URL 是基于资源和状态的,因此 RESTful URL 更加清楚和易于理解,这也是 REST 架构风格被广泛使用的重要原因之一。
3. Spring MVC 中使用  RESTFul 编程风格(增删改查)的使用

3.1 预备工作

导入相干依赖 jar 包。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5.     <modelVersion>4.0.0</modelVersion>
  6.     <groupId>com.rainbowsea</groupId>
  7.     <artifactId>springmvc-007</artifactId>
  8.     <version>1.0-SNAPSHOT</version>
  9.     <packaging>war</packaging>
  10.     <properties>
  11.         <maven.compiler.source>17</maven.compiler.source>
  12.         <maven.compiler.target>17</maven.compiler.target>
  13.     </properties>
  14.     <dependencies>
  15.         
  16.         <dependency>
  17.             <groupId>org.springframework</groupId>
  18.             <artifactId>spring-webmvc</artifactId>
  19.             <version>6.1.4</version>
  20.         </dependency>
  21.         
  22.         <dependency>
  23.             <groupId>ch.qos.logback</groupId>
  24.             <artifactId>logback-classic</artifactId>
  25.             <version>1.5.3</version>
  26.         </dependency>
  27.         
  28.         <dependency>
  29.             <groupId>jakarta.servlet</groupId>
  30.             <artifactId>jakarta.servlet-api</artifactId>
  31.             <version>6.0.0</version>
  32.             <scope>provided</scope>
  33.         </dependency>
  34.         
  35.         <dependency>
  36.             <groupId>org.thymeleaf</groupId>
  37.             <artifactId>thymeleaf-spring6</artifactId>
  38.             <version>3.1.2.RELEASE</version>
  39.         </dependency>
  40.     </dependencies>
  41. </project>
复制代码
相干包 / 目录的创建,配置。

springmvc.xml 配置文件的配置;
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.        xmlns:context="http://www.springframework.org/schema/context"
  5.        xmlns:mvc="http://www.springframework.org/schema/mvc"
  6.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
  7.    
  8.     <context:component-scan base-package="com.rainbowsea.springmvc.controller"></context:component-scan>
  9.    
  10.     <bean id="thymeleafViewResolver" >
  11.         
  12.         <property name="characterEncoding" value="UTF-8"/>
  13.         
  14.         <property name="order" value="1"/>
  15.         
  16.         <property name="templateEngine">
  17.             <bean >
  18.                
  19.                 <property name="templateResolver">
  20.                     <bean >
  21.                         
  22.                         <property name="prefix" value="/WEB-INF/templates/"/>
  23.                         
  24.                         <property name="suffix" value=".html"/>
  25.                         
  26.                         <property name="templateMode" value="HTML"/>
  27.                         
  28.                         <property name="characterEncoding" value="UTF-8"/>
  29.                     </bean>
  30.                 </property>
  31.             </bean>
  32.         </property>
  33.     </bean>
  34.    
  35.     <mvc:annotation-driven></mvc:annotation-driven>
  36.    
  37.     <mvc:view-controller path="/" view-name="index"></mvc:view-controller>
  38. </beans>
复制代码
3.2 RESTFul 风格的 “查询” 所有(RESTFul 规范 需要发送 GET请求)

RESTFul 规范中规定,如果要查询数据,需要发送 GET 请求。
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6. </head>
  7. <body>
  8. <h1>测试 RESTFul 编程风格</h1>
  9. <hr>
  10. <a th:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
  11. </body>
  12. </html>
复制代码
控制器 Controller:
  1. import com.rainbowsea.springmvc.bean.User;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.PathVariable;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestMethod;
  6. @Controller  // 交给 Spring IOC 容器进行管理
  7. public class UserController {
  8.     @RequestMapping(value = "/user", method = RequestMethod.GET)
  9.     public String getAll() {
  10.         System.out.println("正在查询所有用户信息...");
  11.         return "ok";
  12.     }
  13. }
复制代码
ok 的页面视图:
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>OK页面</title>
  6. </head>
  7. <body>
  8. <h1>OK !</h1>
  9. </body>
  10. </html>
复制代码
启动服务器,测试:http://localhost:8080/springmvc



3.3 RESTFul 风格的 根据 “id 查询”( RESTFul 规范 需要发送 GET请求)

RESTFul 规范中规定,如果要查询数据,需要发送GET请求。
首页index.html
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6. </head>
  7. <body>
  8. <h1>测试 RESTFul 编程风格</h1>
  9. <hr>
  10. <a th:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
  11. </body>
  12. </html>[url=https://www.cnblogs.com/@{/user/1}]查询id=1的这个用户信息[/url]
复制代码
控制器 Controller:
  1. import com.rainbowsea.springmvc.bean.User;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.bind.annotation.PathVariable;
  4. import org.springframework.web.bind.annotation.RequestMapping;
  5. import org.springframework.web.bind.annotation.RequestMethod;
  6. @Controller  // 交给 Spring IOC 容器进行管理
  7. public class UserController {
  8.     //@RequestMapping(value = "/user/{占位符}",method = RequestMethod.GET)
  9.     @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
  10.     public String getById(@PathVariable(value = "id") String id) {
  11.         System.out.println("正在根据用户 id 查询用户信息...用户 id 是" + id);
  12.         return "ok";
  13.     }
  14. }
复制代码
启动服务器测试:



3.4 RESTFul 风格的 “增长数据” (RESTFul 规范 需要发送 POST 请求)

RESTFul规范中规定,如果要举行保存操纵,需要发送POST请求。
这里我们添加一个 User Bean 类,用于作为对象举行存储。
  1. package com.rainbowsea.springmvc.bean;
  2. public class User {
  3.     private String username;
  4.     private String password;
  5.     private Integer age;
  6.     public User() {
  7.     }
  8.     public User(String username, String password, Integer age) {
  9.         this.username = username;
  10.         this.password = password;
  11.         this.age = age;
  12.     }
  13.     @Override
  14.     public String toString() {
  15.         return "User{" +
  16.                 "username='" + username + '\'' +
  17.                 ", password='" + password + '\'' +
  18.                 ", age=" + age +
  19.                 '}';
  20.     }
  21.     public String getUsername() {
  22.         return username;
  23.     }
  24.     public void setUsername(String username) {
  25.         this.username = username;
  26.     }
  27.     public String getPassword() {
  28.         return password;
  29.     }
  30.     public void setPassword(String password) {
  31.         this.password = password;
  32.     }
  33.     public Integer getAge() {
  34.         return age;
  35.     }
  36.     public void setAge(Integer age) {
  37.         this.age = age;
  38.     }
  39. }
复制代码
页面编写:
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6. </head>
  7. <body>
  8. <h1>测试 RESTFul 编程风格</h1>
  9. <hr>
  10. <a th:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
  11. </body>
  12. </html>[url=https://www.cnblogs.com/@{/user/1}]查询id=1的这个用户信息[/url]
  13.     用户名:
  14.     密码:
  15.     年岁:
  16.     <hr>
复制代码
控制器 Controller:

启动服务器测试:


3.5 RESTFul 风格的 “修改数据” (RESTFul 规范 需要发送 PUT 请求)

RESTFul规范中规定,如果要举行保存操纵,需要发送PUT请求。
如何发送PUT请求?
第一步:首先你必须是一个POST请求。
第二步:在发送POST请求的时候,提交如许的数据:_method=PUT ,使用隐藏域举行配置

第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter
注意:
  1.   
  2.     <input type="hidden" name="_method" value="put">
  3. 隐藏域的 name 必须只能是 “_method”, value是 put(大小写忽略)
复制代码
第一步:首先你必须是一个POST请求。
第二步:在发送POST请求的时候,提交如许的数据:_method=PUT
  1. <h2>修改</h2>
  2. <form th:action="@{/user}" method="post">
  3.    
  4.     <input type="hidden" name="_method" value="put">
  5.     用户名: <input type="text" name="username">
  6.     密码:<input type="password" name="password">
  7.     年龄: <input type="text" name="age">
  8.     <input type="submit" value="修改">
  9. </form>
复制代码

第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter
注意:该过滤器一定要在字符编码过滤器背面配置,不然,先设置的话,可能会出现获取到的请求数据是乱码
  1.    
  2.     <filter>
  3.         <filter-name>HiddenHttpMethodFilter</filter-name>
  4.         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  5.     </filter>
  6.     <filter-mapping>
  7.         <filter-name>HiddenHttpMethodFilter</filter-name>
  8.         <url-pattern>/*</url-pattern>
  9.     </filter-mapping>
复制代码
页面编写:
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6. </head>
  7. <body>
  8. <h1>测试 RESTFul 编程风格</h1>
  9. <hr>
  10. <a th:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
  11. </body>
  12. </html>[url=https://www.cnblogs.com/@{/user/1}]查询id=1的这个用户信息[/url]
  13.     用户名:
  14.     密码:
  15.     年岁:
  16.     <hr><h2>修改</h2>
  17. <form th:action="@{/user}" method="post">
  18.    
  19.     <input type="hidden" name="_method" value="put">
  20.     用户名: <input type="text" name="username">
  21.     密码:<input type="password" name="password">
  22.     年龄: <input type="text" name="age">
  23.     <input type="submit" value="修改">
  24. </form>
复制代码
控制器 Controller:

启动服务器测试:


3.6 RESTFul 风格的 “删除数据” 数据(RESTFul 规范 需要发送 DELETE 请求)

RESTFul规范中规定,如果要举行 删除 操纵,需要发送DELETE 请求。
如何发送 DELETE 请求?,和 发送  PUT 请求的三步是一样的,只需要将 value 的值改为 delete 即可
第一步:首先你必须是一个POST请求。
第二步:在发送POST请求的时候,提交如许的数据:_method=PUT ,使用隐藏域举行配置

第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter
注意:
  1.   
  2.     <input type="hidden" name="_method" value="delete">
  3. 隐藏域的 name 必须只能是 “_method”, value是 delete (大小写忽略)
复制代码
页面编写:
  1. <hr>
  2. <h2>删除用户</h2>
  3. <a th:target="_blank" href="https://www.cnblogs.com/@{user/120}" onclick="del(event)">删除用户id = 120 的用户信息</a>
  4. <form id="delForm" method="post">
  5.     <input type="hidden" name="_method" value="delete">
  6. </form>
复制代码
  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <title>首页</title>
  6. </head>
  7. <body>
  8. <h1>测试 RESTFul 编程风格</h1>
  9. <hr>
  10. <a th:target="_blank" href="https://www.cnblogs.com/@{/user}">查看用户列表</a>
  11. </body>
  12. </html>[url=https://www.cnblogs.com/@{/user/1}]查询id=1的这个用户信息[/url]
  13.     用户名:
  14.     密码:
  15.     年岁:
  16.     <hr><h2>修改</h2>
  17. <form th:action="@{/user}" method="post">
  18.    
  19.     <input type="hidden" name="_method" value="put">
  20.     用户名: <input type="text" name="username">
  21.     密码:<input type="password" name="password">
  22.     年龄: <input type="text" name="age">
  23.     <input type="submit" value="修改">
  24. </form><hr>
  25. <h2>删除用户</h2>
  26. <a th:target="_blank" href="https://www.cnblogs.com/@{user/120}" onclick="del(event)">删除用户id = 120 的用户信息</a>
  27. <form id="delForm" method="post">
  28.     <input type="hidden" name="_method" value="delete">
  29. </form>
复制代码
控制器 Controller:
  1. package com.rainbowsea.springmvc.controller;
  2. import com.rainbowsea.springmvc.bean.User;
  3. import org.springframework.stereotype.Controller;
  4. import org.springframework.web.bind.annotation.PathVariable;
  5. import org.springframework.web.bind.annotation.RequestMapping;
  6. import org.springframework.web.bind.annotation.RequestMethod;
  7. @Controller  // 交给 Spring IOC 容器进行管理
  8. public class UserController {
  9.     //@RequestMapping(value = "/user/{占位符}",method = RequestMethod.GET)
  10.     @RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
  11.     public String getById(@PathVariable(value = "id") String id) {
  12.         System.out.println("正在根据用户 id 查询用户信息...用户 id 是" + id);
  13.         return "ok";
  14.     }
  15.     @RequestMapping(value = "/user", method = RequestMethod.GET)
  16.     public String getAll() {
  17.         System.out.println("正在查询所有用户信息...");
  18.         return "ok";
  19.     }
  20.     @RequestMapping(value = "/user", method = RequestMethod.POST)
  21.     public String save(User user) {
  22.         System.out.println("正在保存用户信息");
  23.         System.out.println(user);
  24.         return "ok";
  25.     }
  26.     @RequestMapping(value = "/user", method = RequestMethod.PUT)
  27.     public String modify(User user) {
  28.         System.out.println("正在修改用户信息" + user);
  29.         return "ok";
  30.     }
  31.     @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
  32.     public String del(@PathVariable(value = "id") String id) {
  33.         System.out.println("正删除用户 : " + id);
  34.         return "ok";
  35.     }
  36. }
复制代码
启动服务器测试:


4. 补充: HiddenHttpMethodFilter 过滤器源码阐明

HiddenHttpMethodFilter是Spring MVC框架提供的,专门用于RESTFul编程风格。
实现原理可以通过源码查看:



通过源码可以看到,if语句中,首先判断是否为POST请求,如果是POST请求,调用request.getParameter(this.methodParam)。可以看到this.methodParam是_method,如许就要求我们在提交请求方式的时候必须采用这个格式:_method=put。获取到请求方式之后,调用了toUpperCase转换成大写了。因此前端页面中小写的put或者大写的PUT都是可以的。if语句中嵌套的if语句说的是,只有请求方式是 PUT,DELETE,PATCH的时候会创建HttpMethodRequestWrapper对象。而HttpMethodRequestWrapper对象的构造方法是如许的:

如许method就从POST酿成了:PUT/DELETE/PATCH。
重点注意事项:CharacterEncodingFilter和HiddenHttpMethodFilter的顺序
细心的同学应该注意到了,在HiddenHttpMethodFilter源码中有如许一行代码:

)
大家是否还记得,字符编码过滤器执行之前不能调用 request.getParameter方法,如果提前调用了,乱码问题就无法办理了。因为request.setCharacterEncoding()方法的执行必须在所有request.getParameter()方法之前执行。因此这两个过滤器就有先后顺序的要求,在web.xml文件中,应该先配置CharacterEncodingFilter,然后再配置HiddenHttpMethodFilter。
5. 总结:


  • RESTFul风格与传统方式对比区别
  • RESTFul 风格的 “查询” 所有(RESTFul 规范 需要发送 GET请求)
  • RESTFul 风格的 根据 “id 查询”( RESTFul 规范 需要发送 GET请求)
  • RESTFul 风格的 “增长数据” (RESTFul 规范 需要发送 POST 请求)
  • RESTFul 风格的 “修改数据” (RESTFul 规范 需要发送 PUT 请求)
    如何发送PUT请求?
    第一步:首先你必须是一个POST请求。
    第二步:在发送POST请求的时候,提交如许的数据:_method=PUT ,使用隐藏域举行配置

第三步:在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter**
注意:
  1.   
  2.     <input type="hidden" name="_method" value="put">
  3. 隐藏域的 name 必须只能是 “_method”, value是 put(大小写忽略)
复制代码

  • RESTFul 风格的 “删除数据” 数据(RESTFul 规范 需要发送 DELETE 请求);如何发送 DELETE 请求?,和 发送  PUT 请求的三步是一样的,只需要将 value 的值改为 delete 即可
  • HiddenHttpMethodFilter  该过滤器一定要在字符编码过滤器背面配置,不然,先设置的话,可能会出现获取到的请求数据是乱码。
6. 末了:

“在这个末了的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上汲取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

圆咕噜咕噜

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表