Mybatis、Maven、Spring、struts2结合使用详解

来源:互联网 发布:淘宝网书店 编辑:程序博客网 时间:2024/04/29 18:04

 Mybatis 与 maven、Spring、struts2 结合使用

首先通过maven的pom.xml文件来导入所需要的jar包,采用的spring4、struts2、maven 和 mybatis3.2。

步骤如下执行。

一、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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.struts.xwork</groupId>
            <artifactId>xwork-core</artifactId>
            <version>2.3.16.2</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils-core</artifactId>
            <version>1.8.3</version>
        </dependency>
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>20040616</version>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.2</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>commons-i18n</groupId>
            <artifactId>commons-i18n</artifactId>
            <version>0.5</version>
            <type>zip</type>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>3.0-alpha-1</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun</groupId>
            <artifactId>tools</artifactId>
            <version>1.5.0</version>
            <scope>system</scope>
            <systemPath>D:\Program Files\java\jre\lib\rt.jar</systemPath>
        </dependency>
  
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.3.5.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>4.3.5.Final</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.3.16.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-dojo-plugin</artifactId>
            <version>2.3.16.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-json-plugin</artifactId>
            <version>2.3.16.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-spring-plugin</artifactId>
            <version>2.3.16.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.0-beta8</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.23</version>
        </dependency>
        <!-- mybatis jar -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.2.4</version>
        </dependency>
        <!-- mybatis-spring jar -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.2.2</version>
        </dependency>
        <!-- <dependency> <groupId>org.apache.ibatis</groupId> <artifactId>ibatis-sqlmap</artifactId> 
            <version>2.3.4.726</version> <scope>compile</scope> </dependency> <dependency> 
            <groupId>jetty</groupId> <artifactId>servlet-api</artifactId> <version>2.5-6.0.2</version> 
            </dependency> -->
        <!-- mysql-connector-java jar -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.28</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
        </dependency>
 </dependencies>

二、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
<filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  
    <listener>
        <description>Spring读取配置文件的监听器</description>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <description>Spring防止内存泄漏的监听器</description>
        <listener-class>
            org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
  
    <servlet>
        <servlet-name>JspSupportServlet</servlet-name>
        <servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
  
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath*:/applicationContext.xml
        </param-value>
    </context-param>
  
    <!-- #字符编码 -->
    <filter>
        <filter-name>encodingFilter</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>
        <!-- forceEncoding这个参数,把它设置为true表示不管请求中的编码是什么格式,都
将强制采用encoding中设置的编码方式 -->
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
  
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

三、spring配置

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
<!-- 开启注解方式注入 bean -->
    <context:annotation-config />
    <context:component-scan base-package="census"></context:component-scan>
  
    <!-- 读取 properties 配置信息 -->
    <context:property-placeholder location="classpath:datasource.properties" />
  
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 配置数据源 -->
        <property name="driverClass" value="${jdbc.driverClass}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.user}"></property>
        <property name="password" value="${jdbc.password}"></property>
  
        <!-- 配置 c3p0 数据库连接池 -->
  
        <!--连接池中保留的最小连接数 -->
        <property name="minPoolSize" value="5"></property>
  
        <!--连接池中保留的最大连接数。Default: 15 -->
        <property name="maxPoolSize" value="30"></property>
  
        <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
        <property name="initialPoolSize" value="10"></property>
  
        <!--最大空闲时间,1200秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
        <property name="maxIdleTime" value="60"></property>
  
        <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
        <property name="acquireIncrement" value="5"></property>
  
        <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。
 但由于预缓存的statements 属于单个connection而不是整个连接池。 
            所以设置这个参数需要考虑到多方面的因素。如果maxStatements与
 maxStatementsPerConnection均为0,则缓存被关闭。Default: 
            0 -->
        <property name="maxStatements" value="50"></property>
  
        <!--每60秒检查所有连接池中的空闲连接。Default: 0 -->
        <property name="idleConnectionTestPeriod" value="60"></property>
  
        <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
        <property name="acquireRetryAttempts" value="30"></property>
  
        <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。 
但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。 
            如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。
Default: false -->
        <property name="breakAfterAcquireFailure" value="false"></property>
  
        <property name="debugUnreturnedConnectionStackTraces">
            <value>true</value>
        </property>
    </bean>
  
    <!-- 创建SqlSessionFactory,并指定数据源 -->
    <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--configLocation属性指定mybatis的核心配置文件 -->
        <property name="configLocation" value="classpath:sqlmap-config.xml"></property>
        <!--dataSource属性指定要用到的连接池 -->
        <property name="dataSource" ref="dataSource"></property>
        <!-- 映射文件 -->
        <!-- <property name="mapperLocations" value="classpath:sqlmap/*.xml"></property> -->
    </bean>
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">         
       <constructor-arg index="0" ref="sqlSessionFactoryBean" /> 
    </bean>
<!--   
    <bean abstract="true" id="baseDao" class="census.base.BaseDao">
        <property name="sqlSession" ref="sqlSession" />
    </bean> -->
    <!-- 
    <bean id="userDao" class="census.dao.UserDao" parent="baseDao"></bean> -->
      
    <bean
        class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
</beans>

四、mybatis的config配置文件

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTDConfig 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias type="census.model.User" alias="user"/>
    </typeAliases>
    <mappers>
        <mapper resource="sqlmap/sqlmap-user.xml"/>
    </mappers>
</configuration>

