mysql读写分离之代码实现(3)

来源:互联网 发布:用网络盒子看电视直播 编辑:程序博客网 时间:2024/06/06 02:39

一、编码
1、DynamicDataSource.java

这个类是AbstractRoutingDataSource的子类,重写了determineCurrentLookupKey()方法,作用是返回需要切换的数据源的key。

具体代码如下:

package org.lxl.mr.common.datasourceSwitch;

 

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

 

public class DynamicDataSource extends AbstractRoutingDataSource {

 

@Override

protected Object determineCurrentLookupKey() {

return DataSourceSwitcher.getDataSource();

}

 

}

 

2、DataSourceSwitcher.java

这个类提供了切换数据源的方法,具体代码如下:

package org.lxl.mr.common.datasourceSwitch;

 

import org.springframework.util.Assert;

 

public class DataSourceSwitcher {

@SuppressWarnings("rawtypes")

private static final ThreadLocal contextHolder = new ThreadLocal();

@SuppressWarnings("unchecked")

public static void setDataSource(String dataSource){

Assert.notNull(dataSource"dataSource cannot bu null");

contextHolder.set(dataSource);

}

public static void setMaster(){

clearDataSource();

}

public static void setSlave(){

setDataSource("slave");

}

public static String getDataSource(){

return (String)contextHolder.get();

}

public static void clearDataSource(){

contextHolder.remove();

}

}

 

3、DataSourceAdvice

这个类的before方法是在Service方法前执行,通过方法名判断使用那个DataSource,并调用DataSourceSwitcher的相应方法进行切换;

afterThrowing方法是在异常发生时,切换到slave服务器。

具体代码如下:
package org.lxl.mr.common.datasourceSwitch;

 

import java.lang.reflect.Method;

 

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.aop.MethodBeforeAdvice;

import org.springframework.aop.ThrowsAdvice;

 

