标签:
我个人比较喜欢写注释,在工作中对注释的重要性看的也比较高,所以大部分文字都在注释中,代码外的文字会写的偏少,关键能懂就行
先看一下整合后的工程目录(单工程,多工程以后会采用maven)

5个package分别对应 action, entity, mapper(也就是DAO,采用动态代理), service, service 实现类
resources 下 相关资源文件:
db.properties: 数据库连接参数
log4j.properties: 日志
applicationContext-dao.xml: spring 和 mybatis 整合的一些配置(sqlSessionFactory,mapper 配置)
applicationContext-service.xml: 业务
applicationContext.xml: spring 核心配置文件(配置一些公用的内容,比如数据源,事务)
springmvc.xml: springmvc 全局配置文件
SqlMapConfig.xml: mybatis 全局配置文件
webapp结构简单就不多说了
下面先贴出maven的pom内容:
1 <?xml version="1.0" encoding="UTF-8"?>
2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <groupId>com.lee</groupId>
6 <artifactId>ssm</artifactId>
7 <name>maven-ssm-hello</name>
8 <packaging>war</packaging>
9 <version>1.0.0-BUILD-SNAPSHOT</version>
10 <properties>
11 <java-version>1.7</java-version>
12 <org.springframework-version>3.2.3.RELEASE</org.springframework-version>
13 <org.aspectj-version>1.6.10</org.aspectj-version>
14 <org.slf4j-version>1.6.6</org.slf4j-version>
15 </properties>
16
17 <dependencies>
18 <!-- Spring -->
19 <dependency>
20 <groupId>org.springframework</groupId>
21 <artifactId>spring-context</artifactId>
22 <version>${org.springframework-version}</version>
23 <exclusions>
24 <!-- Exclude Commons Logging in favor of SLF4j -->
25 <exclusion>
26 <groupId>commons-logging</groupId>
27 <artifactId>commons-logging</artifactId>
28 </exclusion>
29 </exclusions>
30 </dependency>
31 <dependency>
32 <groupId>org.springframework</groupId>
33 <artifactId>spring-webmvc</artifactId>
34 <version>${org.springframework-version}</version>
35 </dependency>
36 <dependency>
37 <groupId>org.springframework</groupId>
38 <artifactId>spring-jdbc</artifactId>
39 <version>${org.springframework-version}</version>
40 </dependency>
41
42 <!-- data source: dbcp -->
43 <dependency>
44 <groupId>commons-dbcp</groupId>
45 <artifactId>commons-dbcp</artifactId>
46 <version>1.4</version>
47 </dependency>
48
49
50 <!-- AspectJ -->
51 <dependency>
52 <groupId>org.aspectj</groupId>
53 <artifactId>aspectjrt</artifactId>
54 <version>${org.aspectj-version}</version>
55 </dependency>
56
57 <!-- Logging -->
58 <dependency>
59 <groupId>org.slf4j</groupId>
60 <artifactId>slf4j-api</artifactId>
61 <version>${org.slf4j-version}</version>
62 </dependency>
63 <dependency>
64 <groupId>org.slf4j</groupId>
65 <artifactId>jcl-over-slf4j</artifactId>
66 <version>${org.slf4j-version}</version>
67 <scope>runtime</scope>
68 </dependency>
69 <dependency>
70 <groupId>org.slf4j</groupId>
71 <artifactId>slf4j-log4j12</artifactId>
72 <version>${org.slf4j-version}</version>
73 <scope>runtime</scope>
74 </dependency>
75 <dependency>
76 <groupId>log4j</groupId>
77 <artifactId>log4j</artifactId>
78 <version>1.2.15</version>
79 <exclusions>
80 <exclusion>
81 <groupId>javax.mail</groupId>
82 <artifactId>mail</artifactId>
83 </exclusion>
84 <exclusion>
85 <groupId>javax.jms</groupId>
86 <artifactId>jms</artifactId>
87 </exclusion>
88 <exclusion>
89 <groupId>com.sun.jdmk</groupId>
90 <artifactId>jmxtools</artifactId>
91 </exclusion>
92 <exclusion>
93 <groupId>com.sun.jmx</groupId>
94 <artifactId>jmxri</artifactId>
95 </exclusion>
96 </exclusions>
97 <scope>runtime</scope>
98 </dependency>
99
100 <!-- @Inject -->
101 <dependency>
102 <groupId>javax.inject</groupId>
103 <artifactId>javax.inject</artifactId>
104 <version>1</version>
105 </dependency>
106
107 <!-- Servlet -->
108 <dependency>
109 <groupId>javax.servlet</groupId>
110 <artifactId>servlet-api</artifactId>
111 <version>2.5</version>
112 <scope>provided</scope>
113 </dependency>
114 <dependency>
115 <groupId>javax.servlet.jsp</groupId>
116 <artifactId>jsp-api</artifactId>
117 <version>2.1</version>
118 <scope>provided</scope>
119 </dependency>
120 <dependency>
121 <groupId>javax.servlet</groupId>
122 <artifactId>jstl</artifactId>
123 <version>1.2</version>
124 </dependency>
125
126 <!-- mybatis -->
127 <dependency>
128 <groupId>org.mybatis</groupId>
129 <artifactId>mybatis</artifactId>
130 <version>3.2.3</version>
131 </dependency>
132 <dependency>
133 <groupId>org.mybatis</groupId>
134 <artifactId>mybatis-spring</artifactId>
135 <version>1.2.3</version>
136 </dependency>
137 <dependency>
138 <groupId>mysql</groupId>
139 <artifactId>mysql-connector-java</artifactId>
140 <version>5.1.38</version>
141 </dependency>
142
143 <!-- Test -->
144 <dependency>
145 <groupId>junit</groupId>
146 <artifactId>junit</artifactId>
147 <version>4.7</version>
148 <scope>test</scope>
149 </dependency>
150
151 <dependency>
152 <groupId>com.alibaba</groupId>
153 <artifactId>druid</artifactId>
154 <version>1.0.18</version>
155 </dependency>
156
157 <dependency>
158 <groupId>org.aspectj</groupId>
159 <artifactId>aspectjweaver</artifactId>
160 <version>1.7.2</version>
161 </dependency>
162 <dependency>
163 <groupId>com.alibaba</groupId>
164 <artifactId>fastjson</artifactId>
165 <version>1.1.34</version>
166 </dependency>
167 <dependency>
168 <groupId>com.fasterxml.jackson.core</groupId>
169 <artifactId>jackson-core</artifactId>
170 <version>2.2.2</version>
171 </dependency>
172 <dependency>
173 <groupId>com.fasterxml.jackson.core</groupId>
174 <artifactId>jackson-databind</artifactId>
175 <version>2.2.2</version>
176 </dependency>
177
178 </dependencies>
179
180 <build>
181 <plugins>
182 <plugin>
183 <artifactId>maven-eclipse-plugin</artifactId>
184 <version>2.9</version>
185 <configuration>
186 <additionalProjectnatures>
187 <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
188 </additionalProjectnatures>
189 <additionalBuildcommands>
190 <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
191 </additionalBuildcommands>
192 <downloadSources>true</downloadSources>
193 <downloadJavadocs>true</downloadJavadocs>
194 </configuration>
195 </plugin>
196
197 <plugin>
198 <groupId>org.apache.maven.plugins</groupId>
199 <artifactId>maven-compiler-plugin</artifactId>
200 <version>2.5.1</version>
201 <configuration>
202 <source>1.7</source>
203 <target>1.7</target>
204 <compilerArgument>-Xlint:all</compilerArgument>
205 <showWarnings>true</showWarnings>
206 <showDeprecation>true</showDeprecation>
207 </configuration>
208 </plugin>
209
210 <plugin>
211 <groupId>org.codehaus.mojo</groupId>
212 <artifactId>exec-maven-plugin</artifactId>
213 <version>1.2.1</version>
214 <configuration>
215 <mainClass>org.test.int1.Main</mainClass>
216 </configuration>
217 </plugin>
218 </plugins>
219 </build>
220 </project>
相关资源文件:
SqlMapConfig.xml
1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE configuration 3 PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-config.dtd"> 5 <configuration> 6 7 <!-- 定义别名 --> 8 <typeAliases> 9 <!-- 批量别名定义 10 name:指定包名,将包下边的所有pojo定义别名 ,别名为类名(首字母大写或小写都行) 11 --> 12 <package name="com.mybatis.bean"/> 13 </typeAliases> 14 15 </configuration>
applicationContext-dao.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 6 <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean"> 7 <!-- 数据源 --> 8 <property name="dataSource" ref="dataSource" /> 9 <!-- 配置SqlMapConfig.xml --> 10 <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" /> 11 </bean> 12 13 <!-- 14 使用mapper 批量扫描器扫描mapper接口 15 不需要id,规则:mapper.xml 与 mapper.java 同名并且在同一个包下 16 扫描出来的mapper会自动向spring容器中注册,bean的id就是类名(首字母小写) 17 --> 18 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 19 <!-- 配置会话工厂 --> 20 <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property> 21 <!-- 22 扫描包的路径 23 如果有多个mapper的包,那就用半角的 ‘,‘ 来隔开 24 --> 25 <property name="basePackage" value="com.lee.ssm.dao.mapper"></property> 26 </bean> 27 28 </beans>
applicationContext-service.xml(如果喜欢使用注释来配置,这个文件可以不用)
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 6 <!-- 用户管理 --> 7 <!-- <bean id="userService" class="com.lee.ssm.service.impl.UserServiceImpl" /> --> 8 </beans>
applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?>
2 <beans xmlns="http://www.springframework.org/schema/beans"
3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 xmlns:context="http://www.springframework.org/schema/context"
5 xmlns:tx="http://www.springframework.org/schema/tx"
6 xmlns:aop="http://www.springframework.org/schema/aop"
7 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
9 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
10 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
11
12 <!-- 加载配置文件 -->
13 <context:property-placeholder location="classpath:db.properties" />
14 <!-- 使用第三方的数据库连接池dbcp -->
15 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
16 <property name="driverClassName" value="${jdbc.driver}" />
17 <property name="url" value="${jdbc.url}" />
18 <property name="username" value="${jdbc.username}" />
19 <property name="password" value="${jdbc.password}" />
20 <!-- 开发阶段数据库最大连接数建议设置小一点够用即可,设置为3 ***发布的时候要开*** -->
21 <property name="maxActive" value="${jdbc.maxActive}" />
22 <property name="maxIdle" value="${jdbc.maxIdle}" />
23 </bean>
24
25 <!-- 事务管理器
26 mybatis使用jdbc事务管理
27 -->
28 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
29 <!-- 数据源 -->
30 <property name="dataSource" ref="dataSource"/>
31 </bean>
32
33 <!-- 通知 -->
34 <tx:advice id="txAdvice" transaction-manager="transactionManager">
35 <!--
36 配置传播行为
37 七种配置 - Spring中Propagation类的事务属性:
38 REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
39 SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
40 MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
41 REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
42 NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
43 NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
44 NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
45 **这个配置将影响数据存储,必须根据情况选择。
46 -->
47 <tx:attributes>
48 <!--
49 name: 目标方法的范围, 例如: save* 就是以save开头的所有方法名(saveUser, saveStudent...)
50 isolation: 数据库隔离级别, 一般都是默认default, 有脏读幻读不可重复读等, 设置后会对数据库性能有一定的影响
51 read-only: true只读事务 false读写事务
52 propagation: 事务的传播属性, 可以解决事务的嵌套问题
53 -->
54 <tx:method name="save*" propagation="REQUIRED"/>
55 <tx:method name="insert*" propagation="REQUIRED"/>
56 <tx:method name="update*" propagation="REQUIRED"/>
57 <tx:method name="delete*" propagation="REQUIRED"/>
58 <tx:method name="display*" propagation="REQUIRED"/>
59 <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
60 <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
61 <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
62 </tx:attributes>
63 </tx:advice>
64
65 <!-- aop配置 -->
66 <aop:config>
67 <!-- aop通知 -->
68 <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lee.ssm.service.impl.*.*(..))"/>
69 </aop:config>
70
71 </beans>
springmvc.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans:beans xmlns="http://www.springframework.org/schema/mvc" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:beans="http://www.springframework.org/schema/beans" 5 xmlns:context="http://www.springframework.org/schema/context" 6 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd 7 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 8 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> 9 10 <!-- 组建扫描 --> 11 <context:component-scan base-package="com.lee.ssm" /> 12 13 <annotation-driven /> 14 15 <resources mapping="/resources/**" location="/resources/" /> 16 17 <!-- 18 视图解析器, 解析jsp, 默认使用jstl, lib中要包含 19 --> 20 <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 21 <beans:property name="prefix" value="/WEB-INF/views/" /> 22 <beans:property name="suffix" value=".jsp" /> 23 </beans:bean> 24 25 26 27 </beans:beans>
db.properties
1 jdbc.driver=com.mysql.jdbc.Driver 2 jdbc.url=jdbc:mysql://localhost:3306/order 3 jdbc.username=root 4 jdbc.password=root 5 jdbc.maxActive=3 6 jdbc.maxIdle=1
HelloController.java
1 package com.lee.ssm.action;
2
3 import javax.annotation.Resource;
4
5 import org.springframework.stereotype.Controller;
6 import org.springframework.ui.Model;
7 import org.springframework.web.bind.annotation.RequestMapping;
8
9 import com.lee.ssm.bean.User;
10 import com.lee.ssm.service.IUserService;
11
12 /**
13 *
14 * @Title: HelloController.java
15 * @Package com.lee.ssm.action
16 * @Description: TODO
17 * Copyright: Copyright (c) 2016
18 * Company:Nathan.Lee.Salvatore
19 *
20 * @author leechenxiang
21 * @date 2016年3月25日 下午10:34:51
22 * @version V1.0
23 */
24 @Controller
25 @RequestMapping("/root")
26 public class HelloController {
27
28 @Resource
29 private IUserService userService;
30
31 /**
32 *
33 * @Description: TODO
34 * @param model
35 * @return
36 * @throws Exception
37 *
38 * @author leechenxiang
39 * @date 2016年3月25日 下午10:36:49
40 */
41 @RequestMapping(value = "/hello")
42 public String home(Model model) throws Exception {
43
44 User user = userService.findUserById(1);
45 model.addAttribute("username", user.getName());
46
47 return "home";
48 }
49
50 }
User.java
1 package com.lee.ssm.bean;
2
3 public class User {
4
5 private int id;
6 private String username;
7 private int age;
8 private String sex;
9
10 public User() {
11 super();
12 }
13
14 public User(String username, int age, String sex) {
15 super();
16 this.username = username;
17 this.age = age;
18 this.sex = sex;
19 }
20
21 public int getId() {
22 return id;
23 }
24 public void setId(int id) {
25 this.id = id;
26 }
27 public String getName() {
28 return username;
29 }
30 public void setName(String username) {
31 this.username = username;
32 }
33 public int getAge() {
34 return age;
35 }
36 public void setAge(int age) {
37 this.age = age;
38 }
39 public String getSex() {
40 return sex;
41 }
42 public void setSex(String sex) {
43 this.sex = sex;
44 }
45
46 @Override
47 public String toString() {
48 return "User [id=" + id + ", name=" + username + ", age=" + age + ", sex="
49 + sex + "]";
50 }
51
52 }
UserMapper.xml
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE mapper
3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5
6 <mapper namespace="com.lee.ssm.dao.mapper.UserMapper" >
7
8 <select id="findUserById" parameterType="int" resultType="com.lee.ssm.bean.User">
9 SELECT * FROM USER WHERE id = #{id}
10 </select>
11
12 <insert id="insertUser" parameterType="com.lee.ssm.bean.User">
13 insert into user(username,sex) values(#{name},#{sex})
14 </insert>
15
16 <delete id="deleteUser" parameterType="int">
17 delete from user where id=#{id}
18 </delete>
19
20 <update id="updateUser" parameterType="com.lee.ssm.bean.User">
21 update user set username=#{name},sex=#{sex} where id=#{id}
22 </update>
23
24 </mapper>
UserMapper.java
1 package com.lee.ssm.dao.mapper;
2
3 import com.lee.ssm.bean.User;
4
5 public interface UserMapper {
6
7 public User findUserById(int id) throws Exception;
8
9 public Integer insertUser(User user) throws Exception;
10
11 public void deleteUser(int id) throws Exception;
12
13 public void updateUser(User user) throws Exception;
14 }
IUserService.java
1 package com.lee.ssm.service;
2
3 import com.lee.ssm.bean.User;
4
5 public interface IUserService {
6
7 public User findUserById(int id) throws Exception;
8
9 public void displayUser() throws Exception;
10
11 }
UserServiceImpl.java
1 package com.lee.ssm.service.impl;
2
3 import javax.annotation.Resource;
4
5 import org.springframework.stereotype.Service;
6
7 import com.lee.ssm.bean.User;
8 import com.lee.ssm.dao.mapper.UserMapper;
9 import com.lee.ssm.service.IUserService;
10
11 @Service("userService")
12 public class UserServiceImpl implements IUserService {
13
14 @Resource
15 private UserMapper userMapper;
16
17 @Override
18 public User findUserById(int id) throws Exception {
19 return userMapper.findUserById(id);
20 }
21
22 @Override
23 public void displayUser() throws Exception {
24
25 User u1 = new User("nathan.lee.salvatore", 18, "女");
26 userMapper.insertUser(u1);
27
28 userMapper.deleteUser(1001);
29
30 // int a = 1 / 0;
31
32 User u2 = new User("lee", 22, "男");
33 u2.setId(16);
34 userMapper.updateUser(u2);
35
36 }
37
38 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> 5 6 <!-- 加载spring 容器, 通配符 加载spring的配置文件 --> 7 <context-param> 8 <param-name>contextConfigLocation</param-name> 9 <param-value>classpath:spring/applicationContext.xml, classpath:spring/applicationContext-*.xml</param-value> 10 </context-param> 11 <listener> 12 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 13 </listener> 14 15 <!-- post乱码处理 --> 16 <filter> 17 <filter-name>CharacterEncodingFilter</filter-name> 18 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 19 <init-param> 20 <param-name>encoding</param-name> 21 <param-value>utf-8</param-value> 22 </init-param> 23 </filter> 24 <filter-mapping> 25 <filter-name>CharacterEncodingFilter</filter-name> 26 <url-pattern>/*</url-pattern> 27 </filter-mapping> 28 29 <!-- 前端控制器 --> 30 <servlet> 31 <servlet-name>springmvc</servlet-name> 32 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 33 <init-param> 34 <!-- 35 contextConfigLocation 指定spring mvc 全局配置文件 36 如果 contextConfigLocation不指定,默认找配置文件名称:servlet的name+"-servlet.xml" 37 --> 38 <param-name>contextConfigLocation</param-name> 39 <param-value>classpath:spring/springmvc.xml</param-value> 40 </init-param> 41 <!-- 容器在应用启动时就加载并初始化这个servlet --> 42 <load-on-startup>1</load-on-startup> 43 </servlet> 44 45 <servlet-mapping> 46 <servlet-name>springmvc</servlet-name> 47 <url-pattern>/</url-pattern> 48 </servlet-mapping> 49 50 </web-app>
home.jsp
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <%@ page language="java" contentType="text/html; charset=UTF-8"
3 pageEncoding="UTF-8"%>
4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
5 <html xmlns="http://www.w3.org/1999/xhtml"
6 xmlns:f="http://java.sun.com/jsf/core"
7 xmlns:h="http://java.sun.com/jsf/html">
8 <head>
9 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
10 <title>Insert title here</title>
11 </head>
12 <body>
13 user‘s name is:
14 <font color="red">${username }</font>
15 </body>
16 </html>
启动tomcat,测试地址:http://localhost:8080/ssm/root/hello\
转自:http://www.cnblogs.com/leechenxiang/p/5328962.html
Spring MVC Spring MyBatis 整合 - 快速上手
标签:
原文地址:http://www.cnblogs.com/mfc-itblog/p/5336838.html