Spring+SpringMVC+Mybatis 多資料來源整合
阿新 • • 發佈:2019-01-25
此篇文章是基於Spring3.0和mybatis3.2的
總體大概流程:
1. 拷貝所需jar
2.寫一個數據庫切換的工具類:DataSourceContextHolder,用來切換資料庫
下面看一下我的工程的目錄:
common包存放的是一些公用類
controller包下放的是提供給外部訪問的介面的(.do)類
datasource包下是用來配置資料庫
entity:實體類
下面一步步的來講解:
4. 建立springmvc-servlet.xml檔案,然後建立spring配置檔案(beans.xml),看一下我的springmvc-servlet.xml檔案。
9. 建立一個User物件,配置User.xml檔案。寫一個UserMapper介面,用來操作User物件的介面。
編寫User.xml檔案,該檔案裡面配置User類裡面的屬性和表中的那些欄位進行對應,以及在UserMapper中定義的查詢的方法,在User.xml中寫上對應的查詢語句,我這裡是查的t_expand_user 表
UserServiceImpl裡面要做的就是呼叫UserMapper中的方法
整個Controller類的程式碼
訪問路徑:locahost:8080/RouterWeb/login.do
1. 拷貝所需jar
2.寫一個數據庫切換的工具類:DataSourceContextHolder,用來切換資料庫
3.寫一個DynamicDataSource類來繼承AbstractRoutingDataSource,並重寫determineCurrentLookupKey()方法,來達到動態切換資料庫
4. 建立springmvc-servlet.xml檔案,然後建立spring配置檔案(beans.xml)
5. 在beans.xml檔案中配置資料來源。我這裡配置的三個資料來源
6. 在beans.xml檔案中建立sqlSessionFactory例項
7. 在beans.xml檔案中配置事物、事物的傳播性
8. 在beans.xml檔案中配置AOP
9. 建立一個User物件,配置User.xml檔案。寫一個UserMapper介面,用來操作User物件的介面
10. 將User類的路徑以及User.xml檔案的路徑在mybatis-config.xml檔案中配置
11. 寫一個UserService介面(接口裡面的方法和UserMapper接口裡面的方法一致,返回值和引數可不同,方法名最好一致),並寫UserServiceImpl來實現UserService介面
12.寫Controller類,並在其中寫相對應的方法,給外部呼叫
下面看一下我的工程的目錄:mapper:.....存放XXMapper以及實體類的對應表的關係的xml檔案
下面一步步的來講解:
1、拷貝jar檔案。需要的jar檔案入下圖所示,因為我的專案中用到了json解析,所以匯入了json相關的包
2.寫一個數據庫切換的工具類:DataSourceContextHolder,用來切換資料庫
public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDbType(String dbType) { contextHolder.set(dbType); } public static String getDbType() { return ((String) contextHolder.get()); } public static void clearDbType() { contextHolder.remove(); } }
3.寫一個DynamicDataSource類來繼承AbstractRoutingDataSource,並重寫determineCurrentLookupKey()方法,來達到動態切換資料庫
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder. getDbType();
}
}
4. 建立springmvc-servlet.xml檔案,然後建立spring配置檔案(beans.xml),看一下我的springmvc-servlet.xml檔案。
這裡配置了一個註解掃描器,一般填自己的主包名就可以了,他會自動掃描我的com.baimi.routerweb包下面所有的帶註解的類或者方法,常變數等。
還配置了一個檢視解析器(如果需要用到jsp檔案,就需要配置此解析器)
最後引入我的spring的配置檔案:beans.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:mvc= "http://www.springframework.org/schema/mvc"
xsi:schemaLocation= "http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
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-3.0.xsd">
<!-- 註解掃描器 -->
<context:component-scan base-package ="com.baimi.routerweb"/>
<!-- 配置試圖解析器 -->
<bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name ="prefix" value="/"></ property>
<property name ="suffix" value=".jsp"></ property>
</bean >
<import resource ="classpath:beans.xml"/>
</beans>
5. 在beans.xml檔案中配置資料來源。我這裡配置的三個資料來源,不過在配置資料來源之前,先配置一下註解掃描器。然後我接著配置了三個資料來源,然後配置動態資料來源
<context:component-scan base-package ="com" />
<!-- 多資料來源配置 -->
<bean id ="ds_admin" class= "org.apache.commons.dbcp.BasicDataSource" >
<property name ="driverClassName" value= "com.mysql.jdbc.Driver"></property >
<property name ="url" value= "jdbc:mysql://192.168.19.72:3307/100msh_admin" ></property >
<property name ="username" value="root"></ property>
<property name ="password" value="root"></ property>
</bean >
<bean id ="ds_partner" class= "org.apache.commons.dbcp.BasicDataSource" >
<property name ="driverClassName" value= "com.mysql.jdbc.Driver"></property >
<property name ="url"
value= "jdbc:mysql://192.168.19.72:3308/100msh_partner" ></property >
<property name ="username" value="root"></ property>
<property name ="password" value="root"></ property>
</bean >
<bean id ="ds_mop" class="org.apache.commons.dbcp.BasicDataSource">
<property name ="driverClassName" value= "com.mysql.jdbc.Driver"></property >
<property name ="url" value= "jdbc:mysql://192.168.19.72:3309/100msh_mop" ></property >
<property name ="username" value="root"></ property>
<property name ="password" value="root"></ property>
</bean >
<!-- 動態配置資料來源 -->
<bean id ="dataSource" class= "com.baimi.routerweb.datasource.DynamicDataSource" >
<property name ="targetDataSources">
<map key-type ="java.lang.String">
<entry value-ref ="ds_admin" key= "ds_admin"></entry >
<entry value-ref ="ds_partner" key= "ds_partner"></entry >
<entry value-ref ="ds_mop" key="ds_mop"></ entry>
</map >
</property >
<property name ="defaultTargetDataSource" ref= "ds_mop"></property > <!-- 預設使用ds1的資料來源 -->
</bean >
6. 在beans.xml檔案中建立sqlSessionFactory例項
<!-- 建立SqlSessionFactory -->
<bean id ="sqlSessionFactoryBean" class= "org.mybatis.spring.SqlSessionFactoryBean" >
<!-- 指定資料來源 -->
<property name ="dataSource" ref="dataSource" />
<!-- 指定mybatis 的配置檔案 -->
<property name ="configLocation" value= "classpath:mybatis-config.xml" />
</bean >
7. 在beans.xml檔案中配置事物、事物的傳播性
<!-- 配置事務 -->
<bean id ="transactionManager"
class= "org.springframework.jdbc.datasource.DataSourceTransactionManager" >
<property name ="dataSource" ref="dataSource"></ property>
</bean >
<!-- 對映介面 -->
<bean class ="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name ="basePackage" value= "com.baimi.routerweb.mapper"></property >
</bean >
<!-- 配置事務的傳播特性 -->
<tx:advice id ="txAdvice" transaction-manager="transactionManager">
<tx:attributes >
<tx:method name ="find*" read-only="true" />
<tx:method name ="get*" read-only="true" />
<tx:method name ="query*" read-only="true" />
<tx:method name ="add*" propagation="REQUIRED" />
<tx:method name ="update*" propagation="REQUIRED" />
<tx:method name ="del*" propagation="REQUIRED" />
</tx:attributes >
</tx:advice >
8. 在beans.xml檔案中配置AOP,注意這裡,expression 後面一定要是自己程式所在包名,複製的時候一定要改掉
<!-- 配置AOP -->
<aop:config >
<!-- 切點 -->
<aop:pointcut expression ="execution(* com.baimi.routerweb.service..*.*(..))"
id= "pointcut" />
<aop:advisor advice-ref ="txAdvice" pointcut-ref="pointcut" />
</aop:config >
9. 建立一個User物件,配置User.xml檔案。寫一個UserMapper介面,用來操作User物件的介面。
User類屬性有點長,請忽略這些屬性
public class User {
private int userId;
private int compId;
private String euserName;
private String euserPhone;
private int euserStatus;
private String eAddTime;
private String eLeaveTime;
private String eUserNameCn;
private int cUserId;
private String scDown;
private String userDesc;
public int getUserId() {
return userId;
}
public void setUserId( int userId) {
this. userId = userId;
}
public int getCompId() {
return compId;
}
public void setCompId( int compId) {
this. compId = compId;
}
public String getEuserName() {
return euserName;
}
public void setEuserName(String euserName) {
this. euserName = euserName;
}
public String getEuserPhone() {
return euserPhone;
}
public void setEuserPhone(String euserPhone) {
this. euserPhone = euserPhone;
}
public int getEuserStatus() {
return euserStatus;
}
public void setEuserStatus( int euserStatus) {
this. euserStatus = euserStatus;
}
public String geteAddTime() {
return eAddTime;
}
public void seteAddTime(String eAddTime) {
this. eAddTime = eAddTime;
}
public String geteLeaveTime() {
return eLeaveTime;
}
public void seteLeaveTime(String eLeaveTime) {
this. eLeaveTime = eLeaveTime;
}
public String geteUserNameCn() {
return eUserNameCn;
}
public void seteUserNameCn(String eUserNameCn) {
this. eUserNameCn = eUserNameCn;
}
public int getcUserId() {
return cUserId;
}
public void setcUserId( int cUserId) {
this. cUserId = cUserId;
}
public String getScDown() {
return scDown;
}
public void setScDown(String scDown) {
this. scDown = scDown;
}
public String getUserDesc() {
return userDesc;
}
public void setUserDesc(String userDesc) {
this. userDesc = userDesc;
}
}
編寫UserMapper介面,這裡面的方法是用來操作User物件的,我這裡只是一個簡單的根據手機號碼,得到這個User物件public interface UserMapper {
public User getUser(String euserPhone);
}
編寫User.xml檔案,該檔案裡面配置User類裡面的屬性和表中的那些欄位進行對應,以及在UserMapper中定義的查詢的方法,在User.xml中寫上對應的查詢語句,我這裡是查的t_expand_user 表
<?xml version="1.0" encoding= "UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace= "com.baimi.routerweb.mapper.UserMapper" >
<resultMap type ="User" id="usermap">
<result property ="userId" column="euser_id" />
<result property ="compId" column="comp_id" />
<result property ="euserName" column="euser_name" />
<result property ="euserPhone" column="euser_phone" />
<result property ="euserStatus" column="euser_status" />
<result property ="eAddTime" column="e_add_time" />
<result property ="eLeaveTime" column="e_leave_time" />
<result property ="eUserNameCn" column="euser_name_cn" />
<result property ="cUserId" column="user_id" />
<result property ="scDown" column="sc_own" />
<result property ="userDesc" column="euser_desc" />
</resultMap >
<!-- 查詢一條記錄 -->
<select id ="getUser" parameterType="java.lang.String" resultMap= "usermap">
select * from t_expand_user where euser_phone=#{euserPhone}
</select >
</mapper>
10. 將User類的路徑以及User.xml檔案的路徑在mybatis-config.xml檔案中配置
<?xml version="1.0" encoding= "UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd" >
<configuration>
<!-- 別名 -->
<typeAliases >
<typeAlias type ="com.baimi.routerweb.entity.User" alias= "User" />
</typeAliases >
<mappers >
<mapper resource ="com/baimi/routerweb/mapper/User.xml" />
</mappers >
</configuration>
11. 寫一個UserService介面(接口裡面的方法和UserMapper接口裡面的方法一致,返回值和引數可不同,方法名最好一致),並寫UserServiceImpl來實現UserService介面
public interface UserService {
public User getUser(String euserPhone);
}
UserServiceImpl裡面要做的就是呼叫UserMapper中的方法
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import com.baimi.routerweb.datasource.DataSourceContextHolder;
import com.baimi.routerweb.datasource.DataSourceType;
import com.baimi.routerweb.entity.User;
import com.baimi.routerweb.mapper.UserMapper;
import com.baimi.routerweb.service.UserService;
@Service
public class UserServiceImpl implements UserService {
@Resource(name = "userMapper")
private UserMapper userMapper;
@Override
public User getUser(String euserPhone) {
DataSourceContextHolder. setDbType(DataSourceType.SOURCE_MOP);
return userMapper.getUser(euserPhone);
}
}
12.寫Controller類,並在其中寫相對應的方法,給外部呼叫,這裡主要就是兩行程式碼:注意每次要和資料庫打交道之前,切換到相對應的資料庫,我的DataSourceType. SOURCE_MOP="ds_mop";這裡的名字一定要和beans.xml裡面配置的資料來源的名稱一樣
//切換資料庫
DataSourceContextHolder. setDbType(DataSourceType. SOURCE_MOP);
//從資料庫中得到該使用者的資料
User user= userService.getUser(userId);
整個Controller類的程式碼
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.baimi.routerweb.common.Constant;
import com.baimi.routerweb.common.ErrorHandle;
import com.baimi.routerweb.datasource.DataSourceContextHolder;
import com.baimi.routerweb.datasource.DataSourceType;
import com.baimi.routerweb.entity.User;
import com.baimi.routerweb.service.UserService;
import com.baimi.routerweb.util.HttpUtil;
@Controller
public class MainController {
@Resource(name = "userServiceImpl")
private UserService userService;
@RequestMapping("/login.do")
public String login(HttpServletRequest request, HttpServletResponse response) {
// 獲取客戶端傳過來的code的值
String code = request.getParameter( "code");
if (code == null || "".equals(code)) {
return ErrorHandle.getError(ErrorHandle.INVALID_TOKEN, "invalid token");
}
// 從微信得到token的值
JSONObject objToken = HttpUtil.httpRequest(Constant.URL_WEIXIN_TOKEN, "GET", null);
if (objToken == null || "".equals(objToken)) {
return ErrorHandle.getError(ErrorHandle.SERVICE_UNRESPONSE, "service unresponse");
}
if (!objToken.has( "access_token")) {
return ErrorHandle.getError(ErrorHandle.INVALID_TOKEN, "invalid token");
}
//根據token和code得到UserId
JSONObject objUser = HttpUtil.httpRequest(Constant.URL_GET_USERID,
"POST", "access_token=" + objToken.getString("access_token" )+ "&code=" + code + "&agentid=1");
if(objUser== null|| "".equals(objUser)){
return ErrorHandle.getError(ErrorHandle.SERVICE_UNRESPONSE, "service unresponse");
}
if(!objUser.has( "UserId")){
return ErrorHandle.getError(ErrorHandle.INVALID_TOKEN, "invalid token");
}
String userId=objUser.getString( "UserId");
//切換資料庫
DataSourceContextHolder. setDbType(DataSourceType.SOURCE_MOP);
//從資料庫中得到該使用者的資料
User user= userService.getUser(userId);
if(user!= null){
JSONObject rtObj = new JSONObject();
rtObj.put( "userId", String.valueOf(user.getUserId()));
return rtObj.toString();
}
return ErrorHandle.getError(ErrorHandle.INVALID_USER,"invalid user");
}
}
訪問路徑:locahost:8080/RouterWeb/login.do