暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

使用SSM+Vue前后端分离开发实现增删改查(超详细)

邵奈一 2021-09-09
773

大家好,我是邵奈一,一个不务正业的程序猿、正儿八经的斜杠青年。1、世人称我为:被代码耽误的诗人、没天赋的书法家、五音不全的歌手、专业跑龙套演员、不合格的运动员... 2、这几年,我整理了很多IT技术相关的教程给大家,爱生活、爱分享。3、如果您觉得文章有用,请收藏,转发,评论,并关注我,谢谢!博客导航跳转(请收藏):邵奈一的技术博客导航| 公众号 | 微信 | CSDN | 掘金 | 51CTO | 简书 | 微博 |


00x0 目标

搭建SSM框架,并且能够打通前后端,是一个稍微进阶但是又非常基础的教程。

学习前提

几乎是零基础都可以,当然,如果你有学过一些 SSM
Vue
基础内容,那这篇教程更加适合你!

教程亮点与难点

1、搭建通用的SSM框架 2、直接集成CDN的Vue,脱离Node.js使用Vue 3、实现跨域问题,为后端工程师进阶全栈提供思路

在开始确定题目的时候,我专门去搜了一下百度,看有没有类似的文章,发现很多都是 SpringBoot+SSM+Vue
的,好坑,可能小伙伴们就只是学了 SSM
,能不能快速入门,实现一个增删改查案例呢,答案自然是有的!那让我来实现一下吧,小伙伴们如果觉得文章写得不错,请一键三连,甚至扫个二维码防走丢哈!

00x1 后端代码实现

步骤总览

1、功能需求分析 2、新建数据库表 3、SSM后台代码实现 4、部署Tomcat 5、编写测试用例

步骤实现

1、功能需求分析

因为需求比较简单,我给张图大家应该就清楚了:就是实现增删改查功能,数据表 product
,字段如下:

字段说明
productName商品名称
num数量

其实,这个需求是来源于博主的另外一篇博客:Vue2.x案例之商品增删改查的实现。

只不过呢,这篇博客是没有对接后台的,只是在前端实现了功能而已。而我们这一次,相当于要把后端打通!期不期待呢?!

2、新建数据库表

