天天看點

尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper

SSM-CRUD

ssm:SpringMVC+Spring+Mybatis

CRUD:Create(建立)、Retrieve(查詢)、Update(更新)、Delete(删除)

功能點:

  • 分頁
  • 資料校驗
    • JQuery前端校驗+JSR303後端校驗
  • ajax
  • Rest風格的URI;使用HTTP協定請求方式的動詞,來表示對資源的操作(GET(查詢)、POST(新增)、PUT(修改)、DELETE(删除))

技術點

  • 基礎架構-SSM(SpringMVC+Spring+Mybatis)
  • 資料庫-MySQL
  • 前端架構-BootStrap快速搭建簡潔美觀的界面
  • 項目的依賴管理-Maven
  • 分頁-pagehelper
  • 逆向工程-Mybatis Generator

路徑問題:

不以/開始的相對路徑,找資源,以目前資源的路徑為準,經常容易出現問題

以/開始的相對路徑,找資源,以伺服器的路徑為标準(http://localhost:8080/)需要加上項目名

http://localhost:8080/ssm_crud

基礎環境搭建

建立一個maven工程

尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper

可以看到我們的 dreamland-web 子工程沒有 java、resources 和 test 目錄,我們需要手動建立一下,操作過程如下:

main -> New -> Directory ==> 建立 java

main -> New -> Directory ==> 建立 resources

src -> New -> Directory ==> 建立 test

test -> New -> Directory ==> 建立 java

test -> New -> Directory ==> 建立 resources

然後對建立好的 java、resources 和 test/java、test/resourcs 目錄均右鍵選擇 Mark Diretory as,然後分别進行如下操作:

java -> Sources Root //java源碼根目錄

resources -> Resources Root//java 配置檔案目錄

test/java -> Test Sources Root//java 測試源碼目錄

test/java -> Test Sources Root//java 測試配置檔案目錄

引入項目依賴的jar包

  • spring
  • springmvc
  • mybatis
  • 資料庫連接配接池,驅動包
  • 其他(jstl、servlet-api、junit)
<dependencies>
  <!--引入項目依賴的jar包-->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.3.2</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>5.3.2</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.2</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-expression</artifactId>
    <version>5.3.2</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.2</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.2</version>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.2</version>
  </dependency>

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

  <!--資料庫連接配接池、驅動-->
  <dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.1</version>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.46</version>
  </dependency>

  <!--jstl、servlet-api、junit-->
  <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
  </dependency>

  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
</dependencies>
           

引入BootStrap前端架構

BookStrap官方網站

  1. 在官方網站下載下傳BookStrap 樣式所需css、js
  2. 下載下傳jQuery,因jQuery官網通路一般容易出現問題,可以在這個網站下載下傳jQuery
  3. 引入Bootstrap
    尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
  4. <%
        pageContext.setAttribute("APP_PATH",request.getContextPath());
    %>
    <%--
    不以/開始的相對路徑,找資源,以目前資源的路徑為準,經常容易出現問題
    以/開始的相對路徑,找資源,以伺服器的路徑為标準(http://localhost:8080/)需要加上項目名
                            http://localhost:8080/ssm_crud
    --%>
    
    <link type="text/css" rel="stylesheet" href="${APP_PATH}/static/bootstrap/css/bootstrap.css">
    <%--引入jquery--%>
    <script src="${APP_PATH}/static/js/jquery-3.5.1.js"></script>
    <script src="${APP_PATH}/static/bootstrap/js/bootstrap.js"></script>
               
尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
  1. 測試結果

    可以看到這個按鈕已經發生變化了

    尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
  2. 可能會出現以下錯誤:

    bootstrap.min.js:6 Uncaught Error: Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4

    原因:Bootstrap的JavaScript要求jQuery 1.9.1或更高版本,但低于版本4

編寫SSM整合的關鍵配置檔案

web.xml、spring、springmvc、mybatis

web.xml(web.xml)

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.1"
         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_3_1.xsd">

  <display-name>Archetype Created Web Application</display-name>


  <!--1、配置Spring的配置檔案-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!--2、SpringMVC的前端控制器,攔截所有請求-->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
      <!--    <init-param>-->
<!--      <param-name>contextConfigLocation</param-name>-->
    <!--不指定位置時,預設就是類路徑下servlet-name後加上-servlet-->
<!--      <param-value>classpath:</param-value>-->
<!--    </init-param>-->
  </servlet>
  <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>
</web-app>
           

SpringMVC(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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--SpringMVC的配置檔案,包含網站跳轉邏輯,配置,use-default-filters="false"禁用預設行為,隻掃描Controller注解-->
    <context:component-scan base-package="com.qykhhr.crud" 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></mvc:default-servlet-handler>

    <!--能支援SpringMVC更進階的一些功能,比如JSR303校驗,快捷的ajax請求,映射動态請求-->
    <mvc:annotation-driven></mvc:annotation-driven>
</beans>
           

Spring(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/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--Spring的配置檔案,這裡主要配置和業務邏輯有關的-->
    <!--Spring配置檔案的核心點:資料源、與Mybatis的整合、事務控制-->

    <context:component-scan base-package="com.qykhhr">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></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-config.xml"></property>
        <property name="dataSource" ref="dataSource"></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="com.qykhhr.crud.dao"></property>
    </bean>
    <!--==========================================================================-->

    <!--==============事務控制的配置==============-->
    <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.qykhhr.crud.service..*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPoint"></aop:advisor>
    </aop:config>

    <!--配置事務增強,事務如何切入-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--所有方法都是事務方法-->
            <tx:method name="*"/>
            <!--以get開始的所有方法-->
            <tx:method name="get*" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>
    <!--========================================================-->
</beans>
           

mybatis(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="com.qykhhr.crud.bean"/>
    </typeAliases>
</configuration>
           

使用mybatis的逆向工程生成對應的bean以及mapper

首先導包mybatis-generator-core

<!--MBG,mybatis逆向工程-->
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
  <groupId>org.mybatis.generator</groupId>
  <artifactId>mybatis-generator-core</artifactId>
  <version>1.4.0</version>
</dependency>
           

在目前工程路徑下編寫generatorConfig.xml(mgb.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">

        <!--逆向生成的bean以及mapper沒有注釋-->
        <commentGenerator>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <!--配置資料庫連接配接-->
        <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/ssm_crud?useSSL=false"
                        userId="root"
                        password="614310">
        </jdbcConnection>

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

        <!--指定javaBean生成位置-->
        <javaModelGenerator targetPackage="com.qykhhr.crud.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="com.qykhhr.crud.dao"
                             targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <!--指定每個表的生成政策-->
        <table tableName="tbl_emp" domainObjectName="Employee"></table>
        <table tableName="tbl_dept" domainObjectName="Department"></table>
    </context>
</generatorConfiguration>
           

在編寫一個測試類,運作

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;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class MBGTest {
    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);
    }
}
           
  1. 資料庫表對應的bean以及mapper就會自動生成

    Department.java、DepartmentExample.java、Employee.java、EmployeeExample.java

    DepartmentMapper.java、EmployeeMapper.java

    DepartmentMapper.xml、EmployeeMapper.xml

    尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
    5.在執行main方法的時候出現了報錯

    javax.net.ssl.SSLException MESSAGE: closing inbound before receiving peer's close_notify

    解決辦法:

    設定useSSL為false

    <!--配置資料庫連接配接-->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver"
                    connectionURL="jdbc:mysql://localhost:3306/ssm_crud?useSSL=false"
                    userId="root"
                    password="614310">
    </jdbcConnection>
               

修改mapper檔案,添加自己需要的

​ Employee.java添加

//希望查詢員工的同時,部門資訊也是查詢好的
private Department department;
           

​ EmployeeMapper.java添加

List<Employee> selectByExampleWithDept(EmployeeExample example);

Employee selectByPrimaryKeyWithDept(Integer empId);
           

​ EmployeeMapper.xml添加

<resultMap id="WithDeptResultMap" type="com.qykhhr.crud.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.qykhhr.crud.bean.Department">
    <id column="dept_id" property="deptId"/>
    <result column="dept_name" property="deptName"/>
  </association>
</resultMap>
<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);
    Employee selectByPrimaryKeyWithDept(Integer empId);
    -->
  <!--查詢員工同時帶部門資訊-->
  <select id="selectByExampleWithDept" 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>
  <select id="selectByPrimaryKeyWithDept" 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>
           

測試mapper

package com.qykhhr.crud.test;

import com.qykhhr.crud.dao.DepartmentMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * 測試dao層工作
 * 推薦Spring的項目就可以使用Spring的單元測試,可以自動注入我們需要的元件
 *
 * 1、導入SpringTest子產品
 * 2、@ContextConfiguration指定Spring配置檔案的位置
 * 3、直接autowired要使用的元件即可
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class MapperTest {

    @Autowired
    DepartmentMapper departmentMapper;
    /**
     * 測試DepartmentMapper
     */
    @Test
    public void testCRUD(){
//        //1、建立SpringIOC容器
//        ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
//        //2、從容器中擷取mapper
//        DepartmentMapper bean = ioc.getBean(DepartmentMapper.class);
        System.out.println(departmentMapper);
    }
}
           

測試出現的問題:

Caused by: java.lang.IllegalArgumentException: Result Maps collection already contains value for com.qykhhr.crud.dao.EmployeeMapper.BaseResultMap

原因:

使用MyBatis Generator逆向生成mapper的時候,如果多次生成會造成mapper内容重複生成,然後mapper裡面的id出現了沖突

解決:

在mapper檔案中找到相同的id,會發現後面有一半内容和前面相同,将後面相同的内容删除就行了

查詢

  • 通路index.jsp
  • index.jsp頁面發送查詢員工清單的請求
  • EmployeeController來接收請求,查出員工資料
  • 來到list.jsp頁面進行展示
  1. 引入PageHelper分頁插件
  • 導包
    • <!--pagehelper分頁插件-->
      <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.2.0</version>
      </dependency>
                 
  • 在mybatis配置檔案(mybatis-config.xml)中進行注冊
    • <!--注冊分頁插件-->
      <plugins>
          <plugin interceptor="com.github.pagehelper.PageInterceptor">
          </plugin>
      </plugins>
                 
  • 在Controller中使用
    • import com.github.pagehelper.PageHelper;
      import com.github.pagehelper.PageInfo;
      import com.qykhhr.crud.bean.Employee;
      import com.qykhhr.crud.service.EmployeeService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.stereotype.Repository;
      import org.springframework.ui.Model;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import java.util.List;
      /**
       * 處理員工CRUD請求
       */
      @Controller
      public class EmployeeController {
          @Autowired
          EmployeeService employeeService;
          /**
           * 查詢員工資料(分頁查詢)
           * @return
           */
          @RequestMapping("/emps")
          public String getEmps(@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, Model model){
              //引入PageHelper分頁插件
              //在查詢之前隻需要調用:傳入頁碼以及每頁的大小
              PageHelper.startPage(pageNo,5);
              //startPage後面緊跟的這個查詢就是一個分頁查詢
              List<Employee> emps = employeeService.getAll();
      
              //使用PageInfo包裝查詢後的結果,隻需要将pageInfo交給頁面就行了
              //封裝了詳細的分頁資訊,包括我們查詢出來的資料,傳入連續顯示的頁數
              PageInfo page = new PageInfo(emps,5);
              model.addAttribute("pageInfo",page);
              return "list";
          }
      }
                 

list頁面的編寫

路徑問題:

不以/開始的相對路徑,找資源,以目前資源的路徑為準,經常容易出現問題

以/開始的相對路徑,找資源,以伺服器的路徑為标準(http://localhost:8080/)需要加上項目名

http://localhost:8080/ssm_crud

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: 雨林
  Date: 2021/1/12
  Time: 13:16
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>員工清單</title>
    <%
        pageContext.setAttribute("APP_PATH",request.getContextPath());
    %>
    <%--
    不以/開始的相對路徑,找資源,以目前資源的路徑為準,經常容易出現問題
    以/開始的相對路徑,找資源,以伺服器的路徑為标準(http://localhost:8080/)需要加上項目名
                            http://localhost:8080/ssm_crud
    --%>

    <link type="text/css" rel="stylesheet" href="${APP_PATH}/static/bootstrap/css/bootstrap.css" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >
    <%--引入jquery--%>
    <script src="${APP_PATH}/static/js/jquery-3.5.1.js"></script>
    <script src="${APP_PATH}/static/bootstrap/js/bootstrap.js"></script>
</head>
<body>
    <%--搭建顯示頁面--%>
    <div class="container">
        <%--标題SSM-CRUD--%>
        <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-sm">
                                    <span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
                                    編輯
                                </button>
                                <button class="btn btn-danger btn-sm">
                                    <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?pageNo=1" target="_blank" rel="external nofollow" >首頁</a></li>

                        <c:if test="${pageInfo.hasPreviousPage}">
                            <li>
                                <a href="${APP_PATH}/emps?pageNo=${pageInfo.pageNum-1}" target="_blank" rel="external nofollow"  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="#" target="_blank" rel="external nofollow" >${page_Num}</a></li>
                            </c:if>
                            <c:if test="${page_Num != pageInfo.pageNum}">
                                <li><a href="${APP_PATH}/emps?pageNo=${page_Num}" target="_blank" rel="external nofollow" >${page_Num}</a></li>
                            </c:if>
                        </c:forEach>

                        <c:if test="${pageInfo.hasNextPage}">
                            <li>
                                <a href="${APP_PATH}/emps?pageNo=${pageInfo.pageNum+1}" target="_blank" rel="external nofollow"  aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        </c:if>

                        <li><a href="${APP_PATH}/emps?pageNo=${pageInfo.pages}" target="_blank" rel="external nofollow" >末頁</a></li>
                    </ul>
                </nav>
            </div>

        </div>
    </div>
</body>
</html>
           

展示效果

尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper

查詢-ajax

  • index.jsp頁面直接發送Ajax請求進行員工分頁資料的查詢
  • 伺服器将查出的資料,以json字元串的形式傳回給浏覽器
  • 浏覽器收到json字元串。可以使用js對json進行解析,使用js通過dom增删改改變頁面
  • 傳回json。實作用戶端的無關性
  1. 可以使用@ResponseBody注解将資料以json形式傳回到頁面

    需要導入jackson支援json包

    <[email protected]将資料轉為json需要包-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.3</version>
    </dependency>
               
  2. 編寫一個通用的傳回json的類
    package com.qykhhr.crud.bean;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 通用的傳回json的類
     */
    public class Msg {
    
        private int code;//狀态碼:100-成功 200-失敗
        private String msg;//提示資訊
        private Map<String,Object> extend = new HashMap<>();//裝載要發送到頁面的json資料
    
        public static Msg success(){
            Msg msg = new Msg();
            msg.setCode(100);
            msg.setMsg("處理成功!");
            return msg;
        }
    
        public static Msg fail(){
            Msg msg = new Msg();
            msg.setCode(200);
            msg.setMsg("處理失敗!");
            return msg;
        }
    
        public Msg add(String key,Object value){
            this.getExtend().put(key, value);//将擷取到的資料添加到map中
            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;
        }
    }
               
  3. 在控制器中将資料以json形式發送到前端頁面
    /**
     * 将資料以json的形式傳到頁面
     * 需要導入jackson包
     * @param pageNo
     * @param model
     * @return
     */
    @RequestMapping("/emps")
    @ResponseBody
    public Msg getEmpWithJson(@RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, Model model){
        //引入PageHelper分頁插件
        //在查詢之前隻需要調用:傳入頁碼以及每頁的大小
        PageHelper.startPage(pageNo,5);
        //startPage後面緊跟的這個查詢就是一個分頁查詢
        List<Employee> emps = employeeService.getAll();
    
        //使用PageInfo包裝查詢後的結果,隻需要将pageInfo交給頁面就行了
        //封裝了詳細的分頁資訊,包括我們查詢出來的資料,傳入連續顯示的頁數
        PageInfo page = new PageInfo(emps,5);
        return Msg.success().add("pageInfo",page);
    }
               
  4. 前端對資料進行處理
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--
      Created by IntelliJ IDEA.
      User: 雨林
      Date: 2021/1/12
      Time: 13:16
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>員工清單</title>
        <%
            pageContext.setAttribute("APP_PATH",request.getContextPath());
        %>
        <%--
        不以/開始的相對路徑,找資源,以目前資源的路徑為準,經常容易出現問題
        以/開始的相對路徑,找資源,以伺服器的路徑為标準(http://localhost:8080/)需要加上項目名
                                http://localhost:8080/ssm_crud
        --%>
    
        <link type="text/css" rel="stylesheet" href="${APP_PATH}/static/bootstrap/css/bootstrap.css" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >
        <%--引入jquery--%>
        <script src="${APP_PATH}/static/js/jquery-3.5.1.js"></script>
        <script src="${APP_PATH}/static/bootstrap/js/bootstrap.js"></script>
    </head>
    <body>
    <%--搭建顯示頁面--%>
    <div class="container">
        <%--标題SSM-CRUD--%>
        <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">
        //頁面加載完成之後直接去第1頁
        //1、頁面加載完成以後,直接去發送ajax請求,要到分頁資料
        $(function(){
            $.ajax({
                url:"${APP_PATH}/emps",
                data:"pageNo=1",
                type:"GET",
                success:function (result) {
                    //console.log(result);
    
                    //1.解析并顯示員工資料
                    build_emps_table(result);
                    //2.解析并顯示分頁資訊
                    build_page_info(result);
                    //3、解析顯示分頁條
                    build_emps_nav(result);
                }
            });
        });
    
        //跳轉到指定頁面
        function to_page(pageNo) {
            $.ajax({
                url:"${APP_PATH}/emps",
                data:"pageNo="+pageNo,
                type:"GET",
                success:function (result) {
                    //console.log(result);
    
                    //1.解析并顯示員工資料
                    build_emps_table(result);
                    //2.解析并顯示分頁資訊
                    build_page_info(result);
                    //3、解析顯示分頁條
                    build_emps_nav(result);
                }
            });
        }
    
        /*解析顯示分頁資料*/
        function build_emps_table(result){
            //在發送每個Ajax請求的時候都清空表格内容
            $("#emps_table tbody").empty();
    
            var emps = result.extend.pageInfo.list;//分頁的員工的資訊
            $.each(emps,function (index,item) {
                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")
                                .append($("<span></span>").addClass("glyphicon glyphicon-pencil")).append("編輯");
    
                var delBtn = $("<button></button>").addClass("btn btn-danger btn-sm")
                    .append($("<span></span>").addClass("glyphicon glyphicon-trash")).append("删除");
    
                var btnTd = $("<td></td>").append(editBtn).append(" ").append(delBtn);
    
                //append方法執行完成以後還是傳回原來的元素,這裡每次append都會産生新的<tr></tr>
                $("<tr></tr>").append(empIdTd).append(empNameTd)
                    .append(genderTd).append(emailTd).append(deptNameTd)
                    .append(btnTd)
                    .appendTo("#emps_table tbody");
            })
        }
    
        /*解析顯示分頁資訊*/
        function build_page_info(result){
            //在發送Ajax的請求時要清空裡面的内容,要不然就會追加内容
            $("#page_info_area").empty();
    
            $("#page_info_area").append("目前第"+result.extend.pageInfo.pageNum+"頁,總"
                +result.extend.pageInfo.pages+"頁,總"+result.extend.pageInfo.total+"條記錄")
        }
    
        /*解析顯示分頁條*/
        function build_emps_nav(result){
            $("#page_nav_area").empty();
    
            //$("#page_nav_area")
            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{
                lastPageLi.click(function(){
                    to_page(result.extend.pageInfo.pages);
                });
                nextPageLi.click(function(){
                    to_page(result.extend.pageInfo.pageNum+1)
                });
            }
            
    
            //添加首頁和前一頁的提示
            ul.append(firstPageLi).append(prePageLi);
    
            //周遊給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>
               

    reasonable

    :分頁合理化參數,預設值為

    false

    。當該參數設定為

    true

    時,

    pageNum<=0

    時會查詢第一頁,

    pageNum>pages

    (超過總數時),會查詢最後一頁。預設

    false

    時,直接根據參數進行查詢。
    <!--注冊分頁插件-->
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!--分頁參數合理化,-->
            <property name="reasonable" value="true"/>
        </plugin>
    </plugins>
               

新增

  • 在index.jsp頁面點選“新增”
  • 彈出新增對話框
  • 去資料庫查詢部門清單,顯示在對話框中
  • 使用者輸入資料,并進行校驗
  1. 建立員工添加模态框

    員工資訊添加的表單

    尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
    <%--員工添加的模态框--%>
    <!-- Modal -->
    <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">
                            </div>
                        </div>
                        <div class="form-group">
                            <label class="col-sm-2 control-label">email</label>
                            <div class="col-sm-10">
                                <input type="email" name="email" class="form-control" id="email_add_input" placeholder="[email protected]">
                            </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 name="dId" class="form-control" id="dept_add_select">
    
                                </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>
               
    <script>
        $("#emp_add_modal_btn").click(function(){
            $("#empAddModal").modal({
                backdrop:"static"
            });
        });
    </script>
               
  2. 從資料庫中擷取部門資訊,顯示到添加員工的模态框中
    1. 先建立一個service
    import com.qykhhr.crud.bean.Department;
    import com.qykhhr.crud.dao.DepartmentMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import java.util.List;
    @Service
    public class DepartmentService {
    
        @Autowired
        private DepartmentMapper departmentMapper;
    
        public List<Department> getDepts() {
    
            List<Department> departments = departmentMapper.selectByExample(null);
            return departments;
        }
    
    }
    
               
    1. 再建立一個Controller
      import com.qykhhr.crud.bean.Department;
      import com.qykhhr.crud.bean.Msg;
      import com.qykhhr.crud.service.DepartmentService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.ResponseBody;
      import java.util.List;
      /**
       * 處理和部門有關的請求
       */
      @Controller
      public class DepartmentController {
      
          @Autowired
          private DepartmentService departmentService;
      
          /**
           * 傳回所有的部門資訊
           */
          @RequestMapping("/depts")
          @ResponseBody
          public Msg getDepts(){
              //查出的所有部門資訊
              List<Department> list = departmentService.getDepts();
              return Msg.success().add("depts",list);
          }
      }
                 
  3. 在index.jsp發送Ajax請求
    <script>
    //點選新增按鈕彈出模态框
        $("#emp_add_modal_btn").click(function(){
            $("#dept_add_select").empty();
    
            //發送Ajax請求,查出部門資訊,顯示在下拉清單中
            getDepts();
    
            //彈出模态框
            $("#empAddModal").modal({
                backdrop:"static"
            });
        });
    
        //查出所有的部門資訊并顯示在下拉清單中
        function getDepts(){
               $.ajax({
                   url:"${APP_PATH}/depts",
                   type:"GET",
                   success:function (result) {
                        //console.log(result);
                       $.each(result.extend.depts,function(){
                           var optionEle = $("<option></option>").append(this.deptName).attr("value",this.deptId);
                           optionEle.appendTo("#dept_add_select");
                       });
                   }
               });
        }
    </script>
               

URI:

/emp/{id} GET 查詢員工

/emp POST 儲存員工

/emp/{id} PUT 修改員工

/emp/{id} DELETE 删除員工

儲存員工資訊

在index.jsp中發送Ajax請求

<script>
    $("#emp_save_btn").click(function(){


       //1、模态框中填寫的表單資料送出給伺服器進行儲存
        //2、發送Ajax請求儲存員工

        $.ajax({
            url:"${APP_PATH}/emp",
            type:"POST",
            data:$("#empAddModal form").serialize(),
            success:function () {
                //員工儲存之後
                //1、關閉模态框
                $("#empAddModal").modal('hide');
                // $("#empAddModal input").empty();
                //2、來到最後一頁,顯示剛才儲存的資料
                //發送Ajax請求顯示最後一頁資料即可
                to_page(totalRecord);
            }
        })
    });    
</script>
           

在EmployeeController中儲存員工資訊

/**
 * 定義員工傳回
 * @return
 */
@RequestMapping(value = "/emp",method = RequestMethod.POST)
public String saveEmp(Employee employee){
    employeeService.saveEmp(employee);
    return "/**
     * 定義員工傳回
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/emp",method = RequestMethod.POST)
    public Msg saveEmp(Employee employee){
        employeeService.saveEmp(employee);
//        return "lastPage";
        return Msg.success();
    }lastPage";
}
           

對輸入的員工資訊進行正規表達式校驗

  1. 進行校驗,并以彈窗的形式輸出錯誤資訊
//校驗表單資料
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位英文和數字的組合");
        return false;
    }
    //校驗郵箱格式
    var email = $("#email_add_input").val();
    var regEmail = /^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;

    if(!regEmail.test(email)){
        alert("郵箱格式不正确");
        return false;
    }
    return true;
}

//點選儲存員工的Ajax請求
$("#emp_save_btn").click(function(){


   //1、模态框中填寫的表單資料送出給伺服器進行儲存
    //還需要對将要送出給伺服器的資料進行校驗
   if( !validate_add_form()){
       return false;
   }
    //2、發送Ajax請求儲存員工

    $.ajax({
        url:"${APP_PATH}/emp",
        type:"POST",
        data:$("#empAddModal form").serialize(),
        success:function () {
            //員工儲存之後
            //1、關閉模态框
            $("#empAddModal").modal('hide');
            // $("#empAddModal input").empty();
            //2、來到最後一頁,顯示剛才儲存的資料
            //發送Ajax請求顯示最後一頁資料即可
            to_page(totalRecord);
        }
    })
});
           
  1. 使用正規表達式校驗資訊,将錯誤資訊放到輸入框下面,并将輸入框變成紅色
尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
//校驗表單資料
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位英文和數字的組合");
        // $("#empName_add_input").parent().addClass("has-error");
        // $("#empName_add_input").next("span").text("使用者名可以是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)){
        //alert("郵箱格式不正确");
        // $("#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);
    }
}
           
  1. 使用Ajax校驗使用者名是否重複,從資料庫中查詢

    使用$("#empAddModal form")[0].reset();//清除表單資料(表單重置)

  • 在index.jsp頁面當輸入框發生變化,就發送Ajax請求,到資料庫中檢視新增使用者名是否可用
    //當使用者名輸入框發生變化,發送Ajax請求校驗新增使用者名是否可用
    $("#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");
                }
            }
        });
    
    })
               
  • Controller接收/checkuser請求,去service層調用方法
    /**
     * 用于檢視使用者名是否重複
     * @param empName
     * @return
     */
    @ResponseBody
    @RequestMapping("/checkuser")
    public Msg checkuser(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層建立一個方法,用于檢視資料庫中是否有該使用者名
    /**
     * 校驗使用者名是否可用
     * @param empName
     * @return true 表示可用  false 表示不可用
     */
    public boolean checkUser(String empName) {
        EmployeeExample employeeExample = new EmployeeExample();
        EmployeeExample.Criteria criteria = employeeExample.createCriteria();
        criteria.andEmpNameEqualTo(empName);
        long count = employeeMapper.countByExample(employeeExample);
        return count == 0;//如果count == 0 表示可用
    }
               

清除表單樣式

//清除表單資料(表單完整重置(表單的資料,表單的樣式))
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(){
    $("#dept_add_select").empty();

    //清除表單資料(表單重置)
    reset_form("#empAddModal form");
    // $("#empAddModal form").reset();


    //發送Ajax請求,查出部門資訊,顯示在下拉清單中
    getDepts();

    //彈出模态框
    $("#empAddModal").modal({
        backdrop:"static"
    });
});
           

