Maven+SSM——自动切换多数据源

项目说明:

框架:Spring + Spring MVC + Mybatis + AspectJ

开发环境:jdk1.7,Tomcat7

使用框架AspectJ实现自动切换多数据源,原理是AOP技术,类似于过滤器、监听器、拦截器底层也都是与AOP技术相似,都是将某个你想要做处理的“块”,当成切面或切点。Maven如何创建,我并没有作说明,因为网上的例子实在是太多了,如果有需要我也会添加上的。

本文大部分大部分是代码的实例,一些说明我都写在代码中的注释中了,唯有AspectJ框架需要道友们自己上网查了,这块的知识点还挺丰富的。最后,代码如有不足之处请多指教!

代码展示

pom.xml文件


	4.0.0
	com.test.multipleSource
	multipleSource-ssm
	war
	0.0.1-SNAPSHOT
	multipleSource-ssm Maven Webapp
	http://maven.apache.org

	
		
		4.0.2.RELEASE
		
		3.2.6
		
		1.7.7
		1.2.17
	

	
		
			org.springframework
			spring-aspects
			${spring.version}
		

		
			org.springframework
			spring-orm
			${spring.version}
		
		
			junit
			junit
			4.11
			
			test
		
		
		
			org.springframework
			spring-core
			${spring.version}
		

		
			org.springframework
			spring-web
			${spring.version}
		
		
			org.springframework
			spring-oxm
			${spring.version}
		
		
			org.springframework
			spring-tx
			${spring.version}
		

		
			org.springframework
			spring-jdbc
			${spring.version}
		

		
			org.springframework
			spring-webmvc
			${spring.version}
		
		
			org.springframework
			spring-aop
			${spring.version}
		

		
			org.springframework
			spring-context-support
			${spring.version}
		

		
			org.springframework
			spring-test
			${spring.version}
		
		
		
			org.mybatis
			mybatis
			${mybatis.version}
		
		
		
			org.mybatis
			mybatis-spring
			1.2.2
		
		
		
			javax
			javaee-api
			7.0
		
		
		
			mysql
			mysql-connector-java
			5.1.30
		
		
		
			jstl
			jstl
			1.2
		
		
		
		
			log4j
			log4j
			${log4j.version}
		
		
			org.codehaus.jackson
			jackson-mapper-asl
			1.9.13
		
		
		
			commons-fileupload
			commons-fileupload
			1.3.1
		
		
			commons-io
			commons-io
			2.4
		
		
			commons-codec
			commons-codec
			1.9
		

		
			net.sf.json-lib
			json-lib
			2.4
			jar
			jdk15
		
		
			commons-beanutils
			commons-beanutils
			1.8.0
		
		
			commons-collections
			commons-collections
			3.2.1
			compile
		
		
			commons-lang
			commons-lang
			2.5
			compile
		
	

	
		multipleSource-ssm
		

			
				org.apache.tomcat.maven
				tomcat6-maven-plugin
				2.1
				
					http://localhost:9080
					tomcat6
					8080
					UTF-8
				
			
		
	

spring-mvc.xml文件




	
	
	
	
	
	
	
	
	
		
			
				text/html;charset=UTF-8
			
		
	
	
	
		
			
					
			
		
	
	
	
		
		
		
	

	
	
		
			
				
					
						application/json;charset=UTF-8
					
				
			
		
	

