11.Spring MVC实现RESTful

在 Spring MVC 中,我们可以通过 @RequestMapping +@PathVariable 注解的方式,来实现 RESTful 风格的请求。

1. 通过@RequestMapping 注解的路径设置

当请求中携带的参数是通过请求路径传递到服务器中时,我们就可以在 @RequestMapping 注解的 value 属性中通过占位符 {xxx} 来表示传递的参数,示例代码如下。

  • @RequestMapping("/testRest/{id}/{username}")


注意:value 属性中占位符的位置应当与请求 URL 中参数的位置保持一致,否则会出现传错参数的情况。

2. 通过 @PathVariable 注解绑定参数

我们可以在控制器方法的形参位置通过 @PathVariable 注解,将占位符 {xxx} 所表示的参数赋值给指定的形参。

  1. @RequestMapping("/testRest/{id}/{username}")
  2. public String testRest(@PathVariable("id") String id, @PathVariable("username")
  3. String username) {
  4. System.out.println("id:" + id + ",username:" + username);
  5. return "success";
  6. }

3. 通过 HiddenHttpMethodFilter 对请求进行过滤

由于浏览器默认只支持发送 GET 和 POST 方法的请求,因此我们需要在 web.xml 中使用 Spring MVC 提供的 HiddenHttpMethodFilter 对请求进行过滤。这个过滤器可以帮助我们将 POST 请求转换为 PUT 或 DELETE 请求,其具体配置内容如下。

  1. <!--来处理 PUT 和 DELETE 请求的过滤器-->
  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>


HiddenHttpMethodFilter 处理 PUT 和 DELETE 请求时,必须满足以下 2 个条件:

  • 当前请求的请求方式必须为 POST;
  • 当前请求必须传输请求参数 _method。


在满足了以上条件后,HiddenHttpMethodFilter 过滤器就会将当前请求的请求方式转换为请求参数 _method 的值,即请求参数 _method 的值才是最终的请求方式,因此我们需要在 POST 请求中携带一个名为 _method 的参数,参数值为 DELETE 或 PUT。

注意:若 web.xml 中同时存在 CharacterEncodingFilter 和 HiddenHttpMethodFilter 两个过滤器,必须先注册 CharacterEncodingFilter,再注册 HiddenHttpMethodFilter。

RESTFul 实例演示

下面我们就通过一个实例,来演示下如何通过 RESTFul 风格进行 Spring MVC 项目开发。

