http://www.springsource.org/
下载:http://repo.spring.io/release/org/springframework/spring
或者到http://repo.spring.io->Artifacts->搜索spring-framework-4.x.x.RELEASE
spring是一个设计层面的框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
******************************************************************
一:
最少jar包:
spring-beans-*.jar
spring-context-*.jar
spring-core-*.jar
spring-expression-*.jar
spring-aop-*.jar(4.0以上)
commons-logging-*.jar(struts)
自动提示:xml在schema中找
配置xml(参考文档7.2)
控制反转IOC:Inversion of control
依赖注入DI:Dependency injection
spring注入:
set注入(重要)
构造注入
属性注入
采用p:属性='值' or p:属性-ref=''方式注入(引入头7.4.2)
<bean id='' class='' p:person="张嘎"/>
<bean>中的name属性和id属性一样(name可以使用特殊字符(ey:/ &),可以重名,spring3.1开始id也支持特殊符号)
直接属性值注入:value 属性 少用
bean的生存范围:scope 属性 (文档) 默认singleton prototype(原型) request session...
自动注入autowire:
单个配:在<bean/>中配autowire(byName,byType:只能有1个类型匹配才行,如果两个同类型则报异常,对注解同样有效,无需@Autowired)
配全局:在<beans/>中配default-autowire="byName",默认是no
<bean/>里可以不配,因为默认为default
bean生命周期:(只适用于singleton,prototype的生命周期容器不能控制)
lazy-init(也分局部和全局)
init-method="方法名"、destroy-method="方法名"
要使destroy-method执行使用:ApplicationContext接口的实现类
AbstractApplicationContext ctx = ...
ctx.close();
集合注入:查文档collections(7.4.2)
List、Set、Map、Properties
annotation:(4.0以上依赖aop包)
1、配置xml的context头(参考文档7.9)
<context:annotation-config/>(可选,被componet-scan集成)
<context:component-scan base-package="com.cssl"/>(必须有)
2、@Autowired默认是byType,如果找到多个类型匹配的,则按byName进行注入,如果还找不到对应bean,则报异常
3、多个类型在set方法上或者方法的参数前加 @Qualifier("id的名称")
4、@Resource(name="uDao") 默认是byName,没有则按byType,byType又有多个则异常
name属性解析为bean的名字,而type属性则解析为bean的类型
@Resource(name="usersDao",type=UsersDaoImpl.class)
5、@Component, @Repository, @Service, @Controller效果一样,默认id为类名首字母小写
6、@PostConstruct(init-method) and @PreDestroy(destroy-method)
7、@Scope("prototype")
8、@Value()注入固定值
注解可以不写set方法直接注解到属性上
******************************************************************
二、AOP
A、AOP:Aspect Oriented Programming(见帮助文档11)
引入aspectjweaver和aopalliance的包和spring-aop-x.jar 包
另外转二进制包cglib(无接口的类被代理的情况下使用,spring3.2以上已经集成此包)
JoinPoint 连接点
PointCut 切入点(连接点集合)(切入点一般是定义在方法上,其实也可以在属性甚至类上)
Aspect 切面(切面逻辑类)
Advice 切面对于某个“连接点”所产生的动作,before、after、around(切入点建议)
Target 被织入的对象(被一个或者多个切面所通知的对象)
Weaving 织入
aspectJ语法:11.2.3
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
modifiers-pattern:方法的操作权限
ret-type-pattern:返回值
declaring-type-pattern:方法所在的包
name-pattern:方法名
parm-pattern:参数名
throws-pattern:异常
public * com.cssl.service..*.*(..)
within:spring自己的aop语法
B、annotation配置:
1、xml中必须加<aop:aspectj-autoproxy/>
2、类上加@Aspect(切面逻辑)、@Component
3、织入方法上写@Before(
"execution(public void com.cssl.UserDao.save(com.cssl.Users))")
4、也可以使用@AfterReturning|@After|@Around|@AfterThrowing
5、@AfterReturning只有方法没有抛出异常的情况下执行,不管是否有返回值
6、切面类上加@Order(1)决定哪个切面先执行
注意:
1、这里execution都是切入方法的语法
@AfterThrowing要起作用必须是该切面上的方法抛出了异常(不能在切面方法中处理或调用切面方法的aspect类处理)
2、写通用织入方法:(MyEclipse2014环境下不识别@Pointcut因为JDK7必须匹配aspectjweaver1.7.x)
@Pointcut("execution(public * com.cssl..*.*(..))")
public void cutAll(){};
3、其他方法引入该织入点11.2.4
@Before("cutAll()") || @Before("Logger.cutAll()")
public void before(){}
4、拦截含有参数的方法,并将参数值注入到当前方法的形参id,name中
@Before("cutAll()&&args(id,name)")
public void before(int id,String name)
5、获取被切入方法的返回值
@AfterReturning(pointcut="cutAll()",returning="result")
public void afterReturn(JoinPoint jp,Object result)
C、Spring提供的环绕处理类:
1.)ProceedingJoinPoint proceed()
public void around(ProceedingJoinPoint pjp) throws Throwable{
...
//这里如果异常是自己处理了则@AfterThrowing捕获不到service方法抛出的异常
pjp.proceed();
...
}
2.)JoinPoint
@AfterReturning(pointcut="cut()",returning="result")
public void afterMethod(JoinPoint jp,Object result){
System.out.println(jp.getTarget());
//result被代理方法返回值
System.out.println("结束日志记录...:"+result);
}
D、xml配置:常用,特别是在切面逻辑是第三方提供的情况下
<aop:config>...</aop:config>
<aop:config>
<aop:pointcut expression="execution(* com.cssl.service..*.add(..))" id="cutAll"/>
<aop:aspect ref="logInfo">
<aop:before method="before" pointcut="execution(public * com..*.*(int)) and args(id)" />
<aop:after-returning method="afterReturn" pointcut-ref="cutAll" returning="result"/>
</aop:aspect>
</aop:config>
等同下面
<aop:config>
<aop:aspect id="asp" ref="logInfo">
<aop:before method="before" pointcut="execution(* com.cssl.service..*.add(..))"/>
</aop:aspect>
</aop:config>
Spring的AOP实现:4种(没有AfterAdvice)
MethodBeforeAdvice
前置通知: 在某连接点JoinPoint之前执行的通知,但这个通知不能阻止连接点前的执行。
AfterReturningAdvice
返回后通知:在某连接点正常完成后执行的通知,不包括抛出异常的情况。
MethodInterceptor
环绕通知: 包围一个连接点的通知,类似Web中的Filter的doFilter方法。
ThrowsAdvice
异常通知: 在方法抛出异常退出时执行的通知。
必须使用下面的方法签名:
void afterThrowing([Method method, Object[] arguments, Object target,] Throwable ex)
或者使用:(注意advice-ref引用的bean必须是Advice接口的实现类)
<aop:config>
<aop:pointcut expression="execution(public * com.cssl.service..*.*(..))" id="cut"/>
<aop:advisor advice-ref="myBeforeAdvice" pointcut-ref="cut"/>
</aop:config>
Filter和Interceptor都是典型的面向切面编程
*****************************************************************************************
三、 Spring整合Hibernate4:Data Access(帮助文档17)
导入hibernate包、spring的orm、jdbc、tx包
使用属性配置文件:占位符的方式(${这里绝对不要多加空格}|不要使用byType byName自动注入)
<bean id="ppc" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:jdbc.properties"></property>
</bean>
也可以配置:
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 纯jdbc数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<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.springframework.orm.hibernate4.LocalSessionFactoryBean"
destroy-method="destroy">
<property name="dataSource" ref="dataSource" />
<!--
<property name="annotatedClasses">
<list>
<value>com.cssl.pojo.User</value>
<value>com.cssl.pojo.Log</value>
</list>
</property>
注解
<property name="packagesToScan">
<list>
<value>com.cssl.pojo</value>
</list>
</property>
xml方式
<property name="mappingDirectoryLocations">
<list>
<value>classpath:com/cssl/pojo/</value>
</list>
</property>
-->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.OracleDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- 没有整合spring的事务的时候使用Hibernate的线程管理thread -->
<prop key="hibernate.current_session_context_class">thread</prop>
<!-- 同thread 整合事务后spring可以不配置,如果要配置必须配置spring的currsession管理 -->
<!--<prop key="hibernate.current_session_context_class">org.hibernate.context.internal.ThreadLocalSessionContext</prop>-->
<!--整合spring事务的时候必须使用spring线程管理-->
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext</prop>
<!-- 和javaEE6冲突,解决beanValidate异常 -->
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
</bean>
如果想仍然使用hibernate.cfg.xml:(不用再配置数据库连接,无法注入sessionFactory)
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="configLocations">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
自动搜索实体包(含子包):packagesToScan(annotation) mappingDirectoryLocations(xml)
事务管理:默认catch到RuntimeException自动回滚:(对于手动处理的异常spring不再管理)
(DataAccessException|HibernateException)
<bean id="tx"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="tx">
<tx:attributes>
<tx:method name="exists" read-only="true" />
<tx:method name="add*" propagation="REQUIRED"/>
<tx:method name="*" read-only="true"
rollback-for="DataAccessException"
no-rollback-for="NullPointerException,ClassCastException" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="bussinessService"
expression="execution(public * com.cssl.service..*.*(..))" />
<aop:advisor pointcut-ref="bussinessService"
advice-ref="txAdvice" />
</aop:config>
readOnly:true|false 用于查询提高效率和防止意外插入、删除、更新操作
timeout :事务超时时间,有的数据库事务不支持(mysql事务不支持、oracle注意驱动版本)
bug:
spring3.x整合hibernate4.3.0以上有:
ClassNotFoundException
org.hibernate.service.jta.platform.spi.JtaPlatform
hibernate4.3这个文件的位置变了orghibernateengine ransactionjtaplatformspi导致spring引用出错
使用spring4以上版本整合已修复此bug
事务传播机制:文档17.5(了解)
propagation(查spring_api:org.springframework.transaction.annotation.Propagation共7种,用Required)
REQUIRED:业务方法需要在一个事务里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,否则自己新建一个新的事务。
REQUIRES_NEW:不管是否存在事务,该方法总会为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。
NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中。它是已经存在事务的一个真正的子事务,如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的savepoint。内部事务的回滚不会对外部事务造成影响。
嵌套事务是外部事务的一部分, 只有外部事务结束后它才会被提交。
使用NESTED必须
1、在transactionManager中配置<property name="nestedTransactionAllowed" value="true"/>默认false
2、java.sql.Savepoint 必须存在, 即 jdk 版本要 1.4+
3、jdbc drive 必须支持 JDBC 3.0
注意:
同一个业务类里面,即使声明为 Propagation.REQUIRES_NEW也不会新启一个事务。必须调用另一个类的Propagation.REQUIRES_NEW方法才行,这样每个方法都是独立的事务,是互不影响的,外部事务的回滚不会影响内部事务的提交(不同于NESTED外部事务回滚内部事务也回滚),但如果内部事务回滚(抛出了异常),则相当外部事务的方法也抛出了异常(没有处理的情况)也将回滚!
其他方式整合事务:
annotation方式、拦截器方式、spring AOP方式。。。
annotation事务:
<tx:annotation-driven transaction-manager="txManager"/>
方法前加@Trasactional:(默认Required)
注意:Spring+Hibernate整合问题
1、spring3.1开始支持hibernate4
2、spring4.x整合hibernate4.x可以使用HibernateTemplate类或者HibernateDaoSupport(Template method设计模式)
3、使用继承HibernateTemplate类或HibernateDaoSupport类的方式可以使用xml方式直接注入SessionFactory,
但是如果想用annotation注入SessionFactory就需要重写setSessionFactory方法,然后在方法上用注解。
继承HibernateTemplate可以重写,但继承HibernateDaoSupport不能重写因为该方法为final,所以必须写个其他方法在方法里调用setSessionFactory方法。
4、spring3.x整合hibernate4.x不再支持HibernateTemplate及HibernateDaoSupport(Spring3.1以上的事务实现和hibernateTemplate相冲突)
5、orm的hibernate3.x分xml和annotation的SessionFactory
6、必须使用getCurrentSession(),current_session_context_class对应的class设置为org.springframework.orm.hibernate4.SpringSessionContext或者不指定,在此类中获取session时就已经把事务开启了。
Spring测试框架:导入spring的test包
分Junit3.8和Junit4
(spring4.1.6只支持Junit4.9+hamcrest1.3)
(spring4.3只支持Junit4.12+hamcrest1.3)
数据库现场不受破坏,事务自动回滚(propagation="REQUIRED")
@ContextConfiguation(locations="/applicationContext.xml")
@Rollback(false) //默认为true
//@TransactionConfiguration(过期)
public class STest extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
private ApplicationContext applicationContext;
@Autowired
private IService petService;
@Test
public void testPet(){
this.petService.add();
}
}
*****************************************************************************************
四、spring整合struts2
无缝整合:
需要导入
struts2中8个基本包和struts2-spring-plugin.jar、
spring4中导入spring-web-x.x.x.RELEASE.jar (web-mvc可以不用导)
删除javassist3.x,保留新版本 加入 aopalliance aspectjweave 包
struts-plugin.xml:
<bean type="com.opensymphony.xwork2.ObjectFactory" name="spring" class="org.apache.struts2.spring.StrutsSpringObjectFactory" />
<constant name="struts.objectFactory" value="spring" />
struts.xml可以不用配
struts.objectFactory.spring.autoWire是用spring插件通过覆盖(override)Struts2的ObjectFactory来增强核心框架对象的创建。当创建一个对象的时候,它会用Struts2配置文件中的class属性去和Spring配置文件中的id属性进行关联,如果能找到则由Spring创建,否则由Struts2框架自身创建,然后由Spring来装配。(默认都采用byName方式注入业务类到Action)
步骤:配置web.xml增加spring的监听器
配置web.xml:
struts help spring-plugin
spring help
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
<!-- default: /WEB-INF/applicationContext.xml -->
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<!-- <param-value>/WEB-INF/applicationContext-*.xml,classpath*:applicationContext-*.xml</param-value> -->
<param-value>classpath:applicationContext.xml</param-value> //类路径src
</context-param>
如果class仍然使用的是类路径则所有的action将由struts管理,而且会自动根据byName注入所有的set属性
可以通过配置常量改为byType:
<constant name="struts.objectFactory.spring.autoWire" value="type"/>
改成type拦截器报找不到result:input(疑似bug)
使用Spring容器管理Action对象及他的生命周期prototype、request...
Action中的属性注入也必须配置!
使用通配符:
<action name="*-*" class="{1}Action" method="{2}">
<result>/success.jsp</result>
</action>
class对应spring的bean id
<bean id="usersAction" class="com.cssl.actions.UsersAction" scope="prototype">
<property name="usersBiz" ref="userBiz"></property>
</bean>
<bean name="petsAction" class="com.cssl.actions.PetsAction" scope="session">
<property name="usersBiz" ref="userBiz"></property>
</bean>
在Web环境下,scope还可以使用request,session,global session!
当使用了Spring's DispatcherServlet(springmvc)以外的Servlet 2.5及以上的Web容器时(如使用JSF或Struts),都只需要在Web应用的'web.xml'文件中增加配置:(5.5.4)
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
才能让Spring感知
2.4及以下版本必须使用过滤器:
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
global session仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境,等同于session
注意:session级别同一会话只产生一次Action对象,对于addFieldError将累加错误信息(累加到set)
PO<->VO(DTO):
1、导包dozer-4.2.jar,自定义两个方法
public static void copyProperties(Object src,Object desc){
MapperIF mif = new DozerBeanMapper();
mif.map(src, desc);
}
public static <T> T copyProperties(Object src,Class<T> clazz){
MapperIF mif = new DozerBeanMapper();
return (T) mif.map(src, clazz);
}
2、使用spring自带工具org.springframework.beans.BeanUtils
BeanUtils.copyProperties(source, target)
3、使用struts自带工具org.apache.commons.beanutils.BeanUtils;
BeanUtils.copyProperties(dest, orig)
注意:根据属性名来转换,同名不同类型将注入null
*****************************************************************************************
五、Spring整合MyBatis|JDBC
spring整合mybatis:导包mybatis-spring-1.x.x.jar(mybatis3.4需要1.3+)
<!-- sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
//下面两个可以二选一
<property name="configLocation" value="classpath:mybatis-config.xml"/> //核心配置
<property name="mapperLocations" value="classpath:com/cssl/pojo/*.xml"/> //映射文件
</bean>
<!-- 为每一个dao生成对应的id,一定要注入sqlSessionFactory -->
<bean id="udao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.cssl.dao.UsersDao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
或者使用扫描包下所有类:
注意:
1、sqlSessionFactory可以不用注,可以没有id,自动将dao包下接口根据接口名第一个字母小写生成id名
2、如果使用了default-autowire="byName",DataSource必须使用字符串常量
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cssl.dao"></property>
</bean>
<!-- 事务 -->
<!-- 不加事务每个dao方法为一个事务(和数据库无关),所以我们必须改变事务边界到service -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:config/>和<tx:advice/>配置同hibernate
mybatis-spring-1.x.x.jar中也有支持SqlSessionTemplate和SqlSessionDaoSupport
mybatis整合javaee6后junit测试有bug
Hibernate、MyBatis和JDBC的Template回调机制(模版方法设计模式)
JdbcTemplate和DaoSupport用法(template用的多DaoSupport少)
public List find(final String hql, final int page, final int size) {
List result = getHibernateTemplate().execute(
new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
Query query = session.createQuery(hql);
query.setFirstResult((page - 1) * size);
query.setMaxResults(size);
return query.list();
}
}
);
return result;
}
HibernateTemplate传递给回调接口的session并不是org.hibernate.impl.SessionImpl类,而是SessionImpl类的一个Proxy类。HibernateTemplate的注释说明,Proxy提供了一些额外的功能,包括自动设置Cachable,Transaction的超时时间,Session资源的更积极的关闭等等。
但遗憾的是,Hibernate的DetachedCriteria的setExecutableCriteria方法却要求将session参数强制转为SessionImpl,但是spring传过来的却是一个Proxy类,因此Spring2.5以后用executeWithNativeSession方法传递参数true强制使用SessionImpl
Spring+JDBC: queryForXXX()|query()
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
Users u = template.queryForObject(sql,new BeanPropertyRowMapper<Users>(Users.class));
List<Users> users = template.query(sql,new BeanPropertyRowMapper<Users>(Users.class));
String sql = "select name from users";
System.out.println(this.template.queryForList(sql, String.class));
List<Users> list = template.query(sql, new RowMapper<Users>(){
@Override
public Users mapRow(ResultSet rs, int rowNum) throws SQLException {
//rowNum=0
//不能加判断
//if(rs.next()){
System.out.println(rs.getInt("id")+":"+rs.getString("name"));
Users u = = new Users();
u.setId(rs.getInt(1));
u.setName(rs.getString(2));
//}
return u;
}
});
List<Map<String, Object>> list = this.template.queryForList(sql);
//调用存储过程 mydb->demo
this.template.execute(new CallableStatementCreator(){
@Override
public CallableStatement createCallableStatement(Connection conn) throws SQLException {
...
}
}, new CallableStatementCallback<Integer>(){
@Override
public Integer doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException {
...
}
});
或:
this.template.execute("{call demo(?,?)}", new CallableStatementCallback<Object>() {
@Override
public Object doInCallableStatement(CallableStatement cs)
throws SQLException, DataAccessException {
...
return out;
}
});
*****************************************************************************************
六、Spring+Struts2+DWR整合
1、DWR整合:(如果使用纯注解方式还要导包spring-webmvc包)
第一种方式:
仍然使用dwr自己的原生的servlet:
org.directwebremoting.servlet.DwrServlet
仍然使用dwr.xml文件配置dwr信息
只需要将原来的creator的new改成spring,
name值由原来的class改成beanName,
value的值由原来的类路径改成spring的id属性的值
dwr.xml建议放置在WEB-INF下
第二种方式:
使用spring管理dwr的servlet:
org.directwebremoting.spring.DwrSpringServlet
不在需要dwr.xml文件
在spring的配置文件中配置dwr信息:
添加头:
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd
<!-- dwr集成spring配置 -->
<bean id="usersDwr" class="com.cssl.dwr.UsersDwr">
<property name="usersBiz" ref="userBiz"/>
<dwr:remote javascript="UsersDwr">
<dwr:include method="getUsersSize" />
<dwr:convert type="bean" class="com.cssl.vo.UsersVo" javascript="users"/>
</dwr:remote>
</bean>
2、其他数据源形式:hibernate.cfg.xml不要再配置数据库连接,否则报BasicDataSource NotSupport
A、使用dbcp连接池
使用连接池导commons-dbcp-1.4.jar和commons-pool-1.6.jar
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="maxActive" value="100" />
<property name="maxIdle" value="30" />
<property name="maxWait" value="3000" /> 拿到连接3秒不用自动被容器回收
</bean>
B、C3P0连接池:
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!-- 指定连接数据库的驱动 -->
<property name="driverClass" value="${jdbc.driverClassName}"/>
<!-- 指定连接数据库的URL -->
<property name="jdbcUrl" value="${jdbc.url}"/>
<!-- 指定连接数据库的用户名 -->
<property name="user" value="${jdbc.username}"/>
<!-- 指定连接数据库的密码 -->
<property name="password" value="${jdbc.password}"/>
<!-- 指定连接数据库连接池的最大连接数 -->
<property name="maxPoolSize" value="30"/>
<!-- 指定连接数据库连接池的最小连接数 -->
<property name="minPoolSize" value="3"/>
<!-- 指定连接数据库连接池的初始化连接数 -->
<property name="initialPoolSize" value="1"/>
<!-- 指定连接数据库连接池的连接的最大空闲时间 -->
<property name="maxIdleTime" value="20"/>
</bean>
C、来至于JNDI Java Naming and Directory Interface (使用tomcat作为实例)
必须在web环境下使用
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
//代表命名服务目录名称为jdbc/mysql(实际为:java:comp/env/jdbc/testDB)
<property name="jndiName" value="jdbc/mysql"></property>
//加上这个的意思是不用使用java:comp/env/jdbc/testDB来设置jndiName
<property name="resourceRef" value="true"></property>
</bean>
或者使用
在xml使用jee命名空间
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/testDB" resource-ref="true" />
oracle11G出现的问题:
oracle.jdbc.driver.OracleDatabaseMetaData.supportsGetGeneratedKeys()Z
在hibernate框架上就很容易出现上面的错误,推荐大家使用下面的包ojdbc14_1_.jar
3、懒加载问题:
OpenSessionInView:(解决load及懒加载问题,扩大session范围到view)
org.springframework.orm.hibernate4.support.OpenSessionInView
<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<!-- 默认sessionFactory,可以省略这个配置 -->
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
MyBatis懒加载不需要写过滤器控制事务,业务层提交事务后每一条sql查询自动为一个独立事务!
注意包冲突问题:javassist-x.x.x 版本冲突(ssh整合javassist包删低版本)
懒加载问题:
com.cssl.pojo.Users_$$_javassist_0 cannot be cast to javassist.util.proxy.Proxy
使用了OpenSessionInView模式,Session的生命周期变长。虽然解决了Lazy Load的问题,但是带来的问题就是Hibernate的一级缓存,也就是Session级别的缓存的生命周期会变得更长,那么如果你在你的Service层做大批量的数据操作时,其实这些数据会在缓存中保留一份,这是非常耗费内存的。还有一个数据库连接的问题,存在的原因在于由于数据库的Connection是和Session绑在一起的,所以,Connection也会得不到及时的释放。因而当系统出现业务非常繁忙,而计算量又非常大的时候,往往数据连接池的连接数会不够。
spring解决中文问题:(struts2.1.6有中文bug)
org.springframework.web.filter.CharacterEncodingFilter
<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>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
注意事项:
1、openSessionInView在web.xml中的配置必须在struts2的filter前面(必须struts处理完才提交,和过滤器链的执行顺序有关,先等struts过滤器执行完再执行提交的过滤器),如果没有配置事务,该过滤器会在dao层加只读事务
2、注意必须使用sessionFactory,如果不是则必须在filter中配置
init-param name:seesionFactoryBeanName value:新的beanName(sf)
3、注意openSessionInView默认会认为所有事务是只读的,如果进行增删改操作会报写操作不允许异常(前提是spring本身没有配置事务)
4、获取当前的spring容器
方法一:(通过ServletContext加载spring容器)
ApplicationContext ctx=WebApplicationContextUtils.getWebApplicationContext(application);
方法二:(获取当前的spring容器,任何java类中适用)
ApplicationContext act=ContextLoader.getCurrentWebApplicationContext();
方法三:(重新加载spring容器)
ApplicationContext ac=new FileSystemXmlApplicationContext("applicationContext.xml");