SSM框架超级详细整合记录:Spring+Spring MVC+MyBatis+Maven+MySQL

版权声明:本文为博主hanchao5272原创文章,转载请注明来源,并留下原文链接地址,谢谢! https://blog.csdn.net/hanchao5272/article/details/79305666

1.前言

本文主要对SSM框架整合的过程进行记录,作为之后参考的依据。

1.1.参考文章

Spring代码实例系列-绪论
Spring MVC代码实例系列-绪论
MyBatis代码实例系列-绪论

1.2.技术简介

在整合的SSM框架中,主要涉及的框架、插件或技术有:

  • Spring:一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
  • Spring MVC:一个用于构建 Web 应用程序的MVC框架(Spring的一个模块),可以替代Struts等等。
  • MyBatis:一个基于Java的持久层框架。
  • Maven:一款流行的项目管理与构建工具。
  • Git:一款流行的版本控制工具。
  • MySQL:一款常用的关系型数据库。
  • IDEA:一款流行的Java开发IDE。
  • .gitignore:Git忽略规则文件,控制不需要添加到版本库的文件。
  • README.md:项目说明。
  • Junit4:一款常用的Java单元测试技术。
  • JunitGenerator:一款IDEA提供的Junit插件。
  • log4j:一款流行的开源日志实现项目,可以控制日志信息输送的目的地是控制台、文件等等。
  • maven-compiler-plugin:可以集成到Maven的编译插件,用于解决IDEA项目刷新jdk回退的问题。
  • tomcat7-maven-plugin:可以集成到Maven的tomcat插件,省去tomcat的下载安装等工作。
  • mybatis-generator-maven-plugin:可以集成到Maven的MyBatis代码生成插件,用于生成MyBatis所需的三类文件。
  • com.haier.hairy.mybatis-generator-core:一个可用的mybatis-generator二次开发jar包。
  • org.github.pagehelper:一款可用的MyBatis分页插件。
  • hibernate-validator:一个表单字段校验jar包。
  • JsonResult:一个以泛型编写的通用的返回json对象的类。
  • ValidationUtils:一个简单的校验工具类。
  • CharacterEncodingFilter:编码过滤器,解决POST请求中文乱码问题。
  • IntrospectorCleanupListener:内存清理监听,放置Spring内存泄漏。

1.3.github

项目中只给出关键代码,如需项目的所有源代码,可以查看GitHub : https://github.com/hanchao5272/myssm

2.SSM整合

2.1.项目初始化

2.1.1.创建项目

在IDEA中:
File–>New–>Project...
–>选择Maven项目
–>Project SDK设置为1.8
–>勾选Create from archetype
–>选中maven-archetype-webapp
–>点击Next
–>录入GroupIdArtifactId
–>点击Next
–>点击Finish
–>等待IDEA完成项目初始化
–>完成项目创建

2.1.2.目录初始化

  1. 添加{project}\src\main\java目录。
  2. 添加{project}\src\test\java目录。
  3. File–>Project structure–>Project Settings–>Modules中,将src\main\java设置为Source Folders,将src\test\java设置为Test Source Folders
  4. 添加{project}\.gitignore文件,并编辑不需要上传至版本库的文件类型。
  5. 添加{project}\README.md文件,并编写项目的基本说明。
  6. Git Bash通过git init完成git初始化。

注意:这里没有配置jdk,是因为后面会通过编译插件maven-compiler-plugin完成jdk配置

2.1.3.pom.xml

这里直接列出完整的pom.xml,主要包括:

  • commons基本jar
  • log4j相关jar
  • servlet相关jar
  • Spring相关jar
  • jackson相关jar
  • hibernate-validator表单验证相关jar
  • MyBatis相关jar
  • mybatis.generator相关jar
  • 分页插件pagehelper相关jar
  • MySql相关jar
  • 单元测试Junit4相关jar

如过不需要某个插件或jar包,请自行移除。

