Ssi的整合(Struts2+Spring+Ibatis)
???????? 本文好用的三个框架版本分别为
???????? struts-2.3.8 ,spring-framework-3.0.5.RELEASE,ibatis-2.3.4.726
下载地址:struts
Struts2
http://archive.apache.org/dist/struts/binaries/struts-2.3.8-all.zip
Spring
http://www.springsource.org/spring-community-download(进入后需要录入信息后才能下载)
Ibatis
http://archive.apache.org/dist/ibatis/binaries/ibatis.java/ibatis-2.3.4.726.zip
?
2.1首先在eclipse新建web工程,新建创建的web目录结构如下:
ssi-release
???????? |__compensate
???????? |___webapps
?????????????????? |___META-INF
??????????????????????????? |___MANIFEST.MF?
?????????????????? |___WEB-INF
??????????????????????????? |___classes
??????????????????????????? |___lib
??????????????????????????? |___web.xml
?????????????????? |___index.jsp
?
2.2拷贝Struts2基本的jar包到工程下的lib目录
commons-fileupload-1.2.2.jar
commons-io-2.0.1.jar
commons-lang3-3.1.jar
freemarker-2.3.19.jar
javassist-3.11.0.GA.jar
ognl-3.0.6.jar
struts2-core-2.3.8.jar
xwork-core-2.3.8.jar
log4j-1.2.15.jar(非必须,便于使用log4j所以此处添加本jar包)
2.3在web.xml中添加Struts2的控制分发的Filter
??? <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>
其中mapping中<url-pattern>/*</url-pattern>表示过滤所有请求
?
2.3编写Struts2测试action
??????? 创建com.jshand.ssi.action包
??????? 在com.jshand.ssi.action包下创建TestAction类实现com.opensymphony.xwork2.Action接口
并实现方法execute方法,代码如下:
package com.jshand.ssi.action;
?
import com.opensymphony.xwork2.Action;
?
/**
?*@file_nameTestAction.java
?*@project?????? ssi-release
?*@author? ?? jshand
?*@createDateJun2,2013? 12:37:18PM
?*@version ?? 1.0
?*http://www.jshand.com
?*
?*/
?
publicclass TestAction implements Action{
???
??? public String actionStr = "com.jshand.ssi.action.TestAction";
???
??? public String execute() throws Exception{
?????? System.out.println("execute Struts2 Action ......");
?????? returnSUCCESS;
??? }
??? public String getActionStr() {
?????? returnactionStr;
??? }
?
??? publicvoid setActionStr(String actionStr) {
?????? this.actionStr = actionStr;
??? }
}
其中actionStr属性定义了一个字符串,并设置了set、get方法目的是讲测试Struts2封装的参数传递,将接收的或者默认的字符串输出到jsp中。
2.3编写Struts2的配置文件struts.xml
在源文件目录(工程下compensate目录)创建struts.xml文件,
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC? "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
??? "http://struts.apache.org/dtds/struts-2.3.dtd">
?
<struts>
??? <package name="struts2" extends="struts-default" >
??????? <action name="test" class="com.jshand.ssi.action.TestAction">
??????????? <result name="success">/index.jsp</result>
??????? </action>
??? </package>
</struts>
主要配置xml中aciton节点,
name属性为自定义属性,同一个package不允许出现相同name
class属性为之前编写的TestAction的全路径
<action name="test" class="com.jshand.ssi.action.TestAction">
????? <result name="success">/index.jsp</result>
</action>
?
?
?
action子节点中添加一个result节点当执行完Action后跳转到index.jsp中,在index.jsp中添加如下代码${actionStr},使输入的参数或这作用域内的属性输出到index.jsp中
<body>
??? This is my JSP page. <br>
??? ${actionStr}
? </body>
启动中间件,本文用到的是tomcat6,在浏览器中输入
http://localhost:8080/ssi-release/test.action?actionStr=testParameter
控制台输出如下:
?
?
浏览器跳转到index.jsp,并输出接受到的参数
?
说明Struts2配置成功!接下来我们整合Spring到Struts2中
同Struts2一样大多数框架的第一个步骤都是拷贝jar包到工程中,并配置环境变量?,Spring所需要的包如下,其中struts2-spring-plugin-2.3.8.jar为整合struts2和Spring的包,当然这个包不是必须的,我们可以通过其他方法进行处理。
aopalliance-1.0.jar
aspectj-DEVELOPMENT-20130313082900.jar
aspectjlib-1.5.2.jar
aspectjweaver.jar
commons-attributes-api.jar
commons-attributes-compiler.jar
commons-logging-1.1.1.jar
commons-logging.jar
org.springframework.aop-3.0.5.RELEASE.jar
org.springframework.asm-3.0.5.RELEASE.jar
org.springframework.aspects-3.0.5.RELEASE.jar
org.springframework.beans-3.0.5.RELEASE.jar
org.springframework.context-3.0.5.RELEASE.jar
org.springframework.context.support-3.0.5.RELEASE.jar
org.springframework.core-3.0.5.RELEASE.jar
org.springframework.expression-3.0.5.RELEASE.jar
org.springframework.instrument-3.0.5.RELEASE.jar
org.springframework.instrument.tomcat-3.0.5.RELEASE.jar
org.springframework.jdbc-3.0.5.RELEASE.jar
org.springframework.jms-3.0.5.RELEASE.jar
org.springframework.orm-3.0.5.RELEASE.jar
org.springframework.oxm-3.0.5.RELEASE.jar
org.springframework.test-3.0.5.RELEASE.jar
org.springframework.transaction-3.0.5.RELEASE.jar
org.springframework.web-3.0.5.RELEASE.jar
org.springframework.web.portlet-3.0.5.RELEASE.jar
org.springframework.web.servlet-3.0.5.RELEASE.jar
org.springframework.web.struts-3.0.5.RELEASE.jar
struts2-spring-plugin-2.3.8.jar
?
3.1在web.xml中注册,应用程序启动时,Spring的监听器(Listener),其中context-param节点是初始化监听器的配置文件,即注册的bean从哪里获取,此处使用的是默认文件
WEB-INF
|___applicationContext.xml
?
??? <!-- 指明spring配置文件在何处 -->
<!--
??? <context-param>
?????? <param-name>contextConfigLocation</param-name>
?????? <param-value>classpath*:applicationContext*.xml</param-value>
??? </context-param>
-->
??? <listener>
?????? <listener-class>
?????????? org.springframework.web.context.ContextLoaderListener
?????? </listener-class>
??? </listener>
?
3.2编写测试用bean对象
???????? 此处模仿MVC三层机制,Action中去调用业务辑层bean对象,此对象有Spring创建实例化,Action中只进行声明。
3.2.1编业务逻辑层的接口,遵照面向接口编程的思想,所有业务逻辑层的类,都抽象成接口。
???????? 编写TestService接口如下
package com.jshand.ssi.service;
?
/**
?*@file_nameTestService.java
?*@project?????? ssi-release
?*@author? ?? jshand
?*@createDateJun2,2013? 2:08:53PM
?*@version ?? 1.0
?*http://www.jshand.com
?*
?*/
?
publicinterface TestService {
??? publicvoid service();
}
?
3.2.2编写TestService的实现类TestServiceImpl代码如下:
package com.jshand.ssi.service;
?
/**
?*@file_nameTestServiceImpl.java
?*@project?????? ssi-release
?*@author? ?? jshand
?*@createDateJun2,2013? 2:08:53PM
?*@version ?? 1.0
?*http://www.jshand.com
?*
?*/
?
publicclass TestServiceImpl implements TestService {
???
??? publicvoid service()throws Exception {
?????? System.out.println("this is service function ");
??? }
}
?
3.3 编写Spring配置文件,并在配置文件中注册TestAction和TestService实现类
??? 在WEB-INF目录下创建aplicationContext.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:aop="http://www.springframework.org/schema/aop"
??? xmlns:tx="http://www.springframework.org/schema/tx"?
??? xmlns:context="http://www.springframework.org/schema/context"?
??? xsi:schemaLocation="??
????????? http://www.springframework.org/schema/beans???
????????? http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
????????? http://www.springframework.org/schema/aop???
????????? http://www.springframework.org/schema/aop/spring-aop-2.0.xsd??
????????? http://www.springframework.org/schema/tx???
????????? http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
??? ?
?
??? <bean id="testAction" class="com.jshand.ssi.action.TestAction">
?????? <property name="testService" ref="testService"></property>
??? </bean>
???
??? <bean id="testService" class="com.jshand.ssi.service.TestServiceImpl" />
???
</beans>
?
?
3.4在TestAction中声明service的应用,并添加set、get方法
声明的属性名称需要跟applicationContext.xml中注入的属性的那么相同
<property name="testService">testService</property>
在TestAction的execute方法中添加service的调用,testService.service();
Execute方法如下:
??? public String execute() throws Exception {
?????? System.out.println("execute Struts2 Action ...... && actionStr = "+actionStr);
??????
???????? testService.service();
?????? returnSUCCESS;
??? }
?
3.5 指定Struts2的Action初始化由Spring接管
由于我们添加Spring依赖的jar包是已经将struts2-spring-plugin-2.3.8.jar添加到应用的环境变量中,该jar包中包含了如下的struts-plugin.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
?* $Id: struts-plugin.xml 1221225 2011-12-20 12:22:28Z jogep $
?*
?* Licensed to the Apache Software Foundation (ASF) under one
?* or more contributor license agreements.? See the NOTICE file
?* distributed with this work for additional information
?* regarding copyright ownership.? The ASF licenses this file
?* to you under the Apache License, Version 2.0 (the
?* "License"); you may not use this file except in compliance
?* with the License.? You may obtain a copy of the License at
?*
?*? http://www.apache.org/licenses/LICENSE-2.0
?*
?* Unless required by applicable law or agreed to in writing,
?* software distributed under the License is distributed on an
?* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
?* KIND, either express or implied.? See the License for the
?* specific language governing permissions and limitations
?* under the License.
?*/
-->
<!DOCTYPE struts PUBLIC
??? "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
??? "http://struts.apache.org/dtds/struts-2.3.dtd">
???
<struts>
??? <bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
???
??? <!--? Make the Spring object factory the automatic default -->
??? <constant name="struts.objectFactory" value="spring" />
?
??? <constant name="struts.class.reloading.watchList" value="" />
??? <constant name="struts.class.reloading.acceptClasses" value="" />
??? <constant name="struts.class.reloading.reloadConfig" value="false" />
?
??? <package name="spring-default">
??????? <interceptors>
??????????? <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>
??????? </interceptors>
??? </package>???
</struts>
?
?
那么Struts2启动扫描扩展插件时,会把该插件装载。其中如下声明即将Sturts2的创建对象工厂指定给Spring。
?<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
如果没有导入此jar包则,需要在Struts2配置文件中进行相应的声明和处理。此处就不进行详细的讲述,感兴趣的可以上网搜索。下面打开浏览器重新敲入刚才的请求,
?
后台打印如下:
?
?
?
打印“execute Struts2 Action ...... && actionStr = testParameter”,说明进入到Action的execute方法,执行testService.service();时,testService对象我们在声明的时候并没有实例化,说明此处的testService对象是由Spring帮助我们创建的,至此整合Spring和Struts2的工作就完成了。
4.1拷贝Ibatis基本的jar包到工程下的lib目录
ibatis-2.3.4.726.jar???? ibatis必备的jar包
commons-dbcp-1.4.jar???? dbcp连接池必备的包(便于整合Spring使用)
commons-pool-1.6.jar???? 便于整合Spring使用同上
mysql-connector-java-5.1.18-bin.jar??? mysql数据库的驱动
classes12.jar???????????????? Oracle数据库的驱动
4.2在前面的步骤没有添加log4j的属性文件,所以,所有的log4j都无法用,下面我们想使用log4j进行控制台信息的输出,所以此处添加log4j的属性文件,文件如下,此处不过多的对log4j进行介绍,感兴趣的朋友可以上网搜索相关内容,也可以参考我之前的一片文章
http://314649444.iteye.com/blog/1874814
#
# Log4J Settings for log4j 1.2.x (via jakarta-commons-logging)
#
# The five logging levels used by Log are (in order):
#
#?? 1. DEBUG (the least serious)
#?? 2. INFO
#?? 3. WARN
#?? 4. ERROR
#?? 5. FATAL (the most serious)
?
?
# Set root logger level to WARN and append to stdout
log4j.rootLogger=DEBUG,stdout
?
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
?
# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%d%5p(%c:%L)-%m%n
?
# Print only messages of level ERROR or above in the package noModule.
log4j.logger.noModule=FATAL
?
# OpenSymphony Stuff
log4j.logger.com.opensymphony=INFO
log4j.logger.org.apache.struts2=INFO
?
# Spring Stuff
log4j.logger.org.springframework=INFO
?
?
?
4.3下面首先让我们在数据库中创建一张表,本文采用的是mysql数据库
建表sql如下:
CREATETABLE`person`
(
?
`personid`
VARCHAR(100)
NOT NULL,
`name`
VARCHAR(100)
NOT NULL,
`age`
VARCHAR(100)
NOT NULL,
`sex`
VARCHAR(100)
NOT NULL,
PRIMARYKEY
(`personid`)
?
)
ENGINE=MYISAM
;
4.4.1创建com.jshand.ssi.model包,并在包下创建person表对应的实体类如下:
package com.jshand.ssi.model;
?
/**
?*@file_namePerson.java
?*@project?????? ssi-release
?*@author? ?? jshand
?*@createDateJun26,2013? 10:32:22AM
?*@version ?? 1.0
?*http://www.jshand.com
?*
?*/
?
publicclass Person {
???
??? private String personid="";
??? private String name="";
??? private String age="";
??? private String sex="";
???
???
??? public String getPersonid() {
?????? returnpersonid;
??? }
??? publicvoid setPersonid(String personid) {
?????? this.personid = personid;
??? }
??? public String getName() {
?????? returnname;
??? }
??? publicvoid setName(String name) {
?????? this.name = name;
??? }
??? public String getAge() {
?????? returnage;
??? }
??? publicvoid setAge(String age) {
?????? this.age = age;
??? }
??? public String getSex() {
?????? returnsex;
??? }
??? publicvoid setSex(String sex) {
?????? this.sex = sex;
??? }
}
?
4.4.2添加实体类Person对应的查询语句配置文件
<?xml version="1.0" encoding="UTF-8" ?>
?
<!DOCTYPE sqlMap?????
??? PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"?????
??? "http://ibatis.apache.org/dtd/sql-map-2.dtd">
?
<sqlMap namespace="Person">
?
? <!-- Use type aliases to avoid typing the full classname every time. -->
? <typeAlias alias="Person" type="com.jshand.ssi.model.Person"/>
?
? <!-- Result maps describe the mapping between the columns returned
?????? from a query, and the class properties.? A result map isn't
?????? necessary if the columns (or aliases) match to the properties
?????? exactly. -->
? <resultMap id="Person" class="Person">
???? ?? <result property="personid"? column="personid" />
?????? <result property="name"???? column="name" />
?????? <result property="age"? column="age" />
?????? <result property="sex" column="sex" />
? </resultMap>
?
? <!-- A simpler select example without the result map.? Note the
?????? aliases to match the properties of the target result class. -->
? <select id="selectPersonById" parameterClass="String" resultClass="Person">
?? select personid, name, age, sex? from Person where personid= #id#
? </select>
??
? <!-- Insert example, using the Person parameter class -->
? <insert id="insertPerson" parameterClass="Person">
??? insert into Person
? ????? (personid, name, age, sex )
??? values
? ????? (#personid#, #name#, #age#, #sex# )
? </insert>
?
? <!-- Update example, using the Person parameter class -->
? <update id="updatePerson" parameterClass="Person">
??? update Person
?? set name = #name#,
?????? age = #age#,
?????? sex = #sex#,
??? where personid = #personid#
? </update>
?
? <!-- Delete example, using an integer as the parameter class -->
? <delete id="deletePersonById" parameterClass="String">
??? delete from Person where personid = #personid#
? </delete>
?
</sqlMap>
?
?
?
4.5 添加一个sqlMapping.properties文件(当然文件名是可以随便起的,只要Spring读取的时候保持一致即可)用于Spring读取配置连接数据库配置包括驱动类,Url、用户名、密码等,内容如下:
#MY SQL
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/test
jdbc.username=root
jdbc.password=root
?
4.6配置sqlMapConfig.xml文件,并在其中注册 TB_Person.xml的SQL
?
<?xml version="1.0" encoding="UTF-8"?>
?
<!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://www.ibatis.com/dtd/sql-map-config-2.dtd">
?
<sqlMapConfig>
?
??? <settings cacheModelsEnabled="true" enhancementEnabled="true"
?????? lazyLoadingEnabled="true" errorTracingEnabled="false" maxRequests="32"
?????? maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />
?
??? <sqlMap resource="com/jshand/ssi/model/TB_Person.xml" />
???
</sqlMapConfig>
?
?
4.7 在Spring配置文件中声明数据源、sqlMapClient操作如下:
在Spring配置文件中添加如下xml节点
?? <!-- 方便查找类路径下 sqlMapping.properties 并读取到内存中-->
??? <bean id="propertyConfigurer"
??? class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
?????? <property name="locations">
?????????? <list>
????????????? <value>classpath:sqlMapping.properties</value>
?????????? </list>
?????? </property>
??? </bean>
?
??? <!-- 数据源配制 -->
??? <bean id="dataSource"
?????? class="org.apache.commons.dbcp.BasicDataSource">
?????? <property name="driverClassName">
?????????? <value>${jdbc.driverClassName}</value>
?????? </property>
?????? <property name="url">
?????????? <value>${jdbc.url}</value>
?????? </property>
?????? <property name="username">
?????????? <value>${jdbc.username}</value>
?????? </property>
?????? <property name="password">
?????????? <value>${jdbc.password}</value>
?????? </property>
??? </bean>
?
??? <!-- 此处应注入ibatis配置文件,而非sqlMap文件,否则会出现“there is no statement.....异常” -->
??? <bean id="sqlMapClient"
?????? class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
?????? <property name="configLocation">
?????????? <value>classpath:SqlMapConfig.xml</value>
?????? </property>
?????? <property name="dataSource" ref="dataSource" />
??? </bean>
?
?
4.8 编写PersonDao类,并继承由Spring提供的SqlMapClientDaoSupport类
实现增删改查的操作,PersonDto内容如下:
package com.jshand.ssi.dao;
?
import java.sql.SQLException;
?
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
?
import com.jshand.ssi.model.Person;
?
/**
?*@file_namePersonDao.java
?*@project?????? ssi-release
?*@author? ?? jshand
?*@createDateJun26,2013? 11:05:55AM
?*@version ?? 1.0
?*http://www.jshand.com
?*
?*/
?
publicclass PersonDao extends SqlMapClientDaoSupport{
???
??? /**
??? ?*按照主键查询
??? ?*@paramid
??? ?*@return
??? ?*@throwsSQLException
??? ?*/
??? public? Object selectObjectById? (String id) throws SQLException {
?????? System.out.println("ID = "+id);
?????? return? getSqlMapClientTemplate().queryForObject("selectPersonById", id);
??? }
???
??? /**
??? ?*插入一条数据
??? ?*@paramobject
??? ?*@return
??? ?*@throwsSQLException
??? ?*/
??? public Object insertObject (Person person) throws SQLException {
?????? return getSqlMapClientTemplate().insert("insertPerson", person);
??? }
???
??? /**
??? ?*按主键更新一条记录
??? ?*@paramobject
??? ?*@return
??? ?*@throwsSQLException
??? ?*/
??? public? int updateObject (Person person) throws SQLException {
?????? return getSqlMapClientTemplate().update("updatePerson", person);
??? }
???
??? /**
??? ?*按主键删除一条记录
??? ?*@paramid
??? ?*@return
??? ?*@throwsSQLException
??? ?*/
??? public? int deleteObject (String id) throws SQLException {
?????? return getSqlMapClientTemplate().delete("deletePerson", id);
??? }
}
?
?
?
4.9 将PersonDao类交给Spring管理,即在Spring配置文件中注册PersonDao类
并将PersonDao注入到上面步骤的testService里面去,最后Spring的完整内容如下:
?
<?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"
??? xmlns:tx="http://www.springframework.org/schema/tx"?
??? xmlns:context="http://www.springframework.org/schema/context"?
??? xsi:schemaLocation="??
????????? http://www.springframework.org/schema/beans???
????????? http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
????????? http://www.springframework.org/schema/aop???
????????? http://www.springframework.org/schema/aop/spring-aop-2.0.xsd??
????????? http://www.springframework.org/schema/tx???
????????? http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
?
??? ? <!-- 方便查找类路径下 sqlMapping.properties 并读取到内存中-->
??? <bean id="propertyConfigurer"
??? ??? class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
?????? <property name="locations">
?????????? <list>
????????????? <value>classpath:sqlMapping.properties</value>
?????????? </list>
?????? </property>
??? </bean>
?
??? <!-- 数据源配制 -->
??? <bean id="dataSource"
?????? class="org.apache.commons.dbcp.BasicDataSource">
?????? <property name="driverClassName">
?????????? <value>${jdbc.driverClassName}</value>
?????? </property>
?????? <property name="url">
?????????? <value>${jdbc.url}</value>
?????? </property>
?????? <property name="username">
?????????? <value>${jdbc.username}</value>
?????? </property>
?????? <property name="password">
?????????? <value>${jdbc.password}</value>
?????? </property>
??? </bean>
?
??? <!-- 此处应注入ibatis配置文件,而非sqlMap文件,否则会出现“there is no statement.....异常” -->
??? <bean id="sqlMapClient"
?????? class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
?????? <property name="configLocation">
?????????? <value>classpath:SqlMapConfig.xml</value>
?????? </property>
?????? <property name="dataSource" ref="dataSource" />
??? </bean>
??? ?
??? <bean id="testAction" class="com.jshand.ssi.action.TestAction">
?????? <property name="testService" ref="testService"></property>
??? </bean>
???
??? <bean id="testService" class="com.jshand.ssi.service.TestServiceImpl" >
?????????? <property name="personDao" ref="personDao"></property>
??? </bean>
???
??? <bean id="personDao" class="com.jshand.ssi.dao.PersonDao" />
???
</beans>
?
4.10下面就是看效果的时候了,我们在testService中声明一个personDao属性,名称与Spring中注册的com.jshand.ssi.dao.PersonDao类的id保持一致即可并设置setter、getter。personDao属性只需声明即可不用实例化,因为此处验证Spring托管
?
因为之前我们整合Spring、Struts2的时候Struts2的Action接收访问后会调用TestServiceImpl的service方法,所以我们在service方法中调用PersonDao的方法插入和查询方法已验证配置是否成功。
内容如下:
package com.jshand.ssi.service;
?
import java.sql.SQLException;
?
import org.apache.log4j.Logger;
?
import com.jshand.ssi.dao.PersonDao;
import com.jshand.ssi.model.Person;
?
/**
?*@file_nameTestService.java
?*@project?????? ssi-release
?*@author? ?? jshand
?*@createDateJun2,2013? 2:08:53PM
?*@version ?? 1.0
?*http://www.jshand.com
?*
?*/
?
publicclass TestServiceImpl implements TestService {
??? Logger logger = Logger.getLogger(TestServiceImpl.class);
??? private PersonDao personDao = null;
???
??? publicvoid service() throws SQLException{
?????? System.out.println("this is service function ");
?????? Person personInsert? = new Person();
?????? personInsert.setPersonid("001");
?????? personInsert.setName("Jhoon");
?????? personInsert.setAge("23");
?????? personInsert.setSex("男");
?????? personDao.insertObject(personInsert);
??????
?????? logger.debug("插入成功");
?????? Person personQuery = null;
?????? personQuery = (Person) personDao.selectObjectById("001");
??????
?????? logger.debug("查询结果 Name = "+personQuery.getName()+"\t age = "+personQuery.getAge()+"\tsex = "+personQuery.getSex());
??????
??????
??? }
?
??? public PersonDao getPersonDao() {
?????? returnpersonDao;
??? }
?
??? publicvoid setPersonDao(PersonDao personDao) {
?????? this.personDao = personDao;
??? }
}
?
?
?
?
下面我们来发布一下程序,并查看执行结果:
?
?
?
控制台打印如上,说明配置成功
5 将ibatis的事物交给Spring管理,
即将数据源的事物交给Spring处理,然后Spring在一个指定的切面打开事物,切面执行完之后如果产生异常就将事物回滚,否则提交。
具体配置,在Spring配置文件添加如下xml节点,这里的切面为
public * com.jshand.ssi.services.*.*(..)? 即所有Service类的所有方法
<!-- 事务的定义 -->
??? <bean id="transactionManager"
??? ??? class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
?????? <property name="dataSource">
?????????? <ref local="dataSource" />
?????? </property>
??? </bean>
?
??? <aop:config>
?????? <aop:pointcut id="daoMethods" expression="execution(public * com.jshand.ssi.services.*.*(..))" />
?????? <aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods" />
??? </aop:config>
?
??? <tx:advice id="txAdvice" transaction-manager="transactionManager">
?????? <tx:attributes>
?????????? <tx:method name="*" rollback-for="Exception" propagation="REQUIRED" />
?????? </tx:attributes>
??? </tx:advice>
?
下面我们将TestServiceImpl类的service方法改造一下,因为我们之前已经插入过一条id为001的对象,现在我们先插入一条002的后插入一条001的记录,因为id是主键所以在此插入的时候001是不能插入的,按照事物的一致性原则,如果成功开始事物,并且回滚的话这两条记录都应该插入不成功,下面来执行看下效果
改造后如下:
??? publicvoid service() throws SQLException{
??????
?????? Person personInsert2? = new Person();
?????? personInsert2.setPersonid("002");
?????? personInsert2.setName("Jhoon");
?????? personInsert2.setAge("23");
?????? personInsert2.setSex("男");
?????? personDao.insertObject(personInsert2);
??????
?????? Person personInsert1? = new Person();
?????? personInsert1.setPersonid("001");
?????? personInsert1.setName("Jhoon");
?????? personInsert1.setAge("23");
?????? personInsert1.setSex("男");
?????? personDao.insertObject(personInsert1);
??????
??? }
?
执行后:后台报错如下,
execute Struts2 Action ...... && actionStr = com.jshand.ssi.action.TestAction
2013-06-26 14:30:58,670 DEBUG (java.sql.Connection:27) - {conn-100000} Connection
2013-06-26 14:30:58,701 DEBUG (java.sql.Connection:27) - {conn-100000} Preparing Statement:????? insert into Person???? (personid, name, age, sex )? values???? (?, ?, ?, ? )??
2013-06-26 14:30:58,780 DEBUG (java.sql.PreparedStatement:27) - {pstm-100001} Executing Statement:????? insert into Person???? (personid, name, age, sex )? values???? (?, ?, ?, ? )??
2013-06-26 14:30:58,780 DEBUG (java.sql.PreparedStatement:27) - {pstm-100001} Parameters: [002, Jhoon, 23, 男]
2013-06-26 14:30:58,780 DEBUG (java.sql.PreparedStatement:27) - {pstm-100001} Types: [java.lang.String, java.lang.String, java.lang.String, java.lang.String]
2013-06-26 14:31:21,026 DEBUG (java.sql.Connection:27) - {conn-100002} Connection
2013-06-26 14:31:21,026 DEBUG (java.sql.Connection:27) - {conn-100002} Preparing Statement:????? insert into Person???? (personid, name, age, sex )? values???? (?, ?, ?, ? )??
2013-06-26 14:31:21,041 DEBUG (java.sql.PreparedStatement:27) - {pstm-100003} Executing Statement:????? insert into Person???? (personid, name, age, sex )? values???? (?, ?, ?, ? )??
2013-06-26 14:31:21,041 DEBUG (java.sql.PreparedStatement:27) - {pstm-100003} Parameters: [001, Jhoon, 23, 男]
2013-06-26 14:31:21,058 DEBUG (java.sql.PreparedStatement:27) - {pstm-100003} Types: [java.lang.String, java.lang.String, java.lang.String, java.lang.String]
2013-06-26 14:31:21,214? INFO (org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315) - Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2013-06-26 14:31:21,495? INFO (org.springframework.jdbc.support.SQLErrorCodesFactory:126) - SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]
2013-06-26 14:31:24,396 ERROR (org.apache.struts2.dispatcher.Dispatcher:38) - Exception occurred during processing request: SqlMapClient operation; SQL [];??
--- The error occurred in com/jshand/ssi/model/TB_Person.xml.?
--- The error occurred while applying a parameter map.?
--- Check the insertPerson-InlineParameterMap.?
--- Check the statement (update failed).?
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:??
--- The error occurred in com/jshand/ssi/model/TB_Person.xml.?
--- The error occurred while applying a parameter map.?
--- Check the insertPerson-InlineParameterMap.?
--- Check the statement (update failed).?
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1
org.springframework.dao.DuplicateKeyException: SqlMapClient operation; SQL [];??
--- The error occurred in com/jshand/ssi/model/TB_Person.xml.?
--- The error occurred while applying a parameter map.?
--- Check the insertPerson-InlineParameterMap.?
--- Check the statement (update failed).?
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:??
--- The error occurred in com/jshand/ssi/model/TB_Person.xml.?
--- The error occurred while applying a parameter map.?
--- Check the insertPerson-InlineParameterMap.?
--- Check the statement (update failed).?
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1
??? at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:241)
??? at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
??? at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:203)
??? at org.springframework.orm.ibatis.SqlMapClientTemplate.insert(SqlMapClientTemplate.java:364)
??? at com.jshand.ssi.dao.PersonDao.insertObject(PersonDao.java:39)
??? at com.jshand.ssi.service.TestServiceImpl.service(TestServiceImpl.java:38)
??? at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
??? at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
??? at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
??? at java.lang.reflect.Method.invoke(Method.java:597)
??? at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
??? at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
??? at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
??? at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
??? at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
??? at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
??? at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
??? at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
??? at $Proxy4.service(Unknown Source)
??? at com.jshand.ssi.action.TestAction.execute(TestAction.java:24)
??? at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
??? at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
??? at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
??? at java.lang.reflect.Method.invoke(Method.java:597)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:446)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:285)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
??? at org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:256)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
??? at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265)
??? at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
??? at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:238)
??? at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:238)
??? at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:252)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:141)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171)
??? at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:176)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:187)
??? at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:242)
??? at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54)
??? at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:544)
??? at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:77)
??? at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:91)
??? at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
??? at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
??? at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
??? at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
??? at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
??? at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
??? at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
??? at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
??? at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:861)
??? at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:606)
??? at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
??? at java.lang.Thread.run(Thread.java:619)
Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:??
--- The error occurred in com/jshand/ssi/model/TB_Person.xml.?
--- The error occurred while applying a parameter map.?
--- Check the insertPerson-InlineParameterMap.?
--- Check the statement (update failed).?
--- Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1
??? at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:107)
??? at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.insert(SqlMapExecutorDelegate.java:393)
??? at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.insert(SqlMapSessionImpl.java:82)
??? at org.springframework.orm.ibatis.SqlMapClientTemplate$8.doInSqlMapClient(SqlMapClientTemplate.java:366)
??? at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:200)
??? ... 82 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '001' for key 1
??? at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
??? at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
??? at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
??? at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
??? at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
??? at com.mysql.jdbc.Util.getInstance(Util.java:386)
??? at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)
??? at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3609)
??? at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3541)
??? at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2002)
??? at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2163)
??? at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2624)
??? at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2127)
??? at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1362)
??? at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
??? at org.apache.commons.dbcp.DelegatingPreparedStatement.execute(DelegatingPreparedStatement.java:172)
??? at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
??? at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
??? at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
??? at java.lang.reflect.Method.invoke(Method.java:597)
??? at com.ibatis.common.jdbc.logging.PreparedStatementLogProxy.invoke(PreparedStatementLogProxy.java:62)
??? at $Proxy7.execute(Unknown Source)
??? at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeUpdate(SqlExecutor.java:80)
??? at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.sqlExecuteUpdate(MappedStatement.java:216)
??? at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeUpdate(MappedStatement.java:94)
??? ... 86 more
?
表中的数据还是之前插入的一条,新插入的两条都没成功。
?
下面我们将service方法再次改造一下,将001的id换成003,我们DEBUG执行下
改造后的service方法如下:
??? ??? publicvoid service() throws SQLException{
??????
?????? Person personInsert2? = new Person();
?????? personInsert2.setPersonid("002");
?????? personInsert2.setName("Jhoon");
?????? personInsert2.setAge("23");
?????? personInsert2.setSex("男");
?????? personDao.insertObject(personInsert2);
??????
?????? Person personInsert3? = new Person();
?????? personInsert3.setPersonid("003");
?????? personInsert3.setName("Jhoon");
?????? personInsert3.setAge("23");
?????? personInsert3.setSex("男");
?????? personDao.insertObject(personInsert3);
??????
??? }
我们在Person personInsert3? = new Person();这句话上打一个端点,当我们执行到这酷话的时候如果没有开启事物那么id为002的记录应该是插入到数据库中的,在这里测试事物的正确与否:
开始执行:
?
说明插入002的操作已经执行这个时候我们看一下数据库:
?
发现记录中不存在002的id所以证明事物成功开启未提交,当把service全部执行完毕后,在查看数据库发现,id为002、003的记录都已经成功插入,说明数据库事物是正确的。
?
?
总结:至此整合Struts2、Spring、Ibatis已经结束了,需要值得注意的是,
mysql中表创建时需要选择存储引擎,本文中用的是mysql5.4提供七种种Storage Engine
,而其中MyISAM对事物的支持比较特殊,所以没有使用个,本文中建表使用?? InnoDB作为存储引擎的。
?
?
?
本文中搭建好的应用可以到下面的地址下载:
http://test-jshand.googlecode.com/files/ssi-release.rar