SSM整合

数据库

 /*
 SQLyog Community v13.1.6 (64 bit)
 MySQL - 5.5.62 : Database - ssm_crud
 *********************************************************************
 */
 ​
 /*!40101 SET NAMES utf8 */;
 ​
 /*!40101 SET SQL_MODE=''*/;
 ​
 /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
 /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
 /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
 /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
 CREATE DATABASE /*!32312 IF NOT EXISTS*/`ssm_crud` /*!40100 DEFAULT CHARACTER SET utf8 */;
 ​
 USE `ssm_crud`;
 ​
 /*Table structure for table `tbl_emp` */
 ​
 DROP TABLE IF EXISTS `tbl_emp`;
 ​
 CREATE TABLE `tbl_emp` (
   `emp_id` int(11) NOT NULL AUTO_INCREMENT,
   `emp_name` varchar(255) NOT NULL,
   `gender` char(1) DEFAULT NULL,
   `email` varchar(255) DEFAULT NULL,
   `d_id` int(11) DEFAULT NULL,
   PRIMARY KEY (`emp_id`),
   KEY `fk_emp_dept` (`d_id`),
   CONSTRAINT `fk_emp_dept` FOREIGN KEY (`d_id`) REFERENCES `tnl_dept` (`dept_id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=126 DEFAULT CHARSET=utf8;
 ​
 /*Data for the table `tbl_emp` */
 ​
 insert  into `tbl_emp`(`emp_id`,`emp_name`,`gender`,`email`,`d_id`) values 
 (7,'d69a84','M','d69a84@liu.com',7),
 (8,'ff7685','M','ff7685@liu.com',7),
 (9,'ac0346','M','ac0346@liu.com',7),
 (10,'ee9b37','M','ee9b37@liu.com',7),
 (11,'61fa38','M','61fa38@liu.com',7),
 (12,'060c69','M','060c69@liu.com',7),
 (13,'ad6e310','M','ad6e310@liu.com',7),
 (14,'53c9811','M','53c9811@liu.com',7),
 (15,'9a73712','M','9a73712@liu.com',7),
 (16,'5261d13','M','5261d13@liu.com',7),
 (17,'7f43614','M','7f43614@liu.com',7),
 (18,'12d3415','M','12d3415@liu.com',7),
 (19,'be24116','M','be24116@liu.com',7),
 (20,'7ca1017','M','7ca1017@liu.com',7),
 (21,'8defe18','M','8defe18@liu.com',7),
 (22,'0fe9c19','M','0fe9c19@liu.com',7),
 (23,'d78d320','M','d78d320@liu.com',7),
 (24,'4af6c21','M','4af6c21@liu.com',7),
 (25,'f240522','M','f240522@liu.com',7),
 (26,'634fc23','M','634fc23@liu.com',7),
 (27,'f885d24','M','f885d24@liu.com',7),
 (28,'8274625','M','8274625@liu.com',7),
 (29,'3390226','M','3390226@liu.com',7),
 (30,'a46c827','M','a46c827@liu.com',7),
 (31,'7a36728','M','7a36728@liu.com',7),
 (32,'df76c29','M','df76c29@liu.com',7),
 (33,'e4be130','M','e4be130@liu.com',7),
 (34,'83af331','M','83af331@liu.com',7),
 (35,'4a53332','M','4a53332@liu.com',7),
 (36,'7d0b033','M','7d0b033@liu.com',7),
 (37,'7511934','M','7511934@liu.com',7),
 (38,'4725635','M','4725635@liu.com',7),
 (39,'11f3e36','M','11f3e36@liu.com',7),
 (40,'a6a6337','M','a6a6337@liu.com',7),
 (41,'b6a8138','M','b6a8138@liu.com',7),
 (42,'797ab39','M','797ab39@liu.com',7),
 (43,'b9e5040','M','b9e5040@liu.com',7),
 (44,'867d041','M','867d041@liu.com',7),
 (45,'241f942','M','241f942@liu.com',7),
 (46,'d226d43','M','d226d43@liu.com',7),
 (47,'55f3444','M','55f3444@liu.com',7),
 (48,'77fe445','M','77fe445@liu.com',7),
 (49,'4ab1a46','M','4ab1a46@liu.com',7),
 (50,'78d6447','M','78d6447@liu.com',7),
 (51,'558e848','M','558e848@liu.com',7),
 (52,'5070b49','M','5070b49@liu.com',7),
 (53,'153dd50','M','153dd50@liu.com',7),
 (54,'5d62c51','M','5d62c51@liu.com',7),
 (55,'4537552','M','4537552@liu.com',7),
 (56,'0d7f653','M','0d7f653@liu.com',7),
 (57,'33b1754','M','33b1754@liu.com',7),
 (58,'06c6555','M','06c6555@liu.com',7),
 (59,'b9cd156','M','b9cd156@liu.com',7),
 (60,'a9edf57','M','a9edf57@liu.com',7),
 (61,'c7ce658','M','c7ce658@liu.com',7),
 (62,'0da0359','M','0da0359@liu.com',7),
 (63,'8e30260','M','8e30260@liu.com',7),
 (64,'7776061','M','7776061@liu.com',7),
 (65,'8310962','M','8310962@liu.com',7),
 (66,'ed68963','M','ed68963@liu.com',7),
 (67,'d545e64','M','d545e64@liu.com',7),
 (68,'41ea165','M','41ea165@liu.com',7),
 (69,'3eb7066','M','3eb7066@liu.com',7),
 (70,'eeab567','M','eeab567@liu.com',7),
 (71,'dd8c068','M','dd8c068@liu.com',7),
 (72,'c3bf569','M','c3bf569@liu.com',7),
 (73,'7fc8770','M','7fc8770@liu.com',7),
 (74,'b1c5071','M','b1c5071@liu.com',7),
 (75,'a636372','M','a636372@liu.com',7),
 (76,'a385f73','M','a385f73@liu.com',7),
 (77,'98d7674','M','98d7674@liu.com',7),
 (78,'a35b075','M','a35b075@liu.com',7),
 (79,'aaa7e76','M','aaa7e76@liu.com',7),
 (80,'5b30b77','M','5b30b77@liu.com',7),
 (81,'70d9378','M','70d9378@liu.com',7),
 (82,'e68c579','M','e68c579@liu.com',7),
 (83,'fb70380','M','fb70380@liu.com',7),
 (84,'05b7d81','M','05b7d81@liu.com',7),
 (85,'d107d82','M','d107d82@liu.com',7),
 (86,'79b4583','M','79b4583@liu.com',7),
 (87,'b57f984','M','b57f984@liu.com',7),
 (88,'7803885','M','7803885@liu.com',7),
 (89,'ca60886','M','ca60886@liu.com',7),
 (90,'a765287','M','a765287@liu.com',7),
 (91,'7c08488','M','7c08488@liu.com',7),
 (92,'85edf89','M','85edf89@liu.com',7),
 (93,'95ba790','M','95ba790@liu.com',7),
 (94,'5da2791','M','5da2791@liu.com',7),
 (95,'d0d6892','M','d0d6892@liu.com',7),
 (96,'a2be093','M','a2be093@liu.com',7),
 (97,'f1d1f94','M','f1d1f94@liu.com',7),
 (98,'b315695','M','b315695@liu.com',7),
 (99,'77fb596','M','77fb596@liu.com',7),
 (100,'86efe97','M','86efe97@liu.com',7),
 (101,'f4acd98','M','f4acd98@liu.com',7),
 (102,'f14d399','M','f14d399@liu.com',7),
 (117,'tomcat','F','12313@liu.com',8),
 (118,'tomcat','F','12313@liu.com',8),
 (119,'admin','F','123123@liu.com',8),
 (120,'at','M','at@liu.com',7),
 (121,'liu','M','liu@liu.com',8),
 (122,'huang','M','huang@liu.com',7),
 (123,'1122','F','123@qq.com',7);
 ​
 /*Table structure for table `tnl_dept` */
 ​
 DROP TABLE IF EXISTS `tnl_dept`;
 ​
 CREATE TABLE `tnl_dept` (
   `dept_id` int(11) NOT NULL AUTO_INCREMENT,
   `dept_name` varchar(255) NOT NULL,
   PRIMARY KEY (`dept_id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
 ​
 /*Data for the table `tnl_dept` */
 ​
 insert  into `tnl_dept`(`dept_id`,`dept_name`) values 
 (7,'开发部'),
 (8,'测试部');
 ​
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
 /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
 /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
 /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
 

一、功能点

 1、分页
 2、数据校验
     jQuery前端校验+JSR303后端校验
 3、Ajax
 4、Rest风格的URI,使用HTTP协议请求方式的动词,来表示对资源的操作(GET(查询),POST(新增),PUT(修改),DELETE(删除))

二、技术点

 基础框架-SSM (SpringMVC+Spring+MyBatis)
 数据库+MySQL
 前端框架-bootstrap快速搭建简洁美观的界面
 项目的依赖管理-Maven
 分页-pagehelper
 逆向工程-MyBatis Generator

三、基础环境搭建

 1、创建Maven工程
 2、引入依赖的jar包
     Spring
     SpringMVC
     MyBatis
     数据库连接池,驱动包
     其他(jstl servlet-api junit)
 3、引入bootstrap前端框架
 4、编写ssm整合的关键配置文件
     web.xml,spring,springmvc,mybatis,使用mybatis的逆向工程生成对应的bean以及mapper
 5、测试mapper

四、配置文件

POM.xml

 <!--引入项目依赖的jar包 -->
     <!-- SpringMVC、Spring -->
     <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
     <dependencies>
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.12</version>
     </dependency>
 ​
     <!--引入pageHelper分页插件-->
     <dependency>
       <groupId>com.github.pagehelper</groupId>
       <artifactId>pagehelper</artifactId>
       <version>5.1.4</version>
     </dependency>
 ​
     <!--MBG-->
     <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
     <dependency>
       <groupId>org.mybatis.generator</groupId>
       <artifactId>mybatis-generator-core</artifactId>
       <version>1.3.5</version>
     </dependency>
 ​
     <!--  引入项目依赖的jar包  -->
     <!--  SpringMVC Spring -->
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-webmvc</artifactId>
       <version>4.3.7.RELEASE</version>
     </dependency>
 ​
     <!--返回json字符串的支持-->
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
       <artifactId>jackson-databind</artifactId>
       <version>2.8.8</version>
     </dependency>
 ​
     <!--JSR303数据校验支持:tomcat7以上的服务器,直接在项目POM导入即可
         tomcat7以下的:el表达式不是新的表达所以功能不强大,需要额外的给服务器的lib包中替换新的标准的el
       -->
     <dependency>
       <groupId>org.hibernate</groupId>
       <artifactId>hibernate-validator</artifactId>
       <version>5.4.1.Final</version>
     </dependency>
 ​
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>
       <version>4.3.7.RELEASE</version>
       <scope>provided</scope>
     </dependency>
 ​
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-jdbc</artifactId>
       <version>4.3.7.RELEASE</version>
     </dependency>
 ​
     <!--Spring面向切面编程-->
     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-aspects</artifactId>
       <version>4.3.7.RELEASE</version>
     </dependency>
 ​
     <!--Mybatis-->
     <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis</artifactId>
       <version>3.4.6</version>
     </dependency>
 ​
     <!--MyBatis整合Spring的适配包-->
     <dependency>
       <groupId>org.mybatis</groupId>
       <artifactId>mybatis-spring</artifactId>
       <version>1.3.1</version>
     </dependency>
 ​
     <!--数据库连接池、驱动-->
     <dependency>
       <groupId>com.mchange</groupId>
       <artifactId>c3p0</artifactId>
       <version>0.9.5.2</version>
     </dependency>
 ​
     <dependency>
       <groupId>mysql</groupId>
       <artifactId>mysql-connector-java</artifactId>
       <version>5.1.41</version>
     </dependency>
 ​
     <!--  jstl servlet-api junit  -->
     <dependency>
       <groupId>jstl</groupId>
       <artifactId>jstl</artifactId>
       <version>1.2</version>
     </dependency>
 ​
     <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
     <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>javax.servlet-api</artifactId>
       <version>3.0.1</version>
       <scope>provided</scope>
     </dependency>
 ​
     <!-- https://mvnrepository.com/artifact/javax.servlet/jsp-api -->
     <dependency>
       <groupId>javax.servlet</groupId>
       <artifactId>jsp-api</artifactId>
       <version>2.0</version>
       <scope>provided</scope>
     </dependency>
 ​
   </dependencies>

Web.xml

 <!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd" >
 ​
 <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns="http://java.sun.com/xml/ns/javaee"
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
          id="WebApp_ID" version="2.5">
 ​
   <display-name>Archetype Created Web Application</display-name>
 ​
   <!--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 applicationContext before-->
   <listener>
     <listener-class>org.springframework.web.context.ContextCleanupListener</listener-class>
   </listener>
 ​
   <!--2、springmvc的前端控制器,拦截所有请求-->
   <!--The front controller of this SpringWeb application,responsible for handling all application requestts-->
   <servlet>
     <servlet-name>dispatcherServlet</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
   </servlet>
 ​
   <!--Map all request to the DispatcherServlet for handling-->
   <servlet-mapping>
     <servlet-name>dispatcherServlet</servlet-name>
     <url-pattern>/</url-pattern>
   </servlet-mapping>
 ​
   <!--3、字符编码过滤器,一定要放在所有过滤器之前-->
   <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、使用Rest风格的URI,将页面普通的post请求转为指定的delete或者put请求-->
   <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>

dispatcherServlet-servlet.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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 ​
     <!--SpringMVC的配置文件,包含网站跳转逻辑的控制,配置  -->
     <context:component-scan base-package="cn.liu" use-default-filters="false">
         <!--只扫描控制器。  -->
         <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
     </context:component-scan>
 ​
     <!--配置视图解析器,方便页面返回  -->
     <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <property name="prefix" value="/WEB-INF/views/"></property>
         <property name="suffix" value=".jsp"></property>
     </bean>
 ​
     <!--两个标准配置  -->
     <!-- 将springmvc不能处理的请求交给tomcat -->
     <mvc:default-servlet-handler/>
     <!-- 能支持springmvc更高级的一些功能,JSR303校验,快捷的ajax...映射动态请求 -->
     <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:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
         http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
 ​
     <context:component-scan base-package="cn.liu">
         <context:exclude-filter type="annotation"
                                 expression="org.springframework.stereotype.Controller" />
     </context:component-scan>
 ​
     <!-- Spring的配置文件,这里主要配置和业务逻辑有关的 -->
     <!--=================== 数据源,事务控制,xxx ================-->
     <context:property-placeholder location="classpath:dbconfig.properties" />
     <bean id="pooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
         <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
         <property name="driverClass" value="${jdbc.driverClass}"></property>
         <property name="user" value="${jdbc.user}"></property>
         <property name="password" value="${jdbc.password}"></property>
     </bean>
 ​
     <!--================== 配置和MyBatis的整合=============== -->
     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
         <!-- 指定mybatis全局配置文件的位置 -->
         <property name="configLocation" value="classpath:mybatis.xml"></property>
         <property name="dataSource" ref="pooledDataSource"></property>
         <!-- 指定mybatis,mapper文件的位置 -->
         <property name="mapperLocations" value="classpath:mapper/*.xml"></property>
     </bean>
 ​
     <!-- 配置扫描器,将mybatis接口的实现加入到ioc容器中 -->
     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
         <!--扫描所有dao接口的实现,加入到ioc容器中 -->
         <property name="basePackage" value="cn.liu.dao"></property>
     </bean>
 ​
     <!-- 配置一个可以执行批量的sqlSession -->
     <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
         <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
         <constructor-arg name="executorType" value="BATCH"></constructor-arg>
     </bean>
     <!--=============================================  -->
 ​
     <!-- ===============事务控制的配置 ================-->
     <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
         <!--控制住数据源  -->
         <property name="dataSource" ref="pooledDataSource"></property>
     </bean>
     <!--开启基于注解的事务,使用xml配置形式的事务(必要主要的都是使用配置式)  -->
     <aop:config>
         <!-- 切入点表达式 -->
         <aop:pointcut expression="execution(* cn.liu.service..*(..))" 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>
 ​
     <!-- Spring配置文件的核心点(数据源、与mybatis的整合,事务控制) -->
 </beans>

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"/>
    </settings>
    <typeAliases>
        <package name="cn.liu.bean"/>
    </typeAliases>
    <plugins>
          <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
      </plugins>
</configuration>

dbconfig.peroperties

jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ssm_crud?characterEncoding=UTF-8
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.password=123456

五、使用代码生成器

对应的依赖

<!--MBG-->
    <!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
    <dependency>
      <groupId>org.mybatis.generator</groupId>
      <artifactId>mybatis-generator-core</artifactId>
      <version>1.3.5</version>
    </dependency>

配置mbg.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>
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <!--阻止生成注释-->
        <commentGenerator>
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!-- 配置数据库连接 -->
        <jdbcConnection
                driverClass="com.mysql.jdbc.Driver"
                connectionURL="jdbc:mysql://localhost:3306/ssm_crud"
                userId="root"
                password="123456">
        </jdbcConnection>

        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- 指定javaBean生成的位置 -->
        <javaModelGenerator targetPackage="cn.liu.bean"
                            targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--指定sql映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="mapper" targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!-- 指定dao接口生成的位置,mapper接口 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="cn.liu.dao" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>


        <!-- table指定每个表的生成策略 -->
        <table tableName="tbl_emp" domainObjectName="Employee"></table>
        <table tableName="tnl_dept" domainObjectName="Department"></table>
    </context>
</generatorConfiguration>

创建MBGTest类生成

//对应的包
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

	public static void main(String[] args) throws Exception {
        List<String> warnings = new ArrayList<String>();
        boolean overwrite = true;
        File configFile = new File("mbg.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,
                callback, warnings);
        myBatisGenerator.generate(null);
    }

六、测试功能点

依赖 POM

	<dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.4</version>
    </dependency>

使用Spring测试模块提供的测试请求功能,测试CRUD请求的正确性

//对应的包
import cn.liu.bean.Employee;
import com.github.pagehelper.PageInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "classpath:applicationContext.xml",
        "classpath:dispatcherServlet-servlet.xml"})