<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>pers.hanchao</groupId>
    <artifactId>myssm</artifactId>
    <packaging>war</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>Spring + Spring MVC + MyBaits + Maven Example</name>
    <url>http://maven.apache.org</url>
    <properties>
        <!--maven基本插件-->
        <!--compiler编译插件-->
        <compiler-plugin.version>3.7.0</compiler-plugin.version>
        <!--tomcat插件-->
        <tomcat-plugin.version>2.2</tomcat-plugin.version>

        <!--公用基本包-->
        <commons-logging.version>1.2</commons-logging.version>
        <commons-lang3.version>3.3.2</commons-lang3.version>
        <commons-io.version>2.4</commons-io.version>
        <commons-fileupload.version>1.3.1</commons-fileupload.version>
        <!--日志包-->
        <log4j.version>1.2.17</log4j.version>

        <!--web基本包-->
        <!--servlet、jsp、jstl包-->
        <servlet-api.version>3.1.0</servlet-api.version>
        <jsp-api.version>2.0</jsp-api.version>
        <jstl.version>1.2</jstl.version>


        <!--Spring/Spring MVC 相关包-->
        <springframework.version>5.0.0.RELEASE</springframework.version>
        <!--JSON与POJO互转:@RequestBody、@ResponseBody-->
        <jackson.version>2.9.0</jackson.version>
        <!--表单验证-->
        <hibernate-validator.version>5.4.1.Final</hibernate-validator.version>

        <!--MyBatis相关包-->
        <mybatis.version>3.4.5</mybatis.version>
        <mybatis-spring.version>1.3.1</mybatis-spring.version>
        <!--MyBatis代码自动生成插件:MyBatis Generator-->
        <mybatis-generator.version>1.3.2</mybatis-generator.version>
        <hairy.mybatis-generator.version>1.0.1</hairy.mybatis-generator.version>
        <!--MyBatis分页查询插件-->
        <pagehelper.version>5.1.2</pagehelper.version>
        <!--数据库包-->
        <mysql.version>5.1.40</mysql.version>

        <!--单元测试包-->
        <junit.version>4.12</junit.version>
    </properties>
    <dependencies>
        <!--基本包-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>${commons-lang3.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>${commons-io.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>${commons-logging.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>${commons-fileupload.version}</version>
        </dependency>

        <!--日志log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>

        <!-- servlet相关jar -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>${jsp-api.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>${jstl.version}</version>
        </dependency>

        <!--Spring相关jar包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${springframework.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!-- Needed for XML View (with JAXB2) -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-oxm</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <!-- Needed for JSON View -->
        <!--jackson 通过@RquestBody传参时,将对象转换成json格式。
        通过@ResponseBody返回值时,将对象转换成json格式-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <!-- 表单验证的jar -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>${hibernate-validator.version}</version>
        </dependency>
        <!--MyBatis框架-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${mybatis.version}</version>
        </dependency>
        <!--mybatis-mvc:将 MyBatis 代码无缝地整合到 Spring 中-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>${mybatis-spring.version}</version>
        </dependency>
        <!--MyBatis代码自动生成插件-->
        <!--MyBatis Generator-->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>${mybatis-generator.version}</version>
        </dependency>
        <!--分页插件-->
        <!--https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/HowToUse.md-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>${pagehelper.version}</version>
        </dependency>
        <!--mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <!--单元测试Junit4-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>myssm</finalName>
        <!-- 插件 -->
        <plugins>
            <!-- 后续章节再讲解 -->
        </plugins>
    </build>
</project>

2.1.4.配置编译插件

在pom.xml中配置编译插件maven-compiler-plugin,如下:

<plugins>
  <!--Maven编译插件:解决属性项目,编译配置回退至jdk1.5的问题-->
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${compiler-plugin.version}</version>
    <configuration>
      <!--开发环境:1.8-->
      <source>1.8</source>
      <!--编译环境:1.8-->
      <target>1.8</target>
      <!--编码方式-->
      <encoding>UTF-8</encoding>
    </configuration>
  </plugin>
</plugins>

2.1.5.配置tomcat插件

在pom.xml中配置tomcat插件tomcat7-maven-plugin,如下:

<plugins>
<!--tomcat插件:集成tomcat,无需手动下载安装tomcat-->
      <plugin>
        <groupId>org.apache.tomcat.maven</groupId>
        <artifactId>tomcat7-maven-plugin</artifactId>
        <version>${tomcat-plugin.version}</version>
        <configuration>
          <path>/</path>
          <port>8080</port>
          <!--解决中文乱码措施之一-->
          <uriEncoding>utf-8</uriEncoding>
        </configuration>
      </plugin>
</plugins>

2.1.6.配置欢迎页

修改web.xml,进行web项目最初始配置:display-name和welcome-file-list,如下:

<web-app 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"
         version="3.0">
  <display-name>Spring + Spring MVC + MyBatis + Maven Web Application</display-name>

  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

2.1.7.运行配置

在IDEA中Edit Run/Debug configurations界面,添加一个Maven配置,修改Name,并将Command line设置为clean tomcat7:run -e,然后保存退出。
这里写图片描述

2.1.8.运行项目

通过点击或快捷键启动项目,在浏览器录入http://localhost:8080/,显示如下页面,证明项目初始化成功。
这里写图片描述

2.2.配置log4j并进行验证

2.2.1.jar包依赖

<!--日志包-->
<log4j.version>1.2.17</log4j.version>

2.2.2.配置log4j

编写main\resources\log4j.properties,如下:

# 日志级别为DEBUG级别,设置两类日志信息存储媒介:控制台和文件
log4j.rootLogger = DEBUG,console,file
# 控制台日志配置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
# 日志文件配置
log4j.appender.file = org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.File = himybatis.log
log4j.appender.file.datePattern = '.'yyyy-MM-dd
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.console.file.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

有关log4j的更详细配置,可以参考:Spring MVC代码实例系列-05:配置Log4j以及 log4j.properties 属性详解

2.2.3.验证log4j

创建pers.hanchao.myssm.test.log4j.Log4jDemo.java,如下

/**
 * <p>测试log4j</p>
 * @author hanchao 2018/2/10 21:11
 **/
public class Log4jDemo {
    private static final Logger LOGGER = Logger.getLogger(Log4jDemo.class);

    public static void main(String[] args) {
         LOGGER.info("Hello World!");
    }
}

运行,控制信息如下:

2018-02-10 21:14:01 INFO  Log4jDemo:12 - Hello World!

这表明log4j配置正确。

2.3.安装JUnitGenerator插件验证junit

2.3.1.jar包依赖

<!--单元测试包-->
<junit.version>4.12</junit.version>

2.3.2.插件安装与配置

JUnitGenerator插件的安装可以参考: IDEA中使用Junit4进行测试的入门配置

2.3.3.验证Junit

编写测试类JunitDemo.java

/**
 * <p>测试junit</p>
 * @author hanchao 2018/2/5 22:03
 **/
public class JunitDemo {
    private static final Logger LOGGER = Logger.getLogger(JunitDemo.class);
    /**
     * <p>加法</p>
     * @author hanchao 2018/2/5 22:02
     **/
    public static int add(int a,int b){
        LOGGER.info(a + b);
        return a + b;

通过Alt+Insert的快捷菜单生成junit4单元测试类:JunitDemoTest.java,进行测试方法修改:

@Test
public void testAdd() throws Exception {
    Assert.assertEquals(2,JunitDemo.add(1,1));
} 

运行测试用例,显示1 test passed,表名Junit4可用。

2.4.初步整合Spring+Spring MVC

本节记录如何配置Spring+Spring MVC。可供参考的文章如下:
Spring MVC代码实例系列-01:Spring MVC项目简单搭建与Hello Wolrd:较为详细的说明了Spring+SpringMVC整合及Spring MVC的工作原理。

2.4.1.jar包依赖

<!--公用基本包-->
<commons-logging.version>1.2</commons-logging.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<commons-io.version>2.4</commons-io.version>

<!--web基本包-->
<!--servlet、jsp、jstl包-->
<servlet-api.version>3.1.0</servlet-api.version>
<jsp-api.version>2.0</jsp-api.version>
<jstl.version>1.2</jstl.version>

<!--Spring/Spring MVC 相关包-->
<springframework.version>5.0.0.RELEASE</springframework.version>
<!--JSON与POJO互转:@RequestBody、@ResponseBody-->
<jackson.version>2.9.0</jackson.version>

2.4.2.配置web.xml

web.xml中关于Spring和Spring MVC的主要配置项:

  • DispatcherServlet:Spring MVC前端分发器,负责控制分发web请求。
  • contextConfigLocation:Spring配置文件配置,读取applicationContext.xml。
  • ContextLoaderListener:Spring 上下文环境监听器。

此外,还有两个不必须但很重要的配置:

  • characterEncodingFilter:编码过滤器,解决post请求中文参数乱码问题。
  • IntrospectorCleanupListener:防止Spring内存溢出监听器。

全部的web.xml配置如下:

<web-app 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"
         version="3.0">
  <display-name>Spring + Spring MVC + MyBatis + Maven Web Application</display-name>
  <!--编码过滤器:解决post请求参数乱码问题-->
  <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>
  </filter>

  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

  <!--Spring MVC前端分发器-->
  <servlet>
    <servlet-name>spring-mvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <!--配置Spring MVC需要加载的文件-->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

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

  <!--Spring 上下文环境监听器-->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!--防止Spring内存溢出监听器-->
  <listener>
    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
  </listener>

  <servlet-mapping>
    <servlet-name>spring-mvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>


  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

2.4.3.配置spring-mvc-servlet.xml

spring-mvc-servlet.xml是Spring MVC的主要配置文件,在这里主要配置一下内容:

spring-mvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!--开启Spring注解-->
    <context:annotation-config/>
    <!--开启Spring MVC注解-->
    <mvc:annotation-driven/>
    <!--开启自动扫描装配-->
    <context:component-scan base-package="pers.hanchao.myssm.*"/>

    <!--静态资源配置:js/css等等,缓存1年(即 : 31536000秒)-->
    <mvc:resources mapping="/static/**" location="/static/" cache-period="31536000"/>

    <!--默认的视图解析器(这里是jsp)-->
    <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="contentType" value="charset=utf-8"/>
        <property name="order" value="10"/>
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

2.4.4.创建applicationContext.xml

创建Spring的主配置文件applicationContext.xml,到这个阶段还是空配置,后续会增加配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/cache"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

</beans>

2.4.5.测试Spring+Spring MVC的整合

编写一个测试Controller,如下:

package pers.hanchao.myssm.test.spring;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * <p>测试Spring 和 Spring MVC的整合</p>
 * @author hanchao 2018/2/5 23:01
 **/
@Controller
public class SpringMVCDemoController {
    @GetMapping("/mvc/test")
    public String mvcTest(Model model){
        model.addAttribute("mvc","Spring + Spring MVC is OK!");
        return "/mvc";
    }
}

编写一个测试jsp,如下:

<%--
  Created by IntelliJ IDEA.
  User: hanchao
  Date: 2018/2/5
  Time: 23:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Spring + Spring MVC test</title>
</head>
<body>
Hi, ${mvc}
<br>
<a href="/index.jsp">返回首页</a>
</body>
</html>

测试结果:
这里写图片描述
测试结果表明Spring和Spring MVC初步整合成功。

2.5.添加表单校验:hibernate-validator

参考文章:
Spring MVC代码实例系列-12:使用自带的validation实现自定义message表单校验
Spring MVC代码实例系列-06:Spring MVC配置Hibernate-Validator以及自定义校验注解
这里使用的是Spring MVC代码实例系列-12所描述的配置方式,能够通过properties文件自定义message信息。
而且,可以通过EL表达式动态加载最大值、最小值之类的信息。

2.5.1.jar包依赖

<!--表单验证-->
<hibernate-validator.version>5.4.1.Final</hibernate-validator.version>

2.5.2.创建Resources Bundle(message资源包)

在src/main/resources/目录下依次创建:
ValidationMessages.properties、ValidationMessages_zh_CN.properties
在IDEA中,能够自动将这两个文件转换成一个Resources Bundle(国际化资源包),如下图所示:
这里写图片描述
ValidationMessages.properties:

# 全局配置/默认配置
user.username.length = 用户名 [${validatedValue}] 的长度必须在{min}至{max}之间!
user.password.length = 密码 [${validatedValue}] 的长度必须在{min}至{max}之间!

ValidationMessages_zh_CN.properties

# 中文(大陆)配置
user.username.length = 用户名 [${validatedValue}] 的长度必须在{min}至{max}之间!
user.password.length = 密码 [${validatedValue}] 的长度必须在{min}至{max}之间!

2.5.3.编写校验示例

编写校验实体类User.java:

public class User {
    /** 用户名 */
    @NotNull
    @Length(min = 5,max = 10, message = "{user.username.length}")
    private String username;

    /** 密码 */
    @NotNull
    @Length(min = 5,max = 10, message= "{user.password.length}")
    private String password;

    //setter getter toString equals&hashCode
}

编写JsonResult.java,以泛型方式装载返回对象

public class JsonResult<E> {
    /** 响应状态 */
    private Integer code = 1;
    /** 响应消息 */
    private String message = "success!";
    /** 响应内容 */
    private List<E> list;

    //setter getter toString equals&hashCode
}

编写ValidationUtils,统一处理校验失败信息:

public class ValidationUtils {

    /**
     * <p>进行校验,如果有错误,将结果赋给jsonResult,并返回false;如果无错误,则返回true</p>
     * @author hanchao 2018/2/7 23:33
     **/
    public static boolean validateAndSetJsonResult(BindingResult bindingResult, JsonResult jsonResult){
        if (bindingResult.hasErrors()){
            StringBuffer errors = new StringBuffer();
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            for (ObjectError objectError : allErrors){
                errors.append(objectError.getDefaultMessage() + "\n");
            }
            jsonResult.setCode(-1);
            jsonResult.setMessage(errors.toString());
            return false;
        }else {
            return true;
        }
    }
}

修改SpringMVCDemoController,编写表单校验测试方法:

    /**
     * <p>简单测试注解、校验和JsonResult</p>
     * @author hanchao 2018/2/7 23:27
     **/
    @PostMapping("/mvc/login")
    @ResponseBody
    public JsonResult<User> loginTest(@Valid @RequestBody User user, BindingResult bindingResult){
        LOGGER.info(user.toString());
        //定义返回值
        JsonResult<User> jsonResult = new JsonResult<User>();
        //表单校验
        if (ValidationUtils.validateAndSetJsonResult(bindingResult,jsonResult)){//如果没错误
            List list = new ArrayList();
            list.add(user);
            jsonResult.setList(list);
        }
        //返回结果
        return jsonResult;
    }

在这里用到了@PostMapping、@ResponseBody、@RequestBody等注解,参考文件:
Spring MVC代码实例系列-03:@PathVariable、@RequestHeader、@RequestParam、@RequestBody等

编写校验测试页面login.jsp:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录测试:注解、校验</title>
</head>
<script type="text/javascript" src="../static/js/jquery-3.2.1.min.js"></script>
<body>
<div>
    <input type="text" value="David" name="username" id="username"/>
    <input type="password" value="123456" name="password" id="password"/>
    <input type="button" value="校验测试" onclick="login()"/>
</div>
</body>
<script type="text/javascript">
    function login() {
        $.ajax({
            type:'POST',
            url:'/mvc/login',
            data:JSON.stringify({username:$('#username').val(),password:$('#password').val()}),
            contentType:'application/json;charset=utf-8',
            success:function (data) {
                alert(data.message);
            },
            error:function (data) {
                alert(data.message);
            }
        });
    }
</script>
</html>

2.5.4.校验结果

这里写图片描述
表明,hibernate-validator配置成功。

2.6.配置Spring MVC拦截器

拦截器是Spring AOP(Aspected-Oriented Programming,面向切面的编程)的一种实现。
拦截器的应用场景有很多,如:日志记录、权限检查、性能监控、通用行为等等。
这里只给出一个简单的方法执行时间拦截器作为测试。如果想了解更多内容,可以参考:
Spring MVC代码实例系列-11:Spring MVC实现简单的权限控制拦截器和请求信息统计拦截器

2.6.1.编写简单的测试拦截器

编写MethodTimeInterceptor,计算每个方法的执行时间:

package pers.hanchao.myssm.test.interceptor;

import org.apache.log4j.Logger;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Clock;

/**
 * 简单的方法执行时间拦截器,用来验证mvc拦截器可用
 * Created by 韩超 on 2018/2/8.
 */
public class MethodTimeInterceptor extends HandlerInterceptorAdapter{
    private final static Logger LOGGER = Logger.getLogger(MethodTimeInterceptor.class);
    private ThreadLocal<Long> startTime = new ThreadLocal<Long>();
    /**
     * <p>Title: 方法执行前记录时间</p>
     * @author 韩超@bksx 2018/2/8 10:20
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果是方法处理
        if (handler instanceof HandlerMethod){
            //Java 8 Clock
            startTime.set(Clock.systemDefaultZone().millis());
        }
        return true;
    }

    /**
     * <p>Title: 方法执行完成计算时间</p>
     * @author 韩超@bksx 2018/2/8 10:20
     */
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        //如果是方法处理
        if (handler instanceof HandlerMethod){
            //获取方法处理时间
            Long useTime = Clock.systemDefaultZone().millis() - startTime.get();
            StringBuffer sb = new StringBuffer();
            //设置访问URI
            sb.append("[URI = ").append(request.getRequestURI());
            //设置请求类型
            sb.append(", type = ").append(request.getMethod());
            //设置用时
            sb.append(", useTime = ").append(useTime).append("ms]");
            LOGGER.info(sb.toString());
        }
    }
}

2.6.2.修改spring-mvc-serlvet.xml

修改spring-mvc-serlvet.xml,通过mvc:interceptor标签配置MehtodTimeInterceptor拦截器,如下:

    <!--拦截器-->
    <mvc:interceptors>
        <!--拦截器示例:计算方法执行时间-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="pers.hanchao.myssm.test.interceptor.MethodTimeInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

2.6.3.测试拦截器

任意运行一个请求,如登录,查看控制台日志如下:

2018-02-10 22:16:04 INFO  MethodTimeInterceptor:49 - [URI = /mvc/login, type = POST, useTime = 297ms]

表明拦截器配置成功。其他更高级的拦截器都按照这个模式进行配置即可。

2.7.配置Spring MVC文件上传

这里只给出简单的文件上传配置,参考文章:
Spring MVC代码实例系列-10:Spring MVC实现简单的文件上传和下载

2.7.1.jar包依赖

<commons-fileupload.version>1.3.1</commons-fileupload.version>

2.7.2.配置spring-mvc-servlet.xml

修改spring-mvc-servlet.xml添加CommonsMultpartResolver,尤其注意:
- maxUploadSize:一次上传文件的最大byte值.
- maxUploadSizePerFile:一个上传文件的最大byte值
.

配置如下:

    <!--上传文件配置-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!--单次上传文件大小限制 : 10 MB-->
        <property name="maxUploadSize" value="10485760"/>
        <!--单个上传文件大小限制 : 1 MB-->
        <property name="maxUploadSizePerFile" value="1048576"/>
        <!--编码格式utf-8-->
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>

2.7.2.测试文件上传

编写上传文件控制器

/**
 * 简单的文件上传:用于展示MultiPartFile
 * Created by 韩超 on 2018/2/8.
 */
@Component
@RequestMapping("file")
public class FileUtilsDemo {
    private final static Logger LOGGER = Logger.getLogger(FileUtilsDemo.class);

    /**
     * <p>Title: 文件上传</p>
     * @author 韩超@bksx 2018/2/8 11:12
     */
    @PostMapping("/upload")
    public String upload(HttpServletRequest request, @RequestBody MultipartFile[] multiFiles,Model model){
        //获取上传根目录
        String uploadRootPath = request.getServletContext().getRealPath("upload");
        LOGGER.info("当前上传文件根路径:" + uploadRootPath);
        File rootFile = new File(uploadRootPath);
        //判断目录是否存在,不存在层级目录
        if (!rootFile.exists()){
            rootFile.mkdirs();
        }
        //设置返回值,默认为成功
        JsonResult jsonResult = new JsonResult();
        //上传目录
        try {
            for (MultipartFile file : multiFiles){
                //如果文件不为空,则可以上传
                if (null != file){
                    File serverFile = new File(rootFile.getAbsolutePath() + File.separator + file.getOriginalFilename());
                    LOGGER.info("当前上传文件路径:" + serverFile.getAbsolutePath());
                    if (serverFile.exists()){
                        serverFile.delete();
                    }
                    file.transferTo(serverFile);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.info("文件上传失败!");
            //设置返回消息为失败
            jsonResult.setCode(-1);
            jsonResult.setMessage("文件上传失败!");
        }
        model.addAttribute("result",jsonResult);
        return "test/file";
    }
}

编写测试jsp页面,尤其注意:

  • enctype=”multipart/form-data”.
  • 文件上传input框的name应该与Controller的传参名一致。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>简单文件上传示例</title>
</head>
<body>
<form method="post" action="/file/upload" enctype="multipart/form-data">
    <input type="file" name="multiFiles"/><br/>
    <input type="file" name="multiFiles"/><br/>
    <input type="file" name="multiFiles"/><br/>
    <input type="submit" value="上传"/>
</form>
<div>
    <h3>code:${code},message:${message}</h3>
</div>
</body>
</html>

测试结果:
这里写图片描述
表明,上传文件可用。

2.8.初步整合MyBatis

参考文章:
MyBatis代码实例系列-05:Mybatis初步整合Spring + Spring MVC框架,实现Web请求实例

2.8.1.通过Spring引入Spring-Mybatis配置

通过修改applicationContext.xml,引入(import)Spring-Mybatis的配置文件:

<!--加载Spring-MyBatis配置文件-->
<import resource="spring-mybatis.xml"/>

2.8.2.spring-mybatis.xml

spring-mybatis.xml依赖于mybatis-spring-x.y.z.jar,能够帮助我们将MyBatis大部分配置无缝地整合到 Spring 中。spring-mybatis.xml的主要配置:

  • 通过属性文件定位器(property-placeholder)读取数据库连接资源文件
  • 配置数据源(dataSource)进行数据库连接
  • 通过会话工厂bean(sqlSessionFactoryBean)配置XML映射文件路径
  • 通过映射扫描配置(MapperScannerConfigurer)配置数据访问层(Dao)路径
  • 通过事务控制(DataSourceTransactionManager)配置Spring事务控制。
  • 通过tx:annotation-driven开启声明式的事务注解

详细配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--通过spring标签加载属性文件-->
    <context:property-placeholder file-encoding="UTF-8" location="classpath:jdbc.properties"/>

    <!--MyBatis配置-->
    <!--配置数据源:DataSource(有没有更好的DataSource??)-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--配置会话工厂bean:SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置MyBatis配置文件-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--配置类型别名,类似于MyBatis配置文件的typeAliases。因为使用的是全名,所以不需要配置-->
        <!--<property name="typeAliasesPackage" value="pers.hanchao.myssm.**.entity"/>-->
        <!--配置数据源,类似于MyBatis配置文件的environment中的DataSource标签-->
        <property name="dataSource" ref="dataSource"/>
        <!--配置映射文件地址,于MyBatis配置文件的mapper-->
        <property name="mapperLocations" value="classpath:mybatis-mapper/*.xml"/>
    </bean>
    <!--配置映射扫描配置:MapperScannerConfigurer-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--配置SqlSessionFactory-->
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
        <!--配置Dao层目录所在-->
        <property name="basePackage" value="pers.hanchao.myssm.**.dao"/>
    </bean>
    <!--配置Spring的事务控制bean-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!--开启基于注解的声明式事务-->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

关于context:property-placeholder的作用,可以参考:
Spring代码实例系列-09:通过Spring PropertyPlaceholderConfigurer将properties配置的属性注入到xml配置文件中

2.8.3.创建jdbc.properties

创建jdbc.properties,用于配置数据库连接信息:

# 数据库连接信息
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/exam?useSSL=false
jdbc.username=root
jdbc.password=******

2.8.4.创建mybatis-config.xml

创建MyBatis的主配置文件mybatis-config.xml,用于配置一些Mybatis的专有配置(目前为空配置):

<?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">
<!--MyBatis的总配置文件-->
<configuration>

</configuration>

2.8.5.测试MyBatis

SQL语句:

drop table topic;
create table `topic`(
    `id` int(5) unsigned not null auto_increment comment '话题',
    `title` varchar(20) not null comment '题目',
    `score` int(3) not null comment '分数',
    `answer` varchar(100) comment '答案',
    primary key(id)
)engine=InnoDB comment='话题' auto_increment=1 default charset=utf8;
insert into topic values(99999,'题目1',100,'你好吗?');

目录结构:

src\main\java\
|   pers.hanchao.myssm.test.curd
|       \---controller
|           \---TopicController.java
|       \---dao
|           \---TopicDao.java
|       \---entity
|           \---TopicEntity.java
|       \---service
|           \---TopicService.java
|           |---impl
|               \---TopicServiceImpl
src\main\resources\
    mybatis-mapper
        \---TopicDao.xml

TopicController.java
控制层,通过@Autowired自动装配接口TopicService,符合设计模式中的面向接口编程

/**
 * <p>简单实例测试Mybatis的事务控制和增删改查</p>
 * @author hanchao 2018/2/8 23:55
 **/
@Controller
public class TopicController {

    @Autowired
    private TopicService topicService;
    /**
     * <p>简单测试增删改查</p>
     * @author hanchao 2018/2/8 23:41
     **/

    @GetMapping("mybatis/curd")
    public String  curdTest(){
        this.topicService.curdTest();
        return "test/curd";
    }
}

TopicService.java
服务接口层,注意:在接口中通过注解@Transactional进行声明式事务控制

public interface TopicService {
    @Transactional
    void curdTest();
}

TopicServiceImpl.java
服务实现层,注意:通过@Autowired自动装配的接口TopicDao并没有显示实现。
因为在TopicService.java已经进行了事务控制,这里不需要再进行注解。

@Service
public class TopicServiceImpl implements TopicService {
    private static final Logger LOGGER = Logger.getLogger(TopicServiceImpl.class);

    @Autowired
    private TopicDao topicDao;

    /**
     * <p>简单测试事务注解和增删改查</p>
     * @author hanchao 2018/2/8 23:45
     **/
    @Override
    public void curdTest() {
        //查询所有
        LOGGER.info("查询所有");
        LOGGER.info(this.topicDao.selectAll());
        //插入一个,查询所有
        System.out.println();
        LOGGER.info("插入一个");
        TopicEntity newTopic = new TopicEntity();
        newTopic.setId(100);
        newTopic.setTitle("新增的标题");
        newTopic.setScore(200);
        newTopic.setAnswer("新增的答案");
        this.topicDao.insert(newTopic);
        LOGGER.info(this.topicDao.selectAll());
        //查询一个
        System.out.println();
        LOGGER.info("查询一个");
        LOGGER.info(this.topicDao.selectByPrimaryKey(99999));
        //修改一个,然后查询
        System.out.println();
        LOGGER.info("修改一个");
        newTopic = new TopicEntity();
        newTopic.setId(1);
        newTopic.setTitle("修改的标题");
        newTopic.setScore(1000);
        newTopic.setAnswer("修改的答案");
        this.topicDao.updateByPrimaryKey(newTopic);
        LOGGER.info(this.topicDao.selectByPrimaryKey(99999));
        //删除一个,然后查询
        System.out.println();
        LOGGER.info("删除一个,然后查询");
        this.topicDao.deleteByPrimaryKey(99999);
        LOGGER.info(this.topicDao.selectByPrimaryKey(99999));
    }
}

TopicDao.java

/**
 * <p>话题Dao</p>
 * @author hanchao 2018/2/8 23:39
 **/
@Repository
public interface TopicDao {
    /**
     * 根据主键删除数据库的记录
     *
     * @param id
     */
    int deleteByPrimaryKey(Integer id);

    /**
     * 插入数据库记录
     *
     * @param record
     */
    int insert(TopicEntity record);

    /**
     * 根据主键获取一条数据库记录
     *
     * @param id
     */
    TopicEntity selectByPrimaryKey(Integer id);

    /**
     * 获取全部数据库记录
     *
     */
    List<TopicEntity> selectAll();

    /**
     * 根据主键来更新数据库记录
     *
     * @param record
     */
    int updateByPrimaryKey(TopicEntity record);
}

TopicEntity.java:

/**
 * <p>话题</p>
 * @author hanchao 2018/2/8 23:33
 **/
public class TopicEntity {
    /**
     * <pre>
     * 话题
     * 表字段 : topic.id
     * </pre>
     */
    private Integer id;

    //other fields
    // setter getter toString equals&hashCode
}

TopicDao.xml
好吧,我承认这里偷懒了,这里是用MBG(后面会讲)生成的代码。

<?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="pers.hanchao.myssm.test.curd.dao.TopicDao">
  <resultMap id="BaseResultMap" type="pers.hanchao.myssm.test.curd.entity.TopicEntity">
    <!--
    @mbggenerated
    -->
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="title" jdbcType="VARCHAR" property="title" />
    <result column="score" jdbcType="INTEGER" property="score" />
    <result column="answer" jdbcType="VARCHAR" property="answer" />
  </resultMap>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    <!--
    @mbggenerated
    -->
    delete from topic
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <!-- 其他方法 -->
</mapper>

测试结果

2018-02-10 22:54:01 INFO  TopicServiceImpl:32 - 查询所有
2018-02-10 22:54:01 INFO  TopicServiceImpl:33 - [TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?], TopicEntity [Hash = -1744284694, id=100000, title=新增的标题, score=200, answer=新增的答案], TopicEntity [Hash = -1744254903, id=100001, title=新增的标题, score=200, answer=新增的答案], TopicEntity [Hash = -1744225112, id=100002, title=新增的标题, score=200, answer=新增的答案]]

2018-02-10 22:54:01 INFO  TopicServiceImpl:45 - 插入一个
2018-02-10 22:54:01 INFO  TopicServiceImpl:52 - [TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?], TopicEntity [Hash = -1744284694, id=100000, title=新增的标题, score=200, answer=新增的答案], TopicEntity [Hash = -1744254903, id=100001, title=新增的标题, score=200, answer=新增的答案], TopicEntity [Hash = -1744225112, id=100002, title=新增的标题, score=200, answer=新增的答案], TopicEntity [Hash = -1744195321, id=100003, title=新增的标题, score=200, answer=新增的答案]]

2018-02-10 22:54:01 INFO  TopicServiceImpl:55 - 查询一个
2018-02-10 22:54:01 INFO  TopicServiceImpl:56 - TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?]

2018-02-10 22:54:01 INFO  TopicServiceImpl:59 - 修改一个
2018-02-10 22:54:01 INFO  TopicServiceImpl:66 - TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?]

2018-02-10 22:54:01 INFO  TopicServiceImpl:69 - 删除一个,然后查询
2018-02-10 22:54:01 INFO  TopicServiceImpl:71 - 
2018-02-10 22:54:02 INFO  MethodTimeInterceptor:49 - [URI = /mybatis/curd, type = GET, useTime = 1100ms]

测试结果,证明MyBatis整合成功。

2.9.实现MyBatis对SQL的打印

参考文章:
MyBatis代码实例系列-02:MyBatis用log4j打印SQL以及MyBatis的事务控制
MyBatis代码实例系列-09:初步整合Spring + Spring MVC框架之后,如何打印MyBatis的SQL语句
实现对MyBatis对SQL的打印在我们开发调试中十分有用,下面对其配置方法进行说明:

2.9.1.修改log4j.propertis

将log4j的日志级别设置为debug或更低级别

log4j.rootLogger = debug,console,file

2.9.2.修改mybatis-config.xml

在MyBatis配置文件中添加setting配置:name="logImpl" value="LOG4J",指定使用log4j作为日志实现:

<configuration>
    <settings>
        <!--指定日志实现方式是log4j-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>
</configuration>

2.9.3.测试结果

2018-02-10 23:14:44 INFO  TopicServiceImpl:55 - 查询一个
2018-02-10 23:14:44 DEBUG SqlSessionUtils:97 - Creating a new SqlSession
2018-02-10 23:14:44 DEBUG SqlSessionUtils:148 - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10e54129] was not registered for synchronization because synchronization is not active
2018-02-10 23:14:44 DEBUG DataSourceUtils:114 - Fetching JDBC Connection from DataSource
2018-02-10 23:14:44 DEBUG DriverManagerDataSource:143 - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/exam?useSSL=false]
2018-02-10 23:14:44 DEBUG SpringManagedTransaction:87 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@294e531c] will not be managed by Spring
2018-02-10 23:14:44 DEBUG selectByPrimaryKey:159 - ==>  Preparing: select id, title, score, answer from topic where id = ? 
2018-02-10 23:14:44 DEBUG selectByPrimaryKey:159 - ==> Parameters: 99999(Integer)
2018-02-10 23:14:44 DEBUG selectByPrimaryKey:159 - <==      Total: 0
2018-02-10 23:14:44 DEBUG SqlSessionUtils:191 - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10e54129]
2018-02-10 23:14:44 DEBUG DataSourceUtils:340 - Returning JDBC Connection to DataSource
2018-02-10 23:14:44 INFO  TopicServiceImpl:56 - 

