• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

SSM整合项目

武飞扬头像
poixao
帮助1



项目简介

使用 SSM 框架搭建出一套简单的 CRUD 项目示例,主要涉及两张表:员工表和部门表,其中每个员工都对应一个部门

主要实现的功能

1、分页查询所有员工信息并展示列表。

2、添加一条员工的信息。

3、新增数据需要校验:

  • jQuery 前端校验用户名和邮箱是否合法。
  • Ajax 请求校验用户名是否重复。
  • JSR 303 后端校验用户名、邮箱是否合法以及用户名是否重复。

4、编辑修改某条员工的信息。

5、删除某条员工的信息,批量删除所选员工的信息。

6、RESTful 风格的URI。

涉及的技术

1、后端框架:SSM(Spring 5 Spring MVC MyBatis 3) Maven 3.6.3

2、MyBatis 分页插件:PageHelper

3、MyBatis 逆向工程:MyBatis Generator

4、数据库:MySQL 5.7 Druid 数据库连接池

5、前端框架:BootStrap 5

最终效果图

学新通

 
 

一、搭建环境

1. 添加依赖,打包方式为 war

    <packaging>war</packaging>
    <!--引入项目依赖的jar包 -->
    <!-- SpringMVC、Spring -->
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <dependencies>

        <!--引入pageHelper分页插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.0.0</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>


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

        <!-- 返回json字符串的支持 -->
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.8.8</version>
        </dependency>

        <!--JSR303数据校验支持;tomcat7及以上的服务器,
        tomcat7以下的服务器:el表达式。额外给服务器的lib包中替换新的标准的el
        -->
        <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>

        <!-- Spring-Jdbc -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

        <!--Spring-test -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>


        <!-- Spring面向切面编程 -->
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.7.RELEASE</version>
        </dependency>

        <!--MyBatis -->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!-- MyBatis整合Spring的适配包 -->
        <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.1</version>
        </dependency>

        <!--druid连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.7</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <!-- (jstl,servlet-api,junit) -->
        <!-- https://mvnrepository.com/artifact/jstl/jstl -->

        <!--引入jsp-->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>

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


        <!-- junit -->
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>


    </dependencies>
    <!--逆向工程的插件-->
    <!-- 控制Maven在构建过程中相关配置 -->
    <build>
        <!-- 构建过程中用到的插件 -->
        <plugins>
            <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.0</version>
                <!-- 插件的依赖 -->
                <dependencies>
                    <!-- 逆向工程的核心依赖 -->
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.2</version>
                    </dependency>
                    <!-- 数据库连接池 -->
                    <dependency>
                        <groupId>com.alibaba</groupId>
                        <artifactId>druid</artifactId>
                        <version>1.2.7</version>
                    </dependency>
                    <!-- MySQL驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.41</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>
学新通

2. 创建webapp目录,添加web.xml

注意路径:\src\main\webapp\web.xml

学新通

3. 配置tomcat服务器

学新通

4. 引入 BootStrap 前端框架

Bootstrap 官网:https://getbootstrap.com/,图标资源官网:https://icons.getbootstrap.com/

中文第3版Bootstrap的学习资料:https://v3.bootcss.com/getting-started/

学新通

5. 引入jquery

学新通


二、整合SSM