問題

前端校驗可以通過修改頁面内容或者通過禁用js功能,跳過js校驗,是以我們需要進行後端校驗

重要資料(後端校驗(JSR303),唯一限制)

通過修改頁面内容,實作跳過前端校驗

尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper

使用JSR303校驗

  1. 導包,導入Hibernate-Validator
    <!--JSR303校驗支援:tomcat7及以上的伺服器
    tomcat7及以下的伺服器:el表達式。額外給伺服器的lib包中替換新的标準的el
    -->
    <!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
    <dependency>
      <groupId>org.hibernate.validator</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>7.0.0.Final</version>
    </dependency>
               
  2. 在bean中修改屬性
    @Pattern(regexp = "(^[a-zA-Z0-9_-]{6,16}$)|(^[\\u2E80-\\u9FFF]{2,5})"
            ,message = "使用者名必須是2-5位中文或者6-16位英文和數字的組合")
    private String empName;
    
    //@Email
    @Pattern(regexp = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$"
            ,message = "郵箱格式不正确")
    private String email;
               
  3. 對前端傳來的資料進行JSR303校驗

    @Valid Employee employee, BindingResult result

    /**
         * 員工儲存
         * 1、支援JSR303校驗
         * 2、導入Hibernate-Validator
         * @return
         */
        @ResponseBody
        @RequestMapping(value = "/emp",method = RequestMethod.POST)
        public Msg saveEmp(@Valid Employee employee, BindingResult result){
            if(result.hasErrors()){
                Map<String,Object> map = new HashMap<>();
    
                //校驗失敗,在模态框中顯示校驗失敗的錯誤資訊
                List<FieldError> fieldErrors = result.getFieldErrors();
                for (FieldError fieldError : fieldErrors){
                    System.out.println("錯誤的字段名:" + fieldError.getField());
                    System.out.println("錯誤資訊:" + fieldError.getDefaultMessage());
                    map.put(fieldError.getField(),fieldError.getDefaultMessage());
                }
                return Msg.fail().add("errorFields",map);
            }else{
                employeeService.saveEmp(employee);
    //        return "lastPage";
                return Msg.success();
            }
    
        }
               
  4. 進行校驗,判斷是否有效
    //點選儲存員工的Ajax請求
    $("#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:$("#empAddModal form").serialize(),
            success:function (result) {
                //員工儲存之後
                if(result.code == 100){
                    //1、關閉模态框
                    $("#empAddModal").modal('hide');
                    // $("#empAddModal input").empty();
                    //2、來到最後一頁,顯示剛才儲存的資料
                    //發送Ajax請求顯示最後一頁資料即可
                    to_page(totalRecord);
                }else{
                    //顯示失敗資訊
                    // console.log(result);
                    //有哪個字段的錯誤就顯示哪個字段的
                    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);
                    }
                }
    
    
            }
        })
               