public class DataSourceAdvice implements MethodBeforeAdvice, ThrowsAdvice {

private static final Logger logger = LoggerFactory.getLogger(DataSourceAdvice.class);

@Override

public void before(Method method, Object[] args, Object targetthrows Throwable {

logger.info("切入点:"+target.getClass().getName()+"类中"+method.getName()+"方法");

if(method.getName().startsWith("add")

|| method.getName().startsWith("create")

|| method.getName().startsWith("save")

|| method.getName().startsWith("update")

|| method.getName().startsWith("delete")

|| method.getName().startsWith("remove")

|| method.getName().startsWith("register")){

logger.info("切换到:master");

DataSourceSwitcher.setMaster();

}else{

logger.info("切换到:slave");

DataSourceSwitcher.setSlave();

}

}

 

//抛出Exception之后被调用

public void afterThrowing(Method method,Object[] args,Object target,Exception exthrows Throwable{

DataSourceSwitcher.setSlave();

logger.info("出现异常,切换到:slave");

}

}

 

二、配置

1、jdbc.properties

master.jdbc.driverClassName=com.mysql.jdbc.Driver

master.jdbc.url=jdbc:mysql://60.60.61.244:3306/mr?useUnicode=true&characterEncoding=utf-8&useOldAliasMetadataBehavior=true

master.jdbc.username=mr_master

master.jdbc.password=mrmaster123

 

slave.jdbc.driverClassName=com.mysql.jdbc.Driver

slave.jdbc.url=jdbc:mysql://60.60.61.245:3306/mr?useUnicode=true&characterEncoding=utf-8&useOldAliasMetadataBehavior=true

slave.jdbc.username=mr_slave

slave.jdbc.password=mrslave123

 

jdbc.dialect=org.hibernate.dialect.MySQLDialect

2、application.xml

在spring的主配置文件applicationContent.xml(用STS创建工程是root-context.xml)中,配置如下内容:

 

<!-- 加载properties配置文件 -->

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<property name="locations">

<list>

<value>classpath:/jdbc.properties</value>

</list>

</property>

</bean>

 

<!-- 配置连接池 -->

<bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource">

</bean>

<!-- 主数据源 -->

<bean id="masterDataSource" parent="parentDataSource">

<property name="driverClassName" value="${master.jdbc.driverClassName}"/>

<property name="url" value="${master.jdbc.url}"/>

<property name="username" value="${master.jdbc.username}"/>

<property name="password" value="${master.jdbc.password}"/>

</bean>

<!-- 从数据源 -->

<bean id="slaveDataSource" parent="parentDataSource">

<property name="driverClassName" value="${slave.jdbc.driverClassName}"/>

<property name="url" value="${slave.jdbc.url}"/>

<property name="username" value="${slave.jdbc.username}"/>

<property name="password" value="${slave.jdbc.password}"/>

</bean>

 

<!-- 动态数据源 -->

<bean id="dataSource" class="org.lxl.mr.common.datasourceSwitch.DynamicDataSource">

<property name="targetDataSources">

<map key-type="java.lang.String">

<entry key="slave" value-ref="slaveDataSource"/>

</map>

</property>

<property name="defaultTargetDataSource" ref="masterDataSource"/>

</bean>

<!-- <bean id="dataSource" parent="parentDataSource">

<property name="driverClassName" value="${master.jdbc.driverClassName}"/>

<property name="url" value="${master.jdbc.url}"/>

<property name="username" value="${master.jdbc.username}"/>

<property name="password" value="${master.jdbc.password}"/>

</bean> -->

<!-- 配置sessionFactory -->

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<property name="dataSource" ref="dataSource"/>

<property name="packagesToScan" value="org.lxl.mr.pojo"/>

<property name="hibernateProperties">

<props>

<prop key="hibernate.dialect">${jdbc.dialect}</prop>

<prop key="hibernate.show_sql">true</prop>

<prop key="hibernate.hbm2ddl.auto">update</prop> 

</props>

</property>

</bean>

<!-- 切换数据源 -->

<bean id="dataSourceAdvice" class="org.lxl.mr.common.datasourceSwitch.DataSourceAdvice"/>

<aop:config>

<aop:advisor 

pointcut="execution(* org.lxl.mr.service..*Service.*(..))" 

advice-ref="dataSourceAdvice"/>

<aop:advisor 

  pointcut="execution(* org.lxl.mr.service..*ServiceImpl.*(..))"

   advice-ref="dataSourceAdvice"/>

</aop:config>

<!-- 配置事务管理器 -->

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<property name="sessionFactory">

<ref bean="sessionFactory"/>

</property>

</bean>

<!-- 配置事务的传播特性 -->

<tx:advice id="txAdvice" transaction-manager="transactionManager">

<tx:attributes>

<!-- 对增、删、改方法进行事务支持 -->

<tx:method name="add*" propagation="REQUIRED"/>

<tx:method name="create*" propagation="REQUIRED"/>

<tx:method name="save*" propagation="REQUIRED"/>

<tx:method name="edit*" propagation="REQUIRED"/>

<tx:method name="update*" propagation="REQUIRED"/>

<tx:method name="delete*" propagation="REQUIRED"/>

<tx:method name="remove*" propagation="REQUIRED"/>

<tx:method name="register*" propagation="REQUIRED"/>

<!-- 对查找方法进行只读事务 -->

<tx:method name="loadByUsername*" propagation="SUPPORTS" read-only="true"/>

<!-- 对其它方法进行只读事务 -->

<tx:method name="*" propagation="SUPPORTS" read-only="true"/>

</tx:attributes>

</tx:advice>

<!-- 哪些类的哪些方法参与事务 -->

<aop:config>

<aop:advisor 

  pointcut="execution(* org.lxl.mr.service..*Service.*(..))" 

  advice-ref="txAdvice"/>

 <aop:advisor 

  pointcut="execution(* org.lxl.mr.service..*ServiceImpl.*(..))"

   advice-ref="txAdvice"/>

</aop:config>

 

<!-- 配置hibernateTemplate --> 

  <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">

  <property name="sessionFactory" ref="sessionFactory"/>

  <property name="flushMode" value="1"/>

  <property name="cacheQueries" value="true"/>

</bean>

</beans>

3、log4j.xml

log4j要放在classpath下,具体配置如下:

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

<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

 

<!-- Appenders -->

<appender name="console" class="org.apache.log4j.ConsoleAppender">

<param name="Target" value="System.out" />

<layout class="org.apache.log4j.PatternLayout">

<param name="ConversionPattern" value="%-5p: %c - %m%n" />

</layout>

</appender>

<!-- Application Loggers -->

<logger name="org.lxl.mr">

<level value="info" />

</logger>

<!-- 3rdparty Loggers -->

<logger name="org.springframework.core">

<level value="info" />

</logger>

<logger name="org.springframework.beans">

<level value="info" />

</logger>

<logger name="org.springframework.context">

<level value="info" />

</logger>

 

<logger name="org.springframework.web">

<level value="info" />

</logger>

 

<!-- Root Logger -->

<root>

<priority value="warn" />

<appender-ref ref="console" />

</root>

</log4j:configuration>

 

 

PS:这里的配置是读写分离的最核心的配置,如果使用SpringMVC或者集成Struts2等还需要其它的配置,这些与本文内容无关,就没过多的叙述。

本文中的程序开发环境是:

IDE工具:STS

工程类型:Spring MVC Project

框架:spring+springmvc+hibernate

版本工具:maven3.2.1

 

附录:pom.xml

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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>org.lxl</groupId>

<artifactId>mr</artifactId>

<name>myRestaurant</name>

<packaging>war</packaging>

<version>1.0.0-BUILD-SNAPSHOT</version>

<properties>

<java-version>1.6</java-version>

<org.springframework-version>3.1.1.RELEASE</org.springframework-version>

<org.aspectj-version>1.6.10</org.aspectj-version>

<org.slf4j-version>1.6.6</org.slf4j-version>

<!-- Hibernate /JPA -->

   <hibernate.groupId>org.hibernate</hibernate.groupId>

   <hibernate.version>3.5.5-Final</hibernate.version>

</properties>

<!-- Spring -->

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>${org.springframework-version}</version>

<exclusions>

<!-- Exclude Commons Logging in favor of SLF4j -->

<exclusion>

<groupId>commons-logging</groupId>

<artifactId>commons-logging</artifactId>

 </exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-webmvc</artifactId>

<version>${org.springframework-version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-orm</artifactId>

<version>${org.springframework-version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-aop</artifactId>

<version>${org.springframework-version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-tx</artifactId>

<version>${org.springframework-version}</version>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>${org.springframework-version}</version>

</dependency>

<!-- AspectJ -->

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjrt</artifactId>

<version>${org.aspectj-version}</version>

</dependency>

<dependency>

<groupId>org.aspectj</groupId>

<artifactId>aspectjweaver</artifactId>

<version>${org.aspectj-version}</version>

</dependency>

<!-- Logging -->

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-api</artifactId>

<version>${org.slf4j-version}</version>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>jcl-over-slf4j</artifactId>

<version>${org.slf4j-version}</version>

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>org.slf4j</groupId>

<artifactId>slf4j-log4j12</artifactId>

<version>${org.slf4j-version}</version>

<scope>runtime</scope>

</dependency>

<dependency>

<groupId>log4j</groupId>

<artifactId>log4j</artifactId>

<version>1.2.15</version>

<exclusions>

<exclusion>

<groupId>javax.mail</groupId>

<artifactId>mail</artifactId>

</exclusion>

<exclusion>

<groupId>javax.jms</groupId>

<artifactId>jms</artifactId>

</exclusion>

<exclusion>

<groupId>com.sun.jdmk</groupId>

<artifactId>jmxtools</artifactId>

</exclusion>

<exclusion>

<groupId>com.sun.jmx</groupId>

<artifactId>jmxri</artifactId>

</exclusion>

</exclusions>

<scope>runtime</scope>

</dependency>

 

<!-- @Inject -->

<dependency>

<groupId>javax.inject</groupId>

<artifactId>javax.inject</artifactId>

<version>1</version>

</dependency>

<!-- Servlet -->

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>servlet-api</artifactId>

<version>2.5</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>javax.servlet.jsp</groupId>

<artifactId>jsp-api</artifactId>

<version>2.1</version>

<scope>provided</scope>

</dependency>

<dependency>

<groupId>javax.servlet</groupId>

<artifactId>jstl</artifactId>

<version>1.2</version>

</dependency>

<!-- Hibernate -->

<dependency>

<groupId>${hibernate.groupId}</groupId>

<artifactId>hibernate-core</artifactId>

<version>${hibernate.version}</version>

</dependency>

<dependency>

<groupId>${hibernate.groupId}</groupId>

<artifactId>hibernate-annotations</artifactId>

<version>${hibernate.version}</version>

</dependency>

<dependency>

<groupId>${hibernate.groupId}</groupId>

<artifactId>hibernate-ehcache</artifactId>

<version>${hibernate.version}</version>

</dependency>

<dependency>

<groupId>${hibernate.groupId}</groupId>

<artifactId>hibernate-validator</artifactId>

<version>4.1.0.Final</version>

</dependency>

<!-- 验证框架 -->

<dependency>

<groupId>javassist</groupId>

<artifactId>javassist</artifactId>

<version>3.12.1.GA</version>

</dependency>

<dependency>

<groupId>asm</groupId>

<artifactId>asm</artifactId>

<version>3.2</version>

</dependency>

<!-- mysql驱动 -->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<version>5.1.6</version>

</dependency>

<!-- 数据库连接池 -->

<dependency>

<groupId>commons-dbcp</groupId>

<artifactId>commons-dbcp</artifactId>

<version>1.3</version>

</dependency>

<!-- utils begin -->

<dependency>

<groupId>commons-lang</groupId>

<artifactId>commons-lang</artifactId>

<version>2.5</version>

</dependency>

<dependency>

<groupId>commons-configuration</groupId>

<artifactId>commons-configuration</artifactId>

<version>1.8</version>

</dependency>

<!-- Test -->

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.7</version>

<scope>test</scope>

</dependency>        

</dependencies>

    <build>

        <plugins>

            <plugin>

                <artifactId>maven-eclipse-plugin</artifactId>

                <version>2.9</version>

                <configuration>

                    <additionalProjectnatures>

                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>

                    </additionalProjectnatures>

                    <additionalBuildcommands>

                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>

                    </additionalBuildcommands>

                    <downloadSources>true</downloadSources>

                    <downloadJavadocs>true</downloadJavadocs>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.apache.maven.plugins</groupId>

                <artifactId>maven-compiler-plugin</artifactId>

                <version>2.5.1</version>

                <configuration>

                    <source>1.6</source>

                    <target>1.6</target>

                    <compilerArgument>-Xlint:all</compilerArgument>

                    <showWarnings>true</showWarnings>

                    <showDeprecation>true</showDeprecation>

                </configuration>

            </plugin>

            <plugin>

                <groupId>org.codehaus.mojo</groupId>

                <artifactId>exec-maven-plugin</artifactId>

                <version>1.2.1</version>

                <configuration>

                    <mainClass>org.test.int1.Main</mainClass>

                </configuration>

            </plugin>

        </plugins>

    </build>

</project>

0 0
原创粉丝点击