1. 配置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">

    <!--指定Spring配置文件-->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application.xml</param-value>
    </context-param>

    <!--该监听器将根据contextConfigLocation参数加载Spring配置文件, 初始化Spring应用上下文-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!--过滤器-->
    <!--配置字符编码过滤器,一定要放在所有过滤器之前,/* 表示拦截所有请求-->
    <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>

    <!-- 配置HTTP方法过滤器, 实现REST风格的增删改查 -->
    <!-- 该过滤器根据指定的请求参数(默认是"_method")来修改请求的类型 -->
    <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>


    <!--HttpPutFormContentFilter过滤器会自动的封装前台传递过来的PUT请求的参数-->
    <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>

    <!--2、配置 Spring MVC 的前端控制器,拦截所有请求-->
    <servlet>
        <servlet-name>DispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <!--指定SpringMVC的配置文件-->
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mvc.xml</param-value>
        </init-param>
        <!--随着tomcat的启动-->
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>DispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
学新通

2. 配置application.xml

Spring 的配置文件,主要配置业务逻辑相关的内容:数据源、与MyBatis的整合、事务控制等。

(1)先创建一个 dbconfig.properties,用来保存数据库驱动的配置信息

jdbc.url=jdbc:mysql://localhost:3306/ssm_crud
jdbc.driver=com.mysql.jdbc.Driver
jdbc.username=root
jdbc.password=123456

(2)在配置文件中进行配置

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


    <!--1、配置扫描包,不扫描controller-->
    <context:component-scan base-package="com.study.ssm">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!--2、引入数据库驱动的properties文件-->
    <context:property-placeholder location="classpath:dbconfig.properties"/>

    <!--3、配置数据源-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="url" value="${jdbc.url}"></property>
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!--4、与 MyBatis 的整合配置-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--指定数据源-->
        <property name="dataSource" ref="dataSource"></property>
        <!--指定 MyBatis 全局配置文件的位置-->
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <!--指定 MyBatis 映射文件的位置-->
        <property name="mapperLocations" value="classpath:com/study/ssm/dao/*.xml"></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>

    <!--配置扫描器,将 MyBatis 接口的实现加入到 IOC 容器中-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--扫描所有的 DAO 接口的实现,加入到 IOC 容器中-->
        <property name="basePackage" value="com.study.ssm.dao"></property>
    </bean>

    <!--4、事务控制-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--指定数据源-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--开启基于注解的事务,使用 XML 配置形式的事务(比较主要的事务都用配置式)-->
    <aop:config>
        <!--切入点表达式-->
        <aop:pointcut id="txPoint" expression="execution(* com.study.ssm.service..*(..))"/>
        <!--配置事务增强-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>

    <!--配置事务增强,事务如何增强-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">

        <tx:attributes>
            <!--
                 * 代表所有方法都是事务方法
                 get* 代表以get开始的所有方法
            -->
            <tx:method name="*"/>
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
</beans>
学新通

3. 配置spring-mvc.xml

Spring MVC 的配置文件,主要包含网站跳转逻辑的控制、配置。

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

    <!-- Spring MVC 的配置文件,主要包含网站跳转逻辑的控制、配置-->
    <context:component-scan base-package="com.study.ssm" 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/js/"></property>
        <property name="suffix" value=".jsp"></property>
    </bean>

    <!--将 Spring MVC 不能处理的请求交给 tomcat 处理-->
    <mvc:default-servlet-handler/>

    <!-- 开启mvc注解驱动 -->
    <!--能支持 Spring MVC 更高级的一些功能,比如 JSR 303 校验、快捷的 Ajax 映射动态请求等-->
    <mvc:annotation-driven/>

</beans>
学新通

4. 配置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>
        <!--给Java Bean起别名-->
        <package name="com.study.ssm.bean"/>
    </typeAliases>


    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!--分页查询合理化-->
            <property name="reasonable" value="true"/>
        </plugin>
    </plugins>
</configuration>
学新通

5. 创建数据库表

CREATE TABLE `tbl_emp` (
  `emp_id` int(11)  PRIMARY KEY AUTO_INCREMENT NOT NULL  ,
  `emp_name` varchar(255) DEFAULT NULL,
  `gender` char(1) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  `d_id` int(11) DEFAULT NULL,
	FOREIGN KEY (d_id) REFERENCES tbl_dept(dept_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `tbl_dept` (
  `dept_id` int(11) PRIMARY KEY AUTO_INCREMENT NOT NULL,
  `dept_name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

6. Mybatis 逆向工程

(1)配置 generatorConfig.xml 逆向工程配置文件(必须叫这名)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>

    <!--targetRuntime设置生成的模式-->
    <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="com.study.ssm.bean"
                            targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!--指定sql映射文件生成的位置 -->
        <!-- <sqlMapGenerator> 的 targetPackage属性 最好与 <javaClientGenerator> 的targetPackage属性一致-->
        <sqlMapGenerator targetPackage="com/study/ssm/dao" targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

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


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

(2)使用逆向工程插件

学新通

7. 项目完整的结构

学新通

修改 Employee 类,添加部门属性

...
    private Department department;

    public Employee() {
    }

    public Employee(Integer empId, String empName, String gender, String email, Integer dId) {
        this.empId = empId;
        this.empName = empName;
        this.gender = gender;
        this.email = email;
        this.dId = dId;
    }

    @Override
    public String toString() {
        return "Employee{"  
                "empId="   empId  
                ", empName='"   empName   '\''  
                ", gender='"   gender   '\''  
                ", email='"   email   '\''  
                ", dId="   dId  
                ", department="   department  
                '}';
    } 
...
学新通

修改 EmployeeMapper 接口,增加下面内容

...
    //带上部门查询的条件查询
    List<Employee> selectByExampleWithDept(EmployeeExample example);
	
	//带上部门的主键查询
    Employee selectByPrimaryKeyWithDept(Integer empId);
...

修改 EmployeeMapper.xml,增加下面内容

<!--新增的带有部门信息的返回结果集-->
<resultMap id="WithDeptResultMap" type="com.study.ssm.bean.Employee">
    <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="d_id" jdbcType="INTEGER" property="dId" />
    <association property="department" javaType="com.study.ssm.bean.Department">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </association>
</resultMap>

<!--带部门列的sql-->
<sql id="WithDept_Column_List">
    e.emp_id, e.emp_name, e.gender, e.email, e.d_id, d.dept_id, d.dept_name
</sql>


<!--List<Employee> selectByExampleWithDept(EmployeeExample example);-->
<!--新增的带部门查询-->
<select id="selectByExampleWithDept"
        parameterType="com.study.ssm.bean.EmployeeExample"
        resultMap="WithDeptResultMap">
    select
    <if test="distinct">
        distinct
    </if>
    <include refid="WithDept_Column_List" />
    from tbl_emp e left join tbl_dept d on e.d_id=d.dept_id
    <if test="_parameter != null">
        <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
        order by ${orderByClause}
    </if>
</select>

<!--Employee selectByPrimaryKeyWithDept(Integer empId);-->
<select id="selectByPrimaryKeyWithDept"
        parameterType="java.lang.Integer"
        resultMap="WithDeptResultMap">
    select
    <include refid="WithDept_Column_List" />
    from tbl_emp e left join tbl_dept d on e.d_id=d.dept_id
    where emp_id = #{empId,jdbcType=INTEGER}
</select>
学新通

8. Spring 整合 Junit 4测试 Mapper 添加数据

/**
 * 推荐Spring的项目就可以使用Spring的单元测试,可以自动注入我们需要的组件
 * 1、导入SpringTest模块
 * 2、@ContextConfiguration指定Spring配置文件的位置
 * 3、直接autowired要使用的组件即可
 */
