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的主要配置文件,在这里主要配置一下内容:

  • 通过context:annotation-config开启Spring注解
  • 通过mvc:annotation-driven开启Spring MVC注解
  • 通过context:component-scan开启自动扫描装配(@Component等)。相关参考文章:
    Spring代码实例系列-06:通过注解@Component、@Controller、@Service和@Repository定义bean
  • 通过mvc:resources定义静态资源,即不需要DispatcherServlet分发的请求。
  • 通过InternalResourceViewResolver配置默认的视图解析器。相关参考文章:
    Spring MVC代码实例系列-04:通过自定义视图(继承InternalResourceView),解析Jsp页面、Html页面

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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/mvchttp://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: hanchaoDate: 2018/2/5Time: 23:03To 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")@ResponseBodypublic 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*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//如果是方法处理if (handler instanceof HandlerMethod){//Java 8 ClockstartTime.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();//设置访问URIsb.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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/txhttp://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 {@Autowiredprivate 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 {@Transactionalvoid curdTest();
}

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

@Service
public class TopicServiceImpl implements TopicService {private static final Logger LOGGER = Logger.getLogger(TopicServiceImpl.class);@Autowiredprivate TopicDao topicDao;/*** <p>简单测试事务注解和增删改查</p>* @author hanchao 2018/2/8 23:45**/@Overridepublic 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 topicwhere 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类型转换成ListList<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 generatorConfigurationPUBLIC "-//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都不是必须的,但是确是常用的。
  • 可以根据项目情况选择取舍。

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

  1. ssm毕设项目基于框架的众筹管理系统f5244(java+VUE+Mybatis+Maven+Mysql+sprnig)

    ssm毕设项目基于框架的众筹管理系统f5244(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + ...

  2. ssm毕设项目计件工资管理系统15ik6(java+VUE+Mybatis+Maven+Mysql+sprnig)

    ssm毕设项目计件工资管理系统15ik6(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HB ...

  3. SSM毕设项目游泳馆管理系统851a0(java+VUE+Mybatis+Maven+Mysql)

    SSM毕设项目游泳馆管理系统851a0(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX( ...

  4. ssm毕设项目酒店管理系统08281(java+VUE+Mybatis+Maven+Mysql+sprnig)

    ssm毕设项目酒店管理系统08281(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBui ...

  5. ssm毕设项目企业门户网站f24qk(java+VUE+Mybatis+Maven+Mysql+sprnig)

    ssm毕设项目企业门户网站f24qk(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBui ...

  6. ssm毕设项目陈氏商城9pd36(java+VUE+Mybatis+Maven+Mysql+sprnig)

    ssm毕设项目陈氏商城9pd36(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuild ...

  7. SSM毕设项目酒店餐饮管理系统ls1a2(java+VUE+Mybatis+Maven+Mysql)

    SSM毕设项目酒店餐饮管理系统ls1a2(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX ...

  8. SSM毕设项目重点实验室sjm8x(java+VUE+Mybatis+Maven+Mysql)

    SSM毕设项目重点实验室sjm8x(java+VUE+Mybatis+Maven+Mysql) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(We ...

  9. ssm毕设项目美容院管理系统jn8j9(java+VUE+Mybatis+Maven+Mysql+sprnig)

    ssm毕设项目美容院管理系统jn8j9(java+VUE+Mybatis+Maven+Mysql+sprnig) 项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBu ...

最新文章

  1. WebSphere安装
  2. Kali Linux 2020.1快速修改root用户密码
  3. python【力扣LeetCode算法题库】121-买卖股票的最佳时机
  4. python 类属性排序_Python实现多属性排序的方法
  5. Apache OpenOffice 下载量突破一亿次
  6. Fiori launchpad里Enter Group name这个tile是怎么配置出来的
  7. 计算机二级考试c语言公共基础知识,全国计算机二级c语言公共基础知识考试内容.doc...
  8. mysql 用户管理系统_mysql 用户管理
  9. FullCalendar 四:FullCalendar应用——新建日程事件
  10. C语言,利用一维数组选择法排序,使学生成绩高低排序(要求输入为负值时输入结束)
  11. java的runtime error_Java常见的运行起异常(runtime exception)
  12. arcgis server site 快速恢复与重建
  13. 方块方舟怎么自建服务器,方块方舟新版更新,玩家可自定义单机局域网数值
  14. 360修复高危漏洞可以修复吗_360提示的高危漏洞要不要修复怎样关闭 - 卡饭网
  15. uniapp 标签打印 笔记
  16. 南洋理工大学“网络安全高级研修班”寒假访学记
  17. Rayson API 框架分析系列之3:RSON序列化格式
  18. 推荐|从云生物科技行业数据安全解决方案
  19. USACO Section 1.2 Broken Necklace
  20. 启动虚拟机异常(完整版)——如果已在 BIOS/固件设置中禁用 Intel VT-x,或主机自更改此设置后从未重新启动,则Intel VT-x处于禁用状态

热门文章

  1. ENVI中基于Modis影像提取NDVI处理步骤
  2. 三百左右的蓝牙耳机哪款好?三百左右的蓝牙耳机推荐
  3. AR127全极低功耗磁控霍尔开关
  4. Ubuntu虚拟机可以上网,可以ping网络,但是无法update和install,显示不能连接或者无网络
  5. 学习Python编程开发,能从事的工作岗位有哪些?
  6. 2020年安全生产监管人员新版试题及安全生产监管人员免费试题
  7. HttpMessageConverter 消息转换器
  8. Java static变量保存在哪?
  9. java集群技术面试的一些知识准备
  10. 云时代运维需收藏的三张武功心法图