SSM整合案例
- 關于jdbcurl后面跟的引數問題
- SpringBoot中lombok提供的注解如下:
- 功能
- 技術
- 需要的依賴
- 通過cdn引入bootstrap及注意事項
- 使用MBG逆向工程
- 資料庫環境搭建---含外鍵關聯
- maven靜態資源匯出問題---在web.xml中進行配置
- 在spring核心配置容器中配置可以執行批量sqlsession
- Spring核心組態檔
- SpringMVC的核心組態檔
- Mybaits核心組態檔
- web.xml組態檔
- 使用分頁插件
- controller層
- 查詢所有員工并分頁顯示的方法
- 如何通過spring單元測驗,完成對上面controller層代碼的測驗呢? 看下面的步驟
- 查詢員工的思路---ajax
- 新增員工的思路
- ajax使用時需要注意的問題:當我們使用ajax向某個標簽中追加資料的時候,例如點擊一個按鈕,向一個div追加5條記錄,那么下一次點擊按鈕,又會呼叫一次ajax請求,向里面追擊五條與先前重復的記錄,因此每一次在追加之前,需要先將之前追加的記錄或者追加的標簽屬性清除
- jquery中的正則運算式以及其他常用函式
- js清除表單內容的reset方法
- java中string類里面的matches校驗正則運算式函式
- 使用springmvc的JSR303資料校驗需要引入一下的依賴
- @Pattern注解中常用的校驗正則運算式筆記
- jQuery之$(document)和on(events,[selector],[data],fn)方法
- jquery中的val可以獲取或者設定對應的value值,設定單、多選框中被選中的狀態
- springmvc兩篇好文
- 占位符引數也會嘗試去系結函式中同名引數或者物件中同名屬性
- ajax可以直接發送put和delete請求
- ajax發送put請求引發的血案
- 問題: 使用ajax直接發送put請求,封裝的資料值為null
- 原因,這里也揭示了引數系結的原理
- 血案:
- 注意如果不是直接使用ajax發送put請求,而是下面這種:
- 直接通過ajax發送put請求的解決方案:
- 洗掉員工
- jquery中獲取所有祖先并可以加以篩選的函式
- 彈出框confirm()的使用
- ctrl+f快捷查找某個標簽,變數在當前頁面的具體位值
- length函式,回傳查找到的元素個數
- 查找被選中的元素---checked
- prop函式,設定單選框是否被選中,使用true或者false
- jquery中的each方法來遍歷陣列和物件
- 在后代元素中進行篩選---find函式
- js中的substring和substr的區別
- 專案完整邏輯鏈代碼
- 主頁:這里是采用的模板,具體鏈接如下
- 員工展示頁面,即增刪查改頁面
- POJO層除了逆向工程自動生成的四個類外,還額外增添了一個訊息類msg,將其作為json字串回傳給前端,并且使用鏈式編程和靜態函式,方便直接呼叫
- Dao層就是逆向工程自動生成的三個介面
- 注意:Dao層對應的三個逆向工程自動生成的.xml檔案中,我們還需要增添兩個查出員工的同時查出部門資訊的方法,一個是單個員工,一個是多個員工,這里使用的是聯合查詢里面的左連接
- service層---兩個類,一個處理部門的資料庫操作,一個處理員工的資料庫操作
- controller層對應也有兩個類,一個處理部門請求,一個處理員工請求
- 總結
- ajax和js使用注意事項
關于jdbcurl后面跟的引數問題
解釋jdbcUrl后面的引數useUnicode
Mysql jdbc URL連接引數useSSL、serverTimezone 相關問題
SpringBoot中lombok提供的注解如下:
@Data注解如何使用
java添加@Data注解的步驟
@Data注解使用/注解getset不起作用
功能

技術

需要的依賴
<!--匯入spring的坐標-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--匯入aspectj的坐標-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.4</version>
</dependency>
<!--引入Spring測驗坐標-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--junit坐標-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
</dependency>
<!--spring tx的坐標,處理事務的-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--spring jdbc的坐標-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--SpringWeb模塊相關的坐標-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!--jstl的依賴-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--標準標簽庫的依賴-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!-- maven管理引入springmvc注解資料校驗所需jar包:-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
<!--檔案上傳的依賴-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<!--引入jquery的依賴-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1-2</version>
</dependency>
<!--jackSon的依賴===>ajax-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
<!--MyBaits依賴-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.1</version>
</dependency>
<!--log4j日志依賴-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.14.1</version>
</dependency>
<!--ehcache第三方專業快取框架的依賴-->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.8</version>
</dependency>
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.3</version>
</dependency>
<!--除了log4j,還需要匯入slf4j-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.21</version>
<scope>test</scope>
</dependency>
<!--mysql驅動的坐標-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!--c3p0資料庫連接池的坐標-->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!--druid資料庫連接池坐標-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!--mybaits和spring整合包的依賴-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<!--lombok注解-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<!--jsp相關依賴-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<!--pagehelper-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.3</version>
</dependency>
<!-- pagehelper的依賴包:jsqlparser -->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.5</version>
</dependency>
<!--mybatis的逆向工程-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
<!--使用插件啟動mbg-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
</dependency>
<!-- maven管理引入springmvc注解資料校驗所需jar包:-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
通過cdn引入bootstrap及注意事項
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
參考時的注意事項
使用MBG逆向工程
MBG逆向工程使用說明
資料庫環境搭建—含外鍵關聯