//指定单元测试类型
@RunWith(SpringJUnit4ClassRunner.class)
//指定配置文件
@ContextConfiguration(locations = {"classpath:application.xml"})
public class MapperTest {
    @Autowired
    DepartmentMapper departmentMapper;

    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    SqlSession sqlSession;

    @Test
    public void testCRUD() {
        System.out.println(departmentMapper);

        //1.插入几个部门
        departmentMapper.insertSelective(new Department(null, "开发部"));
        departmentMapper.insertSelective(new Department(null, "测试部"));

        //插入一条员工数据
        employeeMapper.insertSelective(new Employee(null, "张三", "M", "zhangsan@qq.com", 1));
        employeeMapper.insertSelective(new Employee(null, "李四", "M", "lisi@163.com", 1));
        employeeMapper.insertSelective(new Employee(null, "王五", "M", "wangwu@sina.com", 1));

        //批量插入员工数据
        EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
        for (int i = 0; i < 100; i  ) {
            String uid = UUID.randomUUID().toString().substring(0, 5)   i;
            mapper.insertSelective(new Employee(null, uid, "W", uid   "@gmail.com", 2));
        }
    }
}
学新通


三、规定RESTful 风格的URI

URI 请求方式 功能
/emps GET 获取所有员工信息
/emp POST 保存新增用户信息
/checkEmp GET 检查用户是否重名
/emp/{id} GET 根据id获取用户信息
/emp/{empId} PUT 保存修改用户信息
/emp/{empId} DELETE 删除用户


四、创建index.jsp

基本的骨架搭建

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <%--得到工程路径--%>
    <% pageContext.setAttribute("APP_PATH", request.getContextPath()); %>
    <%--引入js文件--%>
    <script src="https://blog.csdn.net/zyy130988/article/details/${APP_PATH}/static/js/jquery-1.12.4.min.js"></script>
    <%--引入bootstrap--%>
    <script src="https://blog.csdn.net/zyy130988/article/details/${APP_PATH}/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    <link href="https://blog.csdn.net/zyy130988/article/details/${APP_PATH}/static/bootstrap-3.3.7-dist/css/bootstrap.min.css" rel="stylesheet"/>
    <title>首页</title>