public class MVCTest {
    //传入SpringMvc的ioc
    @Autowired
    WebApplicationContext context;

    //虚拟mcv请求,获取到处理结果
    MockMvc mockMvc;

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

    }

    @Test
    public void testPage() throws Exception{
        //需要声明异常,perform才不会报错,明细看里面源码即可 /模拟请求拿到返回值
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/emps").param("pn", "5")).andReturn();
        //请求成功以后 请求域中会有pageInfo 我们可以取出pageInfo进行验证
        MockHttpServletRequest request = result.getRequest();
        PageInfo pi = (PageInfo) request.getAttribute("pageInfo");
        System.out.println("当前页码:"+pi.getPageNum());
        System.out.println("总页码:"+pi.getPages());
        System.out.println("总记录数:"+pi.getTotal());
        System.out.println("在页面需要连续显示的页码");

        int[] nums = pi.getNavigatepageNums();
        for (int i: nums
             ) {
            System.out.println(" "+ i);
        }
        //获取员工数据
        List<Employee> list = pi.getList();
        for (Employee e: list
             ) {
            System.out.println("ID:"+e.getEmpId()+"==>Name:"+e.getEmpName());
        }
    }

运行时遇到这个错误是

原因:Spring4测试的时候需要servlet3.0以上的才支持