maven靜態資源匯出問題—在web.xml中進行配置
<!--讓IDEA不要忽略src目錄下的xml檔案-->
<!--靜態資源匯出問題-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
在spring核心配置容器中配置可以執行批量sqlsession
<!--配置可以執行批量sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
/*使用spring的單元測驗*/
//指定spring組態檔的位置
@ContextConfiguration(locations = {"classpath:Spring/applicationContext.xml"})
//運行單元測驗使用spring環境
@RunWith(SpringJUnit4ClassRunner.class)
public class TestDao {
//直接注入我們需要使用的組件
@Autowired
departmentMapper departmentMapper;
@Autowired
employeeMapper eMapper;
//批量的sqlsession
@Autowired
SqlSession sqlSession;
@Test
public void testDao()
{
//生成員工資料,插入員工
eMapper.insertSelective(new employee(null,"王五","男","3076679687@qq.com",4));
employeeMapper mapper=sqlSession.getMapper(employeeMapper.class);
for(int i=0;i<50;i++)
{
//每一次生成不重復的隨機字串,截取前五個字符
String uid = UUID.randomUUID().toString().substring(0, 5);
mapper.insertSelective(new employee(null,uid,"男","@307667968"+i+"@qq.com",1));
}
}
}
Spring核心組態檔
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">
<!--Spring組態檔,這里注意配置和業務邏輯有關的-->
<!--spring除了控制器不要,剩下的業務邏輯組件都要,包括dao,包括service-->
<context:component-scan base-package="Com">
<!--掃描排除不寫use,使用默認掃描規則-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!--加載外部的properties檔案-->
<!--當前要加載的properties檔案在資源檔案下,前面需要加上classpath:-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--
c3p0:自動化操作(自動化加載組態檔,并且可以自動設定到物件中)
-->
<!--配置資料源-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!--通過鍵值的方式引入值-->
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
<property name="maxPoolSize" value="${jdbc.maxPoolSize}"></property>
<property name="minPoolSize" value="${jdbc.minPoolSize}"></property>
<!--關閉連接后不自動commit-->
<property name="autoCommitOnClose" value="false"/>
<!--獲取連接超時時間-->
<property name="checkoutTimeout" value="10000"/>
<!--獲取連接失敗重試的次數-->
<property name="acquireRetryAttempts" value="2"/>
</bean>
<!--配置使用Mybaits操作資料庫-->
<!--可以根據組態檔得到SqlSessionFactory-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--指定mybaits全域組態檔的位置·-->
<property name="configLocation" value="classpath:MyBaits/mybaits-config.xml"></property>
<property name="dataSource" ref="dataSource"></property>
<!-- 指定xml映射檔案位置--> <!--所有xml都是我們的映射檔案-->
<property name="mapperLocations" value="classpath:MyBaits/mapper/*.xml"></property>
</bean>
<!--配置掃描器: 我們要把dao介面的實作加入到ioc容器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--掃描所有dao介面的實作,加入到IOC容器中-->
<property name="basePackage" value="Com.Dao"></property>
<!-- 因為會自動裝配 SqlSessionFactory和SqlSessionTemplate
所以沒 有 必 要 去 指 定 SqlSessionFactory或 SqlSessionTemplate
因此可省略不配置;
但是,如果你使 用了一個 以上的 DataSource,那么自動裝配可能會失效,
這種 情況下,你可以使用sqlSessionFactoryBeanName或sqlSessionTemplateBeanName屬性來設定正確的 bean名稱來使用;-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
</bean>
<!--配置可以執行批量sqlsession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean"></constructor-arg>
<constructor-arg name="executorType" value="BATCH"></constructor-arg>
</bean>
<!--配置事務控制,配置事務管理器,控制住資料源里面的鏈接的關閉和提交-->
<!--創建事務管理器物件-->
<!--需要匯入aspectj的坐標,即面向切面編程的坐標-->
<!--這里的id可以隨便寫-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--操作事務需要連接物件,連接物件在連接池中(資料源)-->
<!--控制資料源,通過操作connection連接,來進行事務的回滾,自動提交操作-->
<property name="dataSource" ref="dataSource"/>
</bean>
<!--基于xml配置事務,哪些方法切入事務還需要寫切入點運算式-->
<aop:config>
<!--配置切入點運算式-->
<aop:pointcut id="tx" expression="execution(* Com.service.*.*(..))"/>
<aop:advisor advice-ref="myTx" pointcut-ref="tx"/>
</aop:config>
<!--配置事務增強,事務如何切入-->
<tx:advice id="myTx" transaction-manager="transactionManager"><!--這里不寫transaction-manager
,那么默認會去找id為transactionManager的-->
<tx:attributes>
<!--所有方法都是事務方法,任何事務方法出現任何例外都回滾-->
<tx:method name="*" rollback-for="java.lang.Exception"/>
<!--以get開始的所有方法-->
<tx:method name="get*" read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
SpringMVC的核心組態檔
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!--SpringMVC組態檔,包含網站跳轉邏輯的控制和配置-->
<!--SpringMVC只掃描控制器:禁用默認過濾規則-->
<context:component-scan base-package="Com" 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/pages/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--檔案上傳決議器: id必須是multipartFile-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--設定檔案上傳最大量為5m-->
<property name="maxUploadSize" value="5242880"></property><!--spel運算子,計算最大可上傳檔案體積-->
<!--設定默認的編碼-->
<property name="defaultEncoding" value="utf-8"></property>
</bean>
<!--掃描靜態資源-->
<mvc:default-servlet-handler/>
<!--掃描動態資源,也支持一些高級功能:JSR303校驗,快捷的ajax請求-->
<mvc:annotation-driven/>
</beans>
Mybaits核心組態檔
<?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"/>
<!-- 列印sql日志 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!--開啟延遲加載開關-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--開啟屬性按需加載-->
<setting name="aggressiveLazyLoading" value="false"/>
<!--開啟全域快取開關-->
<setting name="cacheEnabled" value="true"/>
</settings>
<!-- 給自定義POJO包下的所有類起別名,默認都是類名-->
<typeAliases>
<package name="Com.POJO"/>
</typeAliases>
<!--配置pageHelper-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--分頁引數合理化,當小于0時,查詢第一頁,當大于總頁數時,查詢最后一頁-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
</configuration>
web.xml組態檔
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<!--配置Spring的ioc容器啟動-->
<context-param>
<param-name>contextConfigLocation</param-name>
<!--指定spring組態檔位置-->
<param-value>classpath:Spring/applicationContext.xml</param-value>
</context-param>
<!--配置監聽器-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--配置springmvc的前端控制器-->
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!--這里我們spring和springmvc分離開了,這里相當于配置springmvc的ioc容器啟動-->
<param-value>classpath:SpringMVC/springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!--兩個標準配置-->
<!--字符編碼-->
<!--配置一個字符編碼的Filter,放在所有過濾器之前-->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<!-- 設定回應和請求為指定的編碼格式-->
<init-param>
<param-name>forceRequestEncoding</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>forceResponseEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--支持REST風格的filter,將put或者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>
<!--spring提供的過濾器解決解決ajax直接發送put請求-->
<filter>
<filter-name>HttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--設定session過期時間-->
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
使用分頁插件
pageHelper----Mybaits分頁插件
controller層
查詢所有員工并分頁顯示的方法
//查詢所有員工,分頁展示
@RequestMapping("/emps")
public String getEmps(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model)
{
//傳入當前顯示的頁碼和每頁顯示記錄的條數,查詢陳述句緊跟在后面
PageHelper.startPage(pn,5);
List<employee> emps = es.getAll();
//使用pageINfo包裝查詢后的結果
//封裝了詳細的分頁資訊,包括查詢出來的資料,傳入連續顯示的頁數
PageInfo page=new PageInfo(emps,5);
model.addAttribute("info",page);
return "list";
}
如何通過spring單元測驗,完成對上面controller層代碼的測驗呢? 看下面的步驟
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration//加了這個注解后,才能獲取到springmvc的ioc容器
@ContextConfiguration(locations = {"classpath:Spring/applicationContext.xml","classpath:SpringMVC/springmvc.xml"})
public class SpringMVCTers {
//傳入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();
//請求成功以后,請求域中會有info,我們可以取出info進行驗證
MockHttpServletRequest request=result.getRequest();
PageInfo pi= (PageInfo) request.getAttribute("info");
System.out.println("當前頁碼:"+pi.getPageNum());
System.out.println("總頁碼:"+pi.getPages());
System.out.println("總記錄數:"+pi.getTotal());
System.out.println("在頁面需要連續顯示的頁碼:");
int[] nums = pi.getNavigatepageNums();
for(int i:nums)
{
System.out.println(" "+i);
}
//獲取員工資料
List<employee> list = pi.getList();
for(employee e:list)
System.out.println("姓名:"+e.getEmpName()+" "+"性別: "+e.getGender());
}
}