</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" id="emp_add_modal_btn">新增</button>
            <button class="btn btn-danger" id="emp_delete_all_btn">删除</button>
        </div>
    </div>
    <!-- 显示表格数据 -->
    <div class="row">
        <div class="col-md-12">
            <table class="table table-hover" id="emps_table">
                <thead>
                <tr>
                    <th>
                        <input type="checkbox" id="check_all"/>
                    </th>
                    <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>
    
<script type="text/javascript">
    // 完善前端代码...
</script>
    
</div>
</body>
</html>
学新通


五、查询

1. 需要实现的功能

(1)第一步,用 JSTL 实现(URI:/emps):

  • 访问 index.jsp 页面。
  • index.jsp 发送出查询员工列表的请求。
  • EmployeeController 接收请求,查出员工的数据。
  • 来到 list.jsp 页面进行展示。
  • 使用 PageHelper 分页插件完成分页查询的功能。

(2)第二步,用 Ajax 实现:

  • index.jsp 页面直接发送 Ajax 请求,进行员工分页数据的查询。
  • 服务器将查出来的数据,通过 JSON 字符串的形式返回给浏览器。
  • 浏览器收到 JSON 字符串后,用 JS 对JSON 解析,通过 DOM 增删改查页面。
  • 返回 JSON,实现客户端的无关性。

2. controller

@Controller
public class EmployeeController {

    @Autowired
    EmployeeService employeeService;
    
    @RequestMapping("/emps")
    public String getEmps(
            @RequestParam(value = "pn", defaultValue = "1") Integer pn,
            Model model) {
        // 这不是一个分页查询;
        // 引入PageHelper分页插件
        // 在查询之前只需要调用,传入页码,以及每页的大小
        PageHelper.startPage(pn, 5);
        // startPage后面紧跟的这个查询就是一个分页查询
        List<Employee> emps = employeeService.getAll();
        // 使用pageInfo包装查询后的结果,只需要将pageInfo交给页面就行了。
        // 封装了详细的分页信息,包括有我们查询出来的数据,传入连续显示的页数
        PageInfo page = new PageInfo(emps, 5);
        model.addAttribute("pageInfo", page);
        return "list";
    }
}
学新通

3. service

@Service
public class EmployeeService {

    @Autowired
    EmployeeMapper employeeMapper;
    
    public List<Employee> getAllEmps() {
        EmployeeExample example = new EmployeeExample();
        example.setOrderByClause("emp_id");
        return employeeMapper.selectByExampleWithDept(example);
    }
}

4. spring 整合 Junit 4测试 MVC

/**
 * 使用Spring测试模块提供的测试请求功能,测试curd请求的正确性
 *
 */
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration()
@ContextConfiguration(locations = {"classpath:applicationContext.xml", "classpath:Spring-mvc.xml"})
public class MvcTest {
    // 传入Springmvc的ioc
    @Autowired
    WebApplicationContext context;
    // 虚拟mvc请求,获取到处理结果。
    MockMvc mockMvc;

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

    @Test
    public void testPage() throws Exception {
        //模拟请求拿到返回值
        MvcResult result = mockMvc.perform(MockMvcRequestBuilders.get("/emps").param("pn", "1"))
                .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.print(" "   i);
        }
        System.out.println();
        //获取员工数据
        List<Employee> list = pi.getList();
        for (Employee employee : list) {
            System.out.println("ID:"   employee.getEmpId()   "==>Name:"   employee.getEmpName());
        }
    }
}
学新通

学新通

5. 添加 Msg 类引入链式编程

public class Msg {
    private String code;
    private String msg;

    private Map<String, Object> extend = new HashMap<>();

    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;
    }
    ...
}
学新通

6. 修改 controller

修改为使用 JSON 格式传输数据,需要 Jackson 的依赖。

    @ResponseBody
    @RequestMapping(value = "/emps", method = RequestMethod.GET)
    public Msg getEmpsWithJson(@RequestParam(value = "pn", defaultValue = "1") Integer pn) {

        PageHelper.startPage(pn, 5);
        List<Employee> emps = employeeService.getAllEmps();
        PageInfo pageInfo = new PageInfo(emps, 5);
        return Msg.success().add("pageInfo", pageInfo);
    }