测试结果证明配置成功。

2.10.配置分页插件PageHelper

参考文章:
MyBatis代码实例系列-10:MyBatis通过PageHelper插件实现分页查询

这里使用的一款开源的MyBatis分页插件:com.github.pagehelper。
GItHub地址:https://github.com/pagehelper/Mybatis-PageHelper

2.10.1.jar包依赖

<!--MyBatis分页查询插件-->
<pagehelper.version>5.1.2</pagehelper.version>

2.10.2.mybatis-config.xml

MyBatis配置文件,添加pagehelper拦截器:

<configuration>
    <plugins>
        <!--分页插件-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!--当pageSize=0时,是否查询全部记录-->
            <property name="pageSizeZero" value="true"/>
            <!--分页合理化参数,当page<=0时,显示第一页;当pageNum>=maxPage时,显示最后一页-->
            <property name="reasonable" value="true"/>
        </plugin>
    </plugins>
</configuration>

2.10.3.修改业务代码

在业务代码中:

  • 在需要分页的查询前,插入PageHelper.startPage(pageNumb,pageSize)
  • 分页查询返回类型为Page,需要手动进行转换

在之前的TopicServiceImpl.java中,进行修改:

 //查询所有
 LOGGER.info("查询所有");
 LOGGER.info(this.topicDao.selectAll());
 //查询所有(分页)
 System.out.println();
 PageHelper.startPage(0,10);
 LOGGER.info("查询所有(分页)");
 //将Page类型转换成List
 List<TopicEntity> topicEntityList = topicDao.selectAll();
 LOGGER.info(topicEntityList);
 //通过lambda表达式输出集合信息
 topicEntityList.forEach(LOGGER::info);

