1 Star 0 Fork 0

SongZX / ssm-crud

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MulanPSL-2.0

SSM整合案例

项目搭建

使用maven创建一个工程

pom.xml

<?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>
        <!--SpringWebMVC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>

        <!--spring-jdbc-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>
        <!--spring-aspects面向切面和事务-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.22.RELEASE</version>
        </dependency>
        <!-- spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.22.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.10</version>
        </dependency>
        <!--mybatis-spring适配包-->
        <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>
        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.6</version>
        </dependency>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <!--jsp-->
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <!-- ServletAPI -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
        </dependency>
        <!-- Spring5和Thymeleaf整合包 -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.12.RELEASE</version>
        </dependency>
        <!-- log4j日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

    <!-- 控制Maven在构建过程中相关配置 -->
    <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>
                    <!-- MySQL驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.29</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

</project>

web.xml

<?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">
    <!-- 1. 配置监听器启动Spring的容器 -->
    <!-- needed for ContextLoaderListener -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:ApplicationContext.xml</param-value>
    </context-param>

    <!-- Bootstraps the root web application context before servlet initialization -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- 2. springmvc的前端控制器 -->
    <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--设置SpringMVC配置文件的地址和名称-->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:SpringMvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- Map all requests to the DispatcherServlet for handling -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <!-- 3. 字符编码过滤器,一定在其余filter之前 -->
    <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>


    <!-- 4. Restful风格的配置 -->
    <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

<?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>

    <!-- 配置Thymeleaf视图解析器 -->
    <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

<?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>

    <!--引入jdbc配置文件-->
    <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>

    <!--配置和mybatis整合-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--设置数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <!--设置mybatis核心配置文件的位置-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <!--指定mybatis mapper文件的位置-->
        <property name="mapperLocations" value="classpath:com/szx/ssm/mapper/*.xml"></property>
    </bean>

    <!--配置一个可以执行批量操作的sqlsession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
        <constructor-arg name="executorType" value="SIMPLE"/>
    </bean>

    <!--配置扫描器,将mybatis接口添加到ioc容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--扫描所有dao接口的实现,加入到ioc容器-->
        <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>
    <!--开启基于注解的事务,使用xml配置形式的事务(必要主要的都是使用配置式)  -->
    <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="*"/>
            <!--以get开始的所有方法只读  -->
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>

</beans>

jdbc.properties

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

<?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

设置逆向工程的配置文件

<?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>
    <!--
    targetRuntime: 执行生成的逆向工程的版本
    MyBatis3Simple: 生成基本的CRUD(清新简洁版)
    MyBatis3: 生成带条件的CRUD(奢华尊享版)
    -->
    <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>
        <!-- javaBean的生成策略-->
        <javaModelGenerator targetPackage="com.szx.ssm.bean" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- SQL映射文件的生成策略 -->
        <sqlMapGenerator targetPackage="com.szx.ssm.mapper"
                         targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
        <!-- Mapper接口的生成策略 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.szx.ssm.dao" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <!-- 逆向分析的表 -->
        <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
        <!-- domainObjectName属性指定生成出来的实体类的类名 -->
        <table tableName="tb_dept" domainObjectName="tbDept"/>
        <table tableName="tb_emp" domainObjectName="tbEmp"/>
    </context>
</generatorConfiguration>

log4j.xml

日志文件

<?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>

执行逆向工程

上面的配置文件配置成功后双击这里自动生成代码

Snipaste_2022-06-28_16-44-08.png

项目结构

Snipaste_2022-06-28_16-42-13.png

测试方法

测试基本查询

@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 之后

<!--配置一个可以执行批量操作的sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"/>
    <constructor-arg name="executorType" value="SIMPLE"/>
</bean>

添加测试方法

/**
 * 批量添加数据
 */
@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模拟接口请求

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;

/**
 * @author songzx
 * @create 2022-06-30 13:54
 */
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {"classpath:ApplicationContext.xml","classpath:SpringMvc.xml"})
public class TestMvc {
    // 拿到SprigMVC的ioc
    @Autowired
    WebApplicationContext ioc;
    // 虚拟mvc,拿到测试方法返回的结果
    MockMvc mockMvc;

    @Before
    public void initMockMvc(){
        mockMvc = MockMvcBuilders.webAppContextSetup(ioc).build();
    }

    @Test
    public void test() throws Exception {
        // 发送get请求到 /,并且传递pageNumber参数,值为2
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/")
                .param("pageNumber", "2"))
                .andReturn();
        // 获取request
        MockHttpServletRequest request = result.getRequest();
        // 读取保存的pageInfo
        PageInfo pageInfo = (PageInfo) request.getAttribute("pageInfo");
        // 从分页信息中获取员工列表
        List empList = pageInfo.getList();
        empList.forEach(emp-> System.out.println(emp));
        System.out.println(pageInfo);
    }

}