7. 补充前端代码,采用Ajax发送请求

<script type="text/javascript">中补充

//总记录数
var totalRecord;
//1、页面加载完成以后,直接去发送一个ajax请求,要到分页数据
$(function () {
    to_page(1);
});

function to_page(pn) {
    $.ajax({
        url: "${APP_PATH}/emps",
        data: "pn="   pn,
        type: "GET",
        success: function (result) {
            //console.log(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);

        //将每行数据以及对应的按钮加入到表格的<tbody>标签中
        //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   "条记录");
    totalRecord = result.extend.pageInfo.total;
    currentPage = result.extend.pageInfo.pageNum;
}

//解析显示分页条,点击分页要能去下一页....
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) {
        //添加不允许点击的样式(css)
        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) {
        //添加不允许点击的样式(css)
        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) {
            //添加不允许点击的样式(css)
            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);
    //添加到id为page_nav_area的元素中
    navEle.appendTo("#page_nav_area");
}
学新通

8. 效果

启动服务,直接显示首页:

学新通


六、新增数据

1. 需要实现的功能

  • 在 index.jsp 页面点击“新增”弹出对话框

  • 去数据库中查询部门列表,显示在对话框内

  • 对用户输入的数据进行校验

    • jQuery 前端校验格式
    • Ajax 校验用户名是否重复
    • 后端校验(JSR 303)
  • 保存用户数据

2. 添加模态框

在标签的开头处添加

<!-- 员工添加的模态框 -->
<div class="modal fade" id="empAddModal" 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 class="col-sm-2 control-label">empName</label>
                        <div class="col-sm-10">
                            <input type="text" name="empName" class="form-control" id="empName_add_input" placeholder="empName">
                            <span class="help-block"></span>
                        </div>
                    </div>
                    <div class="form-group">
                        <label class="col-sm-2 control-label">email</label>
                        <div class="col-sm-10">
                            <input type="text" name="email" class="form-control" id="email_add_input" placeholder="email@atguigu.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="gender1_add_input" value="M" checked="checked"> 男
                            </label>
                            <label class="radio-inline">
                                <input type="radio" name="gender" id="gender2_add_input" 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">关闭</button>
                <button type="button" class="btn btn-primary" id="emp_save_btn">保存</button>
            </div>
        </div>
    </div>
</div>
学新通

3 查询部门列表

Controller

@Controller
public class DepartmentController {

    @Autowired
    private DepartmentService departmentService;

    @ResponseBody
    @RequestMapping("/depts")
    public Msg getDeptsWithJson() {
        List<Department> depts = departmentService.getAllDepts();
        return Msg.success().add("depts", depts);
    }
}

Service

@Service
public class DepartmentService {

    @Autowired
    DepartmentMapper departmentMapper;

    public List<Department> getAllDepts() {
        return departmentMapper.selectByExample(null);
    }
}

补充前端代码

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

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

//查出所有的部门信息并显示在下拉列表中
function getDepts(ele){
    //清空之前下拉列表的值
    $(ele).empty();
    $.ajax({
        url:"${APP_PATH}/depts",
        type:"GET",
        success:function(result){
            //{"code":100,"msg":"处理成功!",
            //"extend":{"depts":[{"deptId":1,"deptName":"开发部"},{"deptId":2,"deptName":"测试部"}]}}
            //console.log(result);
            //显示部门信息在下拉列表中
            $.each(result.extend.depts,function(){
                var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                optionEle.appendTo(ele);
            });
        }
    });
}
学新通

4. jQuery 前端校验格式

//校验表单数据
function validate_add_form(){
    //1、拿到要校验的数据,使用正则表达式
    var empName = $("#empName_add_input").val();
    var regName = /(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})/;
    if(!regName.test(empName)){
        //alert("用户名可以是2-5位中文或者6-16位英文和数字的组合");
        show_validate_msg("#empName_add_input", "error", "用户名可以是2-5位中文或者6-16位英文和数字的组合");
        return false;
    }else{
        show_validate_msg("#empName_add_input", "success", "");
    };

    //2、校验邮箱信息
    var email = $("#email_add_input").val();
    var regEmail = /^([a-z0-9_\.-] )@([\da-z\.-] )\.([a-z\.]{2,6})$/;
    if(!regEmail.test(email)){
        //alert("邮箱格式不正确");
        //应该清空这个元素之前的样式
        show_validate_msg("#email_add_input", "error", "邮箱格式不正确");
        return false;
    }else{
        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);
    }
}
学新通