1. 新建一个名为 springmvc-restful-demo 的 Web 项目,并将 Spring MVC 相关依赖引入到该项目中,web.xml 配置内容如下。

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4.          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  5.          version="4.0">
  6.  
  7.     <!--请求和响应的字符串过滤器-->
  8.     <filter>
  9.         <filter-name>CharacterEncodingFilter</filter-name>
  10.         <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
  11.         <init-param>
  12.             <param-name>encoding</param-name>
  13.             <param-value>UTF-8</param-value>
  14.         </init-param>
  15.         <init-param>
  16.             <param-name>forceResponseEncoding</param-name>
  17.             <param-value>true</param-value>
  18.         </init-param>
  19.     </filter>
  20.     <filter-mapping>
  21.         <filter-name>CharacterEncodingFilter</filter-name>
  22.         <url-pattern>/*</url-pattern>
  23.     </filter-mapping>
  24.  
  25.     <!--来处理 PUT 和 DELETE 请求的过滤器-->
  26.     <filter>
  27.         <filter-name>HiddenHttpMethodFilter</filter-name>
  28.         <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  29.     </filter>
  30.     <filter-mapping>
  31.         <filter-name>HiddenHttpMethodFilter</filter-name>
  32.         <url-pattern>/*</url-pattern>
  33.     </filter-mapping>
  34.  
  35.     <!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
  36.     <servlet>
  37.         <servlet-name>dispatcherServlet</servlet-name>
  38.         <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  39.         <!--配置 DispatcherServlet 的一个初始化参数:spring mvc 配置文件按的位置和名称-->
  40.         <init-param>
  41.             <param-name>contextConfigLocation</param-name>
  42.             <param-value>classpath:springMVC.xml</param-value>
  43.         </init-param>
  44.  
  45.         <!--作为框架的核心组件,在启动过程中有大量的初始化操作要做
  46.             而这些操作放在第一次请求时才执行会严重影响访问速度
  47.             因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时-->
  48.         <load-on-startup>1</load-on-startup>
  49.     </servlet>
  50.  
  51.     <servlet-mapping>
  52.         <servlet-name>dispatcherServlet</servlet-name>
  53.         <!--设置springMVC的核心控制器所能处理的请求的请求路径
  54.         /所匹配的请求可以是/login或.html或.js或.css方式的请求路径
  55.         但是/不能匹配.jsp请求路径的请求-->
  56.         <url-pattern>/</url-pattern>
  57.     </servlet-mapping>
  58. </web-app>


2. 在 src 目录下(类路径下)添加一个 Spring MVC 的配置文件 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
  7. http://www.springframework.org/schema/beans/spring-beans.xsd
  8. http://www.springframework.org/schema/context
  9. https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
  10.  
  11. <!--开启组件扫描-->
  12. <context:component-scan base-package="net.biancheng.c"></context:component-scan>
  13.  
  14. <!-- 配置 Thymeleaf 视图解析器 -->
  15. <bean id="viewResolver"
  16. class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
  17. <property name="order" value="1"/>
  18. <property name="characterEncoding" value="UTF-8"/>
  19. <property name="templateEngine">
  20. <bean class="org.thymeleaf.spring5.SpringTemplateEngine">
  21. <property name="templateResolver">
  22. <bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
  23. <!-- 视图前缀 -->
  24. <property name="prefix" value="/WEB-INF/templates/"/>
  25. <!-- 视图后缀 -->
  26. <property name="suffix" value=".html"/>
  27. <property name="templateMode" value="HTML5"/>
  28. <property name="characterEncoding" value="UTF-8"/>
  29. </bean>
  30. </property>
  31. </bean>
  32. </property>
  33. </bean>
  34.  
  35. <!-- view-name:设置请求地址所对应的视图名称-->
  36. <mvc:view-controller path="/" view-name="login"></mvc:view-controller>
  37.  
  38. <mvc:view-controller path="/addPage" view-name="product_add"></mvc:view-controller>
  39.  
  40. <!--当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要在SpringMVC的核心配置文件中设置开启mvc注解驱动的标签:-->
  41. <mvc:annotation-driven></mvc:annotation-driven>
  42. <!--
  43. 处理静态资源,例如html、js、css、jpg
  44. 若只设置该标签,则只能访问静态资源,其他请求则无法访问
  45. 此时必须设置<mvc:annotation-driven/>解决问题
  46. -->
  47. <mvc:default-servlet-handler/>
  48. </beans>


3. 在 net.biancheng.c.bean 包下,创建一个名为 User 的类,代码如下。

  1. package net.biancheng.c.bean;
  2.  
  3. public class User {
  4. private String userId;
  5. private String userName;
  6. private String password;
  7.  
  8. public String getUserId() {
  9. return userId;
  10. }
  11.  
  12. public void setUserId(String userId) {
  13. this.userId = userId;
  14. }
  15.  
  16. public String getUserName() {
  17. return userName;
  18. }
  19.  
  20. public void setUserName(String userName) {
  21. this.userName = userName;
  22. }
  23.  
  24. public String getPassword() {
  25. return password;
  26. }
  27.  
  28. public void setPassword(String password) {
  29. this.password = password;
  30. }
  31.  
  32. @Override
  33. public String toString() {
  34. return "User{" +
  35. "userId=" + userId +
  36. ", userName='" + userName + '\'' +
  37. ", password='" + password + '\'' +
  38. '}';
  39. }
  40. }


4. 在 net.biancheng.c.bean 包下,创建一个名为 Product 的类,代码如下。

  1. package net.biancheng.c.bean;
  2.  
  3. import java.math.BigDecimal;
  4.  
  5. public class Product {
  6. private String productId;
  7. private String productName;
  8. private BigDecimal price;
  9. private Integer stock;
  10. private String introduction;
  11.  
  12. public String getIntroduction() {
  13. return introduction;
  14. }
  15.  
  16. public void setIntroduction(String introduction) {
  17. this.introduction = introduction;
  18. }
  19.  
  20. public String getProductId() {
  21. return productId;
  22. }
  23.  
  24. public void setProductId(String productId) {
  25. this.productId = productId;
  26. }
  27.  
  28. public String getProductName() {
  29. return productName;
  30. }
  31.  
  32. public void setProductName(String productName) {
  33. this.productName = productName;
  34. }
  35.  
  36. public BigDecimal getPrice() {
  37. return price;
  38. }
  39.  
  40. public void setPrice(BigDecimal price) {
  41. this.price = price;
  42. }
  43.  
  44. public Integer getStock() {
  45. return stock;
  46. }
  47.  
  48. public void setStock(Integer stock) {
  49. this.stock = stock;
  50. }
  51.  
  52. @Override
  53. public String toString() {
  54. return "Product{" +
  55. "productId=" + productId +
  56. ", productName='" + productName + '\'' +
  57. ", price=" + price +
  58. ", stock=" + stock +
  59. ", introduction='" + introduction + '\'' +
  60. '}';
  61. }
  62. }


5. 在 net.biancheng.c.controller 包下,创建一个名为 LoginController 的 Controller 类,代码如下。

  1. package net.biancheng.c.controller;
  2.  
  3. import net.biancheng.c.bean.User;
  4. import net.biancheng.c.dao.UserDao;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Controller;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8.  
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpSession;
  11.  
  12. /**
  13. * @author C语言中文网
  14. */
  15. @Controller
  16. public class LoginController {
  17. @Autowired
  18. private UserDao userDao;
  19.  
  20. /**
  21. * 登录
  22. * @param user
  23. * @param request
  24. * @return
  25. */
  26. @RequestMapping("/login")
  27. public String login(User user, HttpServletRequest request) {
  28. User loginUser = userDao.getUserByUserName(user.getUserName());
  29. if (loginUser != null && loginUser.getPassword().equals(user.getPassword())) {
  30. HttpSession session = request.getSession();
  31. //将用户信息放到 session 域中
  32. session.setAttribute("loginUser", loginUser);
  33. //重定向到商品列表
  34. return "redirect:/products";
  35. }
  36. request.setAttribute("msg", "账号或密码错误");
  37. return "login";
  38. }
  39. }