2.10.4.验证

再次运行,控制台信息:

2018-02-10 22:54:01 INFO  TopicServiceImpl:32 - 查询所有
2018-02-10 22:54:01 INFO  TopicServiceImpl:33 - [TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?], TopicEntity [Hash = -1744284694, id=100000, title=新增的标题, score=200, answer=新增的答案], TopicEntity [Hash = -1744254903, id=100001, title=新增的标题, score=200, answer=新增的答案], TopicEntity [Hash = -1744225112, id=100002, title=新增的标题, score=200, answer=新增的答案]]

2018-02-10 22:54:01 INFO  TopicServiceImpl:37 - 查询所有(分页)
2018-02-10 22:54:01 INFO  TopicServiceImpl:40 - Page{count=true, pageNum=1, pageSize=10, startRow=0, endRow=10, total=4, pages=1, reasonable=true, pageSizeZero=true}
2018-02-10 22:54:01 INFO  TopicServiceImpl:1249 - TopicEntity [Hash = 1936880702, id=99999, title=题目1, score=100, answer=你好吗?]
2018-02-10 22:54:01 INFO  TopicServiceImpl:1249 - TopicEntity [Hash = -1744284694, id=100000, title=新增的标题, score=200, answer=新增的答案]
2018-02-10 22:54:01 INFO  TopicServiceImpl:1249 - TopicEntity [Hash = -1744254903, id=100001, title=新增的标题, score=200, answer=新增的答案]
2018-02-10 22:54:01 INFO  TopicServiceImpl:1249 - TopicEntity [Hash = -1744225112, id=100002, title=新增的标题, score=200, answer=新增的答案]