5. Ajax 校验用户名是否重复

Controller

/**
* 检查用户名是否可用
*/
@ResponseBody
@RequestMapping("/checkuser")
public Msg checkuser(@RequestParam("empName") String empName) {
    //先判断用户名是否是合法的表达式;
    String regx = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5})";
    if (!empName.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", "用户名不可用");
    }
}
学新通

Service

public boolean checkEmp(String empName) {
    EmployeeExample example = new EmployeeExample();
    example.createCriteria().andEmpNameEqualTo(empName);
    return employeeMapper.countByExample(example) == 0;
}

补充前端代码

//校验用户名是否可用
$("#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","用户名可用");
                //添加定义属性ajax-va,值为"success"
                $("#emp_save_btn").attr("ajax-va","success");
            }else{
                show_validate_msg("#empName_add_input","error",result.extend.va_msg);
                //添加定义属性ajax-va,值为"error"
                $("#emp_save_btn").attr("ajax-va","error");
            }
        }
    });
});
学新通

6. 后端校验 保存

Controller

/**
* 校验用户是否可用
*/
@RequestMapping(value = "/emp", method = RequestMethod.POST)
@ResponseBody
/**
* @Valid: 使用JSR303对employee属性进行校验, 校验规则在属性注解的@Pattern中设置
* BindingResult result: 校验后,返回的结果
*/
public Msg saveEmp(@Valid Employee employee, BindingResult result) {
    if (result.hasErrors()) {
        //校验失败,应该返回失败,在模态框中显示校验失败的错误信息
        Map<String, Object> map = new HashMap<>();
        List<FieldError> errors = result.getFieldErrors();
        for (FieldError fieldError : errors) {
            //fieldError.getField(): 错误的字段名
            //fieldError.getDefaultMessage(): 错误信息
            map.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        return Msg.fail().add("errorFields", map);
    } else {
        employeeService.saveEmp(employee);
        return Msg.success();
    }
}
学新通

Service

public void saveEmp(Employee employee) {
    employeeMapper.insert(employee);
}

补充前端代码

//点击保存,保存员工。
$("#emp_save_btn").click(function(){
    //1、模态框中填写的表单数据提交给服务器进行保存
    //1、先对要提交给服务器的数据进行校验
    if(!validate_add_form()){
        return false;
    };
    //1、判断之前的ajax用户名校验是否成功。如果成功。
    if($(this).attr("ajax-va")=="error"){
        return false;
    }

    //2、发送ajax请求保存员工
    $.ajax({
        url:"${APP_PATH}/emp",
        type:"POST",
        data:$("#empAddModal form").serialize(),
        success:function(result){
            //alert(result.msg);
            if(result.code == 100){
                //员工保存成功;
                //1、关闭模态框
                $("#empAddModal").modal('hide');

                //2、来到最后一页,显示刚才保存的数据
                //发送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);
                }
            }
        }
    });
});
学新通

7. 效果

学新通


七、修改数据

1. 需要实现的功能

  • 点击编辑按钮,弹出用户修改的模态框。
  • 模态框可以回显用户的信息。
  • 点击更新,完成修改操作。

2. 添加模态框

<!-- 员工修改的模态框 -->
<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 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 class="col-sm-2 control-label">email</label>
                        <div class="col-sm-10">
                            <input type="text" name="email" class="form-control" id="email_update_input" placeholder="email@atguigu.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="gender1_update_input" value="M" checked="checked"> 男
                            </label>
                            <label class="radio-inline">
                                <input type="radio" name="gender" id="gender2_update_input" 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">关闭</button>
                <button type="button" class="btn btn-primary" id="emp_update_btn">更新</button>
            </div>
        </div>
    </div>
</div>
学新通

3. 获取要修改的员工信息

Controller

@ResponseBody
@RequestMapping(value = "/emp/{id}", method = RequestMethod.GET)
public Msg getEmp(@PathVariable("id") Integer id) {
    Employee employee = employeeService.getEmp(id);
    return Msg.success().add("emp", employee);
}

Service

public Employee getEmp(Integer id) {
    return employeeMapper.selectByPrimaryKey(id);
}

补充前端代码