修改員工資訊

尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
  1. 點選編輯
  2. 彈出使用者修改的模态框(顯示使用者資訊)
  3. 點選更新,完成使用者修改
  • 點選編輯,彈出使用者模态框
    //我們是按鈕建立之前就綁定了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"));
    
        //把員工id傳遞給模态框的更新按鈕
        $("#emp_update_btn").attr("edit-id",$(this).attr("edit-id"));
    
        //3、彈出模态框
        $("#empUpdateModal").modal({
            backdrop: "static"
        });
    })
    
    //根據id查詢員工資料
    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]);
            }
        });
    }
               
    • Controller根據id查詢員工
    /**
     * 根據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);
    }
               
    • Service層從資料庫查詢員工
    /**
     * 安裝員工ID查詢員工資訊
     * @param id
     * @return
     */
    public Employee getEmp(Integer id) {
        return employeeMapper.selectByPrimaryKey(id);
    }
               
  • 點選更新,更新資料
    //點選更新,更新員工資料
    $("#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)){
            show_validate_msg("#email_update_input","error","郵箱格式不正确");
            return false;
        }else {
            show_validate_msg("#email_update_input","success","");
        }
        //發送Ajax請求儲存更新的員工資料
        $.ajax({
            url:"${APP_PATH}/emp/"+$(this).attr("edit-id"),
            type:"PUT",
            // data:$("#empUpdateModal form").serialize()+"&_method=PUT",//type可以用POST送出
            data:$("#empUpdateModal form").serialize(),//直接使用Ajax發送PUT請求
            success:function (result) {
                // alert(result.msg);
                //1、關閉模态框
                $("#empUpdateModal").modal("hide");
                //2、回到本頁面
                to_page(currentPage);
            }
        })
    })
               
    • Controller封裝前端傳來的資料封裝成Employee對象
      /**
       * 員工更新方法
       * 如果直接發ajax=PUT形式的請求
       * 封裝的資料
       * Employee
       * [empId=1014,empName=null,gender=null,email=null,dId=null]
       *
       * 問題:
       * 請求體中有資料,但是Employee對象封裝不上
       * sql拼串就發産生異常 update tbl_emp where emp_id = 1014;
       *
       * 原因:
       * Tomcat:
       *      1、将請求體中的資料,封裝成一個map
       *      2、request.getParameter("empName")就會從這個map中取值
       *      3、SpringMVC封裝POJO對象的時候
       *          會把POJO中每個屬性的值:request.getParameter("email");
       * Ajax發送PUT請求引發的問題
       *      PUT請求,請求體中的資料,request.getParameter("empName");拿不到資料
       *      Tomcat一看是PUT,不會封裝請求體中的資料為map,隻有POST形式的請求才封裝請求體為map
       *
       * 解決方案
       * 1、我們要能支援直接發送PUT之類的請求還要封裝請求體中的資料
       * 2、配置上HttpPutFormContentFilter
       * 3、它的作用:将請求體中的資料解析包裝成一個map,request被重新包裝
       * request.getParameter()被重寫,就會從自己封裝的map中取資料
       * @param employee
       * @return
       */
      @RequestMapping(value = "/emp/{empId}",method = RequestMethod.PUT)
      @ResponseBody
      public Msg saveEmp(Employee employee){
          System.out.println("将要更新的員工資料:" + employee);
      
          employeeService.updateEmmp(employee);
          return Msg.success();
      }
                 
    • Service層更新資料資料
      public void updateEmmp(Employee employee) {
          employeeMapper.updateByPrimaryKeySelective(employee);
      }
                 
    • 配置HttpPutFormContentFilter

      在web.xml中進行配置

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

