SSM framework integration - achieve basic CURD effect

Posted by saronoff on Sun, 03 Oct 2021 21:24:03 +0200

1. Build environment

  1. Create a basic Maven project and import the dependencies required by the project
<?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>org.example</groupId>
    <artifactId>SSM-curd</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>


    <!--Introduce dependency-->
    <dependencies>

        <!--SpringMVC relevant-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.9</version>
        </dependency>

        <!--spring JDBC-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.9</version>
        </dependency>

        <!--spring Face section-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.3.9</version>
        </dependency>

        <!--mybatis relevant-->

        <!--And spring Adaptive package for-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>2.0.6</version>
        </dependency>
        <!--reverse engineering -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator</artifactId>
            <version>1.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.4.0</version>
        </dependency>


        <!--Database connection pool-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.9</version>
        </dependency>

        <!--mysql Database package-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.26</version>
        </dependency>

        <!--jstl Servlet jsp-->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!--unit testing -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        
    </dependencies>
</project>
  1. The related front-end frameworks are introduced. BootStrap and Jquery are used here and stored in the static folder under webapp
    Note: the js file of bootstrap should be imported after the js file,
  2. Write key integration files (web.xml, Spring, Spring MVC, MyBatis)
    )
    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">

    <!--start-up Spring container-->

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring.xml</param-value>
    </context-param>

    <listener>
        <!--Set listener project to start loading spring of xml configuration file-->
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


    <!--SpringMVC The front-end controller intercepts all requests-->
    <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>
    
    <!--Character encoding filtering-->
    <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>forceResponseEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--Request mode filtering is used to write RESTFul Stylized URL-->
    <!--Used to connect the front end post Request converted to PUT or DELETE-->
    <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>
</web-app>


Write spring MVC configuration file

