首页 > cas, spring > cas整合Atomikos分布式事务示例

cas整合Atomikos分布式事务示例

2012年8月13日 发表评论 阅读评论

最近专注sso的研究,其中涉及到多个应用之间的数据同步问题,现阶段采用数据库方式进行融合(也就是分布式事务),也许是心理阴影(两年前使用过但是不是特别文档)使然,放弃了JOTM 这种方案,在google一下并且对比了一下,最后采用Atomikos ,理由如下:

  1. 兼容标准的SUN公司JTA API
  2. 嵌套事务
  3. 为XA和非XA提供内置的JDBC适配器
  4. 内置的JMS适配器XA-capable JMS队列连接器
  5. 通过XA API兼容第三方适配器
  6. 更好的整合您的项目(spring集成方式相当简洁)
  7. 集成Hibernate


列举一下Atomikos 在SSO使用场景:
涉及到三个系统:sso、商城、discuz论坛,用户信息以sso为中心然后同步到相应的子系统 ,涉及到注册、修改密码这些功能的地方都要需要做分布式事务保障。

技术实现:spring+aspectj+Atomikos+JDBC

配置文件:

  • applicationContext-datasource-jta.xml

<?xml version="1.0" encoding="UTF-8"?>

 <!--配置三个数据源 分别是sso服务器、 商城、discuz论坛 begin-->

 
 mysql/sso
 

 <!--  使用Mysql XADataSource(mysql>=5.0, Connector/J>=5.0才可以支持XADatasource)
 -->
 com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
 

 root
 root
 jdbc:mysql://localhost:3306/sso?useUnicode=true&characterEncoding=utf-8
 true
 true

 10


 
 mysql/tshop
 

 <!--  使用Mysql XADataSource(mysql>=5.0, Connector/J>=5.0才可以支持XADatasource)
 -->
 com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
 

 root
 root
 jdbc:mysql://localhost:3306/tshop?useUnicode=true&characterEncoding=utf-8
 true
 true

 10


 
 mysql/Discuz
 

 <!--  使用Mysql XADataSource(mysql>=5.0, Connector/J>=5.0才可以支持XADatasource)
 -->
 com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
 

 root
 root
 jdbc:mysql://localhost:3306/discuz?useUnicode=true&characterEncoding=utf-8
 true
 true

 10



  • applicationContext-jdbc-jta.xml

<?xml version="1.0" encoding="UTF-8"?>












  • applicationContext-tx-jta.xml
</pre>
</div>
&nbsp;

<?xml version="1.0" encoding="UTF-8"?>

<!--Atomikos JTA 事务 begin-->



<!-- IMPORTANT: specify all Atomikos properties here -->
com.atomikos.icatch.standalone.UserTransactionServiceFactory


<!--  Construct Atomikos UserTransactionManager,  needed to configure Spring  -->


<!-- IMPORTANT: disable startup because the userTransactionService above does this -->


<!--  when close is called,  should we force transactions to terminate or not?  -->


<!--  Also use Atomikos UserTransactionImp,  needed to configure Spring  -->



<!--  Configure the Spring framework to use JTA transactions from Atomikos  -->



<!-- 设置userService -->




java代码如下:


package casside.service;
import java.util.Calendar;
import java.util.Map;

import org.apache.commons.lang.RandomStringUtils;
import org.springframework.transaction.annotation.Transactional;

import casside.exception.CassideException;
import casside.exception.MailSendException;
import casside.exception.UserValidationException;
import casside.jdbc.SSOCenterJDBC;
import casside.jdbc.SSORegisterJDBCHandler;
import casside.tools.mail.TouserFindPasswordVO;
import casside.util.MD5;

public class UserServiceImpl implements UserService {
 private SSORegisterJDBCHandler tshopJDBC;
 private SSORegisterJDBCHandler discuzJDBC;
 private SSOCenterJDBC ssoJDBC;
 private IMailService mailService;
 @Transactional(readOnly = false)
 public void registerUser(Map params) throws CassideException{
 String username = (String)params.get("username");
 if(existUser(username)){
 throw new UserValidationException();
 }
 ssoJDBC.registerUser(params);
 discuzJDBC.registerUser(params);
 tshopJDBC.registerUser(params);
 }
 public SSORegisterJDBCHandler getTshopJDBC() {
 return tshopJDBC;
 }
 public void setTshopJDBC(SSORegisterJDBCHandler tshopJDBC) {
 this.tshopJDBC = tshopJDBC;
 }
 public SSORegisterJDBCHandler getDiscuzJDBC() {
 return discuzJDBC;
 }
 public void setDiscuzJDBC(SSORegisterJDBCHandler discuzJDBC) {
 this.discuzJDBC = discuzJDBC;
 }
 public SSOCenterJDBC getSsoJDBC() {
 return ssoJDBC;
 }
 public void setSsoJDBC(SSOCenterJDBC ssoJDBC) {
 this.ssoJDBC = ssoJDBC;
 }
 @Transactional(readOnly = true)
 public boolean existUser(String username) {
 int count=ssoJDBC.existUser(username);
 if(count==0){
 return false;
 }
 return true;
 }
 @Transactional(readOnly = true)
 public boolean existEmail(String email) {
 int count=ssoJDBC.existEmail(email);
 if(count==0){
 return false;
 }
 return true;
 }
 @Transactional(readOnly = false)
 public void updatePwd(String userName, String email)
 throws CassideException {
 if(existUser(userName)){
 Map map=findUserByUserName(userName);
 if(map.get("email").equals(email)){
 String newPwd = RandomStringUtils.randomAlphanumeric(6);
 String destPwd=MD5.MD5(newPwd);
 ssoJDBC.updatePwd(userName, destPwd);
 discuzJDBC.updatePwd(userName, destPwd);
 tshopJDBC.updatePwd(userName, destPwd);

 TouserFindPasswordVO vo = new TouserFindPasswordVO();
 vo.setNewPassword(newPwd);
 vo.setSendTime(Calendar.getInstance().getTime());
 vo.setUserName(userName);
 vo.setSiteName("Tshop");
 vo.setToMail(email);
 try {
 mailService.sendeMailTouserFindPassword(vo);
 } catch (Exception e) {
 e.printStackTrace();
 throw new MailSendException();
 }
 }else{
 throw new UserValidationException();
 }
 }else{
 throw new UserValidationException();
 }
 }
 @Transactional(readOnly = true)
 public Map findUserByUserName(String userName) throws CassideException {
 return ssoJDBC.findUserByUserName(userName);
 }
 public IMailService getMailService() {
 return mailService;
 }
 public void setMailService(IMailService mailService) {
 this.mailService = mailService;
 }
}

期间遇到的问题:

  1. Mysql版本太低不支持XA,必须使用Mysql XADataSource(mysql>=5.0, Connector/J>=5.0才可以支持XADatasource
  2. cas 内部使用的是注解事务配置,我开始没有了解到,使用TransactionProxyFactoryBean作为UserService的配置处理,一个spring控制领域内出现了两种不同的 声音,让我纠结了好久,最后在翻阅源码的时候才惊醒,特此记下。

文章转自:http://www.iitshare.com/cas-integration-atomikos-distributed-transaction.html

除非注明,文章为IT热血青年原创,欢迎转载!转载请注明本文地址,谢谢。
本文地址:http://blog.itblood.com/cas-atomikos-distributed-transaction-case.html

  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.