删除單一員工

發送/emp/id,請求類型是DELETE

//單個删除
$(document).on("click",".delete_btn",function(){
    //1、彈出是否确認删除對話框
    // alert($(this).parents("tr").find("td:eq(1)").text());//目前元素父元素的tr下的第二個td标簽中的内容
    var empName = $(this).parents("tr").find("td:eq(1)").text();
    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);
            }
        })
    }
})
           

Controller接收該請求,調用Service層的方法

@RequestMapping(value = "/emp/{id}",method = RequestMethod.DELETE)
@ResponseBody
public Msg deleteEmpById(@PathVariable("id") Integer id){
    employeeService.deleteEmp(id);
    return Msg.success();
}
           

Service層調用方法,從資料庫中删除資料

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

删除批量資料

全選和全不選

尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper
  • 先将表格樣式改變
    <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>
               
  • 顯示分頁資料的時候加上checkbox,單選框這一項
    /*解析顯示分頁資料*/
    function build_emps_table(result){
        $.each(emps,function (index,item) {
            var checkBoxTd = $("<td><input type='checkbox' class='check_item'/></td>");
          
            //append方法執行完成以後還是傳回原來的元素,這裡每次append都會産生新的<tr></tr>
            $("<tr></tr>").append(checkBoxTd)
                .append(empIdTd).append(empNameTd)
                .append(genderTd).append(emailTd).append(deptNameTd)
                .append(btnTd)
                .appendTo("#emps_table tbody");
        })
    }
               
  • 完成全選和全不選
    //完成全選/全不選
    $("#check_all").click(function(){
        //attr擷取checked是undefined
        //我們這些dom原生的屬性,attr擷取自定義屬性的值
        //prop修改和讀取dom原生屬性的值
        // alert($(this).attr("checked"));
        // alert($(this).prop("checked"));
        // $(this).prop("checked");
        $(".check_item").prop("checked",$(this).prop("checked"));
    
    })
    
    //check_item,
    $(document).on("click",".check_item",function () {
        //判斷目前選中的元素是否5個
        // alert($(".check_item:checked").length);
        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(){
            // alert($(this).parents("tr").find("td:eq(2)").text());
            //組裝員工名字字元串
            empNames += $(this).parents("tr").find("td:eq(2)").text() + ",";
            //組裝員工id字元串
            del_idstr += $(this).parents("tr").find("td:eq(1)").text() + "-"
        });
        empNames = empNames.substring(0,empNames.length-1);
        del_idstr = del_idstr.substring(0,del_idstr.length-1);
        if(confirm("确認删除【"+empNames+"】嗎?")){
            $.ajax({
                url:"${APP_PATH}/emp/" + del_idstr,
                type:"DELETE",
                success:function (result) {
                    alert(result.msg);
                    //回到目前頁面
                    to_page(currentPage);
                }
            })
        }
    });
               
  • Controller接收請求,将字元串進行區分,并進行類型轉換
    /**
     * 單個批量二合一
     * 批量删除:1-2-3
     * 單個删除:1
     * @param
     * @return
     */
    @RequestMapping(value = "/emp/{ids}",method = RequestMethod.DELETE)
    @ResponseBody
    public Msg deleteEmp(@PathVariable("ids") String ids){
        if(ids.contains("-")){
            //批量删除
            String[] str_ids = ids.split("-");
            List<Integer> del_ids = new ArrayList<>();
    
            //組裝id的集合
            for (String id : str_ids){
                del_ids.add(Integer.parseInt(id));
            }
            employeeService.deleteBatch(del_ids);
        }else{
            //單個删除
            Integer id = Integer.parseInt(ids);
            employeeService.deleteEmp(id);
        }
        return Msg.success();
    }
               
  • Service層進行批量删除
    /**
     * 批量删除
     * @param ids
     */
    public void deleteBatch(List<Integer> ids) {
        EmployeeExample employeeExample = new EmployeeExample();
        EmployeeExample.Criteria criteria = employeeExample.createCriteria();
        criteria.andEmpIdIn(ids);
        //delete from xxx where emp_id in (1,2,3);
        employeeMapper.deleteByExample(employeeExample);
    }
               