spring-mybatis.xml



	

	
	
		
	

	
		
		
		
		
	

	
		
		
		
		
	

	
		
			
				
				
			
		
		
		
	

	
	
		
		
		
			
				classpath:com/multiple/master/mapper/*.xml
				classpath:com/multiple/secondary/mapper/*.xml
			
		
	

	
	
		
		
	

	
	
		
	

jdbc.properties

driver=com.mysql.jdbc.Driver
masterUrl=jdbc:mysql://127.0.0.1:3306/master
secondaryUrl=jdbc:mysql://127.0.0.1:3306/secondary
username=root
password=root
initialSize=0
maxActive=20
maxIdle=20
minIdle=1
maxWait=60000

log4j.properties

log4j.rootLogger=INFO,Console,File
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n

log4j.appender.File = org.apache.log4j.RollingFileAppender
log4j.appender.File.File = logs/ssm.log
log4j.appender.File.MaxFileSize = 10MB
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n

web.xml



	Archetype Created Web Application
	
	
		contextConfigLocation
		classpath:spring-mybatis.xml
	
	
	
		encodingFilter
		org.springframework.web.filter.CharacterEncodingFilter
		true
		
			encoding
			UTF-8
		
	
	
		encodingFilter
		/*
	
	
	
		org.springframework.web.context.ContextLoaderListener
	
	
	
		org.springframework.web.util.IntrospectorCleanupListener
	
	

	
	
		SpringMVC
		org.springframework.web.servlet.DispatcherServlet
		
			contextConfigLocation
			classpath:spring-mvc.xml
		
		1
		true
	
	
		SpringMVC
		
		/
	
	
		/index.jsp
	

工程的目录结构图

Maven+SSM——自动切换多数据源_第1张图片

在目录结构上我分com.multiple.master、com.multiple.secondary,这是为了对应AOP的拦截路径

Maven+SSM——自动切换多数据源_第2张图片

DynamicDataSource.java

package com.multiple.utils;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * @author Wh
 * 一个动态数据源
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

	public static final String DATA_SOURCE_MASTER = "dataSourceMaster";	//主数据源名称。与XML文件中名称对应
	public static final String DATA_SOURCE_SECONDARY = "dataSourceSecondary";	//从数据源名称。与XML文件中名称对应
	private static final ThreadLocal contextHolder = new ThreadLocal();

	/**
	 * 参数为要切换的数据源名称,就是上面的final变量
	 * @param customerType
	 */
	public static void setCustomerType(String customerType) {
		contextHolder.set(customerType);
	}

	/**
	 * 通过线程的方式获取数据源,目的是为了在并发的情况下依然能够正常切换
	 * @return
	 */
	public static String getCustomerType() {
		return contextHolder.get();
	}

	/**
	 * 用于关闭当前切换的数据源
	 */
	public static void clearCustomerType() {
		contextHolder.remove();
	}

	/**
	 * @author Wh
	 * 这个用于切换动态数据源必须要实现的一个方法
	 */
	@Override
	protected Object determineCurrentLookupKey() {
		return getCustomerType();
	}

}

ServiceAspect.java

package com.multiple.utils;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author Wh
 * 通过AOP实现对数据源的自动切换,AOP是Spring的核心。通过AspectJ框架实现对AOP的操作
 */
@Component
@Aspect
// 设置当前加载的顺序
@Order(-1)
public class ServiceAspect {

	/**
	 * 设置切点:路径为Secondary层的service层,*.*(..)代表其service报下的所有类和方法
	 */
	@Pointcut("execution(* com.multiple.secondary.service.*.*(..))")
	public void aspect() {
	}

	/**
	 * @param joinPoint
	 * 进入切点方法之前(切点是专业术语,在本文中就是你要切换数据源的的方法)
	 * 切换数据源,当一个工程中两个数据源时可以对不常用的数据源写死,因为工程中必定有一个主数据源,当超过两个以上的数据源时可以通过传参的形式到该方法中
	 */
	@Before("aspect()")
	public void before(JoinPoint joinPoint) {
		DynamicDataSource
				.setCustomerType(DynamicDataSource.DATA_SOURCE_SECONDARY);
	}

	/**
	 * @param joinPoint
	 * 当退出切点方法之后,关闭所切换额数据源
	 */
	@After("aspect()")
	public void after(JoinPoint joinPoint) {
		DynamicDataSource.clearCustomerType();
	}

	/**
	 * @param joinPoint
	 * @param ex
	 * 针对当前拦截的切点方法中出现异常时所做的处理
	 */
	@AfterThrowing(pointcut = "aspect()", throwing = "ex")
	public void afterThrow(JoinPoint joinPoint, Exception ex) {
		DynamicDataSource.clearCustomerType();
	}

}

Master数据源

Goods.java

package com.multiple.master.entity;

import java.util.Date;

/**
 * @author Wh
 * 商品表
 */
public class Goods {

	private String uuid; // uuid
	private String goodsName; // 商品名称
	private float prices; // 商品价格
	private Date generateDate; // 生成日期
	private int number; // 商品数量