经验证,分页插件可用。

2.11.配置MyBatis Generator

参考文章:
MyBatis代码实例系列-08:MyBatisGenerator插件及扩展(中文注释和Mapper重命名为Dao)

在使用MyBatis框架进行开发时,每用到一张表就要手动创建实体类、XML映射文件和映射接口,这些都是重复性工作,耗费了我们大量精力。
MyBatis Generator (简称MBG) 是一个Mybatis的代码生成器。它可以根据数据库中的表,生成对应的实体类、XML映射文件和映射接口,节约了大量的时间去开发和业务逻辑有关的功能。
当然,如果是多表联合查询和存储过程,仍然需要手动处理。

2.11.1.将开源jar包添加到本地仓库

git clone

git clone git@github.com:li24361/mybatis-generator-core.git

mvn install

mvn install -Dmaven.test.skip=true

2.11.2.jar包依赖

<!--MyBatis代码自动生成插件:MyBatis Generator-->
<mybatis-generator.version>1.3.2</mybatis-generator.version>
<hairy.mybatis-generator.version>1.0.1</hairy.mybatis-generator.version>

2.11.3.pom.xml插件

说明:

  • mybatis-generator-maven-plugin是原生的MBG插件。
  • com.haier.hairy.mybatis-generator-core是对MBG一个开源扩展,实现了中文注释等。
 <!--MyBatis Generator插件:根据数据库表结构,自动生成MyBatis所需的实体类、Dao层接口和映射XML文件-->
 <plugin>
     <groupId>org.mybatis.generator</groupId>
     <artifactId>mybatis-generator-maven-plugin</artifactId>
     <version>${mybatis-generator.version}</version>
     <dependencies>
         <!--添加MySql依赖-->
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <version>${mysql.version}</version>
         </dependency>
         <!--添加MyBatis-generator扩展包,将生成结果扩展为XxxDao.xml/XxxDao.java/XxxEntity.java+中文注释。
         可以移除,移除之后为原版MyBatis-generator,生成:XxxMapper.xml/XxxMapper.java/Mxx.java+英文注释。-->
         <dependency>
             <groupId>com.haier.hairy</groupId>
             <artifactId>mybatis-generator-core</artifactId>
             <version>${hairy.mybatis-generator.version}</version>
         </dependency>
     </dependencies>
     <configuration>
         <!--MyBaits-generator的配置文件generatorConfig.xml的位置-->
         <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
         <!--是否覆盖同名文件(只是针对XML文件,java文件生成类似*.java.1、*.java.2形式的文件)-->
         <overwrite>true</overwrite>
         <!--是否将生成过程输出至控制台-->
         <verbose>true</verbose>
     </configuration>
 </plugin>