五、mybatis 映射mapper文件配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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="User">
    <resultMap type="user" id="userMap">
        <id property="uid" column="id" />
        <result property="name" column="name" />
        <result property="age" column="age" />
    </resultMap
      
      
    <select id="getUser" parameterType="user" resultMap="userMap">
        select * from
        t_user where id=#{uid}
    </select>
      
    <select id="getUserList" resultMap="userMap">
        select * from t_user
    </select>
      
      
</mapper>

六、struts 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
  
<struts>
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <constant name="struts.devMode" value="false" />
      
    <package name="default" namespace="/" extends="struts-default">
        <action name="emp-*" class="census.action.UserAction" method="{1}">
            <result name="{1}">/population/census/view/emp-{1}.jsp</result>
        </action>
    </package>
</struts>

七、BaseDao 的代码
因为采用 Mybatis 的这种配置方式,DAO 层都需要SqlSessionTemplate sqlSession ,因此可以写一个BaseDao来存放公共的属性值。

1
2
3
4
5
6
7
8
9
10
11
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
  
public class BaseDao<T>{
    @Autowired //该注解是将sqlsession 注入,必需
    public SqlSessionTemplate sqlSession;
      
    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }
}

八、Dao 层代码

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.stereotype.Repository;
  
import census.base.BaseDao;
import census.model.User;
  
@Repository //该注解是为了让子类 UserDao 的父类 BaseDao 的 sqlsession 不为null
public class UserDao extends BaseDao<User>{
    public User getUser(Integer id){
        return (User) sqlSession.selectOne("User.getUser", id);
    }
}

serviceImpl通过spring 注解注入的方式调用DAO,Action同理

1
2
@Autowired
private UserDao userDao;

九、常见问题
问题1:

Causedby: org.springframework.beans.factory.BeanCreationException:Couldnot autowire field: 

com.uni2uni.service.impl.AuthorityServiceImpl 

com.uni2uni.controller.AdminController.authorityServiceImpl;

nested exception is org.springframework.beans.factory.BeanCreationException:Error creating bean with name 'authorityServiceImpl':

Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: 

Couldnot autowire field:private org.mybatis.spring.SqlSessionTemplate com.uni2uni.service.impl.AuthorityServiceImpl.session; 

nested exception is org.springframework.beans.factory.BeanCreationException:Error creating bean with name 'sqlSessionTemplate'

definedinclass path resource [applicationContext.xml]:Cannot resolve reference to bean 'sqlSessionFactory'while setting

constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException:Error creating bean with name

'sqlSessionFactory'definedinclass path resource [applicationContext.xml]:Invocation of init method failed; nested exception

is org.springframework.core.NestedIOException:Failed to parse mapping resource:'file [D:\Workspaces\liying\webapp\target\webapp\WEB-INF\

classes\mybatis\tb_admin.xml]'; nested exception is org.apache.ibatis.builder.BuilderException:Error parsing Mapper XML.

Cause: java.lang.IllegalArgumentException:MappedStatements collection already contains value forAdmin.resetAdminPassword

遇到这个问题通常原因有两种:
① 相同的命名空间有相同的 id;
② sqlSessionFactory 中配置了多个 xml 的地址
第一种查 Spring 的配置文件,是否有 Bean 的ID 相同
第二种情况应该是在 Spring 配置MyBatis 的配置信息可能写成这样:

1
2
3
4
5
6
7
8
9
<!-- 创建SqlSessionFactory,并指定数据源 -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
    <!--configLocation属性指定mybatis的核心配置文件 -->
    <property name="configLocation" value="classpath:sqlmap-config.xml"></property>
    <!--dataSource属性指定要用到的连接池 -->
    <property name="dataSource" ref="dataSource"></property>
    <!-- 映射文件 -->
    <property name="mapperLocations" value="classpath:sqlmap/*.xml"></property>
</bean>

这里红色标注的地方与 Mybatis congfig配置文件中的

1
2
3
<mappers>
    <mapper resource="sqlmap/sqlmap-user.xml"/>
</mappers>

冲突导致,所以可以把Spring的那块代码去掉,或者将 Mybatis config配置文件中的mappers去掉。
问题2:
java.lang.NullPointerException
    at census.dao.UserDao.getUserList(UserDao.java:17)
    at census.service.impl.UserServiceImpl.getUserList(UserServiceImpl.java:22)
    at census.action.UserAction.list(UserAction.java:47)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:450)
    at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:289)
    at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:252)
    at org.apache.struts2.interceptor.DeprecationInterceptor.intercept(DeprecationInterceptor.java:41)
问题的原因是 DAO 层的 sqlSession 为null,解决办法
① 在Spring 配置文件中加上

1
2
3
4
<bean abstract="true" id="baseDao" class="census.base.BaseDao">
    <property name="sqlSession" ref="sqlSession" />
</bean>
<bean id="userDao" class="census.dao.UserDao" parent="baseDao"></bean>

这种解决办法较为麻烦,如果有很多 Dao 的话,就会写很多的 bean。所以不方便。可以采用以下办法
②在 BaseDao 的public SqlSessionTemplate sqlSession; 上方加@Autowired注解,这样就不会再出现ase
空指针异常,另外也要在 BaseDao 的子类类名上方加上@Repository注解。用于 bean 注入。
 
声明:因为本人刚刚学习Mybatis,尝试性的做了第一个测试,如果本博文有错误或者不足之处,请大家留言指出。谢谢..
^-^
2 0
原创粉丝点击