6. 在 net.biancheng.c.controller 包下,创建一个名为 ProductController 的 Controller 类,代码如下。

  1. package net.biancheng.c.controller;
  2.  
  3. import net.biancheng.c.bean.Product;
  4. import net.biancheng.c.dao.ProductDao;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.ui.Model;
  7. import org.springframework.web.bind.annotation.PathVariable;
  8. import org.springframework.web.bind.annotation.RequestMapping;
  9. import org.springframework.web.bind.annotation.RequestMethod;
  10.  
  11. import javax.annotation.Resource;
  12. import java.util.List;
  13.  
  14. /**
  15. * @author C语言中文网
  16. */
  17. @Controller
  18. public class ProductController {
  19.  
  20. @Resource
  21. private ProductDao productDao;
  22.  
  23. /**
  24. * 获取商品列表
  25. * @param model
  26. * @return
  27. */
  28. @RequestMapping("/products")
  29. public String getProductList(Model model) {
  30. List productList = productDao.getProductList();
  31. model.addAttribute("productList", productList);
  32. return "product_list";
  33. }
  34.  
  35. /**
  36. * 查看或回显商品信息,get:查看商品信息 update:为修改页回显的商品信息
  37. * @param action
  38. * @param productId
  39. * @param model
  40. * @return
  41. */
  42. @RequestMapping("/product/{action}/{productId}")
  43. public String getProductList(@PathVariable("action") String action, @PathVariable("productId") String productId, Model model) {
  44. Product product = productDao.getProductById(productId);
  45. model.addAttribute("product", product);
  46. //根据参数 action 判断跳转到商品详细信息页还是商品修改页
  47. if (action.equals("get")) {
  48. return "product_info";
  49. } else {
  50. return "product_update";
  51. }
  52. }
  53.  
  54. /**
  55. * 新增商品
  56. * @param product
  57. * @return
  58. */
  59. @RequestMapping(value = "/product", method = RequestMethod.POST)
  60. public String addProduct(Product product) {
  61. productDao.addProduct(product);
  62. return "redirect:/products";
  63. }
  64.  
  65. /**
  66. * 修改商品信息
  67. * @param product
  68. * @return
  69. */
  70. @RequestMapping(value = "/product", method = RequestMethod.PUT)
  71. public String updateProduct(Product product) {
  72. productDao.updateProduct(product);
  73. return "redirect:/products";
  74. }
  75.  
  76. /**
  77. * 删除商品
  78. * @param productId
  79. * @return
  80. */
  81. @RequestMapping(value = "/product", method = RequestMethod.DELETE)
  82. public String deleteProduct(String productId) {
  83. productDao.deleteProduct(productId);
  84. return "redirect:/products";
  85. }
  86. }