2.11.4.配置generatorConfig.xml

修改MBG的配置文件:generatorConfig.xml。主要配置项:

  • 通过properties配置jdbc的属性文件
  • 将生成目标定为MyBatis3Simple,不需要example方法
  • 通过Delimiter配置表名区分分隔符
  • 通过plugin生成实体类的toString、equals和hashCode方法
  • 通过commentGenerator配置自定义类,生成中文注释
  • 通过jdbcConnection配置数据库连接信息
  • 通过javaModelGenerator配置实体类的生成配置
  • 通过sqlMapGenerator配置XML映射文件的生成配置
  • 通过javaClientGenerator配置Dao层类的生成配置
  • 通过table配置需要生成的schema、table和pk

详细配置:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!--
MyBatis-generator配置文件:配置数据源、生成目录、方式等。
properties?,classPathEntry*,context+
-->
<generatorConfiguration>
    <!--配置数据库连接、MyBatis-Generator资源文件-->
    <properties resource="jdbc.properties"/>
    <!--
    property*,plugin*,commentGenerator?,jdbcConnection,
    javaTypeResolver?,javaModelGenerator,sqlMapGenerator?,javaClientGenerator?,
    table+
    -->
    <!--MyBatis3Simple:兼容MyBatis3.0或更高版本,无Example方法。
    DefaultModelType=true:每张表一个实体类,包含所有字段。-->
    <context id="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <!--区分表名的分隔符,MySql为`table_name`,oracle为"table_name"-->
        <property name="beginningDelimiter" value="${mgb.table.delimiter}"/>
        <property name="endingDelimiter" value="${mgb.table.delimiter}"/>

        <!--生成的实体类自动添加的方法:toString、equals和hashCode-->
        <plugin type="org.mybatis.generator.plugins.ToStringPlugin"/>
        <plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"/>

        <!--注释配置,这里使用的Hairy提供的注释类,用于生成中文注释,可以去掉-->
        <commentGenerator type="org.mybatis.generator.internal.HairyCommentGenerator">
            <!--HairyCommentGenerator提供的属性,可以去掉-->
            <property name="javaFileEncoding" value="UTF-8"/>
            <!--是否抑制生成所有注释,默认为false-->
            <property name="suppressAllComments" value="${mgb.comment.suppress.all}"/>
            <!--是否抑制生成注释时间,默认为false-->
            <property name="suppressDate" value="${mgb.comment.suppress.date}"/>
        </commentGenerator>

        <!--数据库连接信息-->
        <jdbcConnection driverClass="${jdbc.driverClassName}"
                        connectionURL="${jdbc.url}"
                        userId="${jdbc.username}"
                        password="${jdbc.password}">
        </jdbcConnection>

        <!--Java实体类(XxxxEntity.java)生成配置 targetProject+targetPackage构成全路径-->
        <javaModelGenerator targetPackage="${mgb.entity.package}" targetProject="${mgb.entity.project}">
            <!--是否允许建立子包(对应MySql的scheme)-->
            <property name="enableSubPackages" value="${mgb.enableSubPackages}"/>
            <!--是否对查询结果进行Trim()操作,如return this.username.trim();-->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!--XML映射文件(XxxxDao.xml)生成配置 targetProject+targetPackage构成全路径-->
        <sqlMapGenerator targetPackage="${mgb.xml.package}" targetProject="${mgb.xml.project}">
            <!--是否允许建立子包(对应MySql的scheme)-->
            <property name="enableSubPackages" value="${mgb.enableSubPackages}"/>
        </sqlMapGenerator>

        <!--JavaDao层接口(XxxxDao.java)生成配置 targetProject+targetPackage构成全路径-->
        <javaClientGenerator targetPackage="${mgb.dao.package}" targetProject="${mgb.dao.project}" type="XMLMAPPER">
            <!--是否允许建立子包(对应MySql的scheme)-->
            <property name="enableSubPackages" value="${mgb.enableSubPackages}"/>
        </javaClientGenerator>

        <!--数据库对应关系配置:配置要生成的schema、table-->
        <table schema="exam" tableName="apple">
            <!--将命名为*id的字段生成为主键-->
            <generatedKey column="id" sqlStatement="MySql"/>
        </table>
    </context>