七、启动Tomcat,测试分页查询

List.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>员工列表</title>
    <%
        pageContext.setAttribute("APP_PATH", request.getContextPath());
    %>
    <%--  web路径,不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题
      以/开始的相对路径,找资源,以服务器的路径为标准--%>
    <%--  引入jQuery  --%>
    <script src="${APP_PATH}/static/js/jquery-1.12.4.min.js" type="text/javascript"></script>
    <%--引入样式--%>
    <link href="${APP_PATH}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <script src="${APP_PATH}/static/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
    <!-- 搭建显示页面 -->
    <div class="container">
        <!-- 标题 -->
        <div class="row">
            <div class="col-md-12">
                <h1>SSM-CRUD</h1>
            </div>
        </div>
        <!-- 按钮 -->
        <div class="row">
            <div class="col-md-4 col-md-offset-8">
                <button class="btn btn-primary">新增</button>
                <button class="btn btn-danger">删除</button>
            </div>
        </div>
        <!-- 显示表格数据 -->
        <div class="row">
            <div class="col-md-12">
                <table class="table table-hover">
                    <tr>
                        <th>#</th>
                        <th>empName</th>
                        <th>gender</th>
                        <th>email</th>
                        <th>deptName</th>
                        <th>操作</th>
                    </tr>
                    <c:forEach items="${pageInfo.list}" var="emp">
                        <tr>
                            <th>${emp.empId}</th>
                            <th>${emp.empName}</th>
                            <th>${emp.gender=="M"?"男":"女"}</th>
                            <th>${emp.email}</th>
                            <th>${emp.department.deptName}</th>
                            <th>
                                <button class="btn btn-primary btn-xs">
                                    <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
                                    编辑
                                </button>
                                 <button class="btn btn-danger btn-xs">
                                    <span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
                                    删除
                                </button>

                            </th>
                        </tr>
                    </c:forEach>
                </table>
            </div>
        </div>
        <!-- 显示分页信息 -->
        <div class="row">
            <!-- 分页文字信息 -->
            <div class="col-md-6">
                当前页码:${pageInfo.pageNum},总页码:${pageInfo.pages},总记录数:${pageInfo.total}
            </div>
            <!-- 分页条信息 -->
            <div class="col-md-6">
                <nav aria-label="Page navigation">
                    <ul class="pagination">
                        <li><a href="${APP_PATH}/emps?pn=1">首页</a></li>
                        <c:if test="${pageInfo.hasPreviousPage}">
                            <li>
                                <a href="${APP_PATH}/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_Num">
                            <c:if test="${page_Num == pageInfo.pageNum}">
                                <li class="active"><a href="#">${page_Num}</a></li>
                            </c:if>
                            <c:if test="${page_Num != pageInfo.pageNum}">
                                <li><a href="${APP_PATH}/emps?pn=${page_Num}">${page_Num}</a></li>
                            </c:if>
                        </c:forEach>
                        <c:if test="${pageInfo.hasNextPage}">
                            <li>
                                <a href="${APP_PATH}/emps?pn=${pageInfo.pageNum+1}" aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        </c:if>
                        <li><a href="${APP_PATH}/emps?pn=${pageInfo.pages}">末页</a></li>
                    </ul>
                </nav>
            </div>
        </div>
    </div>