尚矽谷_SSM_雷豐陽整合基礎環境搭建編寫SSM整合的關鍵配置檔案使用mybatis的逆向工程生成對應的bean以及mapper測試mapper

all_btn").click(function () {

var empNames = “”;

var del_idstr = “”;

. e a c h ( .each( .each((".check_item:checked"),function(){

// alert($(this).parents(“tr”).find(“td:eq(2)”).text());

//組裝員工名字字元串

empNames += $(this).parents(“tr”).find(“td:eq(2)”).text() + “,”;

//組裝員工id字元串

del_idstr += $(this).parents(“tr”).find(“td:eq(1)”).text() + “-”

});

empNames = empNames.substring(0,empNames.length-1);

del_idstr = del_idstr.substring(0,del_idstr.length-1);

if(confirm(“确認删除【”+empNames+"】嗎?")){

KaTeX parse error: Expected '}', got 'EOF' at end of input: … url:"{APP_PATH}/emp/" + del_idstr,

type:“DELETE”,

success:function (result) {

alert(result.msg);

//回到目前頁面

to_page(currentPage);

}

})

}

});

- Controller接收請求,将字元串進行區分,并進行類型轉換

```java
/**
 * 單個批量二合一
 * 批量删除:1-2-3
 * 單個删除:1
 * @param
 * @return
 */
@RequestMapping(value = "/emp/{ids}",method = RequestMethod.DELETE)
@ResponseBody
public Msg deleteEmp(@PathVariable("ids") String ids){
    if(ids.contains("-")){
        //批量删除
        String[] str_ids = ids.split("-");
        List<Integer> del_ids = new ArrayList<>();

        //組裝id的集合
        for (String id : str_ids){
            del_ids.add(Integer.parseInt(id));
        }
        employeeService.deleteBatch(del_ids);
    }else{
        //單個删除
        Integer id = Integer.parseInt(ids);
        employeeService.deleteEmp(id);
    }
    return Msg.success();
}
           
  • Service層進行批量删除
    /**
     * 批量删除
     * @param ids
     */
    public void deleteBatch(List<Integer> ids) {
        EmployeeExample employeeExample = new EmployeeExample();
        EmployeeExample.Criteria criteria = employeeExample.createCriteria();
        criteria.andEmpIdIn(ids);
        //delete from xxx where emp_id in (1,2,3);
        employeeMapper.deleteByExample(employeeExample);
    }
               

[外鍊圖檔轉存中…(img-lcUnSKjP-1611281390431)]

至此,SSM整合結束