搭建Spring MVC + MyBatis项目笔记(一) 框架搭建

最近开始着手做一个基于Spring MVC和MyBatis的项目,把搭建过程记录于此备忘

项目架构简介

目前暂定本项目使用Spring MVC+MyBatis框架,数据库使用MySQL

编排项目目录

项目目录按照标准的webapp目录编排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
src
|-main
|-java <-- 源码
|-resources <-- 配置文件等资源
|-mapper <-- MyBatis mapper
|-log4j2.xml
|-mybatis-config.xml
|-spring-aop.xml
|-spring-dao.xml
|-spring-service.xml
|-spring-web.xml
|-webapp <-- 本项目仅提供RESTful接口,不提供页面
|-WEB-INF
|-web.xml
|-index.jsp
|-test
|-java <-- 测试源码
|-resources <-- 测试用的资源
|-sql <-- 单元测试准备测试数据使用的SQL

编写POM

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>

<!-- Version of dependencies -->
<junit.version>4.12</junit.version>
<h2.version>1.4.197</h2.version>
<spring.version>5.0.8.RELEASE</spring.version>
<mybatis.version>3.4.6</mybatis.version>
<mybatis-spring.version>1.3.2</mybatis-spring.version>
<mysql-connector.version>8.0.12</mysql-connector.version>
<log4j.version>2.11.1</log4j.version>
<hikaricp.version>3.2.0</hikaricp.version>
<fastjson.version>1.2.49</fastjson.version>
<lombok.version>1.18.2</lombok.version>
<aspectj.version>1.9.1</aspectj.version>

</properties>

<dependencies>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>

<!-- H2 Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
<scope>test</scope>
</dependency>

<!-- Spring MVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Spring unit test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>

<!-- MySQL Connector/J -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
</dependency>

<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>

<!-- MyBatis Spring integration -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>

<!-- Hikari connection pool -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>${hikaricp.version}</version>
</dependency>

<!-- Fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>

<!-- Logging -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
</dependency>

<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>

<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>

<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>

</dependencies>

编写MyBatis配置文件

可以参考MyBatis配置文档的Settings部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<settings>
<!-- Globally enables or disables any caches configured in any mapper under this configuration -->
<setting name="cacheEnabled" value="false"/>
<!-- 设定驱动程序等待数据库返回数据的时间,单位为秒 -->
<setting name="defaultStatementTimeout" value="5"/>
<!-- 启用该项后,MyBatis 将会自动完成"大写下划线分割命名"与"驼峰式命名"的互相转换 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 允许JDBC使用自动生成的 Key -->
<setting name="useGeneratedKeys" value="true"/>
</settings>

<!-- Continue editing here -->
</configuration>

编写Spring配置文件

Spring配置文件我将根据其用途,分为数据源配置、service配置、web配置、切面配置四部分

数据源配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?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"
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">

<context:component-scan base-package="com.boris1993.tiebacheckin.model"/>

<!--
这部分配置数据库链接信息
我在这里使用了一个名为“光(Hikari)”的数据库连接池
GitHub repo在:https://github.com/brettwooldridge/HikariCP
-->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/cloudcheckin?useSSL=false"/>
<property name="username" value="tieba"/>
<property name="password" value="tieba"/>
</bean>

<!--
MyBatis-Spring 需要至少定义两样东西:sqlSessionFactory 和至少一个 mapper 接口
文档地址:http://www.mybatis.org/spring/getting-started.html
-->

<!--
配置 sqlSessionFactory bean
因为这里使用的是 Mybatis-Spring,所以 class 指定为 SqlSessionFactoryBean 而不是 SqlSessionFactoryBuilder
文档地址:http://www.mybatis.org/spring/factorybean.html
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 指定 MyBatis 的 XML 配置文件所在位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<!--
配置 MyBatis 到哪里去寻找 type aliases
即通过 model 类的类名自动配置其对应的 type alias
此后在 mapper 中就可以使用其 alias 而不用写 model 类的全限定名
-->
<property name="typeAliasesPackage" value="com.boris1993.tiebacheckin.model"/>
<!-- 配置 mapper 文件的位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>