</body>
</html>

pageContext.setAttribute报错

<!-- https://mvnrepository.com/artifact/javax.servlet/jsp-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>

当前所实现的只是一段简单的分页查询,因为当前只能适用于浏览器与服务器的交互模型,而现在的互联网客户端不仅仅只有浏览器,有安卓,ios客户端然后服务器要再去发送请求就有点费劲了,现在最常见的解决方案就是服务器以JSON的形式发送给客户端,这样无论是安卓还是ios,浏览器解析起来就会比较方便,以下就可以解决这些问题了!

使用纯-Ajax查询

1、index.jsp页面直接发送Ajax请求进行员工分页数据的查询
2、服务器将查出的数据,以json字符串的形式返回给浏览器
3、浏览器收到js字符串。可以适用js对json进行解析,使用js通过dom增删改改变页面
4、返回json,实现客户端的无关性。

MSG通用的返回的类

**
 * 通用的返回的类
 * 
 * @author lfy
 * 
 */
public class Msg {
	//状态码   100-成功    200-失败
	private int code;
	//提示信息
	private String msg;
	
	//用户要返回给浏览器的数据
	private Map<String, Object> extend = new HashMap<String, Object>();

	public static Msg success(){
		Msg result = new Msg();
		result.setCode(100);
		result.setMsg("处理成功!");
		return result;
	}
	
	public static Msg fail(){
		Msg result = new Msg();
		result.setCode(200);
		result.setMsg("处理失败!");
		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;
	}
	
	
}

