前面已经说到了集成的问题我们接着上面的讲。
struts2与Spring的集成比较简单主要还是配置文件接下来我们来分析配置文件
主要的配置文件有:
1、applicationContext.xml
2、log4j.properties
3、sqlmap-config.xml
4、struts.properties
5、struts.xml
1)、applicationContext.xml 这个就是Spring的核心配置文件了 如果你的项目比较复杂可能会分多个Spring的配置文件(applicationContext-Action.xml、applicationContext-Dao.xml)但最终都还是会被加载到核心配置文件中来本例直接使用applicationContext.xml配置文件来配置
applicationContext.xml配置文件主要做什么呢?其实他做的就是类的注册工作 并整理类与类之间的关系。
好我们来看看
applicationContext.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
>
<!-- 启用注解 -->
<context:annotation-config />
<context:component-scan base-package="cn.rx.oamp.**" />
<aop:aspectj-autoproxy proxy-target-class="true"/>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- aop -->
<bean id="aspectBean" class="cn.rx.oamp.aop.LogAspect" scope="prototype">
<property name="auditLogService" ref="auditLogService"></property>
</bean>
<!--
<aop:config proxy-target-class="true">
<aop:aspect id="TestAspect" ref="aspectBean">
<!-- 配置com.spring.service包下所有类或接口的所有方法 -->
<aop:pointcut id="businessService"
expression="execution(* cn.rx.oamp.service.impl.*.*(..))" />
<aop:before pointcut-ref="businessService" method="doBefore"/>
<aop:after pointcut-ref="businessService" method="doAfter"/>
<aop:around pointcut-ref="businessService" method="doAround"/>
<aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>
</aop:aspect>
</aop:config> -->
<!--数据库连接-->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
destroy-method="close">
<property name="driverClassName">
<value>oracle.jdbc.driver.OracleDriver</value>
</property>
<property name="url">
<value>jdbc:oracle:thin:@192.168.10.201:1521:ucs</value>
</property>
<property name="username">
<value>ucs</value>
</property>
<property name="password">
<value>ucs</value>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- iBatis 设置 -->
<!-- 数据库适配器 -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation">
<value>classpath:sqlmap-config.xml</value>
</property>
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- Dao -->
......
<!-- Service-->
......
<!-- Action -->
......
</beans>
细心的可以从配置文件中看出本例的结构 这里主要做的事是注册了一个数据库连接bean 注册了ibatis的数据适配器 省略部分是持久化bean(dao)业务逻辑bean(service)与action bean。
仔细看可能会发现<-- aop -->的配置 是的没错 这里通过xml配置方式实现aop功能 顺便分析下:
这个bean是切面类用来记录日志的
<bean id="aspectBean" class="cn.rx.oamp.aop.LogAspect" scope="prototype">
<property name="auditLogService" ref="auditLogService"></property>
</bean>
这段配置是aop的核心配置。
<aop:config proxy-target-class="true">
<aop:aspect id="TestAspect" ref="aspectBean">
<!-- 配置com.spring.service包下所有类或接口的所有方法 -->
<aop:pointcut id="businessService"
expression="execution(* cn.rx.oamp.service.impl.*.*(..))" />
<aop:before pointcut-ref="businessService" method="doBefore"/>
<aop:after pointcut-ref="businessService" method="doAfter"/>
<aop:around pointcut-ref="businessService" method="doAround"/>
<aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>
</aop:aspect>
</aop:config>
先注入上面的切面处理类。
<aop:aspect id="TestAspect" ref="aspectBean">
再来是设置切面作用域 也就是定义横切面
<!-- 配置com.spring.service包下所有类或接口的所有方法 -->
<aop:pointcut id="businessService" expression="execution(* cn.rx.oamp.service.impl.*.*(..))" />
接下来是定义切面类处理方法在什么时候切入程序
<aop:before pointcut-ref="businessService" method="doBefore"/>
<aop:after pointcut-ref="businessService" method="doAfter"/>
<aop:around pointcut-ref="businessService" method="doAround"/>
<aop:after-throwing pointcut-ref="businessService" method="doThrowing" throwing="ex"/>
before 、after 、around 、after-throwing分别表示前置处理方法(切面类作用域中的类的方法被调用前执行)、后置处理方法(调用后执行)、环绕处理方法(调用前后都执行)、异常处理方法(调用方法抛出异常时执行)。
下面是切面类源码
package cn.rx.oamp.aop;
import java.util.Date;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import cn.rx.oamp.action.BaseAction;
import cn.rx.oamp.action.PeopleAction;
import cn.rx.oamp.domain.AuditLog;
import cn.rx.oamp.pagemodel.AuditLogPR;
import cn.rx.oamp.service.dao.AuditLogService;
public class LogAspect extends BaseAction {
private Logger log = Logger.getLogger(PeopleAction.class);
private AuditLogService auditLogService;
/**
* 后置处理方法
*
* @param jp
* 连接点
*/
public void doAfter(JoinPoint jp) {
AuditLogPR auditLog = new AuditLogPR();
System.out.println("切面类输出*********************:");
System.out.println(jp.getArgs().length);
StringBuffer sb = new StringBuffer();
for (int i = 0; i < jp.getArgs().length; i++) {
sb.append(jp.getArgs()[i].toString());
}
log.info(jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName() + "" + jp.getArgs().hashCode());
log.debug(jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName());
}
/**
* 环绕处理方法
*
* @param pjp
* @return
* @throws Throwable
*/
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
long time = System.currentTimeMillis();
Object retVal = pjp.proceed();
time = System.currentTimeMillis() - time;
System.out.println("process time: " + time + " ms");
return retVal;
}
/**
* 前置处理方法
*
* @param jp
*/
public void doBefore(JoinPoint jp) {
System.out.println("切面类输出*********************: "
+ jp.getTarget().getClass().getName() + "."
+ jp.getSignature().getName());
}
/**
* 异常捕捉
*
* @param jp
* 连接点对象
* @param ex
* 异常处理对象
*/
public void doThrowing(JoinPoint jp, Throwable ex) {
}
public AuditLogService getAuditLogService() {
return auditLogService;
}
public void setAuditLogService(AuditLogService auditLogService) {
this.auditLogService = auditLogService;
}
}
关于切面类的一些扩展我就不多说了网上大把的大家想了解可以去网上找找。
applicationContext.xml文件除了做了以上所说的这些还启用了注解、设置了事务管理等。
2)、log4j.properties 这个文件我不想详细分析了内容贴出来 主要是大家注意设置日志输出级别 和日志记录的颗粒度。
log4j.properties
log4j.rootLogger=debug, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%c{1} - %m%n
log4j.logger.java.sql.PreparedStatement=DEBUG
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.com.opensymphony=DEBUG
log4j.logger.org.apache.struts2=DEBUG
log4j.logger.org.apache.axis.ConfigurationException = INFO
这几句说明一下 主要作用是输出ibatis操作数据库的一些sql语句 和传入参数 以及查询结果集等
log4j.logger.com.ibatis=DEBUG
log4j.logger.com.ibatis.common.jdbc.SimpleDataSource=DEBUG
log4j.logger.com.ibatis.common.jdbc.ScriptRunner=DEBUG
log4j.logger.com.ibatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG
log4j.logger.java.sql.Connection=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
3)、sqlmap-config.xml 这个文件是ibatis框架初始化的时候会加载的 作用是配置实体映射文件 想当于Spring中的不bean的注册 ibatis框架通过此文件找到相关的实体映射文件 在此文件中还能控制是否延迟加载 (lazyLoadingEnabled)、全局性地启用或禁用运行时字节码增强(enhancementEnabled) 、全局性地启用或禁用 SqlMapClient 的所有缓存(cacheModelsEnabled)等 。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<settings cacheModelsEnabled="true" enhancementEnabled="true"
lazyLoadingEnabled="true" useStatementNamespaces="true" />
<!-- 系统基本功能映射文件 -->
<sqlMap resource="cn/rx/oamp/domain/TB_NA_AUDIT_ACTION_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_AUDIT_LOG_ARCH_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_AUDIT_LOG_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_MENU_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_PEOPLE_LOGIN_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_PEOPLE_ROLE_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_PEOPLE_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_ROLE_MENU_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_NA_ROLE_SqlMap.xml"/>
<!-- 智能应答业务功能映射文件 -->
<sqlMap resource="cn/rx/oamp/domain/TB_REG_LOG_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_REPORT_DATA_DAY_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_REPORT_DATA_MONTH_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_REPORT_DATA_WEEK_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_SMART_DEFAULT_PLAY_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_SMART_RECORDS_PART_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_SMART_REGLOG_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_SMART_USER_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_STAT_OPTION_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_ALARM_EVENT_SqlMap.xml"/>
<sqlMap resource="cn/rx/oamp/domain/TB_ALARM_STATUS_SqlMap.xml"/>
</sqlMapConfig>
说到这个文件就会想到ibatis怎么和Spring集成的呢?大家不妨向上看看applicationContext.xml文件 上面稍微讲了一下 我们在Spring的配置文件中注册了一个ibatis的数据适配器。没错集成的关键就在这里。我们通过Spring框架提供的org.springframework.orm.ibatis.SqlMapClientFactoryBean类来注册ibatis的数据适配器 SqlMapClientFactoryBean中有一个configLocation属性 ,这个属性会加载sqlmap-config.xml 中的配置 然后把信息交给Spring ,同时SqlMapClientFactoryBean还会调用数据库连接bean来创建数据库连接以满足ibatis操作数据库的需求。这样ibatis也把控制权交给了Spring来管理。这里值得提下的是SqlMapClientFactoryBean封装了访问数据库时的异常处理在后面例子代码分析的时候我会和大家详细讲下。
4)、struts.properties struts2的属性文件先贴内容
struts.objectFactory = spring
struts.multipart.saveDir = /tmp
struts.multipart.maxSize =1000000000
其实这个文件就是Struts2与Spring集成的关键地方,
内容不多主要设置了Struts2的对象池创建工厂是Spring容器,上传文件的目录,上传文件大小的最大值
这里给个链接 struts.properties中大部分属性的说明大家可以去看看。http://www.blogjava.net/hadeslee/archive/2008/12/03/244199.html