	public String getUuid() {
		return uuid;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	public String getGoodsName() {
		return goodsName;
	}

	public void setGoodsName(String goodsName) {
		this.goodsName = goodsName;
	}

	public float getPrices() {
		return prices;
	}

	public void setPrices(float prices) {
		this.prices = prices;
	}

	public Date getGenerateDate() {
		return generateDate;
	}

	public void setGenerateDate(Date generateDate) {
		this.generateDate = generateDate;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

}

GoodsMapper.xml






	

GoodsMapper.java

package com.multiple.master.dao;

import java.util.List;

import com.multiple.master.entity.Goods;

public interface GoodsMapper {

	List queryGoodsList();

}

IGoodsService.java

package com.multiple.master.service;

import java.util.List;

import com.multiple.master.entity.Goods;

public interface IGoodsService {

	List queryGoodsList();

}

GoodsServiceImpl.java

package com.multiple.master.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.multiple.master.dao.GoodsMapper;
import com.multiple.master.entity.Goods;
import com.multiple.master.service.IGoodsService;

/**
 * @author Wh
 * Master数据库下商品表的业务层
 */
@Service("goodsService")
public class GoodsServiceImpl implements IGoodsService {

	@Resource
	private GoodsMapper goodsMapper;

	@Override
	public List queryGoodsList() {
		return goodsMapper.queryGoodsList();
	}

}


Secondary层

Orders.java

package com.multiple.secondary.entity;

/**
 * @author Wh
 * 订单表
 */
public class Orders {

	private String uuid; // 订单uuid
	private String goods_uuids; // 商品UUID组
	private float orderPrice; // 订单价格

	public String getUuid() {
		return uuid;
	}

	public void setUuid(String uuid) {
		this.uuid = uuid;
	}

	public String getGoods_uuids() {
		return goods_uuids;
	}

	public void setGoods_uuids(String goods_uuids) {
		this.goods_uuids = goods_uuids;
	}

	public float getOrderPrice() {
		return orderPrice;
	}

	public void setOrderPrice(float orderPrice) {
		this.orderPrice = orderPrice;
	}

}

OrdersMapper.java

package com.multiple.secondary.dao;


import java.util.List;


import com.multiple.secondary.entity.Orders;


public interface OrdersMapper {


	List queryOrdersList();


}

OrdersMapper.xml








	



IOrdersService.java

package com.multiple.secondary.service;

import java.util.List;

import com.multiple.secondary.entity.Orders;

public interface IOrdersService {
	
	List queryOrdersList();

}

OrdersServiceImpl.java

package com.multiple.secondary.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import com.multiple.secondary.dao.OrdersMapper;
import com.multiple.secondary.entity.Orders;
import com.multiple.secondary.service.IOrdersService;

/**
 * @author Wh
 * Secondary数据库下的订单表的业务层
 */
@Service("ordersService")
public class OrdersServiceImpl implements IOrdersService {
	
	@Resource
	private OrdersMapper ordersMapper;


	@Override
	public List queryOrdersList() {
		return ordersMapper.queryOrdersList();
	}

}

TestController.java

package com.multiple.controller;

import java.io.UnsupportedEncodingException;
import java.util.List;

import javax.annotation.Resource;

import net.sf.json.JSONArray;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.multiple.master.entity.Goods;
import com.multiple.master.service.IGoodsService;
import com.multiple.secondary.entity.Orders;
import com.multiple.secondary.service.IOrdersService;

/**
 * @author Wh
 * 一个测试的Controller类
 */
@Controller
@RequestMapping("/testController")
public class TestController {

	@Resource
	@Qualifier("goodsService")
	private IGoodsService goodsService;

	@Resource
	@Qualifier("ordersService")
	private IOrdersService ordersService;

	/**
	 * 
	 * 实现对Master数据库的信息查询
	 * 
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@RequestMapping(value = "/queryGoods", produces = "application/json;charset=GBK")
	@ResponseBody
	private String queryGoodsList() throws UnsupportedEncodingException {
		List goodsList = goodsService.queryGoodsList();
		JSONArray jsonObject = JSONArray.fromObject(goodsList);
		String jsonStr = jsonObject.toString();
		return jsonStr;
	}

	/**
	 * 实现对Secondary数据库的信息查询
	 * 
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	@RequestMapping(value = "/queryOrders", produces = "application/json;charset=GBK")
	@ResponseBody
	private String queryOrdersList() throws UnsupportedEncodingException {
		List goodsList = ordersService.queryOrdersList();
		JSONArray jsonObject = JSONArray.fromObject(goodsList);
		String jsonStr = jsonObject.toString();
		return jsonStr;
	}

}

你可能感兴趣的:(Java)