修改Controller/emps方法代码

/**
     * 导入Jackson
     * @param pn
     * @return
     */
    @RequestMapping("/emps")
    @ResponseBody
    public Msg getEmpsWithJson(@RequestParam(value = "pn",defaultValue = "1") Integer pn){
        //引入PageHelper分页插件
        //在查询之前只需要调用,传入页码,以及大小
        PageHelper.startPage(pn,5);
        //startPage后面紧跟着这个查询就是一个分页查询
        List<Employee> emps = employeeService.getAll();
        //使用PageInfo包装查询后的结果,只需要将Page Info交给页面就行了
        //封装了纤细的分页信息,包括有我们查询出来的数据 带入连续显示的页数
        PageInfo page = new PageInfo(emps, 5);
        return Msg.success().add("pageInfo", page);
    }

index.jsp

<%--
  Created by IntelliJ IDEA.
  User: Lenovo
  Date: 2020/10/26
  Time: 17:29
  To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>员工列表</title>
    <%
        pageContext.setAttribute("APP_PATH", request.getContextPath());
    %>
    <%--  web路径,不以/开始的相对路径,找资源,以当前资源的路径为基准,经常容易出问题
      以/开始的相对路径,找资源,以服务器的路径为标准--%>
    <%--  引入jQuery  --%>
    <script src="${APP_PATH}/static/js/jquery-1.12.4.min.js" type="text/javascript"></script>
    <%--引入样式--%>
    <link href="${APP_PATH}/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <script src="${APP_PATH}/static/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<!-- 搭建显示页面 -->
<div class="container">
    <!-- 标题 -->
    <div class="row">
        <div class="col-md-12">
            <h1>SSM-CRUD</h1>
        </div>
    </div>
    <!-- 按钮 -->
    <div class="row">
        <div class="col-md-4 col-md-offset-8">
            <button class="btn btn-primary">新增</button>
            <button class="btn btn-danger">删除</button>
        </div>
    </div>
    <!-- 显示表格数据 -->
    <div class="row">
        <div class="col-md-12">
            <table class="table table-hover" id="emps_table">
                <thead>
                    <tr>
                        <th>#</th>
                        <th>empName</th>
                        <th>gender</th>
                        <th>email</th>
                        <th>deptName</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>

                </tbody>
            </table>
        </div>
    </div>
    <!-- 显示分页信息 -->
    <div class="row">
        <!-- 分页文字信息 -->
        <div class="col-md-6" id="page_info_area">

        </div>
        <!-- 分页条信息 -->
        <div class="col-md-6" id="page_nav_area">

        </div>
    </div>
</div>
<script type="text/javascript">
    // var totalRecord,currentPage;
    // //1、页面加载完成以后,直接去发送Ajax请求,要到分页数据
    // $(function () {
    //     //到首页
    //     to_page(1);
    // });

    $(function () {
       to_page(1);
    });

    function to_page(pn) {
        $.ajax({
            url:"${APP_PATH}/emps",
            data:"pn="+pn,
            type:"GET",
            success:function (result) {
                //1、解析并显示员工数据
                build_emps_table(result);
                //2、解析并显示分页信息
                build_page_info(result);
                //3、解析显示分页条数据
                build_page_nav(result);
            }
        });
    }
    //解析并显示员工数据
    function build_emps_table(result) {
        //清空table表格
        $("#emps_table tbody").empty();
        var emps = result.extend.pageInfo.list;
        $.each(emps,function(index,item){
            var checkBoxTd = $("<td><input type='checkbox' class='check_item'/></td>");
            var empIdTd = $("<td></td>").append(item.empId);
            var empNameTd = $("<td></td>").append(item.empName);
            var genderTd = $("<td></td>").append(item.gender=='M'?"男":"女");
            var emailTd = $("<td></td>").append(item.email);
            var deptNameTd = $("<td></td>").append(item.department.deptName);
            var editBtn = $("<button></button>").addClass("btn btn-primary btn-sm edit_btn")
                .append($("<span></span>").addClass("glyphicon glyphicon-pencil")).append("编辑");
            //为编辑按钮添加一个自定义的属性,来表示当前员工id
            editBtn.attr("edit-id",item.empId);
            var delBtn =  $("<button></button>").addClass("btn btn-danger btn-sm delete_btn")
                .append($("<span></span>").addClass("glyphicon glyphicon-trash")).append("删除");
            //为删除按钮添加一个自定义的属性来表示当前删除的员工id
            delBtn.attr("del-id",item.empId);
            var btnTd = $("<td></td>").append(editBtn).append(" ").append(delBtn);
            //var delBtn =
            //append方法执行完成以后还是返回原来的元素
            $("<tr></tr>").append(checkBoxTd)
                .append(empIdTd)
                .append(empNameTd)
                .append(genderTd)
                .append(emailTd)
                .append(deptNameTd)
                .append(btnTd)
                .appendTo("#emps_table tbody");
        });
    }
    //解析显示分页信息
    function build_page_info(result) {
        $("#page_info_area").empty();
        $("#page_info_area").append("当前"+result.extend.pageInfo.pageNum+"页,总"+
            result.extend.pageInfo.pages+"页,总"+
            result.extend.pageInfo.total+"条记录");
    }
    //解析显示分页条数据
    function build_page_nav(result) {
        //清空分页信息
        $("#page_nav_area").empty();
        var ul = $("<ul></ul>").addClass("pagination");

        //构建元素
        var firstPageLi = $("<li></li>").append($("<a></a>").append("首页").attr("href","#"));
        var prePageLi = $("<li></li>").append($("<a></a>").append("&laquo;"));
        if(result.extend.pageInfo.hasPreviousPage == false){
            firstPageLi.addClass("disabled");
            prePageLi.addClass("disabled");
        }else{
            //为元素添加点击翻页的事件
            firstPageLi.click(function(){
                to_page(1);
            });
            prePageLi.click(function(){
                to_page(result.extend.pageInfo.pageNum -1);
            });
        }

        var nextPageLi = $("<li></li>").append($("<a></a>").append("&raquo;"));
        var lastPageLi = $("<li></li>").append($("<a></a>").append("末页").attr("href","#"));
        if(result.extend.pageInfo.hasNextPage == false){
            nextPageLi.addClass("disabled");
            lastPageLi.addClass("disabled");
        }else{
            nextPageLi.click(function(){
                to_page(result.extend.pageInfo.pageNum +1);
            });
            lastPageLi.click(function(){
                to_page(result.extend.pageInfo.pages);
            });
        }

        //添加首页和前一页 的提示
        ul.append(firstPageLi).append(prePageLi);
        //1,2,3遍历给ul中添加页码提示
        $.each(result.extend.pageInfo.navigatepageNums,function(index,item){
            var numLi = $("<li></li>").append($("<a></a>").append(item));
            if(result.extend.pageInfo.pageNum == item){
                numLi.addClass("active");
            }
            numLi.click(function(){
                to_page(item);
            });
            ul.append(numLi);
        });
        //添加下一页和末页 的提示
        ul.append(nextPageLi).append(lastPageLi);

        //把ul加入到nav
        var navEle = $("<nav></nav>").append(ul);
        navEle.appendTo("#page_nav_area");
    }