访问首页并实现分页跳转

添加tbEmpServlet

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;

/**
 * @author songzhengxiang
 * @create 2022-06-29 23:28
 */
@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

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;

/**
 * @author songzx
 * @create 2022-06-28 15:16
 */
@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 相当于 !=
  • 更多语法使用方式
<!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">&laquo;</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">&raquo;</span>
                        </a>
                    </li>
                    <!--尾页-->
                    <li th:class="${pageInfo.pageNum eq pageInfo.pages} ? 'disabled' : ''">
                        <a th:href="@{/(pageNumber=${pageInfo.pages})}">尾页</a>
                    </li>
                </ul>
            </nav>
        </div>
    </div>

    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
</body>
</html>

效果展示

Snipaste_2022-06-30_17-35-02.png

封装msg对象返回json数据

定义通用的msg对象

package com.szx.ssm.bean;

import java.util.HashMap;
import java.util.Map;

/**
 * @author songzx
 * @create 2022-07-02 16:43
 */
public class Msg {
    int code; // 接口响应状态码,500 异常,200 OK
    String message; // 接口返回的信息
    HashMap<String,Object> data = new HashMap<>(); // 接口实际返回的内容

    /**
     * 接口成功返回方法
     * @author Songzx
     * @date 2022/7/2
     */
    public static Msg success(){
        Msg msg = new Msg();
        msg.setCode(200);
        msg.setMessage("成功");
        return msg;
    }

    /**
     * 接口失败返回方法
     * @author Songzx
     * @date 2022/7/2
     */
    public static Msg error(){
        Msg msg = new Msg();
        msg.setCode(500);
        msg.setMessage("失败");
        return msg;
    }

    /**
     * 可以链式调用的add方法
     * @author Songzx
     * @date 2022/7/2
     */
    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的依赖包

<!--返回JSON数据-->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.1</version>
</dependency>

在 SpringMVC.xml 中添加注解驱动

<mvc:annotation-driven/>

重写获取员工列表的接口

// 返回json格式的数据
@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;
}

再次发起请求查看返回

Snipaste_2022-07-02_17-09-41.png

使用vue改写前端页面

<!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">&laquo;</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">&raquo;</span>
                                </a>
                            </li>
                            <!--尾页-->
                            <li @click="pageFun(pageNums)" :class="{disabled:pageNum == pageNums}">
                                <a>尾页</a>
                            </li>
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>

    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- 添加vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <!-- 添加axios请求 -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    <!--js逻辑-->
    <script>
        const http = axios.create({
            baseURL: '/ssmcrud', // tomcat 启动时的默认地址后缀
        });
        // 添加响应拦截器
        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 中添加模糊查询方法

/**
 * 根据姓名模糊查询
 * @author Songzx
 * @date 2022/7/2
 */
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 中调用

/**
 * 模糊查询
 * @author Songzx
 * @date 2022/7/3
 */
@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;
}

前端发起请求

// 查询数据方法
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删除

/**
 * 根据id删除
 * @author Songzx
 * @date 2022/7/3
 */
public int deleteEmpById(Integer id){
    int i = tbEmpMapper.deleteByPrimaryKey(id);
    return i;
}

在 IndexController 中调用 deleteEmpById 方法

/**
 * 根据id删除
 * @author Songzx
 * @date 2022/7/3
 */
@DeleteMapping("/deleteEmp/{id}")
@ResponseBody
public Msg deleteEmpByid(@PathVariable("id") Integer id){
    tbEmpServlet.deleteEmpById(id);
    Msg msg = Msg.success();
    return msg;
}

前端发起请求

<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>
// 删除
deleteEmp(id){
    http.delete(`/deleteEmp/${id}`).then(res=>{
        this.pageNum = 1
        this.getEmpList()
    })
},

编辑和新增方法

首先添加查询所有部门的方法

在 tbDepServlet 添加获取部门

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;

/**
 * @author songzx
 * @create 2022-07-03 9:03
 */
@Service
public class tbDepServlet {
    @Autowired
    tbDeptMapper deptMapper;

    /**
     * 查询所有部门
     * @author Songzx
     * @date 2022/7/3
     */
    public List<tbDept> getDeptList(){
        List<tbDept> tbDepts = deptMapper.selectByExample(null);
        return tbDepts;
    }
}

在 DeptController 调用 getDeptList 方法

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;

