代码地址:https://gitee.com/szxio/ssm-crud
项目搭建 使用maven创建一个工程
pom.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 <?xml version="1.0" encoding="UTF-8"?> <project xmlns ="http://maven.apache.org/POM/4.0.0" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > <modelVersion > 4.0.0</modelVersion > <groupId > com.szx.ssm</groupId > <artifactId > ssmcrud</artifactId > <version > 1.0-SNAPSHOT</version > <packaging > war</packaging > <properties > <maven.compiler.source > 8</maven.compiler.source > <maven.compiler.target > 8</maven.compiler.target > </properties > <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-webmvc</artifactId > <version > 5.2.22.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-jdbc</artifactId > <version > 5.2.22.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-aspects</artifactId > <version > 5.2.22.RELEASE</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-test</artifactId > <version > 5.2.22.RELEASE</version > <scope > test</scope > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.10</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis-spring</artifactId > <version > 2.0.7</version > </dependency > <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 5.2.0</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.6</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.29</version > </dependency > <dependency > <groupId > jstl</groupId > <artifactId > jstl</artifactId > <version > 1.2</version > </dependency > <dependency > <groupId > javax.servlet</groupId > <artifactId > javax.servlet-api</artifactId > <version > 3.1.0</version > <scope > provided</scope > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > </dependency > <dependency > <groupId > org.thymeleaf</groupId > <artifactId > thymeleaf-spring5</artifactId > <version > 3.0.12.RELEASE</version > </dependency > <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.17</version > </dependency > </dependencies > <build > <plugins > <plugin > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-maven-plugin</artifactId > <version > 1.3.0</version > <dependencies > <dependency > <groupId > org.mybatis.generator</groupId > <artifactId > mybatis-generator-core</artifactId > <version > 1.3.2</version > </dependency > <dependency > <groupId > com.alibaba</groupId > <artifactId > druid</artifactId > <version > 1.1.6</version > </dependency > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.29</version > </dependency > </dependencies > </plugin > </plugins > </build > </project >
web.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns ="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation ="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version ="4.0" > <context-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:ApplicationContext.xml</param-value > </context-param > <listener > <listener-class > org.springframework.web.context.ContextLoaderListener</listener-class > </listener > <servlet > <servlet-name > dispatcherServlet</servlet-name > <servlet-class > org.springframework.web.servlet.DispatcherServlet</servlet-class > <init-param > <param-name > contextConfigLocation</param-name > <param-value > classpath:SpringMvc.xml</param-value > </init-param > <load-on-startup > 1</load-on-startup > </servlet > <servlet-mapping > <servlet-name > dispatcherServlet</servlet-name > <url-pattern > /</url-pattern > </servlet-mapping > <filter > <filter-name > CharacterEncodingFilter</filter-name > <filter-class > org.springframework.web.filter.CharacterEncodingFilter</filter-class > <init-param > <param-name > encoding</param-name > <param-value > utf-8</param-value > </init-param > <init-param > <param-name > forceRequestEncoding</param-name > <param-value > true</param-value > </init-param > <init-param > <param-name > forceResponseEncoding</param-name > <param-value > true</param-value > </init-param > </filter > <filter-mapping > <filter-name > CharacterEncodingFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > <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 > <filter > <filter-name > HttpPutFormContentFilter</filter-name > <filter-class > org.springframework.web.filter.HttpPutFormContentFilter</filter-class > </filter > <filter-mapping > <filter-name > HttpPutFormContentFilter</filter-name > <url-pattern > /*</url-pattern > </filter-mapping > </web-app >
SpringMvc.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:mvc ="http://www.springframework.org/schema/mvc" 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/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd" > <context:component-scan base-package ="com.szx.ssm" use-default-filters ="false" > <context:include-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan > <bean id ="viewResolver" class ="org.thymeleaf.spring5.view.ThymeleafViewResolver" > <property name ="order" value ="1" /> <property name ="characterEncoding" value ="UTF-8" /> <property name ="templateEngine" > <bean class ="org.thymeleaf.spring5.SpringTemplateEngine" > <property name ="templateResolver" > <bean class ="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver" > <property name ="prefix" value ="/WEB-INF/static/" /> <property name ="suffix" value =".html" /> <property name ="templateMode" value ="HTML5" /> <property name ="characterEncoding" value ="UTF-8" /> </bean > </property > </bean > </property > </bean > <mvc:default-servlet-handler /> <mvc:annotation-driven /> </beans >
ApplicationContext.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:context ="http://www.springframework.org/schema/context" xmlns:tx ="http://www.springframework.org/schema/tx" xmlns:aop ="http://www.springframework.org/schema/aop" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd" > <context:component-scan base-package ="com.szx" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan > <context:property-placeholder location ="classpath:jdbc.properties" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" > <property name ="url" value ="${jdbc.url}" /> <property name ="username" value ="${jdbc.username}" /> <property name ="password" value ="${jdbc.password}" /> <property name ="driverClassName" value ="${jdbc.driver}" /> </bean > <bean id ="sqlSessionFactory" class ="org.mybatis.spring.SqlSessionFactoryBean" > <property name ="dataSource" ref ="dataSource" > </property > <property name ="configLocation" value ="classpath:mybatis-config.xml" > </property > <property name ="mapperLocations" value ="classpath:com/szx/ssm/mapper/*.xml" > </property > </bean > <bean id ="sqlSession" class ="org.mybatis.spring.SqlSessionTemplate" > <constructor-arg name ="sqlSessionFactory" ref ="sqlSessionFactory" /> <constructor-arg name ="executorType" value ="SIMPLE" /> </bean > <bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer" > <property name ="basePackage" value ="com.szx.ssm.dao" > </property > </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" > </property > </bean > <aop:config > <aop:pointcut expression ="execution(* com.szx.ssm.servlet..*(..))" id ="txPoint" /> <aop:advisor advice-ref ="txAdvice" pointcut-ref ="txPoint" /> </aop:config > <tx:advice id ="txAdvice" transaction-manager ="transactionManager" > <tx:attributes > <tx:method name ="*" /> <tx:method name ="get*" read-only ="true" /> </tx:attributes > </tx:advice > </beans >
jdbc.properties 1 2 3 4 jdbc.url =jdbc:mysql://127.0.0.1:3306/ssm jdbc.username =root jdbc.password =abc123 jdbc.driver =com.mysql.jdbc.Driver
mybatis-config.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="lazyLoadingEnabled" value ="true" /> </settings > <typeAliases > <package name ="com.szx.ssm.bean" /> </typeAliases > <plugins > <plugin interceptor ="com.github.pagehelper.PageInterceptor" > </plugin > </plugins > </configuration >
generatorConfig.xml 设置逆向工程的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" > <generatorConfiguration > <context id ="DB2Tables" targetRuntime ="MyBatis3" > <commentGenerator > <property name ="suppressAllComments" value ="true" > </property > </commentGenerator > <jdbcConnection driverClass ="com.mysql.cj.jdbc.Driver" connectionURL ="jdbc:mysql://localhost:3306/ssm" userId ="root" password ="abc123" > </jdbcConnection > <javaModelGenerator targetPackage ="com.szx.ssm.bean" targetProject =".\src\main\java" > <property name ="enableSubPackages" value ="true" /> <property name ="trimStrings" value ="true" /> </javaModelGenerator > <sqlMapGenerator targetPackage ="com.szx.ssm.mapper" targetProject =".\src\main\resources" > <property name ="enableSubPackages" value ="true" /> </sqlMapGenerator > <javaClientGenerator type ="XMLMAPPER" targetPackage ="com.szx.ssm.dao" targetProject =".\src\main\java" > <property name ="enableSubPackages" value ="true" /> </javaClientGenerator > <table tableName ="tb_dept" domainObjectName ="tbDept" /> <table tableName ="tb_emp" domainObjectName ="tbEmp" /> </context > </generatorConfiguration >
log4j.xml 日志文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE log4j :configuration SYSTEM "log4j.dtd" > <log4j:configuration xmlns:log4j ="http://jakarta.apache.org/log4j/" > <appender name ="STDOUT" class ="org.apache.log4j.ConsoleAppender" > <param name ="Encoding" value ="UTF-8" /> <layout class ="org.apache.log4j.PatternLayout" > <param name ="ConversionPattern" value ="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" /> </layout > </appender > <logger name ="java.sql" > <level value ="debug" /> </logger > <logger name ="org.apache.ibatis" > <level value ="info" /> </logger > <root > <level value ="debug" /> <appender-ref ref ="STDOUT" /> </root > </log4j:configuration >
执行逆向工程 上面的配置文件配置成功后双击这里自动生成代码
项目结构
测试方法 测试基本查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:ApplicationContext.xml"}) public class TestEmp { @Autowired private tbEmpMapper tbEmpMapper; @Autowired private tbDeptMapper tbDeptMapper; @Autowired private SqlSession sqlSession; @Test public void test () { PageHelper.startPage(1 ,5 ); List<tbEmp> tbEmps = tbEmpMapper.selectByExample(null ); PageInfo<tbEmp> pageInfo = new PageInfo<>(tbEmps,5 ); tbEmps.forEach(emp-> System.out.println(emp)); System.out.println(pageInfo); } }
测试批量添加方法 在 ApplicationContext.xml 配置文件中添加如下配置,配置的位置在 sqlSessionFactory 之后
1 2 3 4 5 <bean id ="sqlSession" class ="org.mybatis.spring.SqlSessionTemplate" > <constructor-arg name ="sqlSessionFactory" ref ="sqlSessionFactory" /> <constructor-arg name ="executorType" value ="SIMPLE" /> </bean >
添加测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 @Test public void test6 () { tbEmpMapper mapper = sqlSession.getMapper(tbEmpMapper.class); for (int i = 0 ; i < 200 ; i++) { String empName = UUID.randomUUID().toString().substring(0 , 6 ); tbEmp emp = new tbEmp(null , empName, "1" , empName + "@szx.com" , 1 ); int i1 = mapper.insertSelective(emp); System.out.println(i1); } }
虚拟ioc模拟接口请求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 package com.szx.ssm.test;import com.github.pagehelper.PageInfo;import org.junit.Before;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.mock.web.MockHttpServletRequest;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import org.springframework.test.context.web.WebAppConfiguration;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.MvcResult;import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;import org.springframework.test.web.servlet.setup.MockMvcBuilders;import org.springframework.web.context.WebApplicationContext;import java.util.List;@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(locations = {"classpath:ApplicationContext.xml","classpath:SpringMvc.xml"}) public class TestMvc { @Autowired WebApplicationContext ioc; MockMvc mockMvc; @Before public void initMockMvc () { mockMvc = MockMvcBuilders.webAppContextSetup(ioc).build(); } @Test public void test () throws Exception { MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/" ) .param("pageNumber" , "2" )) .andReturn(); MockHttpServletRequest request = result.getRequest(); PageInfo pageInfo = (PageInfo) request.getAttribute("pageInfo" ); List empList = pageInfo.getList(); empList.forEach(emp-> System.out.println(emp)); System.out.println(pageInfo); } }
访问首页并实现分页跳转 添加tbEmpServlet 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.szx.ssm.servlet;import com.github.pagehelper.PageHelper;import com.github.pagehelper.PageInfo;import com.szx.ssm.bean.tbDept;import com.szx.ssm.bean.tbEmp;import com.szx.ssm.dao.tbDeptMapper;import com.szx.ssm.dao.tbEmpMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Service public class tbEmpServlet { @Autowired tbEmpMapper tbEmpMapper; @Autowired tbDeptMapper tbDeptMapper; public PageInfo getEmpList (Integer pageNumber) { PageHelper.startPage(pageNumber,10 ); List<tbEmp> empList = tbEmpMapper.selectByExample(null ); for (tbEmp tbEmp : empList) { tbDept dept = tbDeptMapper.selectByPrimaryKey(tbEmp.getdId()); tbEmp.setTbDept(dept); } PageInfo<tbEmp> pageInfo = new PageInfo<>(empList,5 ); return pageInfo; } }
添加Controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.szx.ssm.controller;import com.github.pagehelper.PageHelper;import com.github.pagehelper.PageInfo;import com.szx.ssm.bean.tbEmp;import com.szx.ssm.servlet.tbEmpServlet;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.ui.Model;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import java.util.List;@Controller public class IndexController { @Autowired tbEmpServlet tbEmpServlet; @GetMapping("/") public String index (@RequestParam(value = "pageNumber",defaultValue = "1") Integer pageNumber,Model model) { PageInfo pageInfo = tbEmpServlet.getEmpList(pageNumber); model.addAttribute("pageInfo" ,pageInfo); return "index" ; } }
使用BootScript搭建前端页面 用到的 thymeleaf 语法
th:class="${pageInfo.pageNum eq 1} ? 'disabled' : ''"
eq 相当于 ==
th:if="${pageInfo.pageNum ne 1}"
ne 相当于 !=
更多语法使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <!DOCTYPE html > <html lang ="en" xmlns:th ="http://www.thymeleaf.org" > <head > <meta charset ="UTF-8" > <title > Title</title > <link rel ="stylesheet" href ="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" > </head > <body > <div class ="row" style ="margin-top: 30px" > <div class ="col-md-8 col-md-offset-2" > <h3 > 员工管理系统</h3 > <table class ="table table-bordered table-striped" > <tr > <th > 序号</th > <th > 姓名</th > <th > 性别</th > <th > 邮箱</th > <th > 所在部门</th > <th > 操作</th > </tr > <tr th:each ="item : ${pageInfo.list}" > <td th:text ="${item.empId}" > 123</td > <td th:text ="${item.empName}" > 123</td > <td th:text ="${item.gender}" > 123</td > <td th:text ="${item.email}" > 123</td > <td th:text ="${item.tbDept.deptName}" > 123</td > <td > <button type ="button" class ="btn btn-warning" > 编辑</button > <button type ="button" class ="btn btn-danger" > 删除</button > </td > </tr > </table > <nav aria-label ="Page navigation" style ="margin-top: -27px; float: right;" > <ul class ="pagination" > <li th:class ="${pageInfo.pageNum eq 1} ? 'disabled' : ''" > <a th:href ="@{/?pageNumber=1}" > 首页</a > </li > <li th:if ="${pageInfo.pageNum ne 1}" > <a th:href ="@{/(pageNumber=${pageInfo.prePage})}" aria-label ="Previous" > <span aria-hidden ="true" > « </span > </a > </li > <li th:each ="page : ${pageInfo.navigatepageNums}" th:class ="${page eq pageInfo.pageNum} ? 'active' : ''" > <a th:href ="@{/(pageNumber=${page})}" th:text ="${page}" > </a > </li > <li th:if ="${pageInfo.hasNextPage}" > <a th:href ="@{/(pageNumber=${pageInfo.nextPage})}" aria-label ="Next" > <span aria-hidden ="true" > » </span > </a > </li > <li th:class ="${pageInfo.pageNum eq pageInfo.pages} ? 'disabled' : ''" > <a th:href ="@{/(pageNumber=${pageInfo.pages})}" > 尾页</a > </li > </ul > </nav > </div > </div > <script src ="https://code.jquery.com/jquery-3.6.0.min.js" > </script > <script src ="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" > </script > </body > </html >
效果展示
封装msg对象返回json数据 定义通用的msg对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 package com.szx.ssm.bean;import java.util.HashMap;import java.util.Map;public class Msg { int code; String message; HashMap<String,Object> data = new HashMap<>(); public static Msg success () { Msg msg = new Msg(); msg.setCode(200 ); msg.setMessage("成功" ); return msg; } public static Msg error () { Msg msg = new Msg(); msg.setCode(500 ); msg.setMessage("失败" ); return msg; } public Msg add (String key,Object data) { this .getData().put(key,data); return this ; } public int getCode () { return code; } public void setCode (int code) { this .code = code; } public String getMessage () { return message; } public void setMessage (String message) { this .message = message; } public HashMap<String, Object> getData () { return data; } public void setData (HashMap<String, Object> data) { this .data = data; } public Msg (int code, String message, HashMap<String, Object> data) { this .code = code; this .message = message; this .data = data; } public Msg () { } }
添加返回json的依赖包
1 2 3 4 5 6 <dependency > <groupId > com.fasterxml.jackson.core</groupId > <artifactId > jackson-databind</artifactId > <version > 2.12.1</version > </dependency >
在 SpringMVC.xml 中添加注解驱动
1 <mvc:annotation-driven />
重写获取员工列表的接口
1 2 3 4 5 6 7 8 @GetMapping("/") @ResponseBody public Msg getEmpList (@RequestParam(value = "pageNum",defaultValue = "1") Integer pageNum) { PageInfo empList = tbEmpServlet.getEmpList(pageNum); Msg msg = Msg.success().add("empList" , empList); return msg; }
再次发起请求查看返回
使用vue改写前端页面 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <link rel ="stylesheet" href ="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" > </head > <body > <div class ="row" style ="margin-top: 30px" id ="app" > <div class ="col-md-8 col-md-offset-2" > <h3 > 员工管理系统</h3 > <div > <div class ="form-inline" > <div class ="form-group" > <div class ="input-group" > <input type ="text" class ="form-control" v-model ="empname" placeholder ="请输入员工姓名" > </div > </div > <button class ="btn btn-primary" @click ="pageFun(1)" > 查询</button > </div > </div > <table class ="table table-bordered table-striped" > <tr > <th > 序号</th > <th > 姓名</th > <th > 性别</th > <th > 邮箱</th > <th > 所在部门</th > <th > 操作</th > </tr > <tr v-for ="(item,index) in empList" :key ="index" > <td > {{index + 1}}</td > <td > {{item.empName}}</td > <td > {{item.gender == '1' ? '男' : '女'}}</td > <td > {{item.email}}</td > <td > {{item.tbDept ? item.tbDept.deptName : ''}}</td > <td > <button type ="button" class ="btn btn-warning" @click ="showEdit(item)" data-toggle ="modal" data-target ="#myModal" > 编辑 </button > <button type ="button" class ="btn btn-danger" @click ="deleteEmp(item.empId)" > 删除 </button > </td > </tr > </table > <div class ="row" > <div class ="col-md-6" > 当前第{{pageNum}}页,共{{pageNums}}页,一共有{{total}}条数据 </div > <div class ="col-md-6" > <nav aria-label ="Page navigation" style ="margin-top: -27px; float: right;" > <ul class ="pagination" > <li :class ="{disabled:pageNum == 1}" @click ="pageFun(1)" > <a > 首页</a > </li > <li v-show ="hasPreviousPage" @click ="pageFun(pageNum-=1)" > <a aria-label ="Previous" > <span aria-hidden ="true" > « </span > </a > </li > <li v-for ="page in pageList" :key ="page" @click ="pageFun(page)" :class ="{active:pageNum == page}" > <a > {{page}}</a > </li > <li v-show ="hasNextPage" @click ="pageFun(pageNum+=1)" > <a aria-label ="Next" > <span aria-hidden ="true" > » </span > </a > </li > <li @click ="pageFun(pageNums)" :class ="{disabled:pageNum == pageNums}" > <a > 尾页</a > </li > </ul > </nav > </div > </div > </div > </div > <script src ="https://code.jquery.com/jquery-3.6.0.min.js" > </script > <script src ="https://cdn.jsdelivr.net/npm/vue@2.6.14" > </script > <script src ="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" > </script > <script src ="https://unpkg.com/axios/dist/axios.min.js" > </script > <script > const http = axios.create({ baseURL: '/ssmcrud' , }); http.interceptors.response.use(function (response ) { return response.data; }, function (error ) { return Promise .reject(error); }); new Vue({ el: '#app' , data: { empList: [], pageList: [], total:0 , pageNums:0 , hasNextPage:false , hasPreviousPage:false , pageNum:1 , empname:"" , rowEmp:{}, deptList:[] }, mounted: function ( ) { this .getEmpList() }, methods: { pageFun (page ) { this .pageNum = page this .getEmpList() }, getEmpList: function ( ) { http.get(`/getEmpList/${this .pageNum} /${this .empname} ` ).then(res => { console .log(res) this .empList = res.data.empList.list this .pageList = res.data.empList.navigatepageNums this .total = res.data.empList.total this .pageNums = res.data.empList.pages this .hasNextPage = res.data.empList.hasNextPage this .hasPreviousPage = res.data.empList.hasPreviousPage }) }, } }) </script > </body > </html >
模糊查询用户名 在 tbEmpServlet 中添加模糊查询方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public PageInfo getEmpListByName (Integer pageNum,String name) { PageHelper.startPage(pageNum,10 ); tbEmpExample example = new tbEmpExample(); example.createCriteria().andEmpNameLike("%" +name+"%" ); List<tbEmp> tbEmps = tbEmpMapper.selectByExample(example); for (tbEmp tbEmp : tbEmps) { tbDept dept = tbDeptMapper.selectByPrimaryKey(tbEmp.getdId()); tbEmp.setTbDept(dept); } PageInfo<tbEmp> pageInfo = new PageInfo<>(tbEmps,5 ); return pageInfo; }
在 IndexController 中调用
1 2 3 4 5 6 7 8 9 10 11 12 13 @GetMapping("/getEmpList/{pageNum}/{empName}") @ResponseBody public Msg getEmpListByName (@PathVariable("pageNum") Integer pageNum, @PathVariable("empName") String name ) { PageInfo empListByName = tbEmpServlet.getEmpListByName(pageNum, name); Msg msg = Msg.success().add("empList" , empListByName); return msg; }
前端发起请求
1 2 3 4 5 6 7 8 9 10 11 12 getEmpList: function ( ) { http.get(`/getEmpList/${this .pageNum} /${this .empname} ` ).then(res => { console .log(res) this .empList = res.data.empList.list this .pageList = res.data.empList.navigatepageNums this .total = res.data.empList.total this .pageNums = res.data.empList.pages this .hasNextPage = res.data.empList.hasNextPage this .hasPreviousPage = res.data.empList.hasPreviousPage }) },
添加删除方法 在 tbEmpServlet 中添加根据id删除
1 2 3 4 5 6 7 8 9 public int deleteEmpById (Integer id) { int i = tbEmpMapper.deleteByPrimaryKey(id); return i; }
在 IndexController 中调用 deleteEmpById 方法
1 2 3 4 5 6 7 8 9 10 11 12 @DeleteMapping("/deleteEmp/{id}") @ResponseBody public Msg deleteEmpByid (@PathVariable("id") Integer id) { tbEmpServlet.deleteEmpById(id); Msg msg = Msg.success(); return msg; }
前端发起请求
1 2 3 4 5 6 7 8 9 10 <td > <button type ="button" class ="btn btn-warning" data-toggle ="modal" data-target ="#myModal" > 编辑 </button > <button type ="button" class ="btn btn-danger" @click ="deleteEmp(item.empId)" > 删除 </button > </td >
1 2 3 4 5 6 7 deleteEmp (id ) { http.delete(`/deleteEmp/${id} ` ).then(res => { this .pageNum = 1 this .getEmpList() }) },
编辑和新增方法 首先添加查询所有部门的方法
在 tbDepServlet 添加获取部门
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.szx.ssm.servlet;import com.szx.ssm.bean.tbDept;import com.szx.ssm.dao.tbDeptMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.List;@Service public class tbDepServlet { @Autowired tbDeptMapper deptMapper; public List<tbDept> getDeptList () { List<tbDept> tbDepts = deptMapper.selectByExample(null ); return tbDepts; } }
在 DeptController 调用 getDeptList 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 package com.szx.ssm.controller;import com.szx.ssm.bean.Msg;import com.szx.ssm.bean.tbDept;import com.szx.ssm.servlet.tbDepServlet;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.ResponseBody;import java.util.List;@Controller public class DeptController { @Autowired tbDepServlet depServlet; @GetMapping("/getDeptList") @ResponseBody public Msg getDeptList () { List<tbDept> deptList = depServlet.getDeptList(); Msg msg = Msg.success().add("deptList" , deptList); return msg; } }
在 tbEmpServlet 中添加编辑和新增方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public int addEmpInfo (tbEmp tbEmp) { int insert = tbEmpMapper.insertSelective(tbEmp); return insert; } public int updateEmp (tbEmp tbEmp) { int i = tbEmpMapper.updateByPrimaryKeySelective(tbEmp); return i; }
在 IndexController 调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @PostMapping("/andOrUpdateEmp") @ResponseBody public Msg addOrUpdateEmp (@RequestBody tbEmp emp) { System.out.println(emp); if (emp.getEmpId() == null ){ tbEmpServlet.addEmpInfo(emp); }else { tbEmpServlet.updateEmp(emp); } return Msg.success(); }
前端发送请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > <link rel ="stylesheet" href ="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" > </head > <body > <div class ="row" style ="margin-top: 30px" id ="app" > <div class ="col-md-8 col-md-offset-2" > <h3 > 员工管理系统</h3 > <button type ="button" class ="btn btn-primary" @click ="showEdit()" data-toggle ="modal" data-target ="#myModal" > 新增</button > <div > <div class ="form-inline" > <div class ="form-group" > <div class ="input-group" > <input type ="text" class ="form-control" v-model ="empname" placeholder ="请输入员工姓名" > </div > </div > <button class ="btn btn-primary" @click ="pageFun(1)" > 查询</button > </div > </div > <table class ="table table-bordered table-striped" > <tr > <th > 序号</th > <th > 姓名</th > <th > 性别</th > <th > 邮箱</th > <th > 所在部门</th > <th > 操作</th > </tr > <tr v-for ="(item,index) in empList" :key ="index" > <td > {{index + 1}}</td > <td > {{item.empName}}</td > <td > {{item.gender == '1' ? '男' : '女'}}</td > <td > {{item.email}}</td > <td > {{item.tbDept ? item.tbDept.deptName : ''}}</td > <td > <button type ="button" class ="btn btn-warning" @click ="showEdit(item)" data-toggle ="modal" data-target ="#myModal" > 编辑 </button > <button type ="button" class ="btn btn-danger" @click ="deleteEmp(item.empId)" > 删除 </button > </td > </tr > </table > <div class ="row" > <div class ="col-md-6" > 当前第{{pageNum}}页,共{{pageNums}}页,一共有{{total}}条数据 </div > <div class ="col-md-6" > <nav aria-label ="Page navigation" style ="margin-top: -27px; float: right;" > <ul class ="pagination" > <li :class ="{disabled:pageNum == 1}" @click ="pageFun(1)" > <a > 首页</a > </li > <li v-show ="hasPreviousPage" @click ="pageFun(pageNum-=1)" > <a aria-label ="Previous" > <span aria-hidden ="true" > « </span > </a > </li > <li v-for ="page in pageList" :key ="page" @click ="pageFun(page)" :class ="{active:pageNum == page}" > <a > {{page}}</a > </li > <li v-show ="hasNextPage" @click ="pageFun(pageNum+=1)" > <a aria-label ="Next" > <span aria-hidden ="true" > » </span > </a > </li > <li @click ="pageFun(pageNums)" :class ="{disabled:pageNum == pageNums}" > <a > 尾页</a > </li > </ul > </nav > </div > </div > </div > <div class ="modal fade" tabindex ="-1" role ="dialog" aria-labelledby ="myLargeModalLabel" id ="myModal" > <div class ="modal-dialog modal-lg modal-content" role ="document" > <div class ="modal-header" > <button type ="button" class ="close" data-dismiss ="modal" aria-label ="Close" > <span aria-hidden ="true" > × </span > </button > <h4 class ="modal-title" > 编辑</h4 > </div > <div class ="modal-body" style ="padding: 20px" > <div > <div class ="form-group" > <label > 姓名</label > <input v-model ="rowEmp.empName" class ="form-control" placeholder ="请输入姓名" > </div > <div class ="form-group" > <label > 性别</label > <div > <label class ="radio-inline" > <input v-model ="rowEmp.gender" type ="radio" name ="inlineRadioOptions" value ="1" > 男 </label > <label class ="radio-inline" > <input v-model ="rowEmp.gender" type ="radio" name ="inlineRadioOptions" value ="2" > 女 </label > </div > </div > <div class ="form-group" > <label > 邮箱</label > <input v-model ="rowEmp.email" class ="form-control" type ="text" placeholder ="请输入邮箱" > </div > <div class ="form-group" > <label > 部门</label > <select class ="form-control" v-model ="rowEmp.dId" > <option v-for ="item in deptList" :key ="item.deptId" :value ="item.deptId" > {{item.deptName}} </option > </select > </div > </div > </div > <div class ="modal-footer" > <button type ="button" class ="btn btn-default" data-dismiss ="modal" id ="closeBtn" > 关闭</button > <button type ="button" class ="btn btn-primary" @click ="saveEmpForm" > 保存</button > </div > </div > </div > </div > <script src ="https://code.jquery.com/jquery-3.6.0.min.js" > </script > <script src ="https://cdn.jsdelivr.net/npm/vue@2.6.14" > </script > <script src ="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js" > </script > <script src ="https://unpkg.com/axios/dist/axios.min.js" > </script > <script > const http = axios.create({ baseURL: '/ssmcrud' , }); http.interceptors.response.use(function (response ) { return response.data; }, function (error ) { return Promise .reject(error); }); new Vue({ el: '#app' , data: { empList: [], pageList: [], total:0 , pageNums:0 , hasNextPage:false , hasPreviousPage:false , pageNum:1 , empname:"" , rowEmp:{}, deptList:[] }, mounted: function ( ) { this .getEmpList() this .getDeptList() }, methods: { getDeptList ( ) { http.get("/getDeptList" ).then(res => { this .deptList = res.data.deptList }) }, pageFun (page ) { this .pageNum = page this .getEmpList() }, getEmpList: function ( ) { http.get(`/getEmpList/${this .pageNum} /${this .empname} ` ).then(res => { console .log(res) this .empList = res.data.empList.list this .pageList = res.data.empList.navigatepageNums this .total = res.data.empList.total this .pageNums = res.data.empList.pages this .hasNextPage = res.data.empList.hasNextPage this .hasPreviousPage = res.data.empList.hasPreviousPage }) }, deleteEmp (id ) { http.delete(`/deleteEmp/${id} ` ).then(res => { this .pageNum = 1 this .getEmpList() }) }, showEdit (row ) { this .rowEmp = row || {} }, saveEmpForm ( ) { http.post("/andOrUpdateEmp" ,this .rowEmp).then(res => { $("#closeBtn" ).click() this .pageNum = 1 this .getEmpList() }) } } }) </script > </body > </html >
批量删除 在 tbEmpServlet 添加批量删除的方法
1 2 3 4 5 6 7 8 9 10 public void deletesEmp (List<Integer> ids) { for (Integer id : ids) { tbEmpMapper.deleteByPrimaryKey(id); } }
在 IndexController 控制器中调用
1 2 3 4 5 6 7 8 9 10 11 12 @PostMapping("/deleteEmpByIds") @ResponseBody public Msg deleteEmpBuIds (@RequestBody Map<String,List<Integer>> map) { List<Integer> ids = map.get("ids" ); tbEmpServlet.deletesEmp(ids); return Msg.success(); }
前端代码
1 <button type ="button" class ="btn btn-danger" @click ="deleteAll" > 删除</button >
1 2 3 <th > <input type ="checkbox" v-model ="checkAll" @input ="changeCheckAll" > </th >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <tr v-for ="(item,index) in empList" :key ="index" > <td > <input type ="checkbox" v-model ="item.checkOne" @input ="changeCheckOne(item)" > </td > <td > {{index + 1}}</td > <td > {{item.empName}}</td > <td > {{item.gender == '1' ? '男' : '女'}}</td > <td > {{item.email}}</td > <td > {{item.tbDept ? item.tbDept.deptName : ''}}</td > <td > <button type ="button" class ="btn btn-warning" @click ="showEdit(item)" data-toggle ="modal" data-target ="#myModal" > 编辑 </button > <button type ="button" class ="btn btn-danger" @click ="deleteEmp(item.empId)" > 删除 </button > </td > </tr >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 changeCheckAll (statu ) { let checked = statu.target.checked this .empList.forEach(item => { item.checkOne = checked }) this .selectRow = this .empList.filter(item => item.checkOne) }, changeCheckOne ( ) { if (this .empList.every(item => item.checkOne)){ this .checkAll = true }else { this .checkAll = false } this .selectRow = this .empList.filter(item => item.checkOne) }, deleteAll ( ) { http.post("/deleteEmpByIds" ,{ ids:this .selectRow.map(item => item.empId) }).then(res => { this .pageNum = 1 this .getEmpList() }) }
项目总结
idea打包项目
然后会在 target 文件夹中生成一个 war 包
重命名放在 tomcat 服务器中可以在本地运行项目