查詢員工的思路—ajax

員工展示頁面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%pageContext.setAttribute("ctx",request.getContextPath());%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<html>
<head>
<title>員工資訊展示頁面</title>
</head>
<body>
<%--搭建展示頁面--%>
<div class="container">
<%--標題--%>
<div class="row">
<div class="col-md-12">
<h1 style="font-style: italic" >大忽悠集團員工展示頁面</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 class="row">
<div class="col-md-12">
<table class="table table-hover" id="emps_table">
<thead>
<tr class="info">
<th>#</th>
<th>姓名</th>
<th>性別</th>
<th>郵箱</th>
<th>部門名字</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%--使用ajax向里面添加內容--%>
</tbody>
</table>
</div>
</div>
</div>
<%--顯示分頁資訊--%>
<div class="row">
<%--分頁文字資訊--%>
<div class="col-md-6" id="page_info-area">
<%--使用ajax顯示相關資訊--%>
</div>
<%--分頁條資訊--%>
<div class="col-md-6" id="page_info_nav">
<%--使用ajax顯示相關資訊--%>
</div>
</div>
</div>
<script>
//1.頁面加載完成以后,直接發送ajax請求,要到分頁資料
$(function (){
//一開始去首頁
toPage(1)
})
//跳轉到指定頁碼號
function toPage(pn){
$.ajax({
url:"${ctx}/emps",
data:"pn="+pn,
type:"get",
success:function (result)
{
//1,決議并顯示員工資料
build_emps_table(result);
//2,決議并顯示分頁資訊
build_page_info(result);
//3.決議顯示分頁條資料
build_page_nav(result);
},
dataType:"json"
})
}
function build_emps_table(result){
//每次呼叫該方法前,需要先請客表格,因為ajax是無刷更新,每一次呼叫都會重復追加
$("#emps_table tbody").empty();
//拿到員工陣列
var e=result.extent.info.list;
$.each(e,
function(index,item)
{
//動態創建標簽并向里面添加內容
var empID=$("<td></td>").append(item.empId);
var empName=$("<td></td>").append(item.empName);
var empGender=$("<td></td>").append(item.gender);
var empEmail=$("<td></td>").append(item.email);
var deptName=$("<td></td>").append(item.department.depName);
//構建兩個按鈕 addClass方法呼叫后,回傳原來的元素
var editBtn=$("<button></buttom>").addClass("btn btn-primary btn-sm")
.append("<span></span>").addClass("glyphicon glyphicon-pencil").append("編輯");
var delBtn=$("<button></buttom>").addClass("btn btn-danger btn-sm")
.append("<span></span>").addClass("glyphicon glyphicon-trash").append("洗掉");
//將兩個按鈕追加到一個單元格里面
var btnTd=$("<td></td>").append(editBtn).append(" ").append(delBtn);
//append方法執行完成之后還是回傳原來的元素
$("<tr></tr>").append(empID).append(empName).append(empGender)
.append(empEmail).append(deptName).append(btnTd).
appendTo("#emps_table tbody");//整個表格構建完成以后,添加到對應位置中
}
)
}
//決議顯示分頁資訊
function build_page_info(result)
{
//每次呼叫前,先清空所有之前添加的內容
$("#page_info-area").empty();
$("#page_info-area").append("當前第"+result.extent.info.pageNum+"頁,總"+result.extent.info.pages+"共頁,總共" +
result.extent.info.total + "條記錄");
}
//決議顯示分頁條,點擊分頁要能去下一頁
function build_page_nav(result) {
//每次呼叫前,先清空所有之前添加的內容
$("#page_info_nav").empty();
var ul = $("<ul></ul>").addClass("pagination");
//attr賦值后,還是會回傳當前元素,這里不能點擊跳轉,所以傳入#,跳轉到本頁
var firstPageLi = $("<li></li>").append($("<a></a>").append("首頁").attr("href", "#"));
var prePageLi = $("<li></li>").append($("<a></a>").append("«"));
//如果是首頁,那么前進一頁不能點擊
if (result.extent.info.hasPreviousPage == false) {
firstPageLi.addClass("disabled");
prePageLi.addClass("disabled");
} else
{
firstPageLi.click(function (){
toPage(1);
});
prePageLi.click(function (){
toPage(result.extent.info.pageNum+1);
});
}
var nextPageLi=$("<li></li>").append($("<a></a>").append("»"));
var lastPageLi=$("<li></li>").append($("<a></a>").append("末頁").attr("href","#"));
//如果是末頁,沒有下一頁對應也不能點
if(result.extent.info.hasNextPage==false)
{
nextPageLi.addClass("disabled");
lastPageLi.addClass("disabled");
}else
{
lastPageLi.click(function (){
toPage(result.extent.info.pages);
});
nextPageLi.click(function (){
toPage(result.extent.info.pageNum+1);
});
}
//添加首頁和前一頁的提示
ul.append(firstPageLi).append(prePageLi);
//遍歷頁碼號
$.each(result.extent.info.navigatepageNums,function (index,item){
var numLi=$("<li></li>").append($("<a></a>").append(item));
if(result.extent.info.pageNum==item)
{
//如果是當前頁,那么對于頁碼處于激活狀態
numLi.addClass("active");
}
numLi.click(function (){
toPage(item);
});
ul.append(numLi);
});
//添加下一頁和末尾的提示
ul.append(nextPageLi).append(lastPageLi);
//把ul加入到nav中
var navEle=$("<nav></nav>").attr("aria-label","Page navigation").append(ul);
navEle.appendTo("#page_info_nav");
}
</script>
</body>
</html>
目前controller層:
@Controller
public class EmployeeController {
@Autowired
EmployueeService es;
//跳轉到首頁
@RequestMapping("/emp")
public String getEmps()
{
return "list";
}
@RequestMapping("/tolist")
public String toList(user u)
{
System.out.println("tolist");
user admin = es.getUser();
if(u.getName().equals(admin.getName())&&u.getPassword().equals(admin.getPassword()))
return "redirect:/emp";
return "redirect:/index.jsp";
}
//使用ajax技術,顯示資訊
@RequestMapping("/emps")
@ResponseBody//這里需要匯入json的依賴
public msg getEmpWithPageinfo(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model)
{
//傳入當前顯示的頁碼和每頁顯示記錄的條數,查詢陳述句緊跟在后面
PageHelper.startPage(pn,5);
List<employee> emps = es.getAll();
//使用pageINfo包裝查詢后的結果
//封裝了詳細的分頁資訊,包括查詢出來的資料,傳入連續顯示的頁數
PageInfo page=new PageInfo(emps,5);
model.addAttribute("info",page);
System.out.println("emps");
//以json形式回傳---包含info資訊和失敗成功資訊
return msg.success().add("info",page);
}
}
目前效果:


新增員工的思路

ajax使用時需要注意的問題:當我們使用ajax向某個標簽中追加資料的時候,例如點擊一個按鈕,向一個div追加5條記錄,那么下一次點擊按鈕,又會呼叫一次ajax請求,向里面追擊五條與先前重復的記錄,因此每一次在追加之前,需要先將之前追加的記錄或者追加的標簽屬性清除
jquery中的正則運算式以及其他常用函式
jQuery中的正則運算式
Jquery中的正則運算式注意事項

jquery中append()和appendTo()的區別
jQuery 檔案操作 - empty() 方法
jQuery中empty和remove方法
jquery的each遍歷,this指向



jQuery的change()事件
jquery attr和data給元素添加自定義屬性

jQuery中.find()方法?
js清除表單內容的reset方法

使用jquery獲取到要重置的表單后,需要取出陣列中的dom表單物件
//清除表單資料(表單重置)---DOM里面的方法,而不是jquery里面的方法
$("#myModal form")[0].reset();
java中string類里面的matches校驗正則運算式函式
Java字串:matches() 方法
使用springmvc的JSR303資料校驗需要引入一下的依賴

低版本tomcat需要引入validation-api,高版本不需要
<!-- maven管理引入springmvc注解資料校驗所需jar包:-->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.0.Final</version>
</dependency>
@Pattern注解中常用的校驗正則運算式筆記
@Pattern注解中常用的校驗正則運算式筆記
@Pattern進行正則校驗
jQuery之$(document)和on(events,[selector],[data],fn)方法
jQuery之$(document)
jquery中的val可以獲取或者設定對應的value值,設定單、多選框中被選中的狀態


springmvc兩篇好文
SpringMVC學習01:請求路徑匹配和引數系結
SpringMVC01----請求匹配、引數系結、常用注解
占位符引數也會嘗試去系結函式中同名引數或者物件中同名屬性