</generatorConfiguration>

2.11.5.修改jdbc.properties

修改jdbc.properties,添加MBG相关配置:

# MyBatis Generator配置信息
## 表名分隔符
mgb.table.delimiter=`
## 注释抑制配置
mgb.comment.suppress.all=false
mgb.comment.suppress.date=true
## 是否运行根据schema创建子包
mgb.enableSubPackages=true
## entity配置
mgb.entity.project=src\\main\\java
mgb.entity.package=pers.hanchao.myssm.generator.entity
## Dao配置
mgb.dao.project=src\\main\\java
mgb.dao.package=pers.hanchao.myssm.generator.dao
## XML配置
mgb.xml.project=src\\main\\resources
mgb.xml.package=generator

2.11.6.构建测试

构建命令:

mybatis-generator:generate

构建结果:

src\main\java\
|   pers.hanchao.myssm.test.curd
|       \---dao
|           \---AppleDao.java
|       \---entity
|           \---AppleEntity.java
src\main\resources\
    generator
        \---AppleDao.xml

测试成功!

3.总结

全部整合过程:

  1. 目录初始化
  2. 配置log4j并进行验证
  3. 安装JUnitGenerator插件验证junit
  4. 初步整合Spring+Spring MVC
  5. 添加表单校验:hibernate-validator
  6. 配置Spring MVC拦截器
  7. 配置Spring MVC文件上传
  8. 初步整合MyBatis
  9. 实现MyBatis对SQL的打印
  10. 配置分页插件PageHelper
  11. 配置MyBatis Generator

其中,

  • 只有第1、4、8步骤是整合SSM的必须步骤。
  • 第2、3、5、6、7、9、10、11都不是必须的,但是确是常用的。
  • 可以根据项目情况选择取舍。

没有更多推荐了,返回首页