</script>
</body>
</html>

八、新增功能

新增逻辑

1、在index.jsp页面点击 新增
2、弹出新增对话框(模态框)
3、去数据库查询部门列表,显示在对话框中
4、用户输入数据,并进行校验
	·jQuery前端校验,Ajax用户名重复校验,重要数据用后端校验(JSR303),唯一约束
5、完成保存

在index.jsp页面新增对话框

<!-- 员工模态框Modal -->
<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">员工添加</h4>
            </div>
            <div class="modal-body">
                <form class="form-horizontal">  
                    <div class="form-group">
                        <label for="empName_add_input" class="col-sm-2 control-label">empName</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" name="empName" id="empName_add_input" placeholder="empName">
                            <span class="help-block"></span>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="email_add_input" class="col-sm-2 control-label">email</label>
                        <div class="col-sm-10">
                            <input type="email" class="form-control" name="email" id="email_add_input" placeholder="email@liu.com">
                            <span class="help-block"></span>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">gender</label>
                        <div class="col-sm-10">
                            <label class="radio-inline">
                                <input type="radio" name="gender" id="gender_add_input1" value="M" checked="checked"> 男
                            </label>
                            <label class="radio-inline">
                                <input type="radio" name="gender" id="gender_add_input2" value="F"> 女
                            </label>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">deptName</label>
                        <div class="col-sm-4">
                            <!--部门id-->
                            <select class="form-control" name="dId"></select>
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary" id="emp_save_btn">Save changes</button>
            </div>
        </div>
    </div>
</div>

新增功能的Ajax的书写

//清空表单样式及内容
    function reset_form(ele){
        $(ele)[0].reset();
        //清空表单样式
        $(ele).find("*").removeClass("has-error has-success");
        $(ele).find(".help-block").text("");
    }

    //点击新增按钮弹出模态框
    $("#emp_add_model_btn").click(function () {
        //清除表单数据(表单完整重置)
        reset_form("#empAddmyModal form");
        //发送ajax请求,查出部门信息,显示在下拉列表中
        getDepts("#empAddmyModal select");
        //弹出模态框
        $("#empAddmyModal").modal({
            backdrop:"static"
        });
    });
// //进行数据校验
    function validate_add_form(){
        //拿到要校验的数据,使用正则表达式
        var empName = $("#empName_add_input").val();
        var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
        if (!regName.test(empName)){
            // $("#empName_add_input").parent().addClass("has-error");
            // $("#empName_add_input").next("span").text("用户名可以是2-5位中文或者6-16位英文和数字的组合");
            show_validate_msg("#empName_add_input","error","用户名可以是2-5位中文或者6-16位英文和数字的组合");
            return false;
        } else {
            // $("#empName_add_input").parent().addClass("has-success");
            // $("#empName_add_input").next("span").text("");
            show_validate_msg("#empName_add_input","success","");
        }

        //校验邮箱
        var email = $("#email_add_input").val();
        var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
        if (!regEmail.test(email)){
            // $("#email_add_input").parent().addClass("has-error");
            // $("#email_add_input").next("span").text("邮箱格式不正确");
            show_validate_msg("#email_add_input","error","邮箱格式不正确");
            return false;
        } else {
            // $("#email_add_input").parent().addClass("has-success");
            // $("#email_add_input").next("span").text("");
            show_validate_msg("#email_add_input","success","");
        }
        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);
        }
    }

    //校验用户名是否可用
    $("#empName_add_input").change(function () {
        //发送ajax请求校验用户名是否可用
        var empName = this.value;
        $.ajax({
           url: "${APP_PATH}/checkuser",
            data: "empName="+empName,
            type: "POST",
            success:function (result) {
                if (result.code == 100){
                    show_validate_msg("#empName_add_input","success","用户名可用");
                    $("#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");
                }
            }
        });
    });

    //点击保存,员工数据
    $("#emp_save_btn").click(function () {
        //1、模态框中填写的表单数据提交给服务器进行保存
        //先对要提交的服务器的数据进行校验
        if (!validate_add_form()){
            return false;
        }
        //判断之前的Ajax用户名校验
        if ($(this).attr("ajax-va") == "error"){
            return false;
        }
        //2、发送ajax请求保存员工
        $.ajax({
            url: "${APP_PATH}/emp",
            type: "POST",
            data: $("#empAddmyModal form").serialize(),
            success:function (result) {
                if (result.code == 100) {
                    //员工保存成功,关闭模态框,并切换到最后一页
                    $("#empAddmyModal").modal('hide');
                    //发送Ajax请求显示最后一页数据即可
                    to_page(totalRecord);
                } else {
                    //显示失败信息
                    if (undefined != result.extend.errorFields.email){
                        //显示邮箱错误信息
                        show_validate_msg("#email_add_input","error",result.extend.errorFields.email);
                    }
                    if (undefined != result.extend.errorFields.empName){
                        //显示员工名字的错误信息
                        show_validate_msg("#empName_add_input","error",result.extend.errorFields.empName);
                    }
                }
            }
        });
    });

导入JSR303 进行数据校验

