一、创建Maven工程

使用的编辑器是 IntelliJ IDEA, 点击 File > New > Project,选择 Maven,勾选 Create from archetype,选择 maven-archetype-webapp。

等待 Maven 导入完成初始的包。初始的工程结构只有一个 main 里有一个 webapp 文件夹,里面有些初始内容。我们需要额外创建一些文件夹。

在 main 里分别创建 java、resources 文件夹,并分别 右键 > Mark Directory as > Source Root 和 Resource Root ,标记 java 程序的主文件夹和资源文件夹;返回上一层,在 src 里创建 test 文件夹,在 test 里创建 java 和 resources 文件夹,并分别 右键 > Mark Directory as > Test Source Root 和 Test Resource Root。在 webapp/WEB-INF/ 下创建 static 和 jsp 文件夹,分别存放静态资源和 jsp 网页模板。

完成的结构如下所示:

二、开始整合SSM

首先在 Maven 里导入相关的依赖包

pom.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
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
124
125
126
127
128
129
130
131
132
133
134
135
136
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.2.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>


<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>

Resource 文件夹以外的 xml 文件默认是不会被 IDEA 编译的,需要添加以下代码

pom.xml
1
2
3
4
5
6
7
8
9
10
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>

保存,并等待 Maven 导包完毕。

之后我们就可以在 Resources 文件夹里创建各种配置文件,把刚才我们新建的目录都配置上。

首先是 SpringMVC 的配置

SpringMVC.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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?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">


<!-- 自动扫描该包,使SpringMVC认为包下用了 @Controller 注解的类是控制器 -->
<context:component-scan base-package="com.crazykid.ssm.controller">
<!--只扫描 @Controller 注解-->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<!--去掉 @Service 注解-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

<!--启用注解 让其可以识别注解 @Controller-->
<mvc:annotation-driven />

<!--映射静态资源 比如 localhost/static/1.jpg 会读取文件 src/webapp/WEB-INF/static/1.jpg -->
<mvc:resources mapping="/static/**" location="/WEB-INF/static/"/>

<!-- 让SpringMVC支持请求json,响应json, json与pojo的映射 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"></bean>
</list>
</property>
</bean>

<!-- 定义跳转的文件的前后缀 ,视图模式配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>

然后是 Spring(开启注解)、MyBatis(配置数据源,引用配置文件)

spring-mybatis.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
26
27
28
29
30
31
32
33
34
35
36
37
<?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-4.2.xsd">


<!--自动扫描路径下的bean并注入-->
<context:component-scan base-package="com.crazykid.ssm"/>

<!--配置数据源-->
<!--引用配置文件-->
<context:property-placeholder location="classpath:db.properties"/>
<!--带属性的 bean,指定数据源类-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<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 id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!--配置实体类 自动为 domain 起别名-->
<property name="typeAliasesPackage" value="com.crazykid.ssm.domain"/>
<!--载入 MyBatis 配置-->
<property name="configLocation" value="classpath:mybatis_config.xml"/>
</bean>

<!-- 扫描mapper的interface -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.crazykid.ssm.dao" />
</bean>
</beans>

数据库信息 (使用 test 数据库)

db.properties
1
2
3
4
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=123456

mybatis 配置文件

mybatis_config.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
26
<?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>

<!--集成Log4j-->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>

<!--分页插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
</plugin>
</plugins>

<!--扫描包路径下的mapper xml-->
<mappers>
<package name="com.crazykid.ssm.dao"/>
</mappers>

</configuration>

log4j (日志模块) 的配置文件

log4j.properties
1
2
3
4
5
6
7
8
# 全局日志配置
#log4j.rootLogger=ERROR, stdout
log4j.rootLogger=TRACE, stdout

# 控制台输出
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

最后一步,就是配置整个程序的“访问入口”,在 webapp/WEB-INF/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
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
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>Archetype Created Web Application</display-name>

<!-- Spring和mybatis的配置文件 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:Spring-Mybatis.xml</param-value>
</context-param>