<!--
配置自动扫描 mapper
在 Quick Start 中,教程提到了使用 MapperFactoryBean 来指明 mapper 对应的各个接口
但实际上,并不需要手动来一个个指定所有的 mapper
MyBatis可以通过 MapperScannerConfigurer 来自动扫描指定包下面所有的接口
文档地址:http://www.mybatis.org/spring/mappers.html#scan 的 MapperScannerConfigurer 部分
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<property name="basePackage" value="com.boris1993.tiebacheckin.dao"/>
</bean>

<!--
启用由 Spring 管理的事务
MyBatis-Spring 允许 MyBatis 参与到 Spring 的事务中
文档地址:http://www.mybatis.org/spring/transactions.html#configuration
-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

</beans>

service配置

service的配置很简单,一个是配置要扫描的包,一个是启用基于注解的配置,启用后就可以使用Spring的@Transactional配置事务

1
2
3
4
5
6
7
8
9
10
11
<?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">

<context:component-scan base-package="com.boris1993.tiebacheckin.service"/>

<tx:annotation-driven/>

</beans>

web配置

web的配置也很简单,一个是启用基于注解的配置,一个是启用default-servlet-handler,一个是配置要扫描的包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<mvc:annotation-driven/>

<!--
启用该配置后,Spring会将静态文件的请求转发到容器的默认 servlet
这样配置后,就可以在 web.xml 中给 DispatcherServlet 指定 mapping 为 "/"
-->
<mvc:default-servlet-handler/>

<context:component-scan base-package="com.boris1993.tiebacheckin.controller"/>

</beans>

切面配置

这里先暂时放上来不完整的配置文件内容,后续内容将随着文章的继续而补全

1
2
3
4
5
6
7
8
9
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

<!-- 在 Spring 中使用基于 AspectJ 的 AOP -->
<aop:aspectj-autoproxy/>

</beans>

编写Log4j2配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="error" name="LoggerConfig" dest="err">
<Properties>
<!--
创建一个名为 filename 的属性,用于给后文的文件输出指定输出位置
${sys:catalina.home} 取到的即是系统变量 $CATALINA_HOME的值
所以当 $CATALINA_HOME 存在时,日志会被写到 $CATALINA_HOME/logs/tiebacheckin.log
否则将写到 /tmp/logs/tiebacheckin.log
-->
<Property name="filename">${sys:catalina.home:-/tmp}/logs/tiebacheckin.log</Property>
</Properties>
<Appenders>
<!-- 创建一个名为 STDOUT 的控制台输出,输出目标为标准输出(stdout) -->
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout charset="UTF-8" pattern="[%-5p] %d %c - %m%n"/>
</Console>
<!-- 创建一个名为 FILE 的文件输出,文件位置使用上文的 filename 属性 -->
<File name="FILE" filename="${filename}" createOnDemand="true">
<PatternLayout charset="UTF-8" pattern="[%-5p] %d %c - %m%n"/>
</File>
</Appenders>
<Loggers>
<Root level="error">
<AppenderRef ref="STDOUT"/>
</Root>
<Logger name="com.boris1993.tiebacheckin" level="info">
<AppenderRef ref="FILE"/>
</Logger>
</Loggers>
</Configuration>

编写web.xml

最后完成web.xml的编写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<web-app>
<display-name>Tieba Cloud Check-in</display-name>

<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<!--
按照规范,各 servlet 的配置文件默认以 ${servlet-name}-servlet.xml 命名
但是因为本项目中 Spring 的配置文件被分成了4个,并没有遵守默认的约定
所以需要显式指定配置文件的位置
-->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-*.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

至此,本项目的骨架搭建完成

系列链接

  • 搭建Spring MVC + MyBatis项目笔记(一) 框架搭建