zoukankan      html  css  js  c++  java
  • SpringMVC+Spring+Mybatis框架集成

    一、基本概念

    1.Spring      Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

    2.SpringMVC      Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring MVC分离了控制器、模型对象、分派器以及处理程序对象的角色,这种分离让它们更容易进行定制。

    3.MyBatis      MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。MyBatis是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

    二、使用Maven创建web项目

    1.打开Eclipse, 选择File -> New -> Other,在New窗口中选择 Maven -> Maven Project;点击Next。

    2.选择项目路径,这里选择Use default Workspace location默认工作空间。

    3.选择项目类型,在Artifact Id中选择maven-archetype-webapp

    4.输入Group Id和 Artifact Id,package可以不写。

    Group Id:类似于包名 Artifact Id:项目的名称 Version:初始的版本号,一般不需要改动 其他选项设置为空,点击Next创建项目,如下图:

    5.点击Finish,会生成一个这样目录的项目。

    6.修改项目编码方式

    在项目上右键 -> Properties -> Resource -> Text file encoding -> 改为“utf-8”。

    7.添加Source文件夹

    接下来需要添加src/main/java、src/test/java、src/test/resources三个文件夹。注意不是建普通的Folder,而是Source Folder。在项目上右键new -> Other,在New窗口中选择

    Java -> Source Folder。

    如果出现了下面的情况,其实是文件夹已经存在了,只是我们看不到。

    8.在项目上右键,选择Properties,在弹出的属性窗口中依次选择Java Build Path -> Libraries -> JRE System Library -> Edit。

    9.在Edit Library窗口中修改JRE为jdk1.7.0_25。

    10.设置好之后的目录结构如下图所示:

    这时看到src/main/java和src/test/java文件夹就已经显示出来了。

    11.让项目使用jdk 1.7编译

    在项目上右键 -> 选择Properties -> 选择Java Compiler -> 将Compiler Compliance Level 改为“1.7”。

    12.更改class路径

    右键项目,选择Java Build Path -> Source,下面应该有4个文件夹,src/main/java,src/main/resources,src/test/java,src/test/resources。双击每个文件夹的Output folder,选择路径。src/main/java,src/main/resources,选择target/classes;src/test/java ,src/test/resources, 选择target/test-classes。选上Allow output folders for source folders。(如果没有选上的话)

    13.把项目变成Dynamic Web项目 

    右键项目,选择Properties,在属性窗口中选择Project Facets,修改Java版本号为1.7,默认为1.5或其他版本。注:先去掉“Dynamic Web Module”,然后再保存。

    14.接下来继续右键项目 -> Properties ->选择Project Facets -> 勾选“Dynamic Web Module”,选择版本为3.0 -> 然后点击下方的“Further configuration available...”。

    15.在弹出的窗口中修改Content directory为“src/main/webapp”。

    设置好之后的项目结构如下图所示,可以看到在webapp下面多了一个META-INF文件夹。

    或者还有一种做法,就是在“Modify Faceted Project”窗口中不用修改Content directory,即用他的默认值“WebContent”。

    接下来观察我们的项目结构,多了一个WebContent目录。

    这个结构不符合maven的结构,我们还要做如下修改:

    把上图WebContent下面两个目录 META-INF ,WEB-INF 直接剪切到src/main/webapp目录下,并删掉WebContent目录即可。

    16.设置部署程序集(Web Deployment Assembly)

    在项目上右键,选择Properties -> Deployment Assembly,点击进去后,如下图:

    此处列表是,部署项目时,文件发布的路径。

    (1)我们删除跟test相关的项,因为test是测试使用,并不需要部署。

    (2)设置将Maven的jar包发布到lib下。

    在右边点击“Add”按钮,在弹出的窗口中选择Java Build Path Entries。

    点击Next,选择Maven Dependencies

    点击Finish,然后可以看到已经把Maven Dependencies添加到Web应用结构中了,完成后如下图:

    17.至此一个基于maven的webapp就建立好了,并可以直接从eclipse中发布到tomcat。发布完成后,进入到tomcat的部署路径,我的是D:apache-tomcat-7.0.27webappsSSMProDemo,发现WEB-INF目录下自动生成了lib目录,并且所有依赖的jar包也都已经部署进来。如果没有lib目录,说明项目依赖的jar包没有部署进来,这时运行程序会报错:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener。

    三、创建数据库和表

    打开MySQL数据库,创建两张表,一张用于存放用户信息的表tb_user,另一张为字典表tb_dict。SQL脚本如下:

    复制代码
    /*
    Navicat MySQL Data Transfer
    
    Source Server         : local
    Source Server Version : 50617
    Source Host           : localhost:3306
    Source Database       : demodb
    
    Target Server Type    : MYSQL
    Target Server Version : 50617
    File Encoding         : 65001
    
    Date: 2017-01-31 18:39:18
    */
    
    SET FOREIGN_KEY_CHECKS=0;
    
    -- ----------------------------
    -- Table structure for `tb_dict`
    -- ----------------------------
    DROP TABLE IF EXISTS `tb_dict`;
    CREATE TABLE `tb_dict` (
      `dictid` int(11) NOT NULL AUTO_INCREMENT COMMENT '字典id',
      `field` varchar(15) DEFAULT NULL COMMENT '对照字段',
      `fieldname` varchar(20) DEFAULT NULL COMMENT '对照字段名称',
      `code` varchar(10) DEFAULT NULL COMMENT '代码',
      `codedesc` varchar(100) DEFAULT NULL COMMENT '代码描述',
      `enabled` varchar(2) DEFAULT '1' COMMENT '启用状态(0:禁用;1:启用)',
      `sortno` int(4) DEFAULT NULL COMMENT '排序号',
      PRIMARY KEY (`dictid`)
    ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of tb_dict
    -- ----------------------------
    INSERT INTO `tb_dict` VALUES ('1', 'SEX', '性别', '1', '', '1', '1');
    INSERT INTO `tb_dict` VALUES ('2', 'SEX', '性别', '2', '', '1', '2');
    INSERT INTO `tb_dict` VALUES ('3', 'EDU', '学历', '1', '高中', '1', '1');
    INSERT INTO `tb_dict` VALUES ('4', 'EDU', '学历', '3', '本科', '1', '3');
    INSERT INTO `tb_dict` VALUES ('5', 'EDU', '学历', '4', '研究生', '1', '4');
    INSERT INTO `tb_dict` VALUES ('6', 'EDU', '学历', '5', '博士', '1', '5');
    INSERT INTO `tb_dict` VALUES ('7', 'EDU', '学历', '2', '专科', '1', '2');
    
    -- ----------------------------
    -- Table structure for `tb_user`
    -- ----------------------------
    DROP TABLE IF EXISTS `tb_user`;
    CREATE TABLE `tb_user` (
      `user_id` int(11) NOT NULL AUTO_INCREMENT,
      `user_name` varchar(20) DEFAULT NULL COMMENT '姓名',
      `user_sex` varchar(2) DEFAULT NULL COMMENT '性别',
      `user_birthday` date DEFAULT NULL COMMENT '出生日期',
      `user_email` varchar(50) DEFAULT NULL COMMENT '邮箱',
      `user_edu` varchar(2) DEFAULT NULL COMMENT '学历',
      `user_telephone` varchar(30) DEFAULT NULL COMMENT '联系方式',
      `user_address` varchar(100) DEFAULT NULL COMMENT '住址',
      `create_time` datetime DEFAULT NULL COMMENT '创建时间',
      PRIMARY KEY (`user_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;
    
    -- ----------------------------
    -- Records of tb_user
    -- ----------------------------
    INSERT INTO `tb_user` VALUES ('1', '李磊', '1', '1985-01-12', 'lilei123@sina.com', '3', '13211335451', '北京市东城区XXXX', '2017-01-31 18:24:41');
    INSERT INTO `tb_user` VALUES ('2', '张华', '2', '1988-11-15', 'zhanghuajig@163.com', '3', '13811362254', '北京市西城区XXXX', '2017-01-31 18:29:08');
    INSERT INTO `tb_user` VALUES ('3', '王媛媛', '2', '1990-04-06', 'yuanyuan112@sina.com', '3', '13511784568', '北京市西城区XXXX', '2017-01-18 10:30:48');
    INSERT INTO `tb_user` VALUES ('4', '陈迪', '1', '1990-06-16', 'chendi0616@sina.com', '3', '13511697892', '北京市东城区XXXX', '2017-01-10 09:20:50');
    INSERT INTO `tb_user` VALUES ('5', '王海东', '1', '1989-05-23', 'wanghaidong@163.com', '4', '13811981290', '北京市石景山区苹果园XXXXX', '2017-01-12 18:33:31');
    INSERT INTO `tb_user` VALUES ('6', '李雪梅', '2', '1985-05-12', 'lixuemei@163.com', '2', '13911378945', '北京市朝阳区XXX', '2017-01-27 18:34:42');
    INSERT INTO `tb_user` VALUES ('7', '张扬', '1', '1988-04-12', 'zhangyang11@sina.com', '3', '13611651245', '北京市石景山区XXXX', '2017-01-24 18:35:46');
    INSERT INTO `tb_user` VALUES ('8', '赵庆', '1', '1986-05-06', 'zhaoqing56@163.com', '2', '13599632147', '北京市朝阳区XXX', '2017-01-31 18:38:57');
    复制代码

    表结构如下所示:

    四、添加依赖包

    项目主要依赖的jar包有Spring核心包、Spring AOP包、Spring MVC包、MyBatis ORM包、MyBatis-Spring适配包、JSTL、JUnit、Log4j2等,具体的pom.xml文件如下:

    复制代码
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.demo</groupId>
      <artifactId>SSMProDemo</artifactId>
      <packaging>war</packaging>
      <version>0.0.1-SNAPSHOT</version>
      <name>SSMProDemo Maven Webapp</name>
      <url>http://maven.apache.org</url>
      
      <properties>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
          <spring.version>4.3.0.RELEASE</spring.version>
      </properties>
        
      <dependencies>
          <!--Spring框架核心库 -->
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <!-- Spring MVC -->
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-webmvc</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-context-support</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <!-- aspectJ AOP 织入器 -->
          <dependency>
              <groupId>org.aspectj</groupId>
              <artifactId>aspectjweaver</artifactId>
              <version>1.8.9</version>
          </dependency>
          <!--mybatis-spring适配器 -->
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis-spring</artifactId>
              <version>1.3.0</version>
          </dependency>
          <!--Spring java数据库访问包,在本例中主要用于提供数据源 -->
          <dependency>
              <groupId>org.springframework</groupId>
              <artifactId>spring-jdbc</artifactId>
              <version>${spring.version}</version>
          </dependency>
          <!--mysql数据库驱动 -->
          <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
              <version>5.1.38</version>
          </dependency>
          <!--log4j日志包 -->
          <dependency>
              <groupId>org.apache.logging.log4j</groupId>
              <artifactId>log4j-core</artifactId>
              <version>2.6.1</version>
          </dependency>
          <!-- mybatis ORM框架 -->
          <dependency>
              <groupId>org.mybatis</groupId>
              <artifactId>mybatis</artifactId>
              <version>3.4.1</version>
          </dependency>
          <!-- JUnit单元测试工具 -->
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.10</version>
          </dependency>
          <!--c3p0 连接池 -->
          <dependency>
              <groupId>c3p0</groupId>
              <artifactId>c3p0</artifactId>
              <version>0.9.1.2</version>
          </dependency>
          <!-- JSTL -->
          <dependency>
              <groupId>javax.servlet</groupId>
              <artifactId>jstl</artifactId>
              <version>1.2</version>
          </dependency>
          <!-- Servlet核心包 -->
          <dependency>
              <groupId>javax.servlet</groupId>
              <artifactId>javax.servlet-api</artifactId>
              <version>3.0.1</version>
              <scope>provided</scope>
          </dependency>
          <!--JSP -->
          <dependency>
              <groupId>javax.servlet.jsp</groupId>
              <artifactId>jsp-api</artifactId>
              <version>2.1</version>
              <scope>provided</scope>
          </dependency>
          <!-- jackson -->
          <dependency>
              <groupId>com.fasterxml.jackson.core</groupId>
              <artifactId>jackson-core</artifactId>
              <version>2.5.2</version>
          </dependency>
          <dependency>
              <groupId>com.fasterxml.jackson.core</groupId>
              <artifactId>jackson-databind</artifactId>
              <version>2.5.2</version>
          </dependency>
          <!--JSR303 -->
          <dependency>
              <groupId>org.hibernate</groupId>
              <artifactId>hibernate-validator</artifactId>
              <version>5.2.2.Final</version>
          </dependency>
          <!--文件上传 -->
          <dependency>
              <groupId>commons-io</groupId>
              <artifactId>commons-io</artifactId>
              <version>2.4</version>
          </dependency>
          <dependency>
              <groupId>commons-fileupload</groupId>
              <artifactId>commons-fileupload</artifactId>
              <version>1.3.1</version>
          </dependency>
      </dependencies>
      <build>
        <finalName>SSMProDemo</finalName>
      </build>
    </project>
    复制代码

    如果是第一次依赖相关的包,则需要下载时间,请耐心等待,如果下载失败则需要手动下载,下载完成后复制到本地的资源库中。依赖后的项目结果如下:

    五、完成Spring与Mybatis的整合

    1、在src/main/resources目录下新建config.properties文件,用于存放数据库连接信息,文件内容如下:

    复制代码
    mysql.driver=com.mysql.jdbc.Driver
    mysql.url=jdbc:mysql://localhost:3306/ssmdb?useUnicode=true&characterEncoding=utf-8
    mysql.user=root
    mysql.password=root
    mysql.acquireIncrement=5
    mysql.initialPoolSize=10
    mysql.minPoolSize=5
    mysql.maxPoolSize=20
    复制代码

    2、在src/main/resources目录下新建spring-mybatis.xml文件,用于整合MyBatis与Spring,非常关键,具体的内容如下:

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
        
        <!-- 1.引入属性文件 -->
        <context:property-placeholder location="classpath:config.properties" />
        
        <!-- 2.自动扫描service包(自动注入) -->
        <context:component-scan base-package="com.demo.service" />
        
        <!-- ========================================配置数据源========================================= -->
        <!-- 3.配置C3P0数据源 -->  
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"  
            destroy-method="close">
            <!--驱动类名 -->
            <property name="driverClass" value="${mysql.driver}" />
            <!-- url -->
            <property name="jdbcUrl" value="${mysql.url}" />
            <!-- 用户名 -->
            <property name="user" value="${mysql.user}" />
            <!-- 密码 -->
            <property name="password" value="${mysql.password}" />
            <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数 -->
            <property name="acquireIncrement" value="${mysql.acquireIncrement}"></property>
            <!-- 初始连接池大小 -->
            <property name="initialPoolSize" value="${mysql.initialPoolSize}"></property>
            <!-- 连接池中连接最小个数 -->
            <property name="minPoolSize" value="${mysql.minPoolSize}"></property>
            <!-- 连接池中连接最大个数 -->
            <property name="maxPoolSize" value="${mysql.maxPoolSize}"></property>
           
        </bean>  
        
        <!-- ========================================针对myBatis的配置项============================== -->
        <!-- 4.配置sqlSessionFactory -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源以及SQL映射文件 -->
            <!-- 数据源 -->
            <property name="dataSource" ref="dataSource" />
            <!-- sql映射文件路径 -->
            <!-- 自动扫描com/demo/mapping/目录下的所有SQL映射的xml文件, 省掉Configuration.xml里的手工配置
            value="classpath:com/demo/mapping/*.xml"指的是classpath(类路径)下com.demo.mapping包中的所有xml文件 -->
            <property name="mapperLocations" value="classpath:com/demo/mapping/*.xml" />
        </bean>
        
        <!-- 5.配置扫描器  -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <!-- 扫描com.demo.dao这个包以及它的子包下的所有映射接口类 -->
            <property name="basePackage" value="com.demo.dao" />
            <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
        </bean>
        
        <!-- ========================================配置事务============================== -->
        <!-- 6.声明式事务管理 -->
        <!--定义事物管理器,由spring管理事务 -->
        <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!-- 配置数据源 -->
            <property name="dataSource" ref="dataSource" />
        </bean>
    
        <!-- 通知 -->
        <tx:advice id="transactionAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                 <!-- 传播行为 -->
                <tx:method name="add*" propagation="REQUIRED" />
                <tx:method name="append*" propagation="REQUIRED" />
                <tx:method name="save*" propagation="REQUIRED" />
                <tx:method name="update*" propagation="REQUIRED" />
                <tx:method name="modify*" propagation="REQUIRED" />
                <tx:method name="edit*" propagation="REQUIRED" />
                <tx:method name="insert*" propagation="REQUIRED" />
                <tx:method name="delete*" propagation="REQUIRED" />
                <tx:method name="remove*" propagation="REQUIRED" />
                <tx:method name="repair" propagation="REQUIRED" />
    
                <tx:method name="get*" propagation="REQUIRED"  />
                <tx:method name="find*" propagation="REQUIRED" read-only="true" />
                <tx:method name="load*" propagation="REQUIRED" read-only="true" />
                <tx:method name="search*" propagation="REQUIRED" read-only="true" />
                <tx:method name="datagrid*" propagation="REQUIRED" read-only="true" />
    
                <tx:method name="*" propagation="REQUIRED"  />
            </tx:attributes>
        </tx:advice>
        
        <!-- 配置aop  -->
        <aop:config>
            <aop:pointcut id="transactionPointcut" expression="execution(* com.demo.service..*Impl.*(..))" />
            <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />
        </aop:config>
        
    </beans>
    复制代码

    六、整合SpringMVC

    在src/main/java源代码目录下添加Spring MVC配置文件spring-mvc.xml,配置里面的注释也很详细,在此就不说了,主要是自动扫描控制器,视图模式,注解的启动这三个。

    复制代码
    <?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:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/aop   
            http://www.springframework.org/schema/aop/spring-aop-4.3.xsd   
            http://www.springframework.org/schema/beans   
            http://www.springframework.org/schema/beans/spring-beans-4.3.xsd   
            http://www.springframework.org/schema/context   
            http://www.springframework.org/schema/context/spring-context-4.3.xsd   
            http://www.springframework.org/schema/mvc   
            http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd   
            http://www.springframework.org/schema/tx   
            http://www.springframework.org/schema/tx/spring-tx-4.3.xsd" >
        
        <!-- 1.自动扫描包,实现支持注解的IOC  -->
        <!-- 自动扫描该包,使springmvc认为包下用了@Controller注解的类是控制器 -->
        <context:component-scan base-package="com.demo.controller" /> 
        
        <!-- 2.配置注解的处理器映射器和处理器适配器 -->
        <!-- <mvc:annotation-driven /> 是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学者
            快速应用默认配置方案。<mvc:annotation-driven /> 会自动注册DefaultAnnotationHandlerMapping与
            AnnotationMethodHandlerAdapter 两个bean,是spring MVC为@Controllers分发请求所必须的。 -->
        <mvc:annotation-driven />
        
        <!-- 3.Spring MVC不处理静态资源  -->
        <mvc:default-servlet-handler/>
        
        <!-- 4.配置内部视图解析器 -->
          <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/WEB-INF/views/" />
            <property name="suffix" value=".jsp" />
        </bean>
        
        <!--5.配置文件上传解析器 -->
        <!--Spring MVC默认不能识别multipart格式的文件内容 -->
        <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        </bean>
        
    </beans>
    复制代码

    七、配置web.xml文件       web.xml应该是整个项目最重要的配置文件了,不过servlet3.0中已经支持注解配置方式了。在servlet3.0以前每个servlet必须要在web.xml中配置servlet及其映射关系。但是在spring框架中就不用了,因为Spring中是依赖注入(Dependency Injection)的也叫控制反转(Inversion of Control)。但是也要配置一个重要的servlet,就是前端控制器(DispatcherServlet)。配置方式与普通的servlet基本相似,具体内容如下:

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app id="WebApp_ID" version="3.0" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://java.sun.com/xml/ns/javaee" 
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
        http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
        
        <!--  加载spring和mybatis的配置文件 --> 
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-mybatis.xml</param-value>
        </context-param>
          
        <!-- 使用ContextLoaderListener初始化Spring容器 -->
        <!--若没有指定其他参数,默认查找的配置文件位置是:/WEB-INF/applicationContext.xml  -->
        <listener>
            <description>Spring容器加载监听器</description>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        
        <!-- 配置springmvc核心控制器 -->
        <!-- spring MVC servlet -->
        <servlet>
            <servlet-name>SpringMVC</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <description>spring MVC 配置文件路径</description>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
             <!-- 启动动优先级,越小越早加载 -->
            <load-on-startup>1</load-on-startup>
        </servlet>
        <!-- Servlet访问的路径映射,所有的访问都必须经过调度用的前置控制器 -->
        <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
        
        <!--编码过滤器 -->
        <filter>
            <description>字符集过滤器</description>
            <filter-name>encodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <description>字符集编码</description>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
        </filter>
        <!-- 路径映射 -->
        <filter-mapping>
            <filter-name>encodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
          <welcome-file-list>
            <welcome-file>index.jsp</welcome-file>
          </welcome-file-list>
    </web-app>
    复制代码

     八、完善项目结构

    在src/main/java目录下建几个Package,如下图:

    其中controller对应控制层,dao对应持久层,mapping对应SQL映射文件,model对应实体层,service对应业务层。

    九、创建POJO实体类

    在model下面新建三个实体类,分别为用户类(User.java)、字典类(Dict.java)、用户扩展类(UserExtend.java),具体代码如下。

    用户类:

    复制代码
    package com.demo.model;
    
    import org.hibernate.validator.constraints.Email;
    import org.hibernate.validator.constraints.NotEmpty;
    
    public class User {
        
        //用户id
        private int user_id;
        //姓名
        @NotEmpty(message="{user_name.notEmpty}")
        private String user_name;
        //性别
        @NotEmpty(message="{user_sex.notEmpty}")
        private String user_sex;
        //出生日期
        @NotEmpty(message="{user_birthday.notEmpty}")
        private String user_birthday;
        //邮箱
        @NotEmpty(message="{user_email.notEmpty}")
        @Email(message="{user_email.wrong}")
        private String user_email;
        //学历
        @NotEmpty(message="{user_edu.notEmpty}")
        private String user_edu;
        //联系方式
        @NotEmpty(message="{user_telephone.notEmpty}")
        private String user_telephone;
        //住址
        private String user_address;
        
        public int getUser_id() {
            return user_id;
        }
        public void setUser_id(int user_id) {
            this.user_id = user_id;
        }
        public String getUser_name() {
            return user_name;
        }
        public void setUser_name(String user_name) {
            this.user_name = user_name;
        }
        public String getUser_sex() {
            return user_sex;
        }
        public void setUser_sex(String user_sex) {
            this.user_sex = user_sex;
        }
        public String getUser_birthday() {
            return user_birthday;
        }
        public void setUser_birthday(String user_birthday) {
            this.user_birthday = user_birthday;
        }
        public String getUser_email() {
            return user_email;
        }
        public void setUser_email(String user_email) {
            this.user_email = user_email;
        }
        public String getUser_edu() {
            return user_edu;
        }
        public void setUser_edu(String user_edu) {
            this.user_edu = user_edu;
        }
        public String getUser_telephone() {
            return user_telephone;
        }
        public void setUser_telephone(String user_telephone) {
            this.user_telephone = user_telephone;
        }
        public String getUser_address() {
            return user_address;
        }
        public void setUser_address(String user_address) {
            this.user_address = user_address;
        }
        
    }
    复制代码

    字典类:

    复制代码
    package com.demo.model;
    
    public class Dict {
        
        //字典id
        private int dictid;
        //对照字段
        private String field;
        //对照字段名称
        private String fieldname;
        //代码
        private String code;
        //代码描述
        private String codedesc;
        
        public int getDictid() {
            return dictid;
        }
        public void setDictid(int dictid) {
            this.dictid = dictid;
        }
        public String getField() {
            return field;
        }
        public void setField(String field) {
            this.field = field;
        }
        public String getFieldname() {
            return fieldname;
        }
        public void setFieldname(String fieldname) {
            this.fieldname = fieldname;
        }
        public String getCode() {
            return code;
        }
        public void setCode(String code) {
            this.code = code;
        }
        public String getCodedesc() {
            return codedesc;
        }
        public void setCodedesc(String codedesc) {
            this.codedesc = codedesc;
        }
    }
    复制代码

    用户扩展类:

    复制代码
    package com.demo.model;
    
    /**
     * 用户的扩展类
     * @author lixiaoxi
     *
     */
    public class UserExtend extends User{
        
        // 性别描述(对应字典表里的代码描述)
        private String user_sex_desc;
        
        // 学历描述(对应字典表里的代码描述)
        private String user_edu_desc;
        
        public String getUser_sex_desc() {
            return user_sex_desc;
        }
    
        public void setUser_sex_desc(String user_sex_desc) {
            this.user_sex_desc = user_sex_desc;
        }
    
        public String getUser_edu_desc() {
            return user_edu_desc;
        }
    
        public void setUser_edu_desc(String user_edu_desc) {
            this.user_edu_desc = user_edu_desc;
        }
    }
    复制代码

    为了实现校验,在User类的成员变量设置了一些注解信息。

    十、创建Dao层接口(mapper接口)

    在dao层下面新建两个接口文件IUserDao.java和IDictDao.java,具体代码如下:

    复制代码
    package com.demo.dao;
    
    import java.util.List;
    import org.apache.ibatis.annotations.Param;
    
    import com.demo.model.User;
    import com.demo.model.UserExtend;
    
    public interface IUserDao {
        
        /**
         * 查询用户信息并分页
         * @param skip
         * @param size
         * @return
         */
        public List<UserExtend> queryUserPager(@Param("skip") int skip,@Param("size") int size);
        
        /**
         * 查询用户总数
         * @return
         */
        public int queryUserCount();
        
        /**
         * 根据用户id查询用户
         * @param userid
         * @return
         */
        public User queryUserById(int userid);
        
        /**
         * 新增用户
         * @param user
         * @return
         */
        public int insertUser(User user);
        
        /**
         * 修改用户
         * @param user
         * @return
         */
        public int updateUser(User user);
        
        /**
         * 根据用户id删除用户
         * @param user_id
         * @return
         */
        public int deleteUserById(int user_id);
        
        /**
         * 删除多个用户
         * @param userIds
         * @return
         */
        public int deleteUsers(int[] userIds);
    }
    复制代码
    复制代码
    package com.demo.dao;
    
    import java.util.List;
    
    import com.demo.model.Dict;
    
    public interface IDictDao {
        
        /**
         * 根据字段获取字典
         * @param field
         * @return
         */
        public List<Dict> getDictByField(String field);
    }
    复制代码

    十一、创建Mybatis SQL映射文件 在mapping下面创建sql映射文件:

    UserMapper.xml

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper 
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--命名空间应该是对应接口的包名+接口名 -->
    <mapper namespace="com.demo.dao.IUserDao">
        <!--查询用户信息并分页 -->
        <select id="queryUserPager" resultType="com.demo.model.UserExtend">
            select t.user_id,t.user_name,t.user_sex,date_format(t.user_birthday,'%Y-%m-%d')user_birthday,
            t.user_email,t.user_edu,t.user_telephone,t.user_address,p.codedesc as user_sex_desc,
            p1.codedesc as user_edu_desc
            from tb_user t inner join tb_dict p on t.user_sex=p.code and p.field='SEX' 
            inner join tb_dict p1 on t.user_edu = p1.code and p1.field = 'EDU'
            order by t.create_time desc
            limit #{skip},#{size}
        </select>
          
          <!--查询用户总数 -->
        <select id="queryUserCount" resultType="int">
            select count(*) from tb_user
        </select>
        
        <!--根据用户id查询用户 -->
        <select id="queryUserById" parameterType="int" resultType="com.demo.model.User">
            select user_id,user_name,user_sex,date_format(user_birthday,'%Y-%m-%d')user_birthday,
            user_email,user_edu,user_telephone,user_address from tb_user where user_id=#{user_id}
        </select>
        
        <!--新增用户 -->
        <insert id="insertUser" parameterType="com.demo.model.User">
            insert into tb_user(user_name,user_sex,user_birthday,user_email,user_edu,user_telephone,user_address,
                create_time) 
            values(#{user_name},#{user_sex},str_to_date(#{user_birthday},'%Y-%m-%d'),#{user_email},#{user_edu},
                #{user_telephone},#{user_address},now());
        </insert>
        
        <!--编辑用户 -->
        <update id="updateUser" parameterType="com.demo.model.User">
            update tb_user 
            set user_name=#{user_name},user_sex=#{user_sex},user_birthday=str_to_date(#{user_birthday},'%Y-%m-%d'),
            user_email=#{user_email},user_edu=#{user_edu},user_telephone=#{user_telephone},user_address=#{user_address} 
            where user_id=#{user_id}
        </update>
        
        <!--根据用户id删除用户 -->
        <delete id="deleteUserById" parameterType="int">
           delete from tb_user where user_id=#{user_id}
        </delete>
        
        <!--删除多个用户 -->
        <delete id="deleteUsers" parameterType="java.util.List">
           delete from tb_user where user_id in
           <!-- <foreach>标签有循环的功能,可以用来生成有规律的SQL语句,主要属性有:
            item:表示集合每一个元素进行迭代时的别名
            index:表示在迭代过程中,每次迭代到的位置
            open:表示该语句以什么开始
            separator:表示每次迭代之间以什么符号作为分隔
            close:表示该语句以什么结束
            collection:要循环的集合 -->
           <foreach item="item" index="index" collection="array" open="(" separator="," close=")">
               #{item}
             </foreach>
        </delete>
    </mapper>
    复制代码

    DictMapper.xml

    复制代码
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper 
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <!--命名空间应该是对应接口的包名+接口名 -->
    <mapper namespace="com.demo.dao.IDictDao">
        <!--根据字段获取字典 -->
        <select id="getDictByField" parameterType="java.lang.String" resultType="com.demo.model.Dict">
           select code,codedesc from tb_dict 
           where field=#{value} and enabled='1' 
           order by sortno
        </select>
    
    </mapper>
    复制代码

    十二、创建服务层 在包com.demo.service下创建两个接口文件,如下:

    IUserService.java

    复制代码
    package com.demo.service;
    
    import java.util.List;
    
    import com.demo.model.User;
    import com.demo.model.UserExtend;
    
    /**
     * 用户业务接口
     * @author lixiaoxi
     *
     */
    public interface IUserService {
        
        /**
         * 分页
         * @param pageNO
         * @param size
         * @return
         */
        public List<UserExtend> queryUserPager(int pageNO, int size);
        
        /**
         * 查询用户总数
         * @return
         */
        public int queryUserCount();
        
        /**
         * 根据用户id查询用户
         * @param userid
         * @return
         */
        public User queryUserById(int userid);
        
        /**
         * 新增用户
         * @param user
         * @return
         */
        public int insertUser(User user);
        
        /**
         * 修改用户
         * @param user
         * @return
         */
        public int updateUser(User user);
        
        /**
         * 根据用户id删除用户
         * @param user_id
         * @return
         */
        public int deleteUserById(int user_id);
        
        /**
         * 删除多个用户
         * @param userIds
         * @return
         */
        public int deleteUsers(int[] userIds);
    }
    复制代码

    IDictService.java

    复制代码
    package com.demo.service;
    
    import java.util.List;
    
    import com.demo.model.Dict;
    
    /**
     * 字典业务接口
     * @author lixiaoxi
     *
     */
    public interface IDictService {
        
        /**
         * 根据字段获取字典
         * @param field
         * @return
         */
        public List<Dict> getDictByField(String field);
    }
    复制代码

    实现类:

    UserServiceImpl.java

    复制代码
    package com.demo.service.impl;
    
    import java.util.List;
    
    import javax.annotation.Resource;
    import org.springframework.stereotype.Service;
    
    import com.demo.dao.IUserDao;
    import com.demo.model.User;
    import com.demo.model.UserExtend;
    import com.demo.service.IUserService;
    
    @Service
    public class UserServiceImpl implements IUserService{
        
        //自动装配
        @Resource
        private IUserDao userDao;
        
        /**
         * 分页
         */
        public List<UserExtend> queryUserPager(int pageNO, int size) {
            int skip=(pageNO-1)*size;
            return userDao.queryUserPager(skip, size);
        }
        
        /**
         * 查询用户总数
         */
        public int queryUserCount() {
            return userDao.queryUserCount();
        }
        
        /**
         * 根据用户id查询用户
         */
        public User queryUserById(int userid){
            return userDao.queryUserById(userid);
        }
        
        /**
         * 新增用户
         */
        public int insertUser(User user){
            return userDao.insertUser(user);
        }
        
        /**
         * 修改用户
         */
        public int updateUser(User user){
            return userDao.updateUser(user);
        }
        
        /**
         * 根据用户id删除用户
         */
        public int deleteUserById(int user_id){
            return userDao.deleteUserById(user_id);
        }
        
        /**
         * 删除多个用户
         */
        public int deleteUsers(int[] userIds){
            return userDao.deleteUsers(userIds);
        }
    }
    复制代码

    DictServiceImpl.java

    复制代码
    package com.demo.service.impl;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.demo.dao.IDictDao;
    import com.demo.model.Dict;
    import com.demo.service.IDictService;
    
    @Service
    public class DictServiceImpl implements IDictService{
        
        /**
         * 自动装配
         */
        @Autowired
        private IDictDao dictDao;
        /**
         * 根据字段获取字典
         * @param field
         * @return
         */
        public List<Dict> getDictByField(String field){
            return dictDao.getDictByField(field);
        }
    
    }
    复制代码

    十三、完成用户管理功能

    1、用户列表与分页

    在com.demo.controller包下定义UserController控制器,代码如下:

    复制代码
    package com.demo.controller;
    
    import javax.annotation.Resource;
    import javax.validation.Valid;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.servlet.mvc.support.RedirectAttributes;
    
    import com.demo.model.User;
    import com.demo.service.IDictService;
    import com.demo.service.IUserService;
    
    @Controller
    @RequestMapping("/user")
    public class UserController {
         
        @Resource
        private IUserService userService;
        @Autowired
        private IDictService dictService;
         
        /*
         * 用户列表与分页Action
         */
        @RequestMapping("/list")
        public String list(Model model,@RequestParam(required=false,defaultValue="1") int pageNO){
            int size=5;
            model.addAttribute("size",size);
            model.addAttribute("pageNO",pageNO);
            model.addAttribute("count",userService.queryUserCount());
            model.addAttribute("userList", userService.queryUserPager(pageNO, size));
            return "user/list";
        }
    }
    复制代码

    参数size表示每页记录数,pageNO表示当前页号,处于第几页,count表示总记录数。

    在views/user 目录下添加视图list.jsp页面,页面的内容如下:

    复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <link href="<c:url value="/styles/main.css"/>"  type="text/css" rel="stylesheet" />
    <title>用户管理</title>
    </head>
    <body>
        <div class="main">
            <h2 class="title"><span>用户管理</span></h2>
            <form action="deleteUsers" method="post">
            <table border="1" width="100%" class="tab">
                <tr>
                    <th><input type="checkbox" id="chkAll"></th>
                    <th>姓名</th>
                    <th>性别</th>
                    <th>出生日期</th>
                    <th>邮箱</th>
                    <th>学历</th>
                    <th>联系方式</th>
                    <th>家庭住址</th>
                    <th>操作</th>
                </tr>
                <c:forEach var="entity" items="${userList}">
                    <tr>
                        <th><input type="checkbox" name="user_id" value="${entity.user_id}"></th>
                        <td>${entity.user_name}</td>
                        <td>${entity.user_sex_desc}</td>
                        <td>${entity.user_birthday}</td>
                        <td>${entity.user_email}</td>
                        <td>${entity.user_edu_desc}</td>
                        <td>${entity.user_telephone}</td>
                        <td>${entity.user_address}</td>
                        <td>
                        <a href="edit/${entity.user_id}" class="abtn">编辑</a>
                        <a href="deleteUserById/${entity.user_id}" class="abtn">删除</a>
                        </td>
                    </tr>
                </c:forEach>
            </table>
            <div id="pager"></div>
            <p>
                <a href="add" class="abtn out">添加</a>
                <input type="submit"  value="批量删除" class="btn out" onclick="return submitForm();"/>
            </p>
            <p style="color: red">${message}</p>
            <!--分页 -->
            <script type="text/javascript" src="<c:url value="/scripts/jQuery1.11.3/jquery-1.11.3.min.js"/>" ></script>
            <link href="<c:url value="/scripts/pagination22/pagination.css"/>"  type="text/css" rel="stylesheet" />
            <script type="text/javascript" src="<c:url value="/scripts/pagination22/jquery.pagination2.2.js"/>" ></script>
            <script type="text/javascript">
                
                $(document).ready(function(){
                    //全选/取消全选
                    $("#chkAll").click(function(){
                        var checked=$("#chkAll").prop("checked");
                        $("input[name='user_id']").prop("checked",checked);
                    })
                })
            
               //初始化分页组件
               var count=${count};
               var size=${size};
               var pageNO=${pageNO};
               $("#pager").pagination(count, {
                  items_per_page:size,
                   current_page:pageNO-1,
                   next_text:"下一页",
                   prev_text:"上一页",
                   num_edge_entries:2,
                   load_first_page:false,
                  callback:handlePaginationClick
                });
               
               //回调方法
               function handlePaginationClick(new_page_index, pagination_container){
                   location.href="list?pageNO="+(new_page_index+1);
               }
               
               function submitForm(){
                   if($("input[name='user_id']:checked").length==0){
                       alert("请选择要删除的记录!");
                       return false;
                   }
                   return true;
               }
            </script>
        </form>
        </div>
    </body>
    </html>
    复制代码

    为了实现分页,添加了一个jQuery插件pagination,该插件的详细参数如下所示:

    官网
    https://github.com/gbirke/jquery_pagination
    
    jQuery Pagination插件
    参考资料:https://github.com/gbirke/jquery_pagination
    
    jquery paginate插件可以达到我们的要求,使用如下
    
    使用:
    
    1.首先定义一个页码容器
    
    <div id="Pagination"></div>
    
    2.设置属性
    
    $("#Pagination").pagination(122, {
    items_per_page:20,
    callback:handlePaginationClick
    });
    
    3.定义一个相应的回调函数
    
    function handlePaginationClick(new_page_index, pagination_container) {        //new_page_index:页码,从0开始, 
    
    pagination_container:容器对象    return false;}这样就定制了一个简单的分页控件,如需更多功能,请参照如下属性:
    
    callback:回调函数,就是点击页码除法的js事件,如上面定义的handlePaginationClick函数,可以通过ajax读取数据,或者控制数据的显隐
    
    current_page:当前页码
    
    items_per_page:每页的条数,用于计算总页数
    
    link_to:当callback回调函数return true时页码会转到此处定义的链接,其中我们可以用__id__传入页码值
    
    num_display_entries:展示页码的总数,默认为11,如果设置为0则简单的只显示“前一页,后一页”
    
    next_text:下一页文本
    
    next_show_always:是否总显示下一页
    
    prev_text:前一页
    
    prev_show_always:是否总显示前一页
    
    num_edge_entries:显示最前几条,最后几条
    
    load_first_page:初始化插件时是否调用回调函数
    
    
    #我们还可以通过代码调用分页功能:
    $("#News-Pagination").trigger('setPage', [4]);
    // Go to the next page
    $("#News-Pagination").trigger('nextPage');
    // Go to the previous page
    $("#News-Pagination").trigger('prevPage');
    View Code

    测试运行结果:

     2、新增用户

    在控制器中添加两个方法,一个是add用于完成添加页面展示,一个是addSave用于完成添加保存处理,代码如下:

    复制代码
    /**
     * 添加用户
     * @param model
     * @return
     */
    @RequestMapping("/add")
    public String add(Model model){
        // 与form绑定的模型
        model.addAttribute("user",new User());
        // 用于生成“性别”下拉列表
        model.addAttribute("sexList",dictService.getDictByField("SEX"));
        // 用于生成“学历”下拉列表
        model.addAttribute("eduList",dictService.getDictByField("EDU"));
        
        return "user/add";
    }
    
     /**
      * 添加用户保存
      * @param model
      * @param entity
      * @param bindingResult
      * @return
      */
     @RequestMapping("/addSave")
     public String addSave(Model model,@ModelAttribute("user") @Valid User user,BindingResult bindingResult){
        //如果模型中存在错误
        if(!bindingResult.hasErrors()){
            if(userService.insertUser(user)>0){
                return "redirect:/user/list";
            }
        }
        model.addAttribute("user", user);
        // 用于生成“性别”下拉列表
        model.addAttribute("sexList",dictService.getDictByField("SEX"));
        // 用于生成“学历”下拉列表
        model.addAttribute("eduList",dictService.getDictByField("EDU"));
        return "user/add";
     }
    复制代码

    这里有一个问题是因为使用了JSR303校验,当保存对象是需要在参数前注解@ModelAttribute("entity") @Valid,用于激活校验,否则页面将不会有错误展示。

    为了配合Bean Validation,定义的User Bean需要注解,内容如下:

    复制代码
    //姓名
    @NotEmpty(message="{user_name.notEmpty}")
    private String user_name;
    //性别
    @NotEmpty(message="{user_sex.notEmpty}")
    private String user_sex;
    //出生日期
    @NotEmpty(message="{user_birthday.notEmpty}")
    private String user_birthday;
    //邮箱
    @NotEmpty(message="{user_email.notEmpty}")
    @Email(message="{user_email.wrong}")
    private String user_email;
    //学历
    @NotEmpty(message="{user_edu.notEmpty}")
    private String user_edu;
    //联系方式
    @NotEmpty(message="{user_telephone.notEmpty}")
    private String user_telephone;
    复制代码

    这里的错误消息来源一个是直接写在注解中,另一个来自消息文件;{user_name.notEmpty}来自消息文件ValidationMessages.properties,在src/main/resources目录下新建该文件,文件内容如下:

    复制代码
    user_name.notEmpty=姓名不允许为空
    user_sex.notEmpty=性别不允许为空
    user_birthday.notEmpty=出生日期不允许为空
    user_email.notEmpty=邮箱不允许为空
    user_email.wrong=邮箱格式不正确
    user_edu.notEmpty=学历不允许为空
    user_telephone.notEmpty=联系方式不允许为空
    复制代码

    这里需注意的是,默认情况下中文会显示成utf-8编码格式如:

    复制代码
    user_name.notEmpty=u59D3u540Du4E0Du5141u8BB8u4E3Au7A7A
    user_sex.notEmpty=u6027u522Bu4E0Du5141u8BB8u4E3Au7A7A
    user_birthday.notEmpty=u51FAu751Fu65E5u671Fu4E0Du5141u8BB8u4E3Au7A7A
    user_email.notEmpty=u90AEu7BB1u4E0Du5141u8BB8u4E3Au7A7A
    user_email.wrong=u90AEu7BB1u683Cu5F0Fu4E0Du6B63u786E
    user_edu.notEmpty=u5B66u5386u4E0Du5141u8BB8u4E3Au7A7A
    user_telephone.notEmpty=u8054u7CFBu65B9u5F0Fu4E0Du5141u8BB8u4E3Au7A7A
    复制代码

    为了正常显示,可以安装一个插件,让属性文件支持正常显示中文,插件名称是properties-editor,点击“Help”->“Eclipse Marketplace...”,搜索插件名称,显示内容如下:

    点击Installed,进入下一步:

    完成后在properties文件上右键选择“Open With”,具体步骤如下:

    在views/user 目录下添加视图add.jsp页面,页面的内容如下:

    复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <link href="<c:url value="/styles/main.css" />" type="text/css" rel="stylesheet" />
    <script language="javascript" type="text/javascript" 
        src="<c:url value="/scripts/My97DatePicker/WdatePicker.js" />"></script>
    <title>新增用户</title>
    </head>
    <body>
        <div class="main">
            <h2 class="title"><span>新增用户</span></h2>
            <form:form action="addSave" method="post" modelAttribute="user">
            <fieldset>
                <legend>用户</legend>
                <table cellpadding="5" cellspacing="8"> 
                    <tr>
                        <td><label for="user_name">姓名:</label></td>
                        <td><form:input path="user_name" size="40"/></td>
                        <td><form:errors path="user_name" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_sex">性别:</label></td>
                        <td>
                            <form:select path="user_sex" style="100%">
                                 <form:option value="">--请选择--</form:option>
                                 <form:options items="${sexList}"  itemLabel="codedesc" itemValue="code"/>
                            </form:select>
                        </td>
                        <td><form:errors path="user_sex" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_birthday">出生日期:</label></td>
                        <td><form:input path="user_birthday" size="40" class="Wdate" onClick="WdatePicker()"/></td>
                        <td><form:errors path="user_birthday" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_email">邮箱:</label></td>
                        <td><form:input path="user_email" size="40"/></td>
                        <td><form:errors path="user_email" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_edu">学历:</label></td>
                        <td>
                             <form:select path="user_edu" style="100%">
                                 <form:option value="">--请选择--</form:option>
                                 <form:options items="${eduList}"  itemLabel="codedesc" itemValue="code"/>
                            </form:select>
                        </td>
                        <td><form:errors path="user_edu" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_telephone">联系方式:</label></td>
                        <td><form:input path="user_telephone" size="40"/></td>
                        <td><form:errors path="user_telephone" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_address">家庭住址:</label></td>
                        <td><form:input path="user_address" size="40"/></td>
                        <td><form:errors path="user_address" cssClass="error"></form:errors></td>
                    </tr>
                </table>
                <p>
                  <input type="submit" value="保存" class="btn out">
                </p>
            </fieldset>
            <!--<form:errors path="*"></form:errors> -->
            </form:form>
            <p style="color: red">${message}</p>
            <p>
                <a href="<c:url value="/user/list" />"  class="abtn out">返回列表</a>
            </p>
        </div>
    </body>
    </html>
    复制代码

    运行结果:

    3、编辑用户

    与新增用户类似,在控制器下新增两个action,一个用于展示编辑,另一个用于执行编辑后保存,代码如下所示:

    复制代码
     /**
      * 编辑用户
      * @param model
      * @param user_id
      * @return
      */
     @RequestMapping("/edit/{user_id}")
     public String edit(Model model,@PathVariable int user_id){
     
        model.addAttribute("user", userService.queryUserById(user_id));
        // 用于生成“性别”下拉列表
        model.addAttribute("sexList",dictService.getDictByField("SEX"));
        // 用于生成“学历”下拉列表
        model.addAttribute("eduList",dictService.getDictByField("EDU"));
        return "user/edit";
    }
    
    /**
     * 修改用户并保存
     * @param model
     * @param user
     * @param bindingResult
     * @return
     */
    @RequestMapping("/editSave")
    public String editSave(Model model,@ModelAttribute("user") @Valid User user,BindingResult bindingResult){
        //如果模型中存在错误
        if(!bindingResult.hasErrors()){
            if(userService.updateUser(user)>0)
            {
                return "redirect:list";    
            }
        }
        model.addAttribute("user", user);
        model.addAttribute("sexList",dictService.getDictByField("SEX"));
        model.addAttribute("eduList",dictService.getDictByField("EDU"));
        return "/user/edit";
    }
    复制代码

    在views/user 目录下新增加edit.jsp页面,页面的内容如下:

    复制代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
    <%
        String path = request.getContextPath();
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <link href="<c:url value="/styles/main.css" />" type="text/css" rel="stylesheet" />
    <script language="javascript" type="text/javascript" 
        src="<c:url value="/scripts/My97DatePicker/WdatePicker.js" />"></script>
    <title>编辑用户</title>
    <base href="<%=basePath %>" />
    </head>
    <body>
        <div class="main">
            <h2 class="title"><span>编辑用户</span></h2>
            <form:form action="user/editSave" method="post" modelAttribute="user">
            <fieldset>
                <legend>用户</legend>
                <table cellpadding="5" cellspacing="8"> 
                    <tr>
                        <td><label for="user_name">姓名:</label></td>
                        <td><form:input path="user_name" size="40"/></td>
                        <td><form:errors path="user_name" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_sex">性别:</label></td>
                        <td>
                            <form:select path="user_sex" style="100%">
                                 <form:option value="">--请选择--</form:option>
                                 <form:options items="${sexList}"  itemLabel="codedesc" itemValue="code"/>
                            </form:select>
                        </td>
                        <td><form:errors path="user_sex" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_birthday">出生日期:</label></td>
                        <td><form:input path="user_birthday" size="40" class="Wdate" onClick="WdatePicker()"/></td>
                        <td><form:errors path="user_birthday" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_email">邮箱:</label></td>
                        <td><form:input path="user_email" size="40"/></td>
                        <td><form:errors path="user_email" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_edu">学历:</label></td>
                        <td>
                             <form:select path="user_edu" style="100%">
                                 <form:option value="">--请选择--</form:option>
                                 <form:options items="${eduList}"  itemLabel="codedesc" itemValue="code"/>
                            </form:select>
                        </td>
                        <td><form:errors path="user_edu" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_telephone">联系方式:</label></td>
                        <td><form:input path="user_telephone" size="40"/></td>
                        <td><form:errors path="user_telephone" cssClass="error"></form:errors></td>
                    </tr>
                    <tr>
                        <td><label for="user_address">家庭住址:</label></td>
                        <td><form:input path="user_address" size="40"/></td>
                        <td><form:errors path="user_address" cssClass="error"></form:errors></td>
                    </tr>
                </table>
                <p>
                    <form:hidden path="user_id" />
                    <input type="submit" value="保存" class="btn out">
                </p>
            </fieldset>
            <!--<form:errors path="*"></form:errors> -->
            </form:form>
            <p style="color: red">${message}</p>
            <p>
                <a href="<c:url value="/user/list" />"  class="abtn out">返回列表</a>
            </p>
        </div>
    </body>
    </html>
    复制代码

    运行结果:

    4、删除与批量删除用户

         为了实现删除与批量删除功能,修改控制器,增加2个action,deleteUserById请求处理方法用于删除单个记录,deleteUsers用于批量删除记录。rediredtAttributes是为了保持重定向后的message值。

    复制代码
    /**
     * 根据用户id删除用户
     * @param model
     * @param user_id
     * @param pageNO
     * @param redirectAttributes
     * @return
     */
    @RequestMapping("/deleteUserById/{user_id}")
    public String deleteUserById(Model model,@PathVariable int user_id,@RequestParam(required=false,defaultValue="1") int pageNO,
            RedirectAttributes redirectAttributes){
    
        if(userService.deleteUserById(user_id)>0){
            redirectAttributes.addFlashAttribute("message", "删除成功!");
        }else{
            redirectAttributes.addFlashAttribute("message", "删除失败!");
        }
        return "redirect:/user/list?pageNO="+pageNO;
    }
    
    /**
     * 删除多个用户
     * @param model
     * @param userIds
     * @param pageNO
     * @param redirectAttributes
     * @return
     */
    @RequestMapping("/deleteUsers")
    public String deleteUsers(Model model,@RequestParam int[] user_id,@RequestParam(required=false,defaultValue="1") int pageNO,
            RedirectAttributes redirectAttributes){
    
        if(userService.deleteUsers(user_id)>0){
            redirectAttributes.addFlashAttribute("message", "删除成功!");
        }else{
            redirectAttributes.addFlashAttribute("message", "删除失败!");
        }
        return "redirect:/user/list?pageNO="+pageNO;
    }
    复制代码

    运行结果如下所示:

    最终的控制器UserController.java文件内容如下:

    复制代码
    package com.demo.controller;
    
    import javax.annotation.Resource;
    import javax.validation.Valid;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.validation.BindingResult;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.servlet.mvc.support.RedirectAttributes;
    
    import com.demo.model.User;
    import com.demo.service.IDictService;
    import com.demo.service.IUserService;
    
    @Controller
    @RequestMapping("/user")
    public class UserController {
         
        @Resource
        private IUserService userService;
        @Autowired
        private IDictService dictService;
         
        /*
         * 用户列表与分页Action
         */
        @RequestMapping("/list")
        public String list(Model model,@RequestParam(required=false,defaultValue="1") int pageNO){
            int size=5;
            model.addAttribute("size",size);
            model.addAttribute("pageNO",pageNO);
            model.addAttribute("count",userService.queryUserCount());
            model.addAttribute("userList", userService.queryUserPager(pageNO, size));
            return "user/list";
        }
        
        /**
         * 添加用户
         * @param model
         * @return
         */
        @RequestMapping("/add")
        public String add(Model model){
            // 与form绑定的模型
            model.addAttribute("user",new User());
            // 用于生成“性别”下拉列表
            model.addAttribute("sexList",dictService.getDictByField("SEX"));
            // 用于生成“学历”下拉列表
            model.addAttribute("eduList",dictService.getDictByField("EDU"));
            
            return "user/add";
        }
        
         /**
          * 添加用户保存
          * @param model
          * @param entity
          * @param bindingResult
          * @return
          */
         @RequestMapping("/addSave")
         public String addSave(Model model,@ModelAttribute("user") @Valid User user,BindingResult bindingResult){
            //如果模型中存在错误
            if(!bindingResult.hasErrors()){
                if(userService.insertUser(user)>0){
                    return "redirect:/user/list";
                }
            }
            model.addAttribute("user", user);
            // 用于生成“性别”下拉列表
            model.addAttribute("sexList",dictService.getDictByField("SEX"));
            // 用于生成“学历”下拉列表
            model.addAttribute("eduList",dictService.getDictByField("EDU"));
            return "user/add";
         }
         
         /**
          * 编辑用户
          * @param model
          * @param user_id
          * @return
          */
         @RequestMapping("/edit/{user_id}")
         public String edit(Model model,@PathVariable int user_id){
         
            model.addAttribute("user", userService.queryUserById(user_id));
            // 用于生成“性别”下拉列表
            model.addAttribute("sexList",dictService.getDictByField("SEX"));
            // 用于生成“学历”下拉列表
            model.addAttribute("eduList",dictService.getDictByField("EDU"));
            return "user/edit";
        }
        
        /**
         * 修改用户并保存
         * @param model
         * @param user
         * @param bindingResult
         * @return
         */
        @RequestMapping("/editSave")
        public String editSave(Model model,@ModelAttribute("user") @Valid User user,BindingResult bindingResult){
            //如果模型中存在错误
            if(!bindingResult.hasErrors()){
                if(userService.updateUser(user)>0)
                {
                    return "redirect:list";    
                }
            }
            model.addAttribute("user", user);
            model.addAttribute("sexList",dictService.getDictByField("SEX"));
            model.addAttribute("eduList",dictService.getDictByField("EDU"));
            return "/user/edit";
        }
        
        /**
         * 根据用户id删除用户
         * @param model
         * @param user_id
         * @param pageNO
         * @param redirectAttributes
         * @return
         */
        @RequestMapping("/deleteUserById/{user_id}")
        public String deleteUserById(Model model,@PathVariable int user_id,@RequestParam(required=false,defaultValue="1") int pageNO,
                RedirectAttributes redirectAttributes){
    
            if(userService.deleteUserById(user_id)>0){
                redirectAttributes.addFlashAttribute("message", "删除成功!");
            }else{
                redirectAttributes.addFlashAttribute("message", "删除失败!");
            }
            return "redirect:/user/list?pageNO="+pageNO;
        }
        
        /**
         * 删除多个用户
         * @param model
         * @param userIds
         * @param pageNO
         * @param redirectAttributes
         * @return
         */
        @RequestMapping("/deleteUsers")
        public String deleteUsers(Model model,@RequestParam int[] user_id,@RequestParam(required=false,defaultValue="1") int pageNO,
                RedirectAttributes redirectAttributes){
    
            if(userService.deleteUsers(user_id)>0){
                redirectAttributes.addFlashAttribute("message", "删除成功!");
            }else{
                redirectAttributes.addFlashAttribute("message", "删除失败!");
            }
            return "redirect:/user/list?pageNO="+pageNO;
        }
    }
    复制代码
     
  • 相关阅读:
    告别alert,拥抱console
    LeetCode之Max Points on a Line Total
    LeetCode之Maximum Product Subarray
    LeetCode之Reverse Words in a String
    LeetCode之Min Stack
    MySQL之系系统信息函数
    MySQL之日期时间函数
    MysqL之数值函数
    XML文件解析之JDOM解析
    XML文件解析之DOM4J解析
  • 原文地址:https://www.cnblogs.com/yelanggu/p/10024348.html
Copyright © 2011-2022 走看看