ajax可以直接發送put和delete請求
$.ajax({
//這里把員工id傳遞到更新按鈕上,這樣這里的id引數就可以直接從按鈕上獲得
url:"${ctx}/updateEmp/"+$(this).attr("edit-id"),
type:"put",
data:$("#updateModel form").serialize(),//表單序列化,這里是rest風格的url,因此請求引數中要附帶一個_method引數
success:function (res){
alert("成功")
alert(res.msg);
}
ajax發送put請求引發的血案
//員工更新方法
@RequestMapping(value = "/updateEmp/{empId}",method = RequestMethod.PUT)
@ResponseBody
public msg updateEmp(employee e)
{
System.out.println("=======================================");
System.out.println("員工更新方法");
System.out.println(e);
System.out.println("=======================================");
System.out.println(e);
es.updateEmp(e);
return msg.success();
}

問題: 使用ajax直接發送put請求,封裝的資料值為null

原因,這里也揭示了引數系結的原理

getParamter()里面傳入的引數是POJO物件每個屬性的名字,他會嘗試把每一個屬性的名字作為key去請求引數中進行匹配獲取
血案:

注意如果不是直接使用ajax發送put請求,而是下面這種:

直接通過ajax發送put請求的解決方案:
解決方案:在web.xml中配置spring提供的過濾器解決
<filter>
<filter-name>HttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

洗掉員工

jquery中獲取所有祖先并可以加以篩選的函式

彈出框confirm()的使用
彈出框confirm()的使用
ctrl+f快捷查找某個標簽,變數在當前頁面的具體位值
length函式,回傳查找到的元素個數

查找被選中的元素—checked

prop函式,設定單選框是否被選中,使用true或者false


jquery中的each方法來遍歷陣列和物件

在后代元素中進行篩選—find函式

js中的substring和substr的區別
js中substring()與substr()方法的區別
專案完整邏輯鏈代碼
主頁:這里是采用的模板,具體鏈接如下
登錄模板

員工展示頁面,即增刪查改頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%pageContext.setAttribute("ctx",request.getContextPath());%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="stylesheet">
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<html>
<head>
<title>員工資訊展示頁面</title>
</head>
<body>
<!-- 修改員工的模態框---bootstrap -->
<div class="modal fade" id="updateModel" 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">×</span></button>
<h4 class="modal-title" id="myModalUpdate">修改員工資訊</h4>
</div>
<div class="modal-body">
<%--表單添加在此處--%>
<form class="form-horizontal" method="post">
<div class="form-group">
<label for="inputName" class="col-sm-2 control-label">姓名:</label>
<div class="col-sm-10">
<p class="form-control-static" id="UpdateEmpName"></p>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">性別:</label>
<div class="col-sm-10">
<label class="radio-inline">
<input type="radio" name="gender" value="男" checked="checked"> 男
</label>
<label class="radio-inline">
<input type="radio" name="gender" value="女" > 女
</label>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label" >郵箱</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="updateEmail3" name="email" placeholder="請輸入郵箱">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">部門</label>
<div class="col-sm-4">
<select class="form-control" name="dpId" >
<%--下拉串列的內容是動態從資料庫中取出的,并且部門提交部門id即可--%>
<%--通過ajax顯示所有員工資訊--%>
</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="update_btn">更新</button>
</div>
</div>
</div>
</div>
<!-- 新增員工的模態框---bootstrap -->
<div class="modal fade" id="myModal" 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">×</span></button>
<h4 class="modal-title" id="myModalLabel">添加新員工</h4>
</div>
<div class="modal-body">
<%--表單添加在此處--%>
<form class="form-horizontal" method="post">
<div class="form-group">
<label for="inputName" class="col-sm-2 control-label">姓名:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputName" name="empName" placeholder="請輸入員工姓名" >
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">性別:</label>
<div class="col-sm-10">
<label class="radio-inline">
<input type="radio" name="gender" value="男" checked="checked"> 男
</label>
<label class="radio-inline">
<input type="radio" name="gender" value="女" > 女
</label>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label" >郵箱</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="inputEmail3" name="email" placeholder="請輸入郵箱">
<span class="help-block"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">部門</label>
<div class="col-sm-4">
<select class="form-control" name="dpId" >
<%--下拉串列的內容是動態從資料庫中取出的,并且部門提交部門id即可--%>
<%--通過ajax顯示所有員工資訊--%>
</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">保存</button>
</div>
</div>
</div>
</div>
<%--搭建展示頁面--%>
<div class="container">
<%--標題--%>
<div class="row">
<div class="col-md-12">
<h1 style="font-style: italic" >大忽悠集團員工展示頁面</h1>
</div>
</div>
<div class="row">
<%--按鈕--%>
<div class="col-md-4 col-md-offset-8">
<button class="btn btn-primary" id="add_btn">新增</button>
<button class="btn btn-danger" id="del_btn">洗掉</button>
</div>
<%--顯示表格資料--%>
<div class="row">
<div class="col-md-12">
<table class="table table-hover" id="emps_table">
<thead>
<tr class="info">
<th>
<input type="checkbox" id="check-all"/>
</th>
<th>#</th>
<th>姓名</th>
<th>性別</th>
<th>郵箱</th>
<th>部門名字</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<%--使用ajax向里面添加內容--%>
</tbody>
</table>
</div>
</div>
</div>
<%--顯示分頁資訊--%>
<div class="row">
<%--分頁文字資訊--%>
<div class="col-md-6" id="page_info-area">
<%--使用ajax顯示相關資訊--%>
</div>
<%--分頁條資訊--%>
<div class="col-md-6" id="page_info_nav">
<%--使用ajax顯示相關資訊--%>
</div>
</div>
</div>
<script>
//1.頁面加載完成以后,直接發送ajax請求,要到分頁資料
$(function (){
//一開始去首頁
toPage(1)
})
//用一個全域變數,保存總的記錄數
var totalNum;
//定義一個全域變數,保存當前頁碼
var curNum;
//跳轉到指定頁碼號
function toPage(pn){
$.ajax({
url:"${ctx}/emps",
data:"pn="+pn,
type:"get",
success:function (result)
{
//1,決議并顯示員工資料
build_emps_table(result);
//2,決議并顯示分頁資訊
build_page_info(result);
//3.決議顯示分頁條資料
build_page_nav(result);
},
dataType:"json"
})
}
function build_emps_table(result){
//每次呼叫該方法前,需要先請客表格,因為ajax是無刷更新,每一次呼叫都會重復追加
$("#emps_table tbody").empty();
//拿到員工陣列
var e=result.extent.info.list;
$.each(e,
function(index,item)
{
//還需要追加一個多選框用于批量洗掉
var checkBoxId=$("<td><input type='checkbox' class='check-item'/></td>");
//動態創建標簽并向里面添加內容
var empID=$("<td></td>").append(item.empId);
var empName=$("<td></td>").append(item.empName);
var empGender=$("<td></td>").append(item.gender);
var empEmail=$("<td></td>").append(item.email);
var deptName=$("<td></td>").append(item.department.depName);
//構建兩個按鈕 addClass方法呼叫后,回傳原來的元素
var editBtn=$("<button></buttom>").addClass("btn btn-primary btn-sm edit_btn")//添加一個edit-btn屬性方便操作
.append("<span></span>").addClass("glyphicon glyphicon-pencil").append("編輯");
//為編輯按鈕添加一個自定義的屬性,來表示當前員工id
editBtn.attr("edit-id",item.empId);
var delBtn=$("<button></buttom>").addClass("btn btn-danger btn-sm del_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);
//append方法執行完成之后還是回傳原來的元素
$("<tr></tr>").append(checkBoxId).append(empID).append(empName).append(empGender)
.append(empEmail).append(deptName).append(btnTd).
appendTo("#emps_table tbody");//整個表格構建完成以后,添加到對應位置中
}
)
}
//決議顯示分頁資訊
function build_page_info(result)
{
//每次呼叫前,先清空所有之前添加的內容
$("#page_info-area").empty();
$("#page_info-area").append("當前第"+result.extent.info.pageNum+"頁,總"+result.extent.info.pages+"共頁,總共" +
result.extent.info.total + "條記錄");
totalNum=result.extent.info.total;
curNum=result.extent.info.pageNum;
}
//決議顯示分頁條,點擊分頁要能去下一頁
function build_page_nav(result) {
//每次呼叫前,先清空所有之前添加的內容
$("#page_info_nav").empty();
var ul = $("<ul></ul>").addClass("pagination");
//attr賦值后,還是會回傳當前元素,這里不能點擊跳轉,所以傳入#,跳轉到本頁
var firstPageLi = $("<li></li>").append($("<a></a>").append("首頁").attr("href", "#"));
var prePageLi = $("<li></li>").append($("<a></a>").append("«"));
//如果是首頁,那么前進一頁不能點擊
if (result.extent.info.hasPreviousPage == false) {
firstPageLi.addClass("disabled");
prePageLi.addClass("disabled");
} else
{
firstPageLi.click(function (){
toPage(1);
});
prePageLi.click(function (){
toPage(result.extent.info.pageNum+1);
});
}
var nextPageLi=$("<li></li>").append($("<a></a>").append("»"));
var lastPageLi=$("<li></li>").append($("<a></a>").append("末頁").attr("href","#"));
//如果是末頁,沒有下一頁對應也不能點
if(result.extent.info.hasNextPage==false)
{
nextPageLi.addClass("disabled");
lastPageLi.addClass("disabled");
}else
{
lastPageLi.click(function (){
toPage(result.extent.info.pages);
});
nextPageLi.click(function (){
toPage(result.extent.info.pageNum+1);
});
}
//添加首頁和前一頁的提示
ul.append(firstPageLi).append(prePageLi);
//遍歷頁碼號
$.each(result.extent.info.navigatepageNums,function (index,item){
var numLi=$("<li></li>").append($("<a></a>").append(item));
if(result.extent.info.pageNum==item)
{
//如果是當前頁,那么對于頁碼處于激活狀態
numLi.addClass("active");
}
numLi.click(function (){
toPage(item);
});
ul.append(numLi);
});
//添加下一頁和末尾的提示
ul.append(nextPageLi).append(lastPageLi);
//把ul加入到nav中
var navEle=$("<nav></nav>").attr("aria-label","Page navigation").append(ul);
navEle.appendTo("#page_info_nav");
}
//重置表單的函式
function reset_form(ele)
{
//清空表單里面的內容體
$(ele)[0].reset();
//清空之前給可能會給表單添加的樣式
//清除表單下面所有后代中含有這兩個屬性的
$(ele).find("*").removeClass("has-error has-success");
$(ele).find(".help-block").text("");
};
//按鈕被點擊,顯示模態框
$("#add_btn").click(function (){
//清除表單資料(表單重置)---DOM里面的方法,而不是jquery里面的方法
//這里的表單重置,不應該只是重置表單里面的內容體,包括給表單添加的樣式
reset_form("#myModal form");
//發送ajax請求,查出部門資訊,顯示在下拉串列中
getDepts("#myModal select");
$('#myModal').modal({
backdrop:false //點擊頁面其他地方,模態框也不會關閉,或者這里可以寫static
});
})
//查出所有部門資訊,并顯示在下拉串列中
function getDepts(ele)
{
//每次呼叫該方法前,先將之前添加在下拉串列中的資料清除---ajax使用的主要問題
$(ele).empty();
$.ajax({
url:"${ctx}/depts",
type: "GET",
success:function (result){
//顯示部門資訊在下拉串列中
$.each(result.extent.depts,function (){
//this指代當前遍歷的元素
var optionEle=$("<option></option>").append(this.depName).attr("value",this.depId);
//模態框下面只有一個select標簽
optionEle.appendTo(ele);
})
}
})
}
//校驗表單資料
function valid_add_form()
{
//1.拿到要檢驗的資料,使用正則運算式
var empName=$("#inputName").val();
//正則運算式
var regName=/(^[a-zA-Z0-9_-]{6,16}$)|(^[\u2E80-\u9FFF]{2,5}$)/
//每一次給當前標簽添加樣式前,應該清除掉之前添加的樣式
if(!regName.test(empName))
{
//呼叫抽取出來的顯示校驗結果的方法
show_valid_msg("#inputName","error","用戶名可以是2-5位中文或者6-16位英文和數字的組合");
return false;
}else
{
show_valid_msg("#inputName","success","");
}
//校驗郵箱
var email=$("#inputEmail3").val();
var regEmail=/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
if(!regEmail.test(email))
{
show_valid_msg("#inputEmail3","error","郵箱格式有誤");
return false;
}
else
{
show_valid_msg("#inputEmail3","success","");
}
return true;
}
//抽取出展示校驗結果資訊的方法
function show_valid_msg(ele,status,msg)
{
//清除當前元素的校驗狀態---移除多個屬性,用空格分隔開來
$(ele).parent().removeClass("has-success has-error")
$(ele).next("span").text("");
if(status=="success")
{
$(ele).parent().addClass("has-success");
$(ele).next("span").text(msg);
}
if(status=="error")
{
$(ele).parent().addClass("has-error");
$(ele).next("span").text(msg);
}
}
//將用戶名提交到后端,驗證是否可用---用戶名是否重復---前端校驗
$("#inputName").change(function (){
//獲取輸入框的value值
var empName=this.value;
//發送ajax請求校驗用戶名是否可用
$.ajax({
url:"${ctx}/checkEmp",
data:"empName="+empName,
type:"post",
success:function (result){
if(result.code==100)
{
show_valid_msg("#inputName","success","用戶名可用");
//如果校驗成功了,給保存按鈕上增加一個自定義屬性
$("#emp_save").attr("ajax-va","success");
}else
{
//這里如果錯誤了,那么動態顯示是用戶名重復錯誤,還是校驗錯誤
show_valid_msg("#inputName","error",result.extent.va_msg);
$("#emp_save").attr("ajax-va","error");
}
}
});
});
//當保存按鈕點擊以后,提交表單的資料
$("#emp_save").click(function (){
//1.模態框中填寫的表單資料提交給服務器進行保存
//先對要提交給服務器的資料進行資料校驗
if(!valid_add_form())
return false;
//下面是前端校驗用戶名是否重復
//1.判斷之前的用戶名校驗是否成功,獲取到當前按鈕的校驗狀態,上面設定的自定義校驗屬性
//這里還有一個問題需要處理,那就是當我們第一次添加一名符合規定的員工后,下一次打開表單還是上一次符合規定的員工
//并且如果我們不對資料進行修改,那么它的用戶名校驗狀態就是合法的,那么直接再次提交,也不會發送ajax請求進行用戶名校驗
//這樣就會造成人員重復添加的問題,因此這里每一次點擊新增按鈕,彈出模態對話框的時候,對表單進行清除操作
if($(this).attr("ajax-va")=="error")
return false;
//2.發送ajax請求保存員工
$.ajax({
urL:"${ctx}/emp",
type:"post",
data:$("#myModal form").serialize(),//序列化表格內容為字串,
success:function (result){
//員工保存成功:
//關閉模態框之前查看后端校驗結果
if(result.code==100)
{
//1.關閉模態框
$("#myModal").modal("hide");
//2.來到最后一頁,顯示添加的這條記錄
//發送ajax請求,顯示最后一頁資料
//將總記錄數當做頁碼,分頁插件如果頁碼大于總頁碼,顯示最后一頁,直接在xml中配置過了
toPage(totalNum);
}
else
{
//后端校驗用戶名是否重復
if(undefined!=result.extent.errorName)
{
alert("用戶名重復");
show_valid_msg("#inputName","error",result.extent.errorName);
}
//這里可以將前端校驗的方法注釋掉,檢驗后端檢驗正確與否
//有哪個欄位有錯誤,就顯示哪個欄位的錯誤資訊
//如果這里某個欄位沒有錯誤資訊,那么會顯示undefined
if(undefined!=result.extent.errorFields.email)
{
alert("1");
//顯示郵箱錯誤資訊
show_valid_msg("#inputEmail3","error","后端檢驗發現郵箱格式有誤");
}
if(undefined!=result.extent.errorFields.empName)
{
alert("2");
//顯示名字錯誤資訊
show_valid_msg("#inputName","error","后端檢驗發現用戶名格式有誤");
}
}
}
});
});
//此處不能直接系結click的原因是因為,發送ajax請求動態往標簽體內增加內容是在頁面加載完成以后做的
//修改員工
//1.我們是按鈕創建之前就系結了click,所以系結不上事件
//2.1.我們可以在創建按鈕的時候系結,但是很麻煩
//2.2.我們可以live函式,但是新版jquery已經廢棄了這個函式,使用on進行替代
$(document).on("click",".edit_btn",function (){
//首先查出員工的資訊,顯示要修改的員工的資訊
//查出部門資訊,并顯示部門串列
getDepts("#updateModel select");
getEmp($(this).attr("edit-id"));//獲取剛才給新增按鈕添加的自定義屬性,里面存放員工id
//3.把員工的id傳遞給模態框的更新按鈕
$("#update_btn").attr("edit-id",$(this).attr("edit-id"));
$("#updateModel").modal({
backdrop:"static"
})
})
//查詢員工資訊的方法
//思路: 獲取到員工id--->去資料庫中查找對應員工,回傳給前端---->前端獲取資料,直接將資料回顯在對應的位置
function getEmp(id)
{
$.ajax({
url:"${ctx}/emp/"+id,
type:"get",
success:function (result){
var empData=result.extent.emp;
$("#UpdateEmpName").text(empData.empName);
$("#updateEmail3").val(empData.email);//給輸入框賦值,直接往val里面填入引數即可
$("#updateModel input[name=gender]").val(empData.gender);
$("#updateModel select").val(empData.dpId);
}
})
}
//點擊更新,更新員工資訊
$("#update_btn").click(function (){
//驗證郵箱是否合法
//校驗郵箱
var email=$("#updateEmail3").val();
var regEmail=/^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
if(!regEmail.test(email))
{
show_valid_msg("#updateEmail3","error","郵箱格式有誤");
return false;
}
else
{
show_valid_msg("#updateEmail3","success","");
}
//2.發送ajax請求保存更新的員工資料
$.ajax({
//這里把員工id傳遞到更新按鈕上,這樣這里的id引數就可以直接從按鈕上獲得
url:"${ctx}/emp/"+$(this).attr("edit-id"),
type:"put",
data:$("#updateModel form").serialize(),//表單序列化,這里是rest風格的url,因此請求引數中要附帶一個_method引數
success:function (res){
//1.關閉模態框
$("#updateModel").modal("hide");
//2.回到主頁面
toPage(curNum);
}
})
})
//洗掉某個員工
//給洗掉按鈕搞上點擊事件---注意使用on函式
$(document).on("click",".del_btn ",function (){
//1.彈出確認洗掉的對話框
//獲取要洗掉的人的名字
var empName=$(this).parents("tr").find("td:eq(2)").text()
//獲取要洗掉的員工的id---通過在創建洗掉按鈕的時候,直接添加一個屬性記錄當前id即可
var empId=$(this).attr("del-id");
if(confirm("確認洗掉"+empName+"員工嗎?"))
{
//確認,發送ajax請求
$.ajax({
url:"${ctx}/emp/"+empId,
type:"delete",
success:function (res){
//回到本頁
toPage(curNum);
}
})
}
})
//完成全選和全不選的功能
$("#check-all").click(function (){
//attr獲取check是undefined
//對于原生的dom屬性建議使用prop獲取,而attr用來獲取自定義屬性的值
//使用prop修改和讀取dom原生屬性的值
$(".check-item").prop("checked",$(this).prop("checked"));
});
//此處不能直接系結click的原因是因為,發送ajax請求動態往標簽體內增加內容是在頁面加載完成以后做的
//如果單個選擇框當前頁全部選滿了,那么最大的選擇框也會被選中
$(document).on("click",".check-item",function (){
var flag=$(".check-item:checked").length==$(".check-item").length;
$("#check-all").prop("checked",flag);
})
//點擊全部洗掉按鈕,就進行批量洗掉
$("#del_btn").click(function ()
{
var empNames="";
var del_idstr="";//組裝員工id的字串
//遍歷單個被選中的選擇框
$.each($(".check-item:checked"),function (){
//當前正在遍歷的item
//獲取每個單選框對應的員工名字
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:"${ctx}/emp/"+del_idstr,
type:"DELETE",
success:function (res){
//回到當前頁面
toPage(curNum);
}
})
}
});
</script>
</body>
</html>

POJO層除了逆向工程自動生成的四個類外,還額外增添了一個訊息類msg,將其作為json字串回傳給前端,并且使用鏈式編程和靜態函式,方便直接呼叫
package Com.POJO;
import java.util.HashMap;
import java.util.Map;
//通用的json回傳類
public class msg
{
//狀態碼 100--成功 200---失敗
private int code;
//提示資訊
private String msg;
//用戶要回傳的給瀏覽器的資料放在map中
private Map<String,Object> extent=new HashMap<String, Object>();
public static msg success()
{
msg result=new msg();
result.setCode(100);
result.setMsg("處理成功");
return result;
}
public static msg fail()
{
msg result=new msg();
result.setCode(200);
result.setMsg("處理失敗");
return result;
}
public msg add(String key,Object value)
{
this.getExtent().put(key,value);
return this;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Map<String, Object> getExtent() {
return extent;
}
public void setExtent(Map<String, Object> extent) {
this.extent = extent;
}
}

Dao層就是逆向工程自動生成的三個介面
注意:Dao層對應的三個逆向工程自動生成的.xml檔案中,我們還需要增添兩個查出員工的同時查出部門資訊的方法,一個是單個員工,一個是多個員工,這里使用的是聯合查詢里面的左連接
<!--查出員工表的同時,查出部門資訊-->
<resultMap id="DeptResultMap" type="Com.POJO.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="dp_id" jdbcType="INTEGER" property="dpId" />
<!--使用association封裝查詢出來的自定義物件-->
<association property="department" javaType="Com.POJO.department">
<id column="dep_id" property="depId"/>
<result column="dep_name" property="depName"/>
</association>
</resultMap>
<sql id="WithDept_column_list">
emp_id, emp_name, gender, email,dep_id,dep_name
</sql>
<select id="selectByExampleWithDepartmnet" resultMap="DeptResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="WithDept_column_list" />
/*聯合查詢需要對此處進行修改*/
FROM employee LEFT JOIN department ON dep_id=dp_id
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKeyWithDepartmnet" parameterType="java.lang.Integer" resultMap="DeptResultMap">
select
<include refid="Base_Column_List" />
FROM employee LEFT JOIN department ON dep_id=dp_id
</select>
service層—兩個類,一個處理部門的資料庫操作,一個處理員工的資料庫操作

deptService:
package Com.service;
import Com.Dao.departmentMapper;
import Com.POJO.department;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class deptService {
@Autowired
private departmentMapper dm;
public List<department> getDepets()
{
return dm.selectByExample(null);//沒有篩選條件,就是全部查出
}
}
EmployueeService:
package Com.service;
import Com.Dao.employeeMapper;
import Com.Dao.userMapper;
import Com.POJO.departmentExample;
import Com.POJO.employee;
import Com.POJO.employeeExample;
import Com.POJO.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class EmployueeService {
@Autowired
employeeMapper em;
@Autowired
userMapper um;
//查詢所有員工
public List<employee> getAll()
{
//引數是篩選條件
return em.selectByExampleWithDepartmnet(null);
}
//獲取登錄的資訊
public user getUser()
{
return um.getUser();
}
//保存員工
public int saveEmp(employee e)
{
//這里不插入id,因此是有選擇的插入
return em.insertSelective(e);
}
//后端檢驗用戶名是否可用
public boolean checkEmp(String empName)
{
//判斷用戶名在資料庫中有幾個
employeeExample ee=new employeeExample();
employeeExample.Criteria criteria=ee.createCriteria();
criteria.andEmpNameEqualTo(empName);
long count=em.countByExample(ee);
return count==0;//如果用戶名只有一個,為真,否則為假
}
public employee getEmp(Integer id)
{
return em.selectByPrimaryKey(id);
}
public void updateEmp(employee e) {
em.updateByPrimaryKeySelective(e);//根據主鍵有選擇的更新---例如員工名字不可修改,因此封裝的物件的名字為null
}
public void deleteEmp(Integer id) {
em.deleteByPrimaryKey(id);
}
public void deleteBatch(List<Integer> ids)
{
employeeExample ee=new employeeExample();
employeeExample.Criteria criteria = ee.createCriteria();
criteria.andEmpIdIn(ids);//要批量洗掉的id位于某個集合內
em.deleteByExample(ee);//按照條件洗掉
}
}
controller層對應也有兩個類,一個處理部門請求,一個處理員工請求
DeptController:
package Com.Controller;
import Com.POJO.department;
import Com.POJO.msg;
import Com.service.deptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
/*
* 處理和部門有關的請求
* */
@Controller
public class DeptController
{
@Autowired
private deptService ds;
//查出所有部門資訊
@RequestMapping("/depts")
@ResponseBody
public msg getDepts()
{
return msg.success().add("depts",ds.getDepets());
}
}
EmployeeController:
@Controller
public class EmployeeController {
@Autowired
EmployueeService es;
//跳轉到首頁
@RequestMapping("/emp")
public String getEmps()
{
return "list";
}
@RequestMapping("/tolist")
public String toList(user u)
{
System.out.println("tolist");
user admin = es.getUser();
if(u.getName().equals(admin.getName())&&u.getPassword().equals(admin.getPassword()))
return "redirect:/emp";
return "redirect:/index.jsp";
}
//使用ajax技術,顯示資訊
@RequestMapping("/emps")
@ResponseBody//這里需要匯入json的依賴
public msg getEmpWithPageinfo(@RequestParam(value = "pn",defaultValue = "1") Integer pn, Model model)
{
//傳入當前顯示的頁碼和每頁顯示記錄的條數,查詢陳述句緊跟在后面
PageHelper.startPage(pn,5);
List<employee> emps = es.getAll();
//使用pageINfo包裝查詢后的結果
//封裝了詳細的分頁資訊,包括查詢出來的資料,傳入連續顯示的頁數
PageInfo page=new PageInfo(emps,5);
model.addAttribute("info",page);
System.out.println("emps");
//以json形式回傳---包含info資訊和失敗成功資訊
return msg.success().add("info",page);
}
//保存員工的方法:保存之前進行后端校驗,因為有方法可以繞過前端校驗,因此后端校驗必須要有
//后端校驗是在點擊保存按鈕,資料庫回傳給資料庫后,進行校驗,然后才會顯示相關錯誤資訊
//與前端你寫錯后,立馬提示你有錯誤不同
@RequestMapping(value = "/emp",method = RequestMethod.POST)
@ResponseBody
//@Valid注解,告訴SpringMVC,封裝這個javabean物件時,按照這個物件里面變數規定的校驗規則進行校驗
//javaBean后面緊跟一個BindingResult,這個BindingResult就是封裝前一個bean的校驗結果
public msg saveEmp(@Valid employee e,BindingResult result)
{
//后端校驗用戶名和郵箱格式是否正確
if(result.hasErrors())
{
//校驗失敗,應該回傳失敗,在模態框中顯示校驗失敗的錯誤資訊
List<FieldError> errors = result.getFieldErrors();
Map<String ,Object> map=new HashMap<String, Object>();
for(FieldError e1:errors)
{
System.out.println("錯誤的欄位名:"+e1.getField());
System.out.println("錯誤資訊:"+e1.getDefaultMessage());
map.put(e1.getField(),e1.getDefaultMessage());
}
return msg.fail().add("errorFields",map);
}
//這里添加一個后端校驗用戶名是否重復
//校驗用戶名是否重復
if(!es.checkEmp(e.getEmpName()))
{
return msg.fail().add("errorName","后端校驗發現用戶名不可用");
}
es.saveEmp(e);
return msg.success();
}
//驗證用戶名是否可用的方法
@RequestMapping("/checkEmp")
@ResponseBody
public msg checkEmp( 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 ret = es.checkEmp(empName);
if(ret)
return msg.success();
return msg.fail().add("va_msg","用戶名不可用");
}
//查詢員工
@RequestMapping(value = "/emp/{id}",method = RequestMethod.GET)
@ResponseBody
public msg getEmp(@PathVariable("id") Integer id)
{
employee e=es.getEmp(id);
return msg.success().add("emp",e);
}
//員工更新方法
@RequestMapping(value = "/emp/{empId}",method = RequestMethod.PUT)
@ResponseBody
public msg updateEmp(employee e)
{
es.updateEmp(e);
return msg.success();
}
//員工洗掉方法實作
@RequestMapping(value = "/emp/{id}",method = RequestMethod.DELETE)
@ResponseBody
public msg deleteEmpById(@PathVariable("id")String ids)
{
System.out.println("======================================");
if(ids.contains("-"))//批量洗掉
{
System.out.println("批量洗掉中");
String[] str_ids = ids.split("-");
//呼叫批量洗掉的方法
//組裝id集合
List<Integer> del_ids=new ArrayList<Integer>();
for(String s:str_ids)
{
int i = Integer.parseInt(s);
del_ids.add(i);
}
es.deleteBatch(del_ids);
}
else//單個洗掉
{
Integer id=Integer.parseInt(ids);
es.deleteEmp(id);
}
return msg.success();
}
}
總結

ajax和js使用注意事項
- 實作某個功能時,盡量抽取成一個方法,提高重用性,例如本專案中跳轉到某一頁的方法,和抽取出來的顯示校驗結果的方法
- 如果某個值需要在多處使用,那么可以定義一個全域變數保存該值,方便呼叫
- 使用ajax向標簽中追加內容后,標簽體中不會顯示出現追加的內容,但是實際已經存在,那么下一次再次呼叫ajax時,又會重復上一次的追加行為,那么頁面效果就是內容重復追加,解決辦法就是在每次呼叫ajax之前,先將之前重復追加的內容清除掉
- 同理如果ajax是追加或者修改了標簽的屬性,那么對應的被更改的屬性就會一直存在,因此下一次呼叫ajax之前,需要先清除之前追加給標簽的屬性
- 我們可以通過給按鈕或者其他控制元件添加自定義屬性的方式,來保存一些我們需要用到的資料,例如給洗掉按鈕增添一個自定義屬性保存當前員工的id,方便一會通過在按鈕點擊事件中獲取到id值,從而通過ajax回傳給服務器端,進行洗掉邏輯操作
- 使用ajax時,在獲取到服務器端發送來的資料后,可以在成功的回呼函式中,獲取資料,然后通過append等方式,動態向需要的標簽或位置中添加內容
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/291063.html
標籤:其他
上一篇:HarmonyOS 實戰——萬字分析并學習 JsFACard 專案
下一篇:2021年前端開發高效學習流程