7. 在 net.biancheng.c.dao 包下,创建一个名为 UserDao 的类,代码如下。

  1. package net.biancheng.c.dao;
  2.  
  3. import net.biancheng.c.bean.User;
  4. import org.springframework.stereotype.Repository;
  5.  
  6. import java.util.*;
  7.  
  8. @Repository
  9. public class UserDao {
  10. private static Map<String, User> users = null;
  11.  
  12. static {
  13. users = new HashMap<String, User>();
  14.  
  15. User user = new User();
  16. user.setUserId("1001");
  17. user.setUserName("Java用户");
  18. user.setPassword("987654321");
  19.  
  20. User user2 = new User();
  21. user2.setUserId("1002");
  22. user2.setUserName("admin");
  23. user2.setPassword("admin");
  24.  
  25. users.put(user.getUserName(), user);
  26. users.put(user2.getUserName(), user2);
  27. }
  28.  
  29.  
  30. /**
  31. * 根据用户名获取用户信息
  32. *
  33. * @param userName
  34. * @return
  35. */
  36. public User getUserByUserName(String userName) {
  37. User user = users.get(userName);
  38. return user;
  39. }
  40. }


8. 在 net.biancheng.c.dao 包下,创建一个名为 ProductDao 的类,代码如下。

  1. package net.biancheng.c.dao;
  2.  
  3. import net.biancheng.c.bean.Product;
  4. import org.springframework.stereotype.Repository;
  5.  
  6. import java.math.BigDecimal;
  7. import java.util.*;
  8.  
  9. @Repository
  10. public class ProductDao {
  11.  
  12. private static Map<String, Product> products = null;
  13.  
  14. static {
  15. products = new HashMap<String, Product>();
  16. Product product = new Product();
  17. product.setProductId("1");
  18. product.setProductName("茅台");
  19. product.setPrice(new BigDecimal(9999));
  20. product.setStock(1000);
  21. product.setIntroduction("茅台酒是大曲酱香型酒的鼻祖,它具有色清透明、酱香突出、醇香馥郁、幽雅细腻、入口柔绵、清冽甘爽、酒体醇厚丰满、回味悠长的特点、人们把茅台酒独有的香味称为\"茅香\",是中国酱香型风格的典范。");
  22.  
  23. Product product1 = new Product();
  24. product1.setProductId("2");
  25. product1.setProductName("五粮液");
  26. product1.setPrice(new BigDecimal(8888));
  27. product1.setStock(1000);
  28. product1.setIntroduction("五粮液,四川省宜宾市特产,中国国家地理标志产品。以五粮液为代表的中国白酒,有着4000多年的酿造历史,堪称世界最古老、最具神秘特色的食品制造产业之一。");
  29.  
  30. Product product2 = new Product();
  31. product2.setProductId("3");
  32. product2.setProductName("信阳毛尖");
  33. product2.setPrice(new BigDecimal(7777));
  34. product2.setStock(1000);
  35. product2.setIntroduction("信阳毛尖又称豫毛峰,属绿茶类,是中国十大名茶之一,也是河南省著名特产之一;其主要产地在信阳市浉河区(原信阳市)、平桥区(原信阳县)和罗山县。");
  36.  
  37. Product product3 = new Product();
  38. product3.setProductId("4");
  39. product3.setProductName("深州大蜜桃");
  40. product3.setPrice(new BigDecimal(6666));
  41. product3.setStock(1000);
  42. product3.setIntroduction("深州蜜桃,河北省深州市特产,中国国家地理标志产品。深州蜜桃个头硕大,果型秀美,色鲜艳,皮薄肉细,汁甜如蜜。2014年10月8日,国家质检总局正式批准“深州蜜桃”为原产地域保护产品(即地理标志保护产品)。");
  43.  
  44. products.put(product.getProductId(), product);
  45. products.put(product1.getProductId(), product1);
  46. products.put(product2.getProductId(), product2);
  47. products.put(product3.getProductId(), product3);
  48. }
  49.  
  50. /**
  51. * 获取商品列表
  52. *
  53. * @return
  54. */
  55. public List getProductList() {
  56. List productList = new ArrayList();
  57. Set<String> keys = products.keySet();
  58. for (String key : keys) {
  59. Product product = products.get(key);
  60. productList.add(product);
  61. }
  62. return productList;
  63. }
  64.  
  65. /**
  66. * 根据商品 id 获取商品信息
  67. *
  68. * @param productId
  69. * @return
  70. */
  71. public Product getProductById(String productId) {
  72. return products.get(productId);
  73. }
  74.  
  75. /**
  76. * 新增商品
  77. *
  78. * @param product
  79. */
  80. public void addProduct(Product product) {
  81. products.put(product.getProductId(), product);
  82. }
  83.  
  84. /**
  85. * 修改商品
  86. *
  87. * @param product
  88. */
  89. public void updateProduct(Product product) {
  90. products.put(product.getProductId(), product);
  91.  
  92. }
  93.  
  94. /**
  95. * 删除商品
  96. *
  97. * @param productId
  98. */
  99. public void deleteProduct(String productId) {
  100. products.remove(productId);
  101. }
  102. }