```html
<?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 http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
">

    <!--Turn on component scan to scan the controller-->
    <context:component-scan base-package="com.atguigu.controller" use-default-filters="false">
        <!--use-default-filters Used to disable the Default scan rule-->
        <!--Custom scan rules scan only bands Controller The annotated class is the controller-->
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--Configure view parser-->

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--Enable annotation driven-->
    <mvc:annotation-driven/>

    <!--take springmvc Unable to process request to tomcat-->
    <mvc:default-servlet-handler></mvc:default-servlet-handler>

    <!--Home page access-->
    <mvc:view-controller path="/" view-name="index"/>
    
</beans>

Create package structure

Write Spring configuration files (Core: scanning, data source, transaction control, integration with Mybatis, etc.)
Note the introduction of namespaces (tx, aop, context,)

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
">

    <!--spring The configuration file is related to business logic-->

    <context:component-scan base-package="com.atguigu">
        <!--Set scan rules except Controller All annotations other than this annotation are scanned-->
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--Specify the location of the configuration file-->
    <context:property-placeholder location="classpath:druid.properties"></context:property-placeholder>
    <!--Database connection pool-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driverClass}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--Configuration and MyBatis Integration of-->
    <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean
">
        <!--appoint mybatis Global configuration for-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <property name="dataSource" ref="druidDataSource"></property>

        <!--appoint mapper File location-->
        <property name="mapperLocations" value="classpath:mapper/*.xml"></property>


    </bean>

    <!--Configuring the scanner will Mybatis Interface implementation added to IOC In the container-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--Scan all DAO Interface implementation added to IOC in-->
        <property name="basePackage" value="com.atguigu.dao"></property>
    </bean>

    <!--Configuration of transaction control-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--Control data source-->
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>

    <!--Enable annotation based transactions-->
    <!--Turn on based on XML Transaction(recommend)-->
    <aop:config>
        <!--Pointcut expression d-->
        <aop:pointcut id="txAdvice" expression="execution(* com.atguigu.service..*(..))" />

        <!--Configure transaction side-->
        <aop:advisor advice-ref="interceptor" pointcut-ref="txAdvice"></aop:advisor>

    </aop:config>

    <!--How does transaction enhancement cut in-->
    <tx:advice transaction-manager="transactionManager" id="interceptor">
        <tx:attributes>
            <!--All the methods that you cut in are transaction methods-->
            <tx:method name="*"/>

            <!--with GET All methods at the beginning-->
<!--            <tx:method name="get*"/>-->
        </tx:attributes>
    </tx:advice>

    <!--Configuration core: Data source Mybatis Integration, transaction control-->
</beans>

Write Mybatis configuration file (generate code through reverse engineering)

Attachment: database construction and test data

CREATE DATABASE db2;
USE db2;
DROP TABLE t_emp;
DROP TABLE t_dept;

CREATE TABLE t_dept(
   id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
   dname VARCHAR(20) NOT NULL
);

CREATE TABLE t_emp(
   emp_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
   emp_name VARCHAR(10) NOT NULL,
   gender CHAR(1) NOT NULL,
   email VARCHAR(20),
   dept_id INT NOT NULL,
   CONSTRAINT fk_emp_dept_id FOREIGN KEY(dept_id) REFERENCES t_dept(id)
);
INSERT INTO t_dept VALUES(NULL,"Purchasing Department");
INSERT INTO t_dept VALUES(NULL,"Ministry of Personnel");
INSERT INTO t_dept VALUES(NULL,"Security Department");

INSERT INTO t_emp VALUES(NULL,"niko","male","1135552060@qq.com",1);
INSERT INTO t_emp VALUES(NULL,"luna","female","123456789@qq.com",3);

SELECT * FROM t_dept;
SELECT * FROM t_emp;

SELECT
  e.*,d.`dname`
FROM t_emp e LEFT JOIN t_dept d ON e.dept_id = d.id;

Note: in IDEA, you need to execute mgb code through test methods. If the main class cannot be loaded, delete the iml file in the project and refresh maven

First write the main configuration file and the basic configuration

<?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>
        <!--Open hump naming-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
    <typeAliases>
        <!--The default alias is lowercase for the class name-->
        <package name="com.atguigu.bean"/>
    </typeAliases>
</configuration>

Write reverse engineering MGB.xml configuration file

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

    <!--database-->
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/db2"
                        userId="root"
                        password="abc123">
        </jdbcConnection>

        <javaTypeResolver >
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>
         
        <!--generate bean-->
        <javaModelGenerator targetPackage="com.atguigu.bean" targetProject="./src/main/java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        
        <sqlMapGenerator targetPackage="mapper"  targetProject="./src/main/resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>
        
        <!--generate mapper-->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.dao"  targetProject="./src/main/java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        
        <!--Table in database-->
        <table tableName="t_emp" domainObjectName="Emp" >
<!--            <property name="useActualColumnNames" value="true"/>-->
<!--            <generatedKey column="ID" sqlStatement="DB2" identity="true" />-->
<!--            <columnOverride column="DATE_FIELD" property="startDate" />-->
<!--            <ignoreColumn column="FRED" />-->
<!--            <columnOverride column="LONG_VARCHAR_FIELD" jdbcType="VARCHAR" />-->
        </table>

        <table tableName="t_dept" domainObjectName="Dept"></table>

    </context>
</generatorConfiguration>

Write test code

package com.atguigu.test;

import org.junit.Test;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MGB {
    @Test
    public void testMgb() throws XMLParserException, IOException, InvalidConfigurationException, SQLException, InterruptedException {
        List<String> generatorWarnings = new ArrayList<String>();
        File file = new File("mgb.xml");
        ConfigurationParser cp = new ConfigurationParser(generatorWarnings);
        Configuration config = cp.parseConfiguration(file);
        DefaultShellCallback shellCallback = new DefaultShellCallback(true);
        MyBatisGenerator generator = new MyBatisGenerator(config,shellCallback,generatorWarnings);
        generator.generate(null);
    }
}

The directory structure is as follows:

Modify Mapper file to add joint query function
Example: I want to get deptName information through d_id while looking up the emp table

Entity class Emp

EmpMapper.xml

<!--Specify query rules -->
<resultMap id="WithDeptResultMap" type="com.atguigu.curd.bean.Emp">
    <id column="emp_id" jdbcType="INTEGER" property="empId" />
    <result column="emp_name" jdbcType="VARCHAR" property="empName" />
    <result column="gender" jdbcType="CHAR" property="gender" />
    <result column="email" jdbcType="VARCHAR" property="email" />
    <result column="dept_id" jdbcType="INTEGER" property="deptId" />
    <association property="dept" javaType="com.atguigu.curd.bean.Dept">
      <result column="id" property="id"></result>
      <result column="dname" property="dname"></result>
    </association>
  </resultMap>
  <!--Content to query-->
  <sql id="withDept">
    e.*,d.`dname`
  </sql>
  <!--Methods of using federated queries-->
  <select id="selectByExampleWithDept" resultMap="WithDeptResultMap">
    select
    <if test="distinct">
      distinct
    </if>
    <include refid="withDept" />
    from t_emp e left join t_dept d on e.dept_id = d.dept_id
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>
  <select id="selectByPrimaryKeyWithDept" resultMap="WithDeptResultMap">
    select
    <include refid="withDept" />
    FROM t_emp e LEFT JOIN t_dept d ON e.dept_id = d.id;
    where emp_id = #{empId,jdbcType=INTEGER}
  </select>

Build Spring unit test environment
Introduce dependency

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.9</version>
</dependency>

Use annotations to specify the location of the spring file

@RunWith(SpringJUnit4ClassRunner.class)
@SpringJUnitConfig(locations = {"classpath:spring.xml"})
public class MapperTest {

    @Autowired
    private DeptMapper dm;
    @Test
    public void testQuery(){
        int result = dm.insertSelective(new Dept(null, "Purchasing Department"));
        System.out.println(result);
    }
}

2. Query

Create home page forwarding and send / emps when visiting the home page. Please go to the employee list page

Introduce the dependency of paging plug-in pagehelper

  <!--pageHelper-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.0.0</version>
        </dependency>

Create Service layer

@Service
public class EmpService {
    @Autowired
    private EmpMapper empMapper;

    public List<Emp> getEmpAll(){
        return empMapper.selectByExampleWithDept(null);
    }
}

Create Controller layer

@Controller
public class EmpController {
    @Autowired
    private EmpService empService;

    @RequestMapping("/emps")
    public String getEmp(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model){

        // Introducing paging plug-in pageHelper
        // pn page pageSize capacity per page
        PageHelper.startPage(pn,5);
        // startPage is followed by a paging query
        List<Emp> empAll = empService.getEmpAll();
        // Results after packaging query

        // This 5 is the number of consecutive pages
        PageInfo pageInfo = new PageInfo(empAll,5);

        model.addAttribute("pageInfo",pageInfo);

        return "views/list";
    }

}

Employee list front end

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2021/10/1
  Time: 18:34
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<head>
    <title>Employee list</title>
    <!--introduce Jquery and bootstrap-->
    <script type="text/javascript" src="${pageContext.request.contextPath}/static/bootstrap-3.4.1-dist/js/bootstrap.js"></script>
    <script type="text/javascript" src="${pageContext.request.contextPath}/static/jquery-3.5.1/jquery-3.5.1.js"></script>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/static/bootstrap-3.4.1-dist/css/bootstrap.css"/>

</head>
<body>
   <div class="container">
       <!--title-->
       <div class="row">
           <div class="col-md-12">
               <h3>SSM-CURD</h3>
           </div>
       </div>
       <!--Button-->
       <div class="row">
           <div class="col-md-4 col-md-offset-8">
               <button class="btn btn-primary">newly added</button>
               <button class="btn btn-danger">delete</button>
           </div>
       </div>
       <!--form-->
       <div class="row">
           <div class="col-md-12">
               <table class="table table-hover">
                   <tr>
                       <th>empid</th>
                       <th>empName</th>
                       <th>gender</th>
                       <th>email</th>
                       <th>deptName</th>
                       <th>operation</th>
                   </tr>
                   <c:forEach items="${pageInfo.list}" var="emp">
                       <tr>
                           <td>${emp.empId}</td>
                           <td>${emp.empName}</td>
                           <td>${emp.gender}</td>
                           <td>${emp.email}</td>
                           <td>${emp.dept.dname}</td>
                           <td>
                               <button class="btn btn-primary btn-sm">
                               <span class="glyphicon glyphicon-pencil" aria-hidden="true" >

                               </span>edit
                               </button>
                               <button class="btn btn-dangger btn-sm">
                                   <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
                                   delete
                               </button>
                           </td>
                       </tr>
                   </c:forEach>
               </table>
           </div>
       </div>
       <!--paging -->
       <div class="row">
           <!--Pagination text-->
           <div class="col-md-6">
               Current section ${pageInfo.pageNum}page,in total ${pageInfo.pages}page,common ${pageInfo.total}Records
           </div>
           <!--Paging information-->
           <div class="col-md-6">
               <nav aria-label="Page navigation">
                   <ul class="pagination">
                       <li>
                           <a href="${pageContext.request.contextPath}/emps?pn=1">home page</a>
                       </li>
                       <c:if test="${pageInfo.hasPreviousPage}">
                           <li>
                               <a href="${pageContext.request.contextPath}/emps?pn=${pageInfo.pageNum-1}" aria-label="Previous">
                                   <span aria-hidden="true">&laquo;</span>
                               </a>
                           </li>
                       </c:if>
                       <c:forEach items="${pageInfo.navigatepageNums}" var="page">
                           <c:if test="${page == pageInfo.pageNum}">
                               <li class="active">
                                   <a href="#">${page}</a>
                               </li>
                           </c:if>
                           <c:if test="${page != pageInfo.pageNum}">
                               <li>
                                   <a href="${pageContext.request.contextPath}/emps?pn=${page}">${page}</a>
                               </li>
                           </c:if>
                       </c:forEach>
                       <c:if test="${pageInfo.hasNextPage}">
                           <li>
                               <a href="${pageContext.request.contextPath}/emps?pn=${pageInfo.pageNum+1}" aria-label="Next">
                                   <span aria-hidden="true">&raquo;</span>
                               </a>
                           </li>
                       </c:if>
                       <li>
                           <a href="${pageContext.request.contextPath}/emps?pn=${pageInfo.pages}">Last </a>
                       </li>
                   </ul>
               </nav>
           </div>
       </div>
   </div>

</body>
</html>

effect

reform
Using Ajax to return paging data
logic

  1. The index.jsp page directly sends an Ajax request to query employee paging data
  2. The server returns the detected data to the browser in the form of Json string
  3. After the browser receives the JS string, it can use js to parse the json and change the web page through the addition, deletion and modification of dom
  4. Return json to realize client independence

Write a general class Msg that returns JSON data

package com.atguigu.curd.bean;

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

public class Msg {
    // Class that returns JSON data

    private int code;
    // Status code

    private String msg;
    // Prompt information

    // The data that the user wants to return to the browser
    private Map<String,Object> extend = new HashMap<String,Object>();

    public static Msg success(){
        Msg result = new Msg();
        result.setCode(100);
        result.setMsg("Processing succeeded~");

        return result;
    }

    public static Msg fail(){
        Msg result = new Msg();
        result.setCode(200);
        result.setMsg("Processing failed~");

        return result;
    }

    public Msg add(String key,Object value){
        this.getExtend().put(key,value);
        return this;
    }


    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Map<String, Object> getExtend() {
        return extend;
    }

    public void setExtend(Map<String, Object> extend) {
        this.extend = extend;
    }
}

Introduce dependencies for JSON transformation

 <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.4</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.4</version>
        </dependency>

Note that the annotation driver is enabled in the configuration file of spring MVC

Modify Controller layer Controller method

 @RequestMapping("/emps")
    @ResponseBody
    public Msg getEmp(@RequestParam(value = "pn",defaultValue = "1") Integer pn){
        // Introducing paging plug-in pageHelper
        // pn page pageSize capacity per page
        PageHelper.startPage(pn,5);
        // startPage is followed by a paging query
        List<Emp> empAll = empService.getEmpAll();
        // Results after packaging query

        // This 5 is the number of consecutive pages
        PageInfo pageInfo = new PageInfo(empAll,5);

        return Msg.success().add("pageInfo",pageInfo);
    }

Start the project with the following results

Modify the front page and display the table data through the DOM addition, deletion and modification of Js

Employee page

<div class="container">
    <!--title-->
    <div class="row">
        <div class="col-md-12">
            <h3>SSM-CURD</h3>
        </div>
    </div>
    <!--Button-->
    <div class="row">
        <div class="col-md-4 col-md-offset-8">
            <button class="btn btn-primary" id="empAddBtn">newly added</button>
            <button class="btn btn-danger" id="empDelBtn">delete</button>
        </div>
    </div>
    <!--form-->
    <div class="row">
        <div class="col-md-12">
            <table class="table table-hover" id="table_emps">
                <thead>
                    <tr>
                        <th>empid</th>
                        <th>empName</th>
                        <th>gender</th>
                        <th>email</th>
                        <th>deptName</th>
                        <th>operation</th>
                    </tr>
                </thead>
                <tbody>

                </tbody>
            </table>
        </div>
    </div>
    <!--paging -->
    <div class="row">
        <!--Pagination text-->
        <div class="col-md-6" id="page_info_area"></div>
        <!--Paging information-->
        <div class="col-md-6" id="page_info_message"></div>
    </div>
</div>

Manipulate the DOM to add data to tables, paging bars, and so on

<script type="text/javascript">

    var totalRecord;
    // Total number of records

    // After the page is loaded, send Ajax request paging data
    $(function(){
        to_page(1);
    });

    function to_page(pn){
        $.ajax({
            url:"${pageContext.request.contextPath}/emps",
            data:"pn="+pn,
            type:"get",

            success:function(result){
                // 1. Analyze and display employee information on the page
                build_emps_table(result);
                // 2. Parse and display paging information on the page
                build_page_info(result);
                // 3. Parse and display the paging bar on the page
                build_page_nav(result);
            },

            error:function(result){
                alert(result.msg);
            }
        });
    }

    function build_emps_table(result){

        // Empty data in real time
        $("#table_emps tbody").empty();

        var emps = result.extend.pageInfo.list;

        $.each(emps,function(index,item){
            // Get employee information
            var empIdTd = $("<td></td>").append(item.empId);
            var empTd = $("<td></td>").append(item.empName);
            var genderTd = $("<td></td>").append(item.gender == 1 ? "male":"female");
            var emailTd = $("<td></td>").append(item.email);
            var deptNameTd = $("<td></td>").append(item.dept.dname);


            // Button
            var editBtn = $("<button></button>").addClass("btn btn-primary btn-sm").append($("<span></span>")).addClass("glyphicon glyphicon-pencil").append("edit");
            var delBtn = $("<button></button>").addClass("btn btn-danger btn-sm").append($("<span></span>")).addClass("glyphicon glyphicon-trash").append("delete");


            $("<tr></tr>").append(empIdTd).append(empTd).append(genderTd).append(emailTd).append(deptNameTd).append(editBtn).append("    ").append(delBtn)
            .appendTo("#table_emps tbody");

        });
    }

    function build_page_info(result){
        // Empty data in real time
        $("#page_info_area ").empty();

        $("#page_info_area").append(" current "+ result.extend.pageInfo.pageNum +" page, total "+ result.extend.pageInfo.pages +" records ")

        totalRecord = result.extend.pageInfo.total;
    }

    function build_page_nav(result){

        // Empty data in real time
        $("#page_info_message").empty();

        var ul = $("<ul></ul>").addClass("pagination");

        var firstPage = $("<li></li>").append($("<a></a>").append("home page").attr("href","#"));
        var prePage = $("<li></li>").append($("<a></a>").append("&laquo;").attr("href","#"));
        var lastPage = $("<li></li>").append($("<a></a>").append("Last ").attr("href","#"));
        var nextPage = $("<li></li>").append($("<a></a>").append("&raquo;").attr("href","#"));

        if(!result.extend.pageInfo.hasPreviousPage){
            firstPage.addClass("disabled");
            prePage.addClass("disabled");
        }else{
            firstPage.click(function(){
                to_page(1);
            });
            prePage.click(function(){
                to_page(result.extend.pageInfo.pageNum - 1);
            });
        }

        if(!result.extend.pageInfo.hasNextPage){
            nextPage.addClass("disabled");
            lastPage.addClass("disabled");
        }else{
            lastPage.click(function(){
                to_page(result.extend.pageInfo.pages);
            });

            nextPage.click(function(){
                to_page(result.extend.pageInfo.pageNum + 1)
            });
        }

        ul.append(firstPage).append(prePage);

        $.each(result.extend.pageInfo.navigatepageNums,function(index,item){
            var num = $("<li></li>").append($("<a></a>").append(item).attr("href","#"));

            if(result.extend.pageInfo.pageNum == item){
                num.addClass("active")
            }

            num.click(function(){
               to_page(item);
            });

            ul.append(num);

        });
        ul.append(nextPage).append(lastPage);

        var nav = $("<nav></nav>").append(ul);

        nav.attr("aria-label","Page navigation");

        nav.appendTo("#page_info_message");
    }

3. NEW

logic
Click the Add button in the employee list to pop up the modal box, and query the Department information in the database and put it in the drop-down box
This part of the code can be found in the modal box section of the official bootstrap document

<!--Modal box-->
<!-- Implement the new modal box -->
<div class="modal fade" id="empAddmyModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <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" id="myModalLabel">Add employee</h4>
            </div>
            <div class="modal-body">
                <form class="form-horizontal">
                    <div class="form-group">
                        <label class="col-sm-2 control-label">empName</label>
                        <div class="col-sm-8">
                            <input type="text"  name="empName" class="form-control" id="empName_add_input" placeholder="empName"/>
                            <span id="has_error_empName" class="help-block"></span>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">email</label>
                        <div class="col-sm-8">
                            <input type="email" name="email" class="form-control" id="empEmail_add_input" placeholder="empEmail"/>
                            <span id="has_error_email" class="help-block"></span>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">gender</label>
                        <div class="col-sm-8">
                            <label class="radio-inline">
                                <input type="radio" name="gender"  id="genderMan" value="1" checked="checked"/>male
                            </label>
                            <label class="radio-inline">
                                <input type="radio" name="gender"  id="genderWoMan" value="2"/>female
                            </label>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">deptName</label>
                        <div class="col-sm-4">
                            <!--Department submission ID that will do-->
                            <select class="form-control" name="deptId" id="dept_xlk">

                            </select>
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal" id="close_btn">close</button>
                <button type="button" class="btn btn-primary" id="emp_save_btn">preservation</button>
            </div>
        </div>
    </div>
</div>

Js code part

 // Pop up modal box
    $("#empAddBtn").click(function(){
        // Before the modal box pops up, send an Ajax request to find out the Department information and display it in the drop-down list

        formReSet("#empAddmyModal form");
        // Clear the last remaining form information
        getDepts();
        // pick up information
        $("#empAddmyModal").modal({
            // Pop up modal box
            backdrop:"static"
        });
    });

    // Find out all department information and display it in the drop-down list
    function getDepts(){
        $.ajax({
            url:"${pageContext.request.contextPath}/depts",
            type: "get",
            success:function(result){
                $.each(result.extend.depts,function(){
                    var optionEle = $("<option></option>").append(this.dname).attr("value",this.id);

                    optionEle.appendTo("#empAddmyModal select");
                });
            }
        });
    }

Service layer

package com.atguigu.curd.service;


import com.atguigu.curd.bean.Dept;
import com.atguigu.curd.dao.DeptMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class DeptService {

    @Autowired
    private DeptMapper deptMapper;

    public List<Dept> getDeptNames(){
        return deptMapper.selectByExample(null);
    }
}

Controller layer

package com.atguigu.curd.controller;

import com.atguigu.curd.bean.Dept;
import com.atguigu.curd.bean.Msg;
import com.atguigu.curd.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;


@Controller
public class DeptController {

    @Autowired
    private DeptService deptService;

    @RequestMapping("/depts")
    @ResponseBody
    public Msg getDepts(){
        // All department information found
        List<Dept> deptNames = deptService.getDeptNames();
        return Msg.success().add("depts",deptNames);
    }
}

Data validation

Verifying front-end data with Jquery

  // Functions for clearing form data and styles
    function formReSet(ele){
        $(ele)[0].reset();
        // Empty style
        $(ele).find("*").removeClass("has-error has-success");
        $(ele).find(".help-block").text("");
    }

    // Function to validate form data
    function validate_add_form(){
        // Employee name

        var empName = $("#empName_add_input").val();

        var regEmpName = /(^[a-zA-Z0-9_-]{3,16}$)|(^[\u2E80-\u9FFF]{2,5})/;

        if(!regEmpName.test(empName)){
            // alert("the user name can be a combination of 2-5 Chinese characters or 6-16 English characters and numbers!");
            show_validate_msg("#empName_add_input","success "," the user name can be 2-5 Chinese characters or 6-16 English characters combined with numbers! ");
            return false;
        }

        // mailbox
        var email = $("#empEmail_add_input").val();
        var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;

        if(!regEmail.test(email)){
            // alert("incorrect mailbox format");
            show_validate_msg("#empEmail_add_input","error "," incorrect mailbox format ");
            return false;
        }
        return true;
    }

    function show_validate_msg(ele,status,msg){
        $(ele).parent().removeClass("has-success has-error");
        $(ele).next("span").text("");

        if("success" == status){
            $(ele).parent().addClass("has-success");
            $(ele).next("span").text(msg);
        }else if("error" == status){
            $(ele).parent().addClass("has-error");
            $(ele).next("span").text(msg);
        }
    }

Use Ajax to verify that the user name is duplicate

 $("#empName_add_input").change(function(){
        var empName = this.value;
        $.ajax({
            url:"${pageContext.request.contextPath}/checkEmpName",
            type: "get",
            data:"empName="+empName,

            success:function(result){
                if(result.code == 100){
                    show_validate_msg("#empName_add_input","success "," employee name available ");
                    $("#emp_save_btn").attr("ajax-va","success");
                }else{
                    show_validate_msg("#empName_add_input","error",result.extend.va_msg);
                    $("#emp_save_btn").attr("ajax-va","error");
                }
            }
        });
    });

    $("#empEmail_add_input").change(function(){
       var email = this.value;

       $.ajax({
           url: "${pageContext.request.contextPath}/checkEmail",
           type: "get",
           data: "email="+email,

           success:function(result){
               if(result==100){
                   show_validate_msg("#empEmail_add_input","success",result.extend.email_msg);
               }else{
                   show_validate_msg("#empEmail_add_input","error",result.extend.email_msg);
               }
           }
       });
    });

    $("#emp_save_btn").click(function(){
        // Validation data
        if(!validate_add_form()) {
            // Validation failure
            return false;
        };

        if($(this).attr("ajax-va") == "error") {
            return false;
        }

        // The form data filled in the modal box is submitted to the server for saving
        // Send an Ajax request to save the employee
        $.ajax({
            url:"${pageContext.request.contextPath}/emps",
            type: "POST",
            data: $("#empAddmyModal form").serialize(),
            success:function(result){

                if(result.code == 100){
                    // Close the modal box after success
                    $("#empAddmyModal").modal("hide");
                    // Go to the last page and display the data just saved
                    // Send an Ajax request to display the last page of data
                    to_page(totalRecord);
                }else{
                    // Display failure information
                    if(result.extend.errorFields.email != undefined){
                        show_validate_msg("#empEmail_add_input","error",result.extend.errorFields.email);
                    }
                    if(result.extend.errorFields.empName != undefined){
                        show_validate_msg("#empEmail_add_input","error",result.extend.errorFields.empName);
                    }
                }
            }
        });
    });

Controller layer

@RequestMapping("/checkEmail")
    @ResponseBody
    public Msg checkEmpEmail(@RequestParam("email") String email){
        String regEmail = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$";

        if(!email.matches(regEmail)){
            return Msg.fail().add("email_msg","The mailbox format is incorrect!");
        }

        return Msg.success().add("email_msg","The email format is correct!");
    }


    @RequestMapping("/checkEmpName")
    @ResponseBody
    // Method of checking whether the employee name is repeated
    public Msg checkEmpName(@RequestParam("empName") String empName){
        // Back end format validation again
        String regEmp = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})";

        if(!empName.matches(regEmp)){
            return Msg.fail().add("va_msg","Employee name must be 6~16 Is a combination of numbers or letters!");
        }

        // Database user name duplicate validation
        boolean result = empService.checkEmpName(empName);
        return result ? Msg.success():Msg.fail().add("va_msg","Employee name not available,Please re-enter!");
    }

Back end verification using JSR303
Introduce dependency

 <!--Data validation support-->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>

Attributes to be verified in entity class

 @Pattern(regexp ="(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})",message = "Employee name must be 6~16 Is a combination of numbers or letters!")
    private String empName;

Controller layer

 @RequestMapping(value = "/emps",method = {RequestMethod.POST})
    @ResponseBody
    // @Valid validation
    public Msg saveEmp(@Valid Emp emp, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            // Validation failure

            Map<String,Object> map = new HashMap<>();
            List<FieldError> fieldErrors = bindingResult.getFieldErrors();

            for (FieldError fieldError : fieldErrors) {
                map.put(fieldError.getField(),fieldError.getDefaultMessage());
            }


            return Msg.fail().add("errorFields",map);
        }

        empService.saveEmp(emp);
        return Msg.success();
    }

Topics: JavaEE Maven Spring intellij-idea