/**
 * @author songzx
 * @create 2022-07-03 9:05
 */
@Controller
public class DeptController {
    @Autowired
    tbDepServlet depServlet;

    /**
     * 获取所有部门
     * @author Songzx
     * @date 2022/7/3
     */
    @GetMapping("/getDeptList")
    @ResponseBody
    public Msg getDeptList(){
        List<tbDept> deptList = depServlet.getDeptList();
        Msg msg = Msg.success().add("deptList", deptList);
        return msg;
    }
}

在 tbEmpServlet 中添加编辑和新增方法

/**
 * 新增员工
 * @author Songzx
 * @date 2022/7/3
 */
public int addEmpInfo(tbEmp tbEmp){
    int insert = tbEmpMapper.insertSelective(tbEmp);
    return insert;
}

/**
 * 编辑员工
 * @author Songzx
 * @date 2022/7/3
 */
public int updateEmp(tbEmp tbEmp){
    int i = tbEmpMapper.updateByPrimaryKeySelective(tbEmp);
    return i;
}

在 IndexController 调用

/**
 * 增加或者删除
 * @author Songzx
 * @date 2022/7/3
 */
@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();
}

前端发送请求

<!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">&laquo;</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">&raquo;</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">&times;</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>

    <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- 添加vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
    <!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
    <!-- 添加axios请求 -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

    <!--js逻辑-->
    <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 添加批量删除的方法

/**
 * 批量删除
 * @author Songzx
 * @date 2022/7/3
 */
public void deletesEmp(List<Integer> ids){
    for (Integer id : ids) {
        tbEmpMapper.deleteByPrimaryKey(id);
    }
}

在 IndexController 控制器中调用

/**
 * 批量删除
 * @author Songzx
 * @date 2022/7/3
 */
@PostMapping("/deleteEmpByIds")
@ResponseBody
public Msg deleteEmpBuIds(@RequestBody Map<String,List<Integer>> map){
    List<Integer> ids = map.get("ids");
    tbEmpServlet.deletesEmp(ids);
    return Msg.success();
}

前端代码

<button type="button" class="btn btn-danger" @click="deleteAll">删除</button>
<th>
    <input type="checkbox" v-model="checkAll" @input="changeCheckAll">
</th>
<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>
// 切换全选
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()
    })
}

项目总结

Snipaste_2022-07-03_22-23-58.png

idea打包项目

Snipaste_2022-07-03_22-37-48.png

然后会在 target 文件夹中生成一个 war 包

Snipaste_2022-07-03_22-38-35.png

重命名放在 tomcat 服务器中可以在本地运行项目

Snipaste_2022-07-03_22-38-59.png

木兰宽松许可证, 第2版 木兰宽松许可证, 第2版 2020年1月 http://license.coscl.org.cn/MulanPSL2 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: 0. 定义 “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 “法人实体”是指提交贡献的机构及其“关联实体”。 “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 1. 授予版权许可 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 2. 授予专利许可 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 3. 无商标许可 “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 4. 分发限制 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 5. 免责声明与责任限制 “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 6. 语言 “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 条款结束 如何将木兰宽松许可证,第2版,应用到您的软件 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; 3, 请将如下声明文本放入每个源文件的头部注释中。 Copyright (c) [Year] [name of copyright holder] [Software Name] is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details. Mulan Permissive Software License,Version 2 Mulan Permissive Software License,Version 2 (Mulan PSL v2) January 2020 http://license.coscl.org.cn/MulanPSL2 Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: 0. Definition Software means the program and related documents which are licensed under this License and comprise all Contribution(s). Contribution means the copyrightable work licensed by a particular Contributor under this License. Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. Legal Entity means the entity making a Contribution and all its Affiliates. Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. 1. Grant of Copyright License Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. 2. Grant of Patent License Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. 3. No Trademark License No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. 4. Distribution Restriction You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. 5. Disclaimer of Warranty and Limitation of Liability THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 6. Language THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. END OF THE TERMS AND CONDITIONS How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. Copyright (c) [Year] [name of copyright holder] [Software Name] is licensed under Mulan PSL v2. You can use this software according to the terms and conditions of the Mulan PSL v2. You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. See the Mulan PSL v2 for more details.

简介

ssm整合项目,前端使用vue,bootscript,jquery。后端使用 spring,SpringMVC,mybatis。数据库使用 mysql 展开 收起
Java 等 3 种语言
MulanPSL-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
Java
1
https://gitee.com/szxio/ssm-crud.git
git@gitee.com:szxio/ssm-crud.git
szxio
ssm-crud
ssm-crud
master

搜索帮助