9. 在 webapp 下新建一个 js 目录,并将 jquery-3.6.0.min.js 存放到该目录下。

10. 在 webapp/WEB-INF 下,新建一个 templates 目录,并在该目录下添加以下 HTML 文件。

1) 登录页:login.html 代码如下。

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>C语言中文网</title>
  6. </head>
  7. <body>
  8. <form th:action="@{/login}" method="post">
  9.  
  10. <table style="margin: auto">
  11. <tr>
  12. <td th:if="${not #strings.isEmpty(msg)}" colspan="2" align="center">
  13. <p style="color: red;margin: auto" th:text="${msg}"></p>
  14. </td>
  15. </tr>
  16. <tr>
  17. <td>用户名:</td>
  18. <td><input type="text" name="userName" required><br></td>
  19. </tr>
  20. <tr>
  21. <td>密码:</td>
  22. <td><input type="password" name="password" required><br></td>
  23. </tr>
  24. <tr>
  25. <td colspan="2" align="center">
  26. <input type="submit" value="登陆">
  27. <input type="reset" value="重置">
  28. </td>
  29.  
  30. </tr>
  31. </table>
  32. </form>
  33. </body>
  34. </html>


2) 商品列表页:product_list.html,代码如下。

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6.  
  7. <script type="text/javaScript"
  8. src="../../js/jquery-3.6.0.min.js " th:src="@{/js/jquery-3.6.0.min.js}"></script>
  9. </head>
  10. <body>
  11.  
  12. <h1 th:text="'欢迎您:'+${session.loginUser.getUserName()}" th:if="${not #strings.isEmpty(session.loginUser)}"></h1>
  13. <table th:border="1" th:cellspacing="0" th:cellpadding="10" style="text-align: center;">
  14. <thead>
  15. <th>商品id</th>
  16. <th>商品名</th>
  17. <th>商品价格</th>
  18. <th>商品库存</th>
  19. <th>操作</th>
  20. </thead>
  21. <tbody>
  22. <tr th:each="product:${productList}">
  23. <td th:text="${product.getProductId()}"></td>
  24. <td th:text="${product.getProductName()}"></td>
  25. <td th:text="${product.getPrice()}"></td>
  26. <td th:text="${product.getStock()}"></td>
  27. <td>
  28. <a th:href="@{|/product/get/${product.getProductId()}|}">查看商品</a>
  29. <a th:href="@{|/product/update/${product.getProductId()}|}">修改商品</a>
  30. <a href="#" th:onclick="testJson1([[${product.getProductId()}]]);">删除商品</a>
  31. </td>
  32. </tr>
  33. </tbody>
  34. </table>
  35. <br>
  36. <a th:href="@{/addPage}">新增商品</a>
  37.  
  38. <!-- 作用:通过超链接控制表单的提交,将post请求转换为delete请求 -->
  39. <form id="delete_form" method="post" th:action="@{/product}">
  40. <!-- HiddenHttpMethodFilter要求:必须传输_method请求参数,并且值为最终的请求方式 -->
  41. <input type="hidden" name="_method" value="delete"/>
  42. <input type="hidden" name="productId" th:id="form-id"/>
  43. </form>
  44.  
  45. <script type="text/javaScript">
  46.  
  47. function testJson1(productId) {
  48. var b = confirm("确认删除id 为" + productId + " 的商品?");
  49. if (b) {
  50. var delete_form = $("#delete_form");
  51. $("#form-id").val(productId);
  52. delete_form.submit();
  53. }
  54. }
  55. </script>
  56. </body>
  57. </html>