把下面的语句丢去执行即可,当然,你用 navicat
直接填也可以:

  1. DROP TABLE IF EXISTS `product`;

  2. CREATE TABLE `product` (

  3. `id` int(11) NOT NULL AUTO_INCREMENT,

  4. `productname` varchar(255),

  5. `num` int(11) NULL DEFAULT NULL,

  6. PRIMARY KEY (`id`)

  7. ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8;


  8. INSERT INTO `product` VALUES (1, '鞋子', 100);

  9. INSERT INTO `product` VALUES (2, '衬衫', 200);

复制

注意:我这里写的字段名是 productname
,注意大小写!

3、SSM后台代码实现

步骤比较多,总体思路:

新建Maven项目,我们这里选择 空模板
,本意是为了让大家一步一步上手(当然,你也可以选择 webapp
模板),构建好后,结构如下图所示:接着引入SSM依赖, pom.xml
文件中的完整依赖如下:

  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.shaonaiyi</groupId>

  7. <artifactId>minimall</artifactId>

  8. <version>1.0-SNAPSHOT</version>

  9. <packaging>war</packaging>


  10. <properties>

  11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  12. <maven.compiler.source>1.8</maven.compiler.source>

  13. <maven.compiler.target>1.8</maven.compiler.target>

  14. <spring.version>5.2.5.RELEASE</spring.version>

  15. <mybatis.version>3.5.3</mybatis.version>

  16. <jackson.version>2.9.8</jackson.version>

  17. </properties>


  18. <dependencies>

  19. <!--javaWeb组件库-->

  20. <dependency>

  21. <groupId>javax</groupId>

  22. <artifactId>javaee-web-api</artifactId>

  23. <version>8.0.1</version>

  24. <scope>provided</scope>

  25. </dependency>

  26. <!-- Spring核心-->

  27. <dependency>

  28. <groupId>org.springframework</groupId>

  29. <artifactId>spring-core</artifactId>

  30. <version>${spring.version}</version>

  31. </dependency>

  32. <!--Spring 应用上下文,进行注解、xml、config加载-->

  33. <dependency>

  34. <groupId>org.springframework</groupId>

  35. <artifactId>spring-context</artifactId>

  36. <version>${spring.version}</version>

  37. </dependency>

  38. <!--Spring提供的Web上下文,可与Web框架集成,如struts-->

  39. <dependency>

  40. <groupId>org.springframework</groupId>

  41. <artifactId>spring-web</artifactId>

  42. <version>${spring.version}</version>

  43. </dependency>

  44. <!--Spring IOC-->

  45. <dependency>

  46. <groupId>org.springframework</groupId>

  47. <artifactId>spring-beans</artifactId>

  48. <version>${spring.version}</version>

  49. </dependency>

  50. <!--SpringMVC-->

  51. <dependency>

  52. <groupId>org.springframework</groupId>

  53. <artifactId>spring-webmvc</artifactId>

  54. <version>${spring.version}</version>

  55. </dependency>

  56. <!--持久层框架支持-->

  57. <dependency>

  58. <groupId>org.springframework</groupId>

  59. <artifactId>spring-orm</artifactId>

  60. <version>${spring.version}</version>

  61. </dependency>

  62. <!--AOP支持-->

  63. <dependency>

  64. <groupId>org.springframework</groupId>

  65. <artifactId>spring-aop</artifactId>

  66. <version>${spring.version}</version>

  67. </dependency>

  68. <dependency>

  69. <groupId>org.springframework</groupId>

  70. <artifactId>spring-aspects</artifactId>

  71. <version>${spring.version}</version>

  72. </dependency>

  73. <!--spring事务-->

  74. <dependency>

  75. <groupId>org.springframework</groupId>

  76. <artifactId>spring-tx</artifactId>

  77. <version>${spring.version}</version>

  78. </dependency>

  79. <!-- DBCP数据库连接池,SSM框架一般搭配DBCP连接池 -->

  80. <dependency>

  81. <groupId>commons-dbcp</groupId>

  82. <artifactId>commons-dbcp</artifactId>

  83. <version>1.4</version>

  84. </dependency>

  85. <!--MyBatis-->

  86. <dependency>

  87. <groupId>org.mybatis</groupId>

  88. <artifactId>mybatis</artifactId>

  89. <version>${mybatis.version}</version>

  90. </dependency>

  91. <!--MyBatis与Spring的集成-->

  92. <dependency>

  93. <groupId>org.mybatis</groupId>

  94. <artifactId>mybatis-spring</artifactId>

  95. <version>2.0.0</version>

  96. </dependency>

  97. <!--MySql数据库-->

  98. <dependency>

  99. <groupId>mysql</groupId>

  100. <artifactId>mysql-connector-java</artifactId>

  101. <version>5.1.48</version>

  102. </dependency>

  103. <!-- Json -->

  104. <dependency>

  105. <groupId>com.fasterxml.jackson.core</groupId>

  106. <artifactId>jackson-databind</artifactId>

  107. <version>${jackson.version}</version>

  108. </dependency>

  109. <dependency>

  110. <groupId>com.fasterxml.jackson.core</groupId>

  111. <artifactId>jackson-core</artifactId>

  112. <version>${jackson.version}</version>

  113. </dependency>

  114. <dependency>

  115. <groupId>com.fasterxml.jackson.core</groupId>

  116. <artifactId>jackson-annotations</artifactId>

  117. <version>${jackson.version}</version>

  118. </dependency>

  119. <dependency>

  120. <groupId>junit</groupId>

  121. <artifactId>junit</artifactId>

  122. <version>4.11</version>

  123. <scope>test</scope>

  124. </dependency>

  125. </dependencies>


  126. </project>

复制

注意的地方:1、添加了 <packaging>
标签,我们是打包成 war
包,后面是集成 Tomcat
部署。

添加依赖后,需要构建目录结构,把相应的包和文件夹建好:除此之外,因为选择的是 Maven 空模板
项目,所以要设置成 web 项目。先新建 webapp
文件夹和 WEB-INF
子文件夹(不清楚可以看下面第二张图):新建好后,如图所示:接着,就是要新建相应的配置文件了,小伙伴们可以直接复制粘贴,都是新建在 resources
文件夹里。最终目录结构,可以参考这张图:先拷贝 web.xml
的内容:

  1. <context-param>

  2. <param-name>contextConfigLocation</param-name>

  3. <param-value>classpath:applicationContext.xml</param-value>

  4. </context-param>

  5. <listener>

  6. <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

  7. </listener>


  8. <servlet>

  9. <servlet-name>SpringMVC</servlet-name>

  10. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

  11. <init-param>

  12. <param-name>contextConfigLocation</param-name>

  13. <param-value>classpath:springmvc.xml</param-value>

  14. </init-param>

  15. </servlet>

  16. <servlet-mapping>

  17. <servlet-name>SpringMVC</servlet-name>

  18. <url-pattern>/</url-pattern>

  19. </servlet-mapping>

  20. <filter>

  21. <filter-name>characterEncodingFilter</filter-name>

  22. <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

  23. <init-param>

  24. <param-name>encoding</param-name>

  25. <param-value>UTF-8</param-value>

  26. </init-param>

  27. <init-param>

  28. <param-name>forceEncoding</param-name>

  29. <param-value>true</param-value>

  30. </init-param>

  31. </filter>

  32. <filter-mapping>

  33. <filter-name>characterEncodingFilter</filter-name>

  34. <url-pattern>/*</url-pattern>

  35. </filter-mapping>

  36. <welcome-file-list>

  37. <welcome-file>index.html</welcome-file>

  38. <welcome-file>index.htm</welcome-file>

  39. <welcome-file>index.jsp</welcome-file>

  40. <welcome-file>default.html</welcome-file>

  41. <welcome-file>default.htm</welcome-file>

  42. <welcome-file>default.jsp</welcome-file>

  43. </welcome-file-list>

复制

拷贝完会报错,没关系,因为还没有其他文件,可以不用管它,继续操作。接着继续新建 applicationContext.xml
文件:

  1. <beans xmlns="http://www.springframework.org/schema/beans"

  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"

  3. xmlns:context="http://www.springframework.org/schema/context"

  4. xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"

  5. xsi:schemaLocation="http://www.springframework.org/schema/beans

  6. http://www.springframework.org/schema/beans/spring-beans-3.2.xsd

  7. http://www.springframework.org/schema/mvc

  8. http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd

  9. http://www.springframework.org/schema/context

  10. http://www.springframework.org/schema/context/spring-context-3.2.xsd

  11. http://www.springframework.org/schema/aop

  12. http://www.springframework.org/schema/aop/spring-aop-3.2.xsd

  13. http://www.springframework.org/schema/tx

  14. http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">


  15. <!-- 加载db.properties-->

  16. <context:property-placeholder location="classpath:db.properties" />

  17. <!-- 扫描包,将标注Spring注解的类自动转化对象,同时完成Bean的注入 -->

  18. <context:component-scan base-package="com.shaonaiyi.minimall"/>

  19. <!-- 启动对@AspectJ注解的支持 -->

  20. <aop:aspectj-autoproxy></aop:aspectj-autoproxy>


  21. <!-- 配置数据源 ,使用dbcp数据库连接池 -->

  22. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"

  23. destroy-method="close">

  24. <property name="driverClassName" value="${jdbc.driver}" />

  25. <property name="url" value="${jdbc.url}" />

  26. <property name="username" value="${jdbc.username}" />

  27. <property name="password" value="${jdbc.password}" />

  28. <property name="maxActive" value="30" />

  29. <property name="maxIdle" value="20" />

  30. </bean>


  31. <!--配置sqlSessionFactory -->

  32. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

  33. <property name="dataSource" ref="dataSource" />

  34. <property name="mapperLocations" value="classpath:mapper/*.xml"></property>

  35. </bean>

  36. <!-- mapper扫描器 -->

  37. <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

  38. <property name="basePackage" value="com.shaonaiyi.minimall.dao"></property>

  39. <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />

  40. </bean>


  41. <!-- 事务管理器 对mybatis操作数据库事务控制,spring使用jdbc的事务控制类 -->

  42. <bean id="transactionManager"

  43. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

  44. <property name="dataSource" ref="dataSource" />

  45. </bean>


  46. <!-- 通知 -->

  47. <tx:advice id="txAdvice" transaction-manager="transactionManager">

  48. <tx:attributes>

  49. <!-- 传播行为 -->

  50. <tx:method name="save*" propagation="REQUIRED" />

  51. <tx:method name="delete*" propagation="REQUIRED" />

  52. <tx:method name="add*" propagation="REQUIRED" />

  53. <tx:method name="modify*" propagation="REQUIRED" />

  54. <tx:method name="update*" propagation="REQUIRED" />

  55. <tx:method name="find*" propagation="SUPPORTS" read-only="true" />

  56. <tx:method name="get*" propagation="SUPPORTS" read-only="true" />

  57. <tx:method name="select*" propagation="SUPPORTS" read-only="true" />

  58. <tx:method name="search*" propagation="SUPPORTS" read-only="true" />

  59. <tx:method name="list*" propagation="SUPPORTS" read-only="true" />

  60. </tx:attributes>

  61. </tx:advice>

  62. <!-- aop -->

  63. <aop:config>

  64. <aop:advisor advice-ref="txAdvice"

  65. pointcut="execution(* com.shaonaiyi.minimall.service.impl.*.*(..))" />

  66. </aop:config>



  67. </beans>

复制

*.xml
处会报红,是因为还没有xml文件,先不用管。

新建 springmvc.xml
文件:

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <beans default-lazy-init="true"

  3. xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p"

  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"

  5. xmlns:mvc="http://www.springframework.org/schema/mvc"

  6. xsi:schemaLocation="

  7. http://www.springframework.org/schema/beans

  8. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

  9. http://www.springframework.org/schema/mvc

  10. http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd

  11. http://www.springframework.org/schema/context

  12. http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  13. <!-- 扫描带注解的包下的类,注册Bean-->

  14. <context:component-scan base-package="com.shaonaiyi.minimall.controller" />

  15. <!-- 通过注解,把URL映射到Controller上,该标签默认注册DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter -->

  16. <mvc:annotation-driven />

  17. </beans>

复制

新建 db.properties
文件

  1. jdbc.driver=com.mysql.jdbc.Driver

  2. jdbc.url=jdbc:mysql://localhost:3306/minimall?characterEncoding=utf-8

  3. jdbc.username=root

  4. jdbc.password=123456

复制

配置文件都搞定之后,就可以敲代码了,说实话,用过SpringBoot之后,再用起SSM来,就像说一个字:绝!(真繁琐...)

编写代码的顺序一般是这样的,先把对应的实体类给建好,必须清楚自己到底想干啥,然后你可以从 Controller
再到 Service
再到 Dao
层,再把 MyBatis
的xml文件搞定。

但实际上开发要比这个轻松很多,因为一般都会用代码生成工具,把很多琐碎的代码都自动生成了,可以减少很多工作,比如增删改查,只需要写少量 Controller
Service
层代码就可以了。

当然,在实际开发上,还可以继续再简化,这个就需要衡量一下你项目的够不够大了,如果项目比较小,复制粘贴就可以搞定了,但如果体量比较大,复制粘贴都非常繁琐。当然,你也可以选择一些低代码开发平台,配置一下、跑一下,很多功能都可以实现,具体大家也可以去了解一下:

其实只有写教程是最费时间的:!在这里插入图片描述我不忍了,你们在学校学的都是......没有没有,只是太基础而已。

!在这里插入图片描述彩蛋:打印日志实现

为了使用日志,我们在util包里编写工具类:

  1. package com.shaonaiyi.minimall.util;


  2. import org.aspectj.lang.JoinPoint;

  3. import org.aspectj.lang.annotation.After;

  4. import org.aspectj.lang.annotation.Aspect;

  5. import org.aspectj.lang.annotation.Before;

  6. import org.springframework.stereotype.Component;


  7. /**

  8. * @Auther: shaonaiyi@163.com

  9. * @Date: 2021/8/17 23:58

  10. * @Description:

  11. */

  12. @Component

  13. @Aspect

  14. public class LogPrint {

  15. @Before("execution(* com.shaonaiyi.minimall.service.impl.*.*(..))")

  16. public void methodBegin(JoinPoint joinPoint){

  17. System.out.println("方法开始了");

  18. }

  19. @After("execution(* com.shaonaiyi.minimall.service.impl.*.*(..))")

  20. public void methodEnd(){

  21. System.out.println("方法结束了");

  22. }

  23. @Before("execution(* com.shaonaiyi.minimall.service.impl.*.*(..))")

  24. public void methodBegin1(JoinPoint joinPoint){

  25. System.out.println(joinPoint.getTarget()+" "+joinPoint.getSignature().getName()+"方法开始了");

  26. }

  27. }

复制

增删改查实现

先把实体类构建好,然后的写代码顺序可以灵活处理,一般是先写Controller,然后是Service接口,接着是Service实现,然后是Dao层接口,然后是Dao的xml文件。简单来说就是:entity
=> XxxController
=> iXxxService
=> XxxServiceImpl
=> XxxDao.java
=> XxxDao.xml

代码结构请参考下图,以免有些小伙伴不知道要复制到哪里:

编写 Product.java

完整代码:

  1. package com.shaonaiyi.minimall.entity;


  2. /**

  3. * @Auther: shaonaiyi@163.com

  4. * @Date: 2021/8/17 14:09

  5. * @Description: 商品实体类

  6. */

  7. public class Product {


  8. private Integer id;

  9. private String productName;

  10. private Integer nums;


  11. public Integer getId() {

  12. return id;

  13. }


  14. public void setId(Integer id) {

  15. this.id = id;

  16. }


  17. public String getProductName() {

  18. return productName;

  19. }


  20. public void setProductName(String productName) {

  21. this.productName = productName;

  22. }


  23. public Integer getNums() {

  24. return nums;

  25. }


  26. public void setNums(Integer nums) {

  27. this.nums = nums;

  28. }


  29. @Override

  30. public String toString() {

  31. final StringBuffer sb = new StringBuffer("Product{");

  32. sb.append("id=").append(id);

  33. sb.append(", productName='").append(productName).append('\'');

  34. sb.append(", nums=").append(nums);

  35. sb.append('}');

  36. return sb.toString();

  37. }

  38. }

复制

注意:数据库里商品名称为 productname
,而实体类里字段为 productName
,所以后面操作要额外注意,这里写不同,方便各位小伙伴有个区别。

编写 ProductController.java

完整代码:

  1. package com.shaonaiyi.minimall.controller;


  2. import com.shaonaiyi.minimall.entity.Product;

  3. import com.shaonaiyi.minimall.service.IProductService;

  4. import org.springframework.beans.factory.annotation.Autowired;

  5. import org.springframework.stereotype.Controller;

  6. import org.springframework.web.bind.annotation.*;


  7. import java.util.List;


  8. /**

  9. * @Auther: shaonaiyi@163.com

  10. * @Date: 2021/8/17 14:10

  11. * @Description: 商品控制器

  12. */

  13. @Controller

  14. @RequestMapping("/product")

  15. @CrossOrigin

  16. public class ProductController {


  17. @Autowired

  18. private IProductService iProductService;


  19. @RequestMapping("/list")

  20. @ResponseBody

  21. public List<Product> list() {

  22. return iProductService.list();

  23. }


  24. @RequestMapping(value = "/add",method = RequestMethod.POST)

  25. @ResponseBody

  26. public boolean add(@RequestBody Product product) {

  27. return iProductService.add(product);

  28. }


  29. @RequestMapping(value = "/update",method = RequestMethod.POST)

  30. @ResponseBody

  31. public boolean update(@RequestBody Product product) {

  32. return iProductService.update(product);

  33. }


  34. @RequestMapping(value = "/delete",method = RequestMethod.POST)

  35. @ResponseBody

  36. public boolean delete(@RequestBody Product product) {

  37. return iProductService.delete(product);

  38. }


  39. @RequestMapping(value = "/add-test",method = RequestMethod.POST)

  40. @ResponseBody

  41. public boolean addTest(String productName,Integer nums) {

  42. Product product = new Product();

  43. product.setProductName(productName);

  44. product.setNums(nums);

  45. return iProductService.add(product);

  46. }


  47. @RequestMapping(value = "/delete-test",method = RequestMethod.POST)

  48. @ResponseBody

  49. public boolean deleteTest(int id) {

  50. Product product = new Product();

  51. product.setId(id);

  52. return iProductService.delete(product);

  53. }


  54. }

复制

说明:1、这里提供多了两个接口:/add-test
/delete-test
,方便大家对比学习,两种方式的接受参数的方式不一样, Content-Type
一个是 JSON
,一个是 application/x-www-form-urlencoded
,方式不同,如果不对应上,会报400错误,后面有测试用例,可以看后面内容。2、目前的开发模式一般都是前后端分离开发,所以用 JSON
格式进行交互是最常见的;如果想按照自己的风格,没有前后端分离的话,可以使用另外一种。初学者比较容易对这里的内容有误解,可以查阅相关资料。

编写 IProductService.java

完整代码:

  1. package com.shaonaiyi.minimall.service;


  2. import com.shaonaiyi.minimall.entity.Product;


  3. import java.util.List;


  4. /**

  5. * @Auther: shaonaiyi@163.com

  6. * @Date: 2021/8/17 14:13

  7. * @Description: 商品逻辑接口

  8. */

  9. public interface IProductService {


  10. List<Product> list();


  11. boolean add(Product product);


  12. boolean update(Product product);


  13. boolean delete(Product product);


  14. }

复制
编写 ProductServiceImpl.java

完整代码:

  1. package com.shaonaiyi.minimall.service.impl;


  2. import com.shaonaiyi.minimall.dao.ProductDao;

  3. import com.shaonaiyi.minimall.entity.Product;

  4. import com.shaonaiyi.minimall.service.IProductService;

  5. import org.springframework.beans.factory.annotation.Autowired;

  6. import org.springframework.stereotype.Service;


  7. import java.util.List;


  8. /**

  9. * @Auther: shaonaiyi@163.com

  10. * @Date: 2021/8/17 14:13

  11. * @Description: 商品逻辑实现

  12. */

  13. @Service

  14. public class ProductServiceImpl implements IProductService {


  15. @Autowired

  16. private ProductDao productDao;


  17. @Override

  18. public List<Product> list() {

  19. return productDao.list();

  20. }


  21. @Override

  22. public boolean add(Product product) {

  23. int result = productDao.add(product);

  24. return result > 0;

  25. }


  26. @Override

  27. public boolean update(Product product) {

  28. int result = productDao.update(product);

  29. return result > 0;

  30. }


  31. @Override

  32. public boolean delete(Product product) {

  33. int result = productDao.delete(product.getId());

  34. return result > 0;

  35. }

  36. }

复制
编写 ProductDao.java

完整代码:

  1. package com.shaonaiyi.minimall.dao;

  2. import com.shaonaiyi.minimall.entity.Product;

  3. import java.util.List;


  4. /**

  5. * @Auther: shaonaiyi@163.com

  6. * @Date: 2021/8/17 14:18

  7. * @Description: 商品Dao接口

  8. */

  9. public interface ProductDao {


  10. List<Product> list();

  11. int add(Product product);

  12. int update(Product product);

  13. int delete(int id);


  14. }

复制
编写 ProductDao.xml

完整代码:

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <!DOCTYPE mapper PUBLIC

  3. "-//mybatis.org//DTD Mapper 3.0//EN"

  4. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

  5. <mapper namespace="com.shaonaiyi.minimall.dao.ProductDao">

  6. <resultMap id="Product" type="com.shaonaiyi.minimall.entity.Product">

  7. <id property="id" column="id"></id>

  8. <result property="productName" column="productName"/>

  9. <result property="nums" column="nums"/>

  10. </resultMap>


  11. <select id="list" resultMap="Product">

  12. select * from product;

  13. </select>


  14. <insert id="add">

  15. insert into product

  16. (productname,nums) values(#{productName},#{nums})

  17. </insert>


  18. <update id="update" parameterType="com.shaonaiyi.minimall.entity.Product">

  19. update product set productname = #{productName},

  20. nums = #{nums} where

  21. id = #{id}

  22. </update>


  23. <delete id="delete" parameterType="int">

  24. delete from product where

  25. id = #{id}

  26. </delete>

  27. </mapper>

复制

注意:到底是写 productname
还是 productName
,需要分清。写好之后,你就可以进行部署运行和测试了。

4、部署Tomcat

此步骤比较简单,可以自行搜一下资料,灵感参考如下:

5、编写测试用例

随便新建个文件夹,然后新建一个以 http
后缀结尾的文件,然后写测试用例即可:完整的测试用例

  1. ### 1、获取商品列表

  2. GET http://localhost:8080/product/list


  3. ### 2、添加商品

  4. POST http://localhost:8080/product/add

  5. Content-Type: application/json


  6. {

  7. "productName": "裙子",

  8. "nums": 150

  9. }


  10. ### 3、更新商品

  11. POST http://localhost:8080/product/update

  12. Content-Type: application/json


  13. {

  14. "id":1,

  15. "productName": "皮靴",

  16. "nums": 88

  17. }


  18. ### 4、删除商品

  19. POST http://localhost:8080/product/delete

  20. Content-Type: application/json


  21. {

  22. "id":30

  23. }


  24. ### 5、添加商品(非JSON方式)

  25. POST http://localhost:8080/product/add-test

  26. Content-Type: application/x-www-form-urlencoded


  27. productName=裙子&nums=150


  28. ### 6、删除商品(非JSON方式)

  29. POST http://localhost:8080/product/delete-test

  30. Content-Type: application/x-www-form-urlencoded


  31. id=29


  32. ###

复制

写好测试用例后,左边会有个运行按钮,当你的 Tomcat
启动后,点击绿色小三角按钮就可以测试了:下面会有返回的结果。所以,直接使用 IDEA
进行测试是非常方便的。

测试小技巧:

http
文件中,直接打 gtr
gtrp
ptr
ptrg
可以生成相应的代码,只需要写必要的参数就可以了,自己可以多试试。

00x2 前端代码实现

步骤总览

1、编写未对接数据库的前端代码 2、对接查询商品列表接口 3、SSM后台代码实现 4、部署Tomcat 5、编写测试用例

步骤实现

1、编写未对接数据库的前端代码

参考教程::Vue2.x案例之商品增删改查的实现。

在项目中新建一个 web
文件夹,然后新建 index.html
文件,因为代码比较简单,所以这里我使用传统的开发模式,方便大家入门:然后就可以把教程中的代码粘贴进去了,用浏览器打开 index.html
文件,其实就可以实现增删改查了,只不过,页面都是没有对接数据库的,所以刷新页面的时候,页面会恢复原样,这当然不是我们所想要实现的效果!

2、对接查询商品列表接口

目前的商品数据是直接写死的:

  1. var data = {

  2. products: [

  3. { id: 1, productName: '袜子', nums: 15},

  4. { id: 2, productName: '羊毛衫', nums: 20},

  5. { id: 3, productName: '雪纺衫', nums: 24},

  6. { id: 4, productName: '高跟鞋', nums: 30}

  7. ],

  8. product4Add: { id: 0, productName: '', nums: '0'},

  9. product4Update: { id: 0, productName: '', nums: '0'}

  10. };

复制

并且绑定到了Vue里面的data:

  1. var vue = new Vue({

  2. el: '#app',

  3. data: data,

  4. ...

复制

而我们应该做的是从后台的接口里获取到数据。

步骤如下:我们将会引入 axios
,方便我们请求后台接口,然后写 list
方法对接后台的接口,查询到商品列表信息,你可以给出一个按钮,然后再执行list方法,但一般列表应该是一加载页面就去查询的。所以,我们可以使用Vue中的 mounted
钩子函数来达到这个目的。

1、引入axios

添加AJAX

  1. <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>

复制

2、编写list方法对接后台接口

  1. list() {

  2. let _this = this;

  3. axios.get("http://localhost:8080/product/list").then(

  4. (response) => {

  5. console.log("查询用户列表结果:", response);

  6. _this.products = response.data;

  7. }

  8. )

  9. },

复制

3、添加 mounted
钩子函数

  1. mounted: function () {

  2. let _this = this;

  3. _this.list();

  4. },

复制

4、删除初始化的商品数据

  1. var data = {

  2. products: [],

  3. ...

  4. };

复制

目前的完整代码如下:

  1. <html>

  2. <head>

  3. <meta charset="utf-8"/>

  4. <script src="https://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>

  5. <script src="https://cdn.bootcss.com/vue/2.5.22/vue.min.js"></script>

  6. <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>


  7. ...省略部分未变代码


  8. <script type="text/javascript">

  9. $("#div4Update").hide();

  10. //Model

  11. var data = {

  12. products: [],

  13. product4Add: {id: 0, productName: '', nums: '0'},

  14. product4Update: {id: 0, productName: '', nums: '0'}

  15. };


  16. ...省略部分未变代码


  17. //ViewModel

  18. var vue = new Vue({

  19. el: '#app',

  20. data: data,

  21. mounted: function () {

  22. let _this = this;

  23. _this.list();

  24. },

  25. methods: {

  26. list() {

  27. let _this = this;

  28. axios.get("http://localhost:8080/product/list").then(

  29. (response) => {

  30. console.log("查询用户列表结果:", response);

  31. _this.products = response.data;

  32. }

  33. )

  34. },

  35. add: function (event) {

  36. ...省略以下未变代码

复制

代码比较多,其实没改几个地方,放出来代码,方便大家查阅。

3、对接删除商品接口

因为我们目前的 id
不是从后台获取的,所以,你可以把 id
获取到,然后显示出来,当然你也可以隐藏掉。隐藏掉操作如下,只需要加一句话就可以:

  1. <td hidden>{{product.id}}</td>

复制

但是你不获取,其实也可以,目前我们没有涉及到,所以不操作上面的步骤。

我们可以先把这段代码删掉,因为没有意义了:

  1. var maxId = 5;

  2. for (var i = 0; i < data.products.length; i++) {

  3. if (data.products[i].id > maxId)

  4. maxId = this.products[i].id;1

  5. }

复制

然后将删除方法的代码修改为:

  1. deleteProduct: function (id) {

  2. let _this = this;

  3. axios.post("http://localhost:8080/product/delete",

  4. {

  5. id: id

  6. }

  7. ).then(

  8. (response) => {

  9. if (response.data) {

  10. console.log("删除商品成功!");

  11. _this.list();

  12. }

  13. }

  14. )

  15. },

复制

说明:这里传参数,需要传 JSON
格式,否则无法跟后台接口对应上!(教程后面有完整代码

4、对接增加商品接口

增加接口与删除接口类似,把数据 post
给后端就可以了。修改 product4Add
,删除初始值:

  1. var data = {

  2. products: [],

  3. product4Add: {},

  4. product4Update: {id: 0, productName: '', nums: '0'}

  5. };

复制

注意:1、这里是大括号 {}
,不是中括号 []
,不然不行!2、 []
表示一个数组, {}
表示一个对象。

修改 add
方法:

  1. add: function (product) {

  2. let _this = this;

  3. axios.post("http://localhost:8080/product/add", product).then(

  4. (response) => {

  5. if (response.data) {

  6. console.log("添加商品成功!");

  7. _this.product4Add = {};

  8. _this.list();

  9. }

  10. }

  11. )

  12. },

复制

跟删除的方法非常相似,只不过这里是直接就传了一个 product
对象而已,与 JSON
格式是匹配的。注意,此时,在点击 增加
按钮的时候,需要传一个 product
参数进来,所以需要加上:

  1. <button type="button" v-on:click="add(product4Add)">增加</button>

复制
5、对接修改商品接口

修改接口与增加接口类似,修改 product4Update
,删除初始值:

  1. var data = {

  2. products: [],

  3. product4Add: {},

  4. product4Update: {}

  5. };

复制

修改 edit
update
方法

  1. edit: function (product) {

  2. $("#productListTable").hide();

  3. $("#div4Update").show();

  4. let _this = this;

  5. _this.product4Update = product;

  6. },

  7. update: function (product) {

  8. let _this = this;

  9. axios.post("http://localhost:8080/product/update", product).then(

  10. (response) => {

  11. if (response.data) {

  12. console.log("修改商品成功!");

  13. _this.product4Add = {};

  14. $("#productListTable").show();

  15. $("#div4Update").hide();

  16. }

  17. }

  18. )

  19. },

复制

需要传一个 product
参数进来,所以需要加上:

  1. <button type="button" v-on:click="update(product4Update)">修改</button>

复制

说明:虽然更新页面里没有要求输入 id
,但是当你点击 编辑
按钮之后,其实是有带了 id
进去的。

那么到这里,然后修改功能就实现了!

老规矩,下面给出完整的代码!

6、index.html 完整代码
  1. <html>

  2. <head>

  3. <meta charset="utf-8"/>

  4. <script src="https://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>

  5. <script src="https://cdn.bootcss.com/vue/2.5.22/vue.min.js"></script>

  6. <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>


  7. <style type="text/css">

  8. td {

  9. border: 1px solid #000;

  10. }

  11. </style>

  12. </head>


  13. <body>

  14. <div id="app">

  15. <table id="productListTable">

  16. <thead>

  17. <tr>

  18. <th>商品名称</th>

  19. <th>数量</th>

  20. <th>操作</th>

  21. </tr>

  22. </thead>

  23. <tbody>

  24. <tr v-for="product in products">

  25. <td>{{product.productName}}</td>

  26. <td>{{product.nums}}</td>

  27. <td>

  28. <a href="#nowhere" @click="edit(product)">编辑</a>

  29. <a href="#nowhere" @click="deleteProduct(product.id)">删除</a>

  30. </td>

  31. </tr>

  32. <tr>

  33. <td colspan="3">

  34. 商品名称:

  35. <input type="text" v-model="product4Add.productName"/>

  36. <br>

  37. 数量:

  38. <input type="number" v-model="product4Add.nums"/>

  39. <br>

  40. <button type="button" v-on:click="add(product4Add)">增加</button>

  41. </td>

  42. </tr>

  43. </tbody>

  44. </table>


  45. <div id="div4Update">

  46. 商品名称:

  47. <input type="text" v-model="product4Update.productName"/>

  48. <br>

  49. 数量:

  50. <input type="number" v-model="product4Update.nums"/>

  51. <input type="hidden" v-model="product4Update.id"/>

  52. <br>

  53. <button type="button" v-on:click="update(product4Update)">修改</button>

  54. <button type="button" v-on:click="cancel">取消</button>


  55. </div>

  56. </div>


  57. <script type="text/javascript">

  58. $("#div4Update").hide();

  59. //Model

  60. var data = {

  61. products: [],

  62. product4Add: {},

  63. product4Update: {}

  64. };


  65. //ViewModel

  66. var vue = new Vue({

  67. el: '#app',

  68. data: data,

  69. mounted: function () {

  70. let _this = this;

  71. _this.list();

  72. },

  73. methods: {

  74. list() {

  75. let _this = this;

  76. axios.get("http://localhost:8080/product/list").then(

  77. (response) => {

  78. console.log("查询用户列表结果:", response);

  79. _this.products = response.data;

  80. }

  81. )

  82. },

  83. add: function (product) {

  84. let _this = this;

  85. axios.post("http://localhost:8080/product/add", product).then(

  86. (response) => {

  87. if (response.data) {

  88. console.log("添加商品成功!");

  89. _this.product4Add = {};

  90. _this.list();

  91. }

  92. }

  93. )

  94. },

  95. deleteProduct: function (id) {

  96. let _this = this;

  97. console.log("id" + id);

  98. axios.post("http://localhost:8080/product/delete",

  99. {

  100. id: id

  101. }

  102. ).then(

  103. (response) => {

  104. if (response.data) {

  105. console.log("删除商品成功!");

  106. _this.list();

  107. }

  108. }

  109. )

  110. },

  111. edit: function (product) {

  112. $("#productListTable").hide();

  113. $("#div4Update").show();

  114. let _this = this;

  115. _this.product4Update = product;

  116. },

  117. update: function (product) {

  118. let _this = this;

  119. axios.post("http://localhost:8080/product/update", product).then(

  120. (response) => {

  121. if (response.data) {

  122. console.log("修改商品成功!");

  123. _this.product4Add = {};

  124. $("#productListTable").show();

  125. $("#div4Update").hide();

  126. }

  127. }

  128. )

  129. },

  130. cancel: function () {

  131. //恢复显示

  132. $("#productListTable").show();

  133. $("#div4Update").hide();

  134. }

  135. }

  136. });

  137. </script>

  138. </body>

  139. </html>

复制

当然,代码还是有可以优化的地方的,但毕竟不想改那么多,如果你觉得不服,你可以从屏幕里出来打我!这篇文章断断续续写了快一个月才完成,好累啊!将近3w字!!!多多转发,一起学习!!感谢支持!!!

0xFF 总结

  1. 这篇文章使用SSM技术实现了后端,并且通过IDEA实现了测试,完全不依赖前端操作。然后随便建了文件夹就可以把前端给实现了,让有点前端基础的人也能轻松实现我们这一次的操作。完全打工前后端分离开发的流程!

  2. 请关注本博客,本博客很多文章都是在原博客上迭代写的,提供多种解决方案,有利于小伙伴们不迷路,感谢支持!

  3. 小伙伴们肯定觉得这个样式太难看了吧!本博客里有一篇配套的调整样式的文章,请参考:Bootstrap全局css样式的使用,效果是这样子滴,希望大家学得开心: 

邵奈一 原创不易,如转载请标明出处,教育是一生的事业。



文章转载自邵奈一,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论