Business Scenario:
A, b two units, the system deploys the same set of code;
A, b Two systems can access each other;
Request to synchronize data from a system to B system, and then send back the feedback information to A;
Actual development situation:
Because the system is relatively small, the initial design of the architecture did not take into account the way the message interworking, nor design a distributed deployment, so the use of Abstractroutingdatasource flexible data source to directly in the business code to achieve data interaction.
Project Code:
Applicationcontext-common.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:context= "Http://www.springframework.org/schema/context" Xmlns:util= "Http://www.springframework.org/schema/util" xmlns:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xmlns:tx= "Http://www.springframework.org/schema/tx" xsi:schemalocation= "http://www.springframework.org/schema/ Beans Http://www.springframework.org/schema/beans/spring-beans.xsd Http://www.springframework.org/schema/context Http://www.springframework.org/schema/context/spring-context-4.1.xsd Http://www.springframework.org/schema/util Http://www.springframework.org/schema/util/spring-util-4.1.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP/HTTP Www.springframework.org/schema/aop/spring-aop.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/TX/HTTP Www.springframework.org/schema/tx/spring-tx-4.1.xsd "> <context:component-scan Base-pacKage= "COM.FMS;COM.JOB;COM.JMDA;" > <context:exclude-filter type= "regex" expression= ". controller.*"/> </context:component-scan>< Bean id= "Freemarkerconfig" class= "Org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer" >< Property Name= "Templateloaderpaths" ><list><value>/web-inf/pages/</value><value>/ Web-inf/template/</value><value>classpath:/jmda-ftl/</value></list></property> <property name= "freemarkersettings" ><props><prop key= "Template_update_delay" >0</prop> <prop key= "default_encoding" >utf-8</prop><prop key= "Number_format" >0.##########</prop> <prop key= "Datetime_format" >yyyy-mm-dd hh:mm:ss</prop><prop key= "classic_compatible" >true</ Prop><prop key= "Template_exception_handler" >ignore</prop></props></property></ bean><!--Configuring the C3P0 data source--><bean id= "DataSource1" class= "com.mchange.v2.c3p0.combopooleddatasource "destroy-method=" Close "><property name=" Jdbcurl "><value><! [cdata[jdbc:mysql://192.168.5.186:3306/fms-ybj?useunicode=yes&characterencoding=utf8]]></value> </property><property name= "Driverclass" value= "Com.mysql.jdbc.Driver"/><property name= "user" value= "Root"/><property name= "password" value= "root"/><property name= "Maxpoolsize" value= "$"/>< Property Name= "Minpoolsize" value= "1"/><property name= "Initialpoolsize" value= "1"/><property name= " MaxIdleTime "value=" "/><property name=" Acquireincrement "value=" 5 "/><property name=" MaxStatements " Value= "0"/><property name= "Idleconnectiontestperiod" value= "/><property name=" acquireRetryAttempts "Value=" "/><property name=" Breakafteracquirefailure "value=" true "/><property name=" Testconnectiononcheckout "value=" false "/></bean><bean id=" DataSource2 "class=" Com.mchange.v2.c3p0.ComboPoolEddatasource "destroy-method=" Close "><property name=" Jdbcurl "> <value><! [cdata[jdbc:mysql://192.168.5.186:3306/fms-zhs?useunicode=yes&characterencoding=utf8]]></value> </property><property name= "Driverclass" value= "Com.mysql.jdbc.Driver"/><property name= "user" value= "Root"/><property name= "password" value= "root"/><property name= "Maxpoolsize" value= "$"/>< Property Name= "Minpoolsize" value= "1"/><property name= "Initialpoolsize" value= "1"/><property name= " MaxIdleTime "value=" "/><property name=" Acquireincrement "value=" 5 "/><property name=" MaxStatements " Value= "0"/><property name= "Idleconnectiontestperiod" value= "/><property name=" acquireRetryAttempts "Value=" "/><property name=" Breakafteracquirefailure "value=" true "/><property name=" Testconnectiononcheckout "value=" false "/></bean> <bean id=" Multipledatasource "class=" Com.fms.common.datasource.MuLtipledatasource "> <property name=" defaulttargetdatasource "ref=" DataSource1 "/> <property na Me= "Targetdatasources" > <map> <entry key= "DataSource1" value-ref= "DataSource1"/& Gt <entry key= "DataSource2" value-ref= "DataSource2"/> </map> </property> </be An><bean id= "Msqlsessionfactory" class= "Org.mybatis.spring.SqlSessionFactoryBean" ><property name= " DataSource "ref=" Multipledatasource "/><property name=" configlocation "value=" Classpath:mybatis.xml "/> <property name= "Mapperlocations" ><list><value>classpath*:/com/fms/**/dao/*mapper.xml</ Value><value>classpath*:/com/fms/**/dao/*dao.xml</value></list></property></bean ><bean class= "Org.mybatis.spring.mapper.MapperScannerConfigurer" ><property name= "Basepackage" value= " Com.fms.**.dao "/><property name=" sqlsessionfactory "ref= "Msqlsessionfactory"/></bean><bean id= "TransactionManager" class= " Org.springframework.jdbc.datasource.DataSourceTransactionManager "><property name=" datasource "ref=" Multipledatasource "/></bean>
<tx:annotation-driven transaction-manager= "TransactionManager"/>
<!--file Upload configuration-<bean id= "Multipartresolver" class= "Org.springframework.web.multipart.commons.CommonsM Ultipartresolver "> <property name=" maxuploadsize "value=" 10240000 "/> <property name=" maxInMemorySize "Value=" 10240000 "/></bean> </beans>
Springmvc-servlet.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: Cache= "Http://www.springframework.org/schema/cache" xmlns:context= "http://www.springframework.org/schema/ Context "xmlns:jdbc=" Http://www.springframework.org/schema/jdbc "xmlns:jee=" http://www.springframework.org/ Schema/jee "xmlns:jms=" HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/JMS "xmlns:lang=" http://www.springframework.org/ Schema/lang "xmlns:mvc=" Http://www.springframework.org/schema/mvc "xmlns:oxm=" http://www.springframework.org/ SCHEMA/OXM "xmlns:p=" http://www.springframework.org/schema/p "xmlns:task=" http://www.springframework.org/schema/ Task "xmlns:tx=" Http://www.springframework.org/schema/tx "xmlns:mongo=" http://www.springframework.org/schema/ Data/mongo "xmlns:util=" Http://www.springframework.org/schema/util "xmlns:ehcache="/HTTP/ Ehcache-spring-annotations.googlecode.com/svn/schEma/ehcache-spring "xsi:schemalocation=" Http://www.springframework.org/schema/beans/http Www.springframework.org/schema/beans/spring-beans.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP Http://www.spri Ngframework.org/schema/aop/spring-aop-4.1.xsd Http://www.springframework.org/schema/cache Http://www.springfram Ework.org/schema/cache/spring-cache-4.1.xsd Http://www.springframework.org/schema/context Http://www.springfram Ework.org/schema/context/spring-context-4.1.xsd Http://www.springframework.org/schema/jdbc Http://www.springfra Mework.org/schema/jdbc/spring-jdbc-4.1.xsd Http://www.springframework.org/schema/jee Http://www.springframework . org/schema/jee/spring-jee-4.1.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/JMS Http://www.springframework.org/sch Ema/jms/spring-jms-4.1.xsd Http://www.springframework.org/schema/lang Http://www.springframework.org/schema/lan G/spring-lang-4.1.xsd Http://www.springframewORK.ORG/SCHEMA/MVC http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/ SCHEMA/OXM http://www.springframework.org/schema/oxm/spring-oxm-4.1.xsd HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/T Ask Http://www.springframework.org/schema/task/spring-task-4.1.xsd http://www.springframework.org/schema/tx htt P://www.springframework.org/schema/tx/spring-tx-4.1.xsd Http://www.springframework.org/schema/util/HTTP Www.springframework.org/schema/util/spring-util-4.1.xsd "> <context:component-scan base-package=" COM.FMS; Com.job;com.jmda; "/>
<mvc:annotation-driven><mvc:message-converters><bean class= " Org.springframework.http.converter.StringHttpMessageConverter "><property name=" Supportedmediatypes "> <list> <value>text/plain;charset=utf-8</value><value>text/html;charset=utf-8</value ></list></property></bean></mvc:message-converters></mvc:annotation-driven> <bean id= "Viewresolver" class= "Org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" > <property name= "Cache" value= "true"/> <property name= "suffix" value= ". Ftl"/> <property na Me= "ContentType" value= "Text/html;charset=utf-8" ></property> <property name= "Requestcontextattribute" value= "Request"/> <property name= "Exposespringmacrohelpers" value= "true"/> <property name= "exp Oserequestattributes "value=" true "/> <property name=" exposesessionattributes "value=" true "/> </bean><mvc:resources mapping= "/static/**" location= "/static/"/><mvc:resources mapping= "/ jmda-static/** "location="/jmda-static/"/><mvc:resources mapping="/assets/** "location="/assets/"/>< mvc:interceptors> <bean class= "Com.fms.common.listener.SecurityInterceptor"/> </mvc:interceptors> </beans>
Web. xml:
<?xml version= "1.0" encoding= "UTF-8"? ><web-app metadata-complete= "true" xmlns:xsi= "http://www.w3.org/2001 /xmlschema-instance "xmlns=" Http://java.sun.com/xml/ns/javaee "xmlns:web=" http://java.sun.com/xml/ns/javaee/ Web-app_2_5.xsd "xsi:schemalocation=" Http://java.sun.com/xml/ns/javaee Http://java.sun.com/xml/ns/javaee/web-app _2_5.xsd "version=" 2.5 "><context-param><param-name>contextConfigLocation</param-name>< param-value>classpath*:/spring/applicationcontext*.xml</param-value></context-param>< Listener><listener-class>org.springframework.web.context.contextloaderlistener</listener-class> </listener><listener><listener-class> Org.springframework.web.util.introspectorcleanuplistener</listener-class></listener><filter> <filter-name>CharacterEncodingFilter</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>characterencodingfilter</filter-name><url-pattern >/*</url-pattern></filter-mapping><servlet><servlet-name>spring4mvc</ Servlet-name><servlet-class>org.springframework.web.servlet.dispatcherservlet</servlet-class> <init-param><param-name>contextconfiglocation</param-name><param-value>classpath*:/ spring/springmvc-servlet.xml</param-value></init-param><load-on-startup>1</ Load-on-startup></servlet><servlet-mapping><servlet-name>spring4mvc</servlet-name> <url-pattern>/</url-pattern></servlet-mapping><context-param><param-name> Log4jconfiglocation</param-name><param-value>/web-inf/classes/log4j.properties</param-value> </context-param><listener><listener-class>org.springframework.web.util.log4jconfiglistener</listener-class></listener> <listener > <listener-class>com.fms.common.listener.CommListener</listener-class> </listener><!-- 400 error--><error-page><error-code>400</error-code><location>/error</location> </error-page><!--404 page does not exist error--><error-page><error-code>404</error-code>< location>/error</location></error-page><!--403 server denied request--><error-page><error-code >403</error-code><location>/error</location></error-page><!--500 Server Internal Error-- <error-page><error-code>500</error-code><location>/error</location></ error-page><!--503 Service Unavailable--><error-page><error-code>503</error-code><location>/ error</location></error-page><!--java.lang.Exception--><error-page><exception-type>java.lang.exception</exception-type><location>/error</location></error-page><!- -Java.lang.NullPointerException--><error-page><exception-type>java.lang.nullpointerexception </exception-type><location>/error</location></error-page><error-page>< Exception-type>javax.servlet.servletexception</exception-type><location>/error</location> </error-page><welcome-file-list><welcome-file></welcome-file></welcome-file-list ></web-app>
Multipledatasource:
Package Com.fms.common.datasource;import Org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class Multipledatasource extends Abstractroutingdatasource { private static final threadlocal<string> Datasourcekey = new inheritablethreadlocal<string> (); public static void Setdatasourcekey (String dataSource) { datasourcekey.remove (); } public static void Setdatasource (String dataSource) { datasourcekey.remove (); Datasourcekey.set (DataSource); } public static String GetKey () { return datasourcekey.get (); } @Override protected Object Determinecurrentlookupkey () { return datasourcekey.get ();} }
A brief business code
@Transactional (rollbackfor = {exception.class}) @Overridepublic void Test () {///default data source is datasource1//do some SQL operate// Switch data source Multipledatasource.setdatasource ("Datasource2");//do other SQL operate//...}.
Code to the above stage, the business under normal conditions can be executed smoothly, but in the event of an exception when the transaction can not be rolled back, so I find various methods on the Internet to try to modify;
At first, I thought it was abstractroutingdatasource. Multi-data source problem, has been from this aspect to find the answer, find a lot of examples of changes are still unable to open the transaction management, occasionally saw a post on the spring father and son container configuration, after reading after the change, Then restart the project and the results are really successful.
The specific changes are as follows:
In Applicationcontext-common.xml:
<!-- <context:component-scan base-package= "COM.FMS;COM.JOB;COM.JMDA;" > <context:exclude-filter type= "regex" expression= ". controller.*"/> </context:component-scan >--> changed to: <context:component-scan base-package= "COM.FMS;COM.JOB;COM.JMDA;" > <context:exclude-filter type= "annotation" expression= "Org.springframework.stereotype.Controller"/ > </context:component-scan>
In Springmvc-servlet.xml:
<!--<context:component-scan base-package= "COM.FMS;COM.JOB;COM.JMDA;"/>--> instead: <context: Component-scan base-package= "COM.FMS;COM.JOB;COM.JMDA;" > <context:exclude-filter type= "annotation" expression= "Org.springframework.stereotype.Service"/> </context:component-scan>
Reason:
The spring container first loads the parent container generated by Servletcontextlistener (corresponding applicationcontext.xml), and SPRINGMVC (corresponding Mvc_dispatcher_ Servlet.xml) produces a sub-container. The instance of the @service annotation assembled when the sub-container controller is scanned for assembly is not transacted, that is, a service with no transaction capability, and the service that the parent container initializes is a guarantee of the transaction's enhanced processing power. If the service is not exclude in the sub-container, it will be provided as-is service without transaction capability, because in multi-context case, if the same bean is defined two times, the next one takes precedence.
---------Note: This paragraph is excerpted from: http://blog.csdn.net/will_awoke/article/details/12002705
Springmvc+mybatis (when using Abstractroutingdatasource for multi-data source switching) a workaround for transaction management that does not take effect