//1、我们是按钮创建之前就绑定了click,所以绑定不上。
//1)、可以在创建按钮的时候绑定。    2)、绑定点击.live()
//jquery新版没有live,使用on进行替代
$(document).on("click",".edit_btn",function(){
    //alert("edit");
    //1、查出部门信息,并显示部门列表
    getDepts("#empUpdateModal select");
    //2、查出员工信息,显示员工信息
    getEmp($(this).attr("edit-id"));

    //3、把员工的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]);
        }
    });
}
学新通

4. 保存员工信息

Controller

@ResponseBody
@RequestMapping(value = "/emp/{empId}", method = RequestMethod.PUT)
public Msg saveEmp(Employee employee) {
    employeeService.updateEmp(employee);
    System.out.println(employee);
    return Msg.success();
}

Service

public void updateEmp(Employee employee) {
    employeeMapper.updateByPrimaryKeySelective(employee);
}

补充前端代码

//点击更新,更新员工信息
$("#emp_update_btn").click(function(){
    //验证邮箱是否合法
    //1、校验邮箱信息
    var email = $("#email_update_input").val();
    var regEmail = /^([a-z0-9_\.-] )@([\da-z\.-] )\.([a-z\.]{2,6})$/;
    if(!regEmail.test(email)){
        show_validate_msg("#email_update_input", "error", "邮箱格式不正确");
        return false;
    }else{
        show_validate_msg("#email_update_input", "success", "");
    }

    //2、发送ajax请求保存更新的员工数据
    $.ajax({
        url:"${APP_PATH}/emp/" $(this).attr("edit-id"),
        type:"PUT",
        data:$("#empUpdateModal form").serialize(),
        success:function(result){
            //alert(result.msg);
            //1、关闭对话框
            $("#empUpdateModal").modal("hide");
            //2、回到本页面
            to_page(currentPage);
        }
    });
});
学新通

5. 效果

学新通


八、删除数据

1. 需要实现的功能

  • 单个删除,点击某条用户的删除按钮,弹出提示框,点击确定即可删除

  • 批量删除

2. Controller

@ResponseBody
@RequestMapping(value = "/emp/{empId}", method = RequestMethod.DELETE)
public Msg deleteEmp(@PathVariable("empId") String ids) {

    //判断批量删除还是单个删除
    if (ids.contains("-")) {
        ArrayList<Integer> list = new ArrayList<>();
        String[] str_ids = ids.split("-");
        for (String str_id : str_ids) {
            list.add(Integer.parseInt(str_id));
        }
        employeeService.deleteBatch(list);
    } else {
        int id = Integer.parseInt(ids);
        employeeService.deleteEmp(id);
    }
    return Msg.success();
}
学新通

3. Service

public void deleteEmp(Integer empId) {
    employeeMapper.deleteByPrimaryKey(empId);
}

public void deleteBatch(ArrayList<Integer> list) {
    EmployeeExample example = new EmployeeExample();
    example.createCriteria().andEmpIdIn(list);
    employeeMapper.deleteByExample(example);
}

4. 单个删除

补充前端代码

//单个删除
$(document).on("click",".delete_btn",function(){
    //1、弹出是否确认删除对话框
    var empName = $(this).parents("tr").find("td:eq(2)").text();
    var empId = $(this).attr("del-id");
    //alert($(this).parents("tr").find("td:eq(1)").text());
    if(confirm("确认删除【" empName "】吗?")){
        //确认,发送ajax请求删除即可
        $.ajax({
            url:"${APP_PATH}/emp/" empId,
            type:"DELETE",
            success:function(result){
                alert(result.msg);
                //回到本页
                to_page(currentPage);
            }
        });
    }
});
学新通

5. 批量删除

补充前端代码

//完成全选/全不选功能
$("#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(){
        //this
        empNames  = $(this).parents("tr").find("td:eq(2)").text() ",";
        //组装员工id字符串
        del_idstr  = $(this).parents("tr").find("td:eq(1)").text() "-";
    });
    //去除empNames多余的,
    empNames = empNames.substring(0, empNames.length-1);
    //去除删除的id多余的-
    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);
                //每次删除完后,取消全选
                $("#check_all").prop("checked",false);
            }
        });
    }
});
学新通

6. 效果

单个删除

学新通

批量删除

学新通


九、项目总结

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgbgakk
系列文章
更多 icon
同类精品
更多 icon
继续加载