3) 商品详情页:product_info.html,代码如下。

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <h1>商品详情页</h1>
  9. <table th:border="1" th:cellspacing="0" style="width: 600px">
  10. <tr>
  11. <th> 商品ID:</th>
  12. <td th:text="${product.getProductId()}"></td>
  13. </tr>
  14. <tr>
  15. <th>商品名:</th>
  16. <td th:text="${product.getProductName()}"></td>
  17. </tr>
  18. <tr>
  19. <th>商品价格:</th>
  20. <td th:text="${product.getPrice()}"></td>
  21. </tr>
  22. <tr>
  23. <th>商品库存:</th>
  24. <td th:text="${product.getStock()}"></td>
  25. </tr>
  26. <tr>
  27. <th>商品简介:</th>
  28. <td th:text="${product.getIntroduction()}"></td>
  29. </tr>
  30. </table>
  31. <br>
  32. <a th:href="@{/products}">返回商品列表页</a>
  33. </body>
  34. </html>


4) 新增商品页:product_add.html,代码如下。

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form th:action="@{/product}" method="post">
  9. <table style="margin: auto">
  10. <tr>
  11. <td>商品 ID:</td>
  12. <td><input type="text" name="productId" required></td>
  13. </tr>
  14.  
  15. <tr>
  16. <td>商品名称:</td>
  17. <td><input type="text" name="productName" required></td>
  18. </tr>
  19. <tr>
  20. <td>商品价格:</td>
  21. <td><input type="text" name="price" required></td>
  22. </tr>
  23. <tr>
  24. <td>商品库存:</td>
  25. <td><input type="text" name="stock" required></td>
  26. </tr>
  27. <tr>
  28. <td>商品简介:</td>
  29. <td><textarea name="introduction" rows="10" cols="30"></textarea><br></td>
  30. </tr>
  31. <tr>
  32. <td colspan="2" align="center"><input type="submit" value="新增商品"></td>
  33. </tr>
  34. </table>
  35. </form>
  36. </body>
  37. </html>


5) 修改商品页:product_update.html,代码如下。

  1. <!DOCTYPE html>
  2. <html lang="en" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8.  
  9. <form th:action="@{/product}" method="post">
  10. <input type="hidden" name="_method" value="put">
  11. <table style="margin: auto">
  12. <tr>
  13. <td>商品 ID:</td>
  14. <td><input type="text" name="productId" th:value="${product.getProductId()}" readonly></td>
  15. </tr>
  16.  
  17. <tr>
  18. <td>商品名称:</td>
  19. <td><input type="text" name="productName" th:value="${product.getProductName()}" required></td>
  20. </tr>
  21. <tr>
  22. <td>商品价格:</td>
  23. <td><input type="text" name="price" th:value="${product.getPrice()}" required></td>
  24. </tr>
  25. <tr>
  26. <td>商品库存:</td>
  27. <td><input type="text" name="stock" th:value="${product.getStock()}" required></td>
  28. </tr>
  29. <tr>
  30. <td>商品简介:</td>
  31. <td><textarea name="introduction" rows="10" cols="30" th:text="${product.getIntroduction()}"></textarea>
  32. </td>
  33. </tr>
  34. <tr>
  35. <td colspan="2" align="center"><input type="submit" value="修改商品信息"></td>
  36. </tr>
  37. </table>
  38. </form>
  39. </body>
  40. </html>


11. 将 springmvc-restful-demo 部署到 Tomcat 服务器中,启动服务器,并使用浏览器访问“http://localhost:8080/springmvc-restful-demo/”,结果如下图。

登陆页-rest
图1:登录页


12. 在登陆页分别输入用户名(admin)和密码(admin),点击登陆,结果如下图。

商品列表页-rest
图2:商品列表页


13. 点击商品列表页下方的“新增商品”,跳转到新增商品页,并输入商品信息,结果如下图。

新增商品-rest
图3:新增商品


14. 点击下方的“新增商品”,结果如下图。


图4:商品列表页-2


15. 以“衡水老白干”为例,点击商品列表右侧的“查看商品”,结果如下图。

商品详情页-rest
图5:商品详情页


16. 返回商品列表页,返回点击右侧的“修改商品”,结果如下图。


图6:商品信息回显


17. 分别修改商品的名称、价格、库存等信息,如下图。


图7:修改商品信息


18. 点击下方的“修改商品信息”,返回列表页,结果如下图。


图8:商品列表页-3


19. 点击右侧的“删除商品”,删除我们新增的商品“衡水老白干-至尊版”,结果如下图。


图9:删除商品


20. 点击“确认”按钮,删除该商品,结果如下图。

商品列表页-rest
图10:商品删除成功
posted @ 2022-07-31 14:28  随遇而安==  阅读(274)  评论(0编辑  收藏  举报