<!--强制转utf-8解决中文乱码-->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>

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

<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<!-- Spring MVC servlet -->
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:SpringMVC.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup> <!-- 启动级别-->
</servlet>

<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
<url-pattern>/</url-pattern>
</servlet-mapping>

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

</web-app>

三、测试

在 webapp/WEB-INF/jsp 下创建 hello.jsp

hello.jsp
1
2
3
4
5
6
7
8
9
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>

在 控制层的包下创建一个 Hello 类

Hello.java
1
2
3
4
5
6
7
8
9
10
11
12
package com.crazykid.ssm.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Hello {
@RequestMapping("/hello")
public String Hello() {
return "hello";
}
}

把 Tomcat 跑起来,浏览器打开 http://localhost:8080/ssmtest/hello (ssmtest为你设置的上下文路径),显示 HelloWorld! 则代表 SpringMVC 配置成功。

接下来测试 MyBatis,在 test 数据库建立 user 表,添加一些数据。

1
2
3
4
5
6
7
8
9
10
USE test;
CREATE TABLE IF NOT EXISTS `user`(
`id` INT UNSIGNED AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
PRIMARY KEY ( `id` )
)ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT INTO USER (name) VALUES ('CrazyKid1');
INSERT INTO USER (name) VALUES ('CrazyKid2');
INSERT INTO USER (name) VALUES ('CrazyKid3');

现在 user 表 应该有如下内容:

id name
1 CrazyKid1
2 CrazyKid2
3 CrazyKid3

创建 pojo 类

User.java
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
package com.crazykid.ssm.domain;

public class User {
private int id;
private String name;

public User() {
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}

编写 mybatis 的一个 mapper

UserMapper.xml
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.crazykid.ssm.dao.UserMapper">
<select id="findAllUsers" resultType="com.crazykid.ssm.domain.User">
select * from user
</select>
</mapper>

编写它的一个实现接口

UserMapper.java
1
2
3
4
5
6
7
8
9
10
11
package com.crazykid.ssm.dao;

import com.crazykid.ssm.domain.User;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserMapper {
List<User> findAllUsers();
}

编写 Service 层的接口

UserService.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.crazykid.ssm.service.impl;

import com.crazykid.ssm.dao.UserMapper;
import com.crazykid.ssm.domain.User;
import com.crazykid.ssm.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;

@Override
public List<User> findAllUsers() {
return userMapper.findAllUsers();
}
}

编写该接口的实现类

UserServiceImpl.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.crazykid.ssm.service.impl;

import com.crazykid.ssm.dao.UserMapper;
import com.crazykid.ssm.domain.User;
import com.crazykid.ssm.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;

@Override
public List<User> findAllUsers() {
return userMapper.findAllUsers();
}
}

编写测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import com.crazykid.ssm.domain.User;
import com.crazykid.ssm.service.impl.UserServiceImpl;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.List;

public class Tester {
private UserServiceImpl userService;

@Test
public void testFindAllUsers() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("Spring-Mybatis.xml");
userService = (UserServiceImpl) context.getBean("userServiceImpl");
List<User> list = userService.findAllUsers();
System.out.println(list);
}
}

输出结果:

看到该提示即代表 Spring + MyBatis 测试成功。

P.S 添加 Spring Test 模块后可以用注解的方式引入xml配置文件,让测试代码看上去更简洁。

pom.xml
1
2
3
4
5
6
7
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.4.RELEASE</version>
<scope>test</scope>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.crazykid.ssm.domain.User;
import com.crazykid.ssm.service.impl.UserServiceImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/Spring-Mybatis.xml")
public class Tester2 {
@Autowired
UserServiceImpl userService;

@Test
public void testFindAllUsers() {
List<User> list = userService.findAllUsers();
System.out.println(list);
}
}

注意:注解测试要求 JUnit 在 4.12 版本以上,@RunWith 注解不可省略,否则会造成无法正常注入,导致空指针异常。


最后放上程序结构图:

代码下载:SSMtest.rar