程序员社区

SSM整合案例

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("&laquo;"));
            //如果是首页,那么前进一页不能点击
            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("&raquo;"));
            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">&times;</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">&times;</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("&laquo;"));
            //如果是首页,那么前进一页不能点击
            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("&raquo;"));
            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使用注意事项

  1. 实现某个功能时,尽量抽取成一个方法,提高重用性,例如本项目中跳转到某一页的方法,和抽取出来的显示校验结果的方法
  2. 如果某个值需要在多处使用,那么可以定义一个全局变量保存该值,方便调用
  3. 使用ajax向标签中追加内容后,标签体中不会显示出现追加的内容,但是实际已经存在,那么下一次再次调用ajax时,又会重复上一次的追加行为,那么页面效果就是内容重复追加,解决办法就是在每次调用ajax之前,先将之前重复追加的内容清除掉
  4. 同理如果ajax是追加或者修改了标签的属性,那么对应的被更改的属性就会一直存在,因此下一次调用ajax之前,需要先清除之前追加给标签的属性
  5. 我们可以通过给按钮或者其他控件添加自定义属性的方式,来保存一些我们需要用到的数据,例如给删除按钮增添一个自定义属性保存当前员工的id,方便一会通过在按钮点击事件中获取到id值,从而通过ajax返回给服务器端,进行删除逻辑操作
  6. 使用ajax时,在获取到服务器端发送来的数据后,可以在成功的回调函数中,获取数据,然后通过append等方式,动态向需要的标签或位置中添加内容
赞(0) 打赏
未经允许不得转载:IDEA激活码 » SSM整合案例

相关推荐

  • 暂无文章

一个分享Java & Python知识的社区