<!--JSR303数据校验支持:tomcat7以上的服务器,直接在项目POM导入即可
        tomcat7以下的:el表达式不是新的表达所以功能不强大,需要额外的给服务器的lib包中替换新的标准的el
      -->
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>5.4.1.Final</version>
    </dependency>

新增方法

//Service里面的方法
/**
     * 检验用户名是否可用
     *
     * @param empName
     * @return true 代表当前名字可用
     */
    public boolean checkUser(String empName) {
        EmployeeExample example = new EmployeeExample();
        Criteria criteria = example.createCriteria();
        criteria.andEmpNameEqualTo(empName);
        long count = employeeMapper.countByExample(example);
        return count == 0;
    }


/**
     * 检测用户名是否可用
     * @param empName
     * @return
     */
    @RequestMapping("/checkuser")
    @ResponseBody
    public Msg checkUser(@RequestParam("empName") String empName){
        //先判断用户名是否合法的表达式
        String regx = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})";
        if (regx.matches(regx)) {
            return Msg.fail().add("va_msg","用户名必须是6-16位数字和字母的组合或者2-5位中文");
        }
        //数据库用户名重复校验
        boolean b = employeeService.checkUser(empName);
        if (b){
            return Msg.success();
        }else {
            return Msg.fail().add("va_msg","用户名不可用");
        }
    }
/**
     * 员工保存
     * 1-支持JSR303校验
     * 2-导入hibernate-validator
     * @param employee
     * @return
     */
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    @ResponseBody
    public Msg saveEmp(@Valid Employee employee, BindingResult result){
        if (result.hasErrors()) {
            //校验失败,应该返回失败,在模态框中显示校验失败的错误信息
            Map<String, Object> map = new HashMap<>();
            List<FieldError> errors = result.getFieldErrors();
            for (FieldError f : errors) {
                System.out.println("错误的字段名:"+f.getField());
                System.out.println("错误信息:"+f.getDefaultMessage());
                map.put(f.getField(),f.getDefaultMessage());
            }
            return Msg.fail().add("errorFields",map);
        }else {
            employeeService.saveEmp(employee);
            return Msg.success();
        }
    }

九、修改功能

修改逻辑

1、点击编辑
2、弹出用户修改的模态框(显示用户信息)
3、点击更新、进行邮箱验证
4、成用户修改

修改对话框

<!-- 员工修改模态框Modal -->
<div class="modal fade" id="empUpdateModal" 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">员工添加</h4>
            </div>
            <div class="modal-body">
                <form class="form-horizontal">
                    <div class="form-group">
                        <label for="empName_add_input" class="col-sm-2 control-label">empName</label>
                        <div class="col-sm-10">
                            <p class="form-control-static" id="empName_update_static"></p>
                        </div>
                    </div>
                    <div class="form-group">
                        <label for="email_add_input" class="col-sm-2 control-label">email</label>
                        <div class="col-sm-10">
                            <input type="email" class="form-control" name="email" id="email_update_input" placeholder="email@liu.com">
                            <span class="help-block"></span>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">gender</label>
                        <div class="col-sm-10">
                            <label class="radio-inline">
                                <input type="radio" name="gender" id="gender_update_input1" value="M" checked="checked"> 男
                            </label>
                            <label class="radio-inline">
                                <input type="radio" name="gender" id="gender_update_input2" value="F"> 女
                            </label>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">deptName</label>
                        <div class="col-sm-4">
                            <!--部门id-->
                            <select class="form-control" name="dId"></select>
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary" id="emp_update_btn">Update</button>
            </div>
        </div>
    </div>
</div>

修改功能的Ajax

需注意些模态框查询的变化 和 完成后返回显示

//点击新增按钮弹出模态框
    $("#emp_add_model_btn").click(function () {
        //清除表单数据(表单完整重置)
        reset_form("#empAddmyModal form");
        //发送ajax请求,查出部门信息,显示在下拉列表中
        getDepts("#empAddmyModal select");
        //弹出模态框
        $("#empAddmyModal").modal({
            backdrop:"static"
        });
    });

    //查出所有的部门信息并显示在下拉列表中
    function getDepts(ele) {
        $(ele).empty();
        //清空之前下拉列表的值9
        $.ajax({
            url: "${APP_PATH}/depts",
            type: "GET",
            success:function(result){
                $.each(result.extend.depts,function () {
                    var optionEle = $("<option></option>").append(this.deptName)
                        .attr("value",this.deptId);
                    optionEle.appendTo(ele);
                })
            }
        });
    }
//点击编辑
    //我们是按钮创建之前就绑定了click,所以是绑定不上的
    //1、可以在创建按钮的时候绑定,2、绑定点击live
    //jQuery新版没有live使用on进行替代	edit_btn 编辑按钮生成的时候 定义的类样式
    $(document).on("click",".edit_btn",function () {
        //查出部门、员工信息,并显示部门列表
        getDepts("#empUpdateModal select");
        //查出员工信息 edit-id 是为编辑按钮添加的一个自定义属性,表示当前员工id
        getEmp($(this).attr("edit-id"));

        //弹出模态框,把员工的id传递给模态框的更新按钮
        $("#emp_update_btn").attr("edit-id",$(this).attr("edit-id"));
        $("#empUpdateModal").modal({
            backdrop:"static"

        });
    });

    function getEmp(id) {
        $.ajax({
            url: "${APP_PATH}/emp/"+id,
            type: "GET",
            success:function (result) {
                // console.log(result);
                var empData = result.extend.emp;
                $("#empName_update_static").text(empData.empName);
                $("#email_update_input").val(empData.email);
                $("#empUpdateModal input[name=gender]").val([empData.gender]);
                $("#empUpdateModal select").val([empData.dId]);
            }
        });
    }
    
    //点击更新,更新员工信息
    $("#emp_update_btn").click(function () {
        //验证邮箱是否合法
        var email = $("#email_update_input").val();
        var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
        if (!regEmail.test(email)){
            // $("#email_add_input").parent().addClass("has-error");
            // $("#email_add_input").next("span").text("邮箱格式不正确");
            show_validate_msg("#email_add_input","error","邮箱格式不正确");
            return false;
        } else {
            // $("#email_add_input").parent().addClass("has-success");
            // $("#email_add_input").next("span").text("");
            show_validate_msg("#email_add_input","success","");
        }
        //发送ajax请求保存员工信息
        $.ajax({
            url: "${APP_PATH}/emp/"+$(this).attr("edit-id"),
            type: "POST",
            data: $("#empUpdateModal form").serialize()+"&_method=PUT",
            success:function (result) {
                //关闭对话框
                $("#empUpdateModal").modal('hide');
                //回到本页
                to_page(currentPage);
            }
        })
    });

修改方法

 /**
     * 如果直接发送Ajax=PUT形式的请求
     * 封装的数据
     * Employee[empId=1014, empName=null, gender=null, email=null, dId=null]
     * 问题:
     * 	 请求体中有数据;
     * 	 但是Employee对象封装不上;
     * 	 update tbl_emp  where emp_id = 1014;
     *
     * 	 原因:
     * 	 Tomcat:
     * 	 1、将请求体中的数据,封装一个map。
     * 	 2、request.getParameter("empName")就会从这个map中取值。
     * 	 3、SpringMVC封装POJO对象的时候。
     * 	 会把POJO中每个属性的值,request.getParamter("email");
     * 	 AJAX发送PUT请求引发的血案:
     * 	 PUT请求,请求体中的数据,request.getParameter("empName")拿不到
     * 	 Tomcat一看是PUT不会封装请求体中的数据为map,只有POST形式的请求才封装请求体为map
     * 	 org.apache.catalina.connector.Request--parseParameters() (3111);
     *
     * 解决方案
     * 	 我们要能支持直接发送PUT之类的请求还要封装请求体中的数据
     * 	 配置上HttpPutFormContentFilter
     * 	 作用,将请求体中的数据解析包装成一个map
     * 	 request被重新包装,request。getParmeter()被重写,就会从自己封装的map中取数据

     * 员工更新方法
     * @param employee
     * @return
     */
    @RequestMapping(value = "/emp/{empId}",method = RequestMethod.PUT)
    @ResponseBody
    public Msg saveEmp(Employee employee, HttpServletRequest request){
        employeeService.updateEmp(employee);
        return Msg.success();
    }

    /**
     * 根据id查询员工
     * @param id
     * @return
     */
    @RequestMapping(value = "/emp/{id}",method = RequestMethod.GET)
    @ResponseBody
    public Msg getEmp(@PathVariable("id") Integer id){
        Employee employee = employeeService.getEmp(id);
        return Msg.success().add("emp",employee);
    }

十、删除功能

删除逻辑

单个删除
	点击删除按钮,发送删除请求,删除完成后还是回到本页面
多个删除

实现Ajax删除

//点击删除 切记delete_btn前面加上小数点 delete_btn 在Ajax遍历生成按钮的时候就定义了!
    $(document).on("click",".delete_btn",function () {
        //弹出是否确认删除对话框
        var empName = $(this).parents("tr").find("td:eq(2)").text();
      	//del-id 删除按钮添加自定义的属性,表示当前要删除员工的id
        var empId = $(this).attr("del-id");
        if (confirm("确认删除{"+empName+"】吗")){
            //发送Ajax请求
            $.ajax({
                url: "${APP_PATH}/emp/"+empId,
                type: "DELETE",
                success:function (result) {
                    alert(result.msg);
                    //回到本页
                    to_page(currentPage);
                }
            })
        }
    });

    //完成全选/全不选功能
    $("#check_all").click(function(){
        //attr获取checked是undefined;
        //我们这些dom原生的属性;attr获取自定义属性的值;
        //prop修改和读取dom原生属性的值
        $(".check_item").prop("checked",$(this).prop("checked"));
    });

    //check_item
    $(document).on("click",".check_item",function(){
        //判断当前选择中的元素是否5个
        var flag = $(".check_item:checked").length==$(".check_item").length;
        $("#check_all").prop("checked",flag);
    });

    //点击全部删除,点击新增旁边的删除按钮
    $("#emp_delete_all_btn").click(function () {
        var empNames = "";
        var del_idstr = "";
        $.each($(".check_item:checked"),function () {
            empNames += $(this).parents("tr").find("td:eq(2)").text()+",";
            del_idstr += $(this).parents("tr").find("td:eq(1)").text()+"-";
        });
        //去除empNames多余的逗号
        empNames = empNames.substring(0,empNames.length-1);
        del_idstr = del_idstr.substring(0,del_idstr.length-1);
        if (confirm("确认删除【"+empNames+"】")){
            //发送ajax请求
            $.ajax({
                url: "${APP_PATH}/emp/"+del_idstr,
                type: "DELETE",
                success:function (result) {
                    alert(result.msg);
                    //回到本页
                    to_page(currentPage);
                }
            })
        }
    });

删除方法

	 //Service
	/**
     * 员工删除
     * @param id
     */
    public void deleteEmp(Integer id) {
        employeeMapper.deleteByPrimaryKey(id);
    }

    /**
     * 批量删除二合一
     * @param ids
     */
    public void deleteeBatch(List<Integer> ids) {
        EmployeeExample example = new EmployeeExample();
        Criteria criteria = example.createCriteria();
        //criteria.andEmpIdIn(ids);相当于delete from xxx where emp_id in (1,2,3)
        criteria.andEmpIdIn(ids);
        employeeMapper.deleteByExample(example);
    }

/**
     * D单个批量二合一
     * 批量删除:1-2-3
     * 单个删除:1
     * @param ids
     * @return
     */
    @RequestMapping(value = "/emp/{ids}",method = RequestMethod.DELETE)
    @ResponseBody
    public Msg deleteEmp(@PathVariable("ids")String ids){
        //批量删除
        if (ids.contains("-")){
            List<Integer> del_ids = new ArrayList<>();
            String[] str_ids = ids.split("-");
            //组装id的集合
            for (String string: str_ids
                 ) {
                del_ids.add(Integer.parseInt(string));
            }
            employeeService.deleteeBatch(del_ids);

        }else{
            Integer id = Integer.parseInt(ids);
            employeeService.deleteEmp(id);
        }
        return Msg.success();
    }

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值