SPRINGMVC多数据链接Demo
2017-01-09 08:48
246 查看
有的时候项目中可能要从另外一个系统取数据,两种方式
一、接口
SpringMVC简介
一 流程介绍
1.角色划分
前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器(Validator)、命令对象(Command请求参数绑定到的对象就叫命令对象)、表单对象(Form Object提供给表单展示和提交到的对象就叫表单对象)。
2.流程图
3.具体步骤:
(1)首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
(2)DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
(3)DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
(4)HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
(5)ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
(6)View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
(7)返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
二 重要的接口及其实现
1.DispatcherServlet部分
DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。
“某某规则”:是根据你使用了哪个HandlerMapping接口的实现类的不同而不同。
xml代码示例1:
<load-on-startup>1</load-on-startup>是启动顺序,让这个Servlet随Servlet容器一起启动。
<url-pattern>*.form</url-pattern> 会拦截*.form结尾的请求。
<servlet-name>example</servlet-name>这个Servlet的名字是example,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。同时保存的ServletContext中和Request对象中。
在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。
xml代码示例2:
指明了配置文件的文件名,不使用默认配置文件名,而使用springMVC.xml配置文件。
其中<param-value>**.xml</param-value> 这里可以使用多种写法
(1)不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml
(2)<param-value>/WEB-INF/classes/springMVC.xml</param-value>
(3)<param-value>classpath*:springMVC-mvc.xml</param-value>
(4)多个值用逗号分隔
2.配置HandlerMapping、HandlerAdapter
在springMVC.xml中的配置为:
BeanNameUrlHandlerMapping:表示将请求的URL和Bean名字映射,如URL为 “上下文/hello”,则Spring配置文件必须有一个名字为“/hello”的Bean,上下文默认忽略。
SimpleControllerHandlerAdapter:表示所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean可以作为Spring Web MVC中的处理器。如果需要其他类型的处理器可以通过实现HadlerAdapter来解决。
3.配置ViewResolver
InternalResourceViewResolver:用于支持Servlet、JSP视图解析;
viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,classpath中必须包含jstl的相关jar包;
prefix和suffix:查找视图页面的前缀和后缀(前缀[逻辑视图名]后缀),比如传进来的逻辑视图名为hello,则该该jsp视图页面应该存放在“WEB-INF/jsp/hello.jsp”;
一个springMVC-mvc.xml配置文件片段:
注意:
(1)这里使用了<mvc:annotation-driven/>注解,这是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。<mvc:annotation-driven/> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter两个bean,是springMVC为@Controllers分发请求所必须的。并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。
(2)<mvc:interceptors/>是一种简写形式。我们可以配置多个HandlerMapping。<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。其实我们也可以手动配置为每个HandlerMapping注入一个拦截器。
(3)<mvc:default-servlet-handler/> 使用默认的Servlet来响应静态文件。
(4)<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>
匹配URL /images/**的URL被当做静态资源,由Spring读出到内存中再响应http。
4.访问静态文件
如何你的DispatcherServlet拦截"*.do"这样的有后缀的URL,就不存在访问不到静态资源的问题。
如果你的DispatcherServlet拦截"/",为了实现REST风格,拦截了所有的请求,那么同时对*.js,*.jpg等静态文件的访问也就被拦截了。
方案一:激活Tomcat的defaultServlet来处理静态文件
要配置多个,每种文件配置一个。
要写在DispatcherServlet的前面, 让 defaultServlet先拦截请求,这样请求就不会进入Spring了,应该性能是最好的吧。
方案二: 在spring3.0.4以后版本提供了mvc:resources
<mvc:resources mapping="/images/**" location="/images/" />
/images/**映射到ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是web application根目录下、jar包里面,这样可以把静态资源压缩到jar包中。cache-period 可以使得静态资源进行web cache
使用<mvc:resources/>元素,把mapping的URI注册到SimpleUrlHandlerMapping的urlMap中,key为mapping的URI pattern值,而value为ResourceHttpRequestHandler,
这样就巧妙的把对静态资源的访问由HandlerMapping转到ResourceHttpRequestHandler处理并返回,所以就支持classpath目录,jar包内静态资源的访问。
5.拦截器
自定义一个拦截器,要实现HandlerInterceptor接口
在spring MVC的配置文件中配置有三种方法:
方案一,(近似)总拦截器,拦截所有url
<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。总有一个HandlerMapping是可以找到处理器的,最多也只找到一个处理器,所以这个拦截器总会被执行的。起到了总拦截器的作用。如果是REST风格的URL,静态资源也会被拦截。
方案二, (近似) 总拦截器, 拦截匹配的URL
就是比 方案一多了一个URL匹配。如果是REST风格的URL,静态资源也会被拦截。
方案三,HandlerMappint上的拦截器
如果是REST风格的URL,静态资源就不会被拦截。因为我们精准的注入了拦截器。
如果使用了<mvc:annotation-driven />, 它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter 这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。
当然我们可以通过人工配置上面的两个Bean,不使用 <mvc:annotation-driven />,就可以 给interceptors属性 注入拦截器了。
二、配置多个数据源切换访问
<1>:这是数据源和事务扫描注入的配置 访问多个数据源只需要建立多个数据源和事务这一套配置文件
这是第一个数据源
[html] view
plain copy
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
default-lazy-init="true">
<description>Spring公共配置 </description>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:resources.properties</value>
<!-- <value>classpath:memcached.properties</value> -->
</list>
</property>
</bean>
<!-- dubbo配置 -->
<!-- <dubbo:application name="xaUserRegPro" />
<dubbo:registry address="multicast://" />
<dubbo:reference id="userRegProService" interface="com.xinnet.xa.service.UserRegProService" timeout="6000"/> -->
<!-- **************** druid 监控连接池配置 ***************** -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${initialSize}" />
<property name="minIdle" value="${minIdle}" />
<property name="maxActive" value="${maxActive}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${maxWait}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<!-- 如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。分库分表较多的数据库,建议配置为false -->
<property name="poolPreparedStatements" value="${poolPreparedStatements}" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 对泄漏的连接 自动关闭 -->
<property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 打开removeAbandoned功能 -->
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 1800秒,也就是30分钟 -->
<property name="logAbandoned" value="${logAbandoned}" /> <!-- 关闭abanded连接时输出错误日志 -->
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="mergeStat" />
<!-- <property name="filters" value="stat" /> -->
<!-- 慢日志查询 缺省为3秒 修改为10秒 10000 -->
<property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" />
<!-- DruidDataSource各自独立 , 支持配置公用监控数据 -->
<!-- <property name="useGloalDataSourceStat" value="true" /> -->
</bean>
<!-- druid 监控 spring -->
<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor"/>
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
<property name="patterns">
<list>
<value>com.xinnet.*.service.*</value>
</list>
</property>
</bean>
<aop:config>
<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />
</aop:config>
<!-- MyBatis Mapper.XMl 配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:config/mybatis.xml" />
<property name="mapperLocations">
<list>
<!-- 自动匹配Mapper映射文件 -->
<value>classpath:mapper/**/*-mapper.xml</value>
</list>
</property>
<!-- 添加插件 -->
<property name="plugins">
<array>
<ref bean="pagePlugin" />
</array>
</property>
</bean>
<!-- 支持文件上传相关 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<!-- 分页插件,根据方言自动添加分页信息,默认要求 -->
<bean id="pagePlugin" class="com.xinnet.core.mybatis.plugin.PagePlugin">
<property name="properties">
<props>
<prop key="dialect">com.xinnet.core.mybatis.dialet.MySQLDialect</prop>
<prop key="pageSqlId">.*query.*</prop>
</props>
</property>
</bean>
<!-- redis客户端 -->
<!-- jedis pool配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="${redis.maxActive}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWait" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="usePool" value="true"></property>
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.pass}" />
<property name="timeout" value="${redis.timeout}" />
<property name="database" value="${redis.default.db}"></property>
<constructor-arg index="0" ref="jedisPoolConfig" />
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- ***************事务配置************** -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<aop:config>
<aop:advisor pointcut="execution(* com.xinnet..service..*.*(..))" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="load*" read-only="true" />
<tx:method name="select*" read-only="true" />
<tx:method name="count*" read-only="true" />
<tx:method name="search*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 开启注解事务 只对当前配置文件有效 -->
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.xinnet">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 隐式地向 Spring 容器注册 -->
<context:annotation-config/>
</beans>
<2>这是第二个数据源 和第一个数据源一样 需要有事务 扫描注解
不同的是数据源的 url username 和password 用的是第二个数据源的连接 用户名和密码
[html] view
plain copy
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
default-lazy-init="true">
<description>Spring公共配置 </description>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:resources.properties</value>
<!-- <value>classpath:memcached.properties</value> -->
</list>
</property>
</bean>
<!-- **************** druid 监控连接池配置 ***************** -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${url2}" />
<property name="username" value="${username2}" />
<property name="password" value="${password2}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${initialSize}" />
<property name="minIdle" value="${minIdle}" />
<property name="maxActive" value="${maxActive}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${maxWait}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<!-- 如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。分库分表较多的数据库,建议配置为false -->
<property name="poolPreparedStatements" value="${poolPreparedStatements}" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 对泄漏的连接 自动关闭 -->
<property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 打开removeAbandoned功能 -->
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 1800秒,也就是30分钟 -->
<property name="logAbandoned" value="${logAbandoned}" /> <!-- 关闭abanded连接时输出错误日志 -->
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="mergeStat" />
<!-- <property name="filters" value="stat" /> -->
<!-- 慢日志查询 缺省为3秒 修改为10秒 10000 -->
<property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" />
<!-- DruidDataSource各自独立 , 支持配置公用监控数据 -->
<!-- <property name="useGloalDataSourceStat" value="true" /> -->
</bean>
<!-- druid 监控 spring -->
<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor"/>
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
<property name="patterns">
<list>
<value>com.xinnet.*.service.*</value>
</list>
</property>
</bean>
<aop:config>
<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />
</aop:config>
<!-- MyBatis Mapper.XMl 配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:config/mybatis.xml" />
<property name="mapperLocations">
<list>
<!-- 自动匹配Mapper映射文件 -->
<value>classpath:mapper/**/*-mapper.xml</value>
</list>
</property>
<!-- 添加插件 -->
<property name="plugins">
<array>
<ref bean="pagePlugin" />
</array>
</property>
</bean>
<!-- 支持文件上传相关 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<!-- 分页插件,根据方言自动添加分页信息,默认要求 -->
<bean id="pagePlugin" class="com.xinnet.core.mybatis.plugin.PagePlugin">
<property name="properties">
<props>
<prop key="dialect">com.xinnet.core.mybatis.dialet.MySQLDialect</prop>
<prop key="pageSqlId">.*query.*</prop>
</props>
</property>
</bean>
<!-- redis客户端 -->
<!-- jedis pool配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="${redis.maxActive}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWait" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="usePool" value="true"></property>
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.pass}" />
<property name="timeout" value="${redis.timeout}" />
<property name="database" value="${redis.default.db}"></property>
<constructor-arg index="0" ref="jedisPoolConfig" />
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- ***************事务配置************** -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<aop:config>
<aop:advisor pointcut="execution(* com.xinnet..service..*.*(..))" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="load*" read-only="true" />
<tx:method name="select*" read-only="true" />
<tx:method name="count*" read-only="true" />
<tx:method name="search*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 开启注解事务 只对当前配置文件有效 -->
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.xinnet">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 隐式地向 Spring 容器注册 -->
<context:annotation-config/>
</beans>
<3>这个时候就可以用两个数据源进行切换注入 从而使用不同数据源的service
这是service里面的方法 该怎么写就是怎么写 该怎么注解就怎么注解 不用做特殊的步骤
[java] view
plain copy
@Service("partyService")
public class PartyServiceImpl implements PartyService {
@Autowired
private PartyDao partyDao;
@Override
public List<Emp> getAllEmp() throws SQLException {
return partyDao.getAllEmp();
}
}
Dao层也是一样 该怎么写就怎么写 该怎么注解就怎么注解
然后可以写一个测试类试一下连接
[java] view
plain copy
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring.xml" })//这里的spring.xml加载了第一个数据源 spring-commons.xml
public class DataSourceTest extends AbstractTransactionalJUnit4SpringContextTests {
/**
*
* 功能描述:xxxxx
*
* @throws SQLException
*
* @author xxx[973893384@163.com]
*
* @since 2014年3月12日
*
* @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
*/
@Test
@Rollback(true)
public void testGetAllEmp() throws SQLException {
ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:config/hymanager/hymanager_spring.xml");//这里加载的是第二个数据源配置文件路径 使用的时候用application 读取第二个数据源的配置文件 就可以用getBean 获取注入的service 不用ac.getBean 用@Autowired自动注入的 则使用的是第一个数据源
PartyService partyService = (PartyService) ac.getBean("partyService");
List<Emp> list = partyService.getAllEmp();
for (Emp emp : list) {
System.out.println(emp.getEmpno());
}
}
这样就可以封装一个父类
[java] view
plain copy
public class DataSourceChange {
//第二个数据源数据源
public ApplicationContext otherDataSource=new FileSystemXmlApplicationContext("classpath:config/hymanager/hymanager_spring.xml");
//默认数据源
public ApplicationContext defaultDataSource=new FileSystemXmlApplicationContext("classpath:config/spring_commons.xml");
/**
*
* 功能描述:xxxx
*
* @param beanName
* @return
*
* @author xxx[973893384@163.com]
*
* @since 2014年3月12日
*
* @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
*/
public Object now(String beanName) {
return defaultDataSource.getBean(beanName);
}
public Object after(String beanName) {
return otherDataSource.getBean(beanName);
}
}
要使用多个数据源的类就可以继承这个父类
[java] view
plain copy
public class HyMangerEmpDataHandle extends DataSourceChange {
//用父类的after方法更换配置切换第二套数据源获取注入partyService
private PartyService partyService=(PartyService) after("partyService");
//<span style="font-family: Arial, Helvetica, sans-serif;">用父类的now方法</span>更换配置切换第一套数据源获取注入empService
private EmpService empService=(EmpService) now("empService");
private static Logger log=LoggerFactory.getLogger(PartyService.class);
/**
*
* 功能描述:xxxxx
*
* @throws SQLException
*
* @author xxx[973893384@163.com]
*
* @since 2014年3月12日
*
* @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
*/
public void leadingAllEmp() throws SQLException {
List<Emp> partyList=partyService.getAllEmp();//第二个数据源注入的service
for(Emp emp:partyList) {
empService.addEmp(emp);//第一个数据源注入的service
}
}
}
一、接口
SpringMVC简介
一 流程介绍
1.角色划分
前端控制器(DispatcherServlet)、请求到处理器映射(HandlerMapping)、处理器适配器(HandlerAdapter)、视图解析器(ViewResolver)、处理器或页面控制器(Controller)、验证器(Validator)、命令对象(Command请求参数绑定到的对象就叫命令对象)、表单对象(Form Object提供给表单展示和提交到的对象就叫表单对象)。
2.流程图
3.具体步骤:
(1)首先用户发送请求——>DispatcherServlet,前端控制器收到请求后自己不进行处理,而是委托给其他的解析器进行处理,作为统一访问点,进行全局的流程控制;
(2)DispatcherServlet——>HandlerMapping, HandlerMapping将会把请求映射为HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象,通过这种策略模式,很容易添加新的映射策略;
(3)DispatcherServlet——>HandlerAdapter,HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;
(4)HandlerAdapter——>处理器功能处理方法的调用,HandlerAdapter将会根据适配的结果调用真正的处理器的功能处理方法,完成功能处理;并返回一个ModelAndView对象(包含模型数据、逻辑视图名);
(5)ModelAndView的逻辑视图名——> ViewResolver, ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;
(6)View——>渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构,因此很容易支持其他视图技术;
(7)返回控制权给DispatcherServlet,由DispatcherServlet返回响应给用户,到此一个流程结束。
二 重要的接口及其实现
1.DispatcherServlet部分
DispatcherServlet是一个Servlet,所以可以配置多个DispatcherServlet。
DispatcherServlet是前置控制器,配置在web.xml文件中的。拦截匹配的请求,Servlet拦截匹配规则要自已定义,把拦截下来的请求,依据某某规则分发到目标Controller(我们写的Action)来处理。
“某某规则”:是根据你使用了哪个HandlerMapping接口的实现类的不同而不同。
xml代码示例1:
<web-app> <servlet> <servlet-name>example</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>example</servlet-name> <url-pattern>*.form</url-pattern> </servlet-mapping> </web-app>
<load-on-startup>1</load-on-startup>是启动顺序,让这个Servlet随Servlet容器一起启动。
<url-pattern>*.form</url-pattern> 会拦截*.form结尾的请求。
<servlet-name>example</servlet-name>这个Servlet的名字是example,可以有多个DispatcherServlet,是通过名字来区分的。每一个DispatcherServlet有自己的WebApplicationContext上下文对象。同时保存的ServletContext中和Request对象中。
在DispatcherServlet的初始化过程中,框架会在web应用的 WEB-INF文件夹下寻找名为[servlet-name]-servlet.xml 的配置文件,生成文件中定义的bean。
xml代码示例2:
<servlet> <servlet-name>springMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:/springMVC.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
指明了配置文件的文件名,不使用默认配置文件名,而使用springMVC.xml配置文件。
其中<param-value>**.xml</param-value> 这里可以使用多种写法
(1)不写,使用默认值:/WEB-INF/<servlet-name>-servlet.xml
(2)<param-value>/WEB-INF/classes/springMVC.xml</param-value>
(3)<param-value>classpath*:springMVC-mvc.xml</param-value>
(4)多个值用逗号分隔
2.配置HandlerMapping、HandlerAdapter
在springMVC.xml中的配置为:
<!-- HandlerMapping --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/> <!-- HandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
BeanNameUrlHandlerMapping:表示将请求的URL和Bean名字映射,如URL为 “上下文/hello”,则Spring配置文件必须有一个名字为“/hello”的Bean,上下文默认忽略。
SimpleControllerHandlerAdapter:表示所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean可以作为Spring Web MVC中的处理器。如果需要其他类型的处理器可以通过实现HadlerAdapter来解决。
3.配置ViewResolver
<!-- ViewResolver --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean>
InternalResourceViewResolver:用于支持Servlet、JSP视图解析;
viewClass:JstlView表示JSP模板页面需要使用JSTL标签库,classpath中必须包含jstl的相关jar包;
prefix和suffix:查找视图页面的前缀和后缀(前缀[逻辑视图名]后缀),比如传进来的逻辑视图名为hello,则该该jsp视图页面应该存放在“WEB-INF/jsp/hello.jsp”;
一个springMVC-mvc.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:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <!-- 自动扫描的包名 --> <context:component-scan base-package="com.app,com.core,JUnit4" ></context:component-scan> <!-- 默认的注解映射的支持 --> <mvc:annotation-driven /> <!-- 视图解释类 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/><!--可为空,方便实现自已的依据扩展名来选择视图解释类的逻辑 --> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> </bean> <!-- 拦截器 --> <mvc:interceptors> <bean class="com.core.mvc.MyInteceptor" /> </mvc:interceptors> <!-- 对静态资源文件的访问 方案一 (二选一) --> <mvc:default-servlet-handler/> <!-- 对静态资源文件的访问 方案二 (二选一)--> <mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/> <mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/> <mvc:resources mapping="/css/**" location="/css/" cache-period="31556926"/> </beans>
注意:
(1)这里使用了<mvc:annotation-driven/>注解,这是一种简写形式,完全可以手动配置替代这种简写形式,简写形式可以让初学都快速应用默认配置方案。<mvc:annotation-driven/> 会自动注册DefaultAnnotationHandlerMapping与AnnotationMethodHandlerAdapter两个bean,是springMVC为@Controllers分发请求所必须的。并提供了:数据绑定支持,@NumberFormatannotation支持,@DateTimeFormat支持,@Valid支持,读写XML的支持(JAXB),读写JSON的支持(Jackson)。
(2)<mvc:interceptors/>是一种简写形式。我们可以配置多个HandlerMapping。<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。其实我们也可以手动配置为每个HandlerMapping注入一个拦截器。
(3)<mvc:default-servlet-handler/> 使用默认的Servlet来响应静态文件。
(4)<mvc:resources mapping="/images/**" location="/images/" cache-period="31556926"/>
匹配URL /images/**的URL被当做静态资源,由Spring读出到内存中再响应http。
4.访问静态文件
如何你的DispatcherServlet拦截"*.do"这样的有后缀的URL,就不存在访问不到静态资源的问题。
如果你的DispatcherServlet拦截"/",为了实现REST风格,拦截了所有的请求,那么同时对*.js,*.jpg等静态文件的访问也就被拦截了。
方案一:激活Tomcat的defaultServlet来处理静态文件
<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping>
要配置多个,每种文件配置一个。
要写在DispatcherServlet的前面, 让 defaultServlet先拦截请求,这样请求就不会进入Spring了,应该性能是最好的吧。
方案二: 在spring3.0.4以后版本提供了mvc:resources
<mvc:resources mapping="/images/**" location="/images/" />
/images/**映射到ResourceHttpRequestHandler进行处理,location指定静态资源的位置.可以是web application根目录下、jar包里面,这样可以把静态资源压缩到jar包中。cache-period 可以使得静态资源进行web cache
使用<mvc:resources/>元素,把mapping的URI注册到SimpleUrlHandlerMapping的urlMap中,key为mapping的URI pattern值,而value为ResourceHttpRequestHandler,
这样就巧妙的把对静态资源的访问由HandlerMapping转到ResourceHttpRequestHandler处理并返回,所以就支持classpath目录,jar包内静态资源的访问。
5.拦截器
自定义一个拦截器,要实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor { @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { System.out.println("afterCompletion"); } @Override public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3) throws Exception { System.out.println("postHandle"); } @Override public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception { System.out.println("preHandle"); return true; } }
在spring MVC的配置文件中配置有三种方法:
方案一,(近似)总拦截器,拦截所有url
<mvc:interceptors> <bean class="com.app.mvc.MyInteceptor" /> </mvc:interceptors>
<mvc:interceptors/>会为每一个HandlerMapping,注入一个拦截器。总有一个HandlerMapping是可以找到处理器的,最多也只找到一个处理器,所以这个拦截器总会被执行的。起到了总拦截器的作用。如果是REST风格的URL,静态资源也会被拦截。
方案二, (近似) 总拦截器, 拦截匹配的URL
<mvc:interceptors > <mvc:interceptor> <mvc:mapping path="/user/*" /> <!-- /user/* --> <bean class="com.mvc.MyInteceptor"></bean> </mvc:interceptor> </mvc:interceptors>
就是比 方案一多了一个URL匹配。如果是REST风格的URL,静态资源也会被拦截。
方案三,HandlerMappint上的拦截器
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="interceptors"> <list> <bean class="com.mvc.MyInteceptor"></bean> </list> </property> </bean>
如果是REST风格的URL,静态资源就不会被拦截。因为我们精准的注入了拦截器。
如果使用了<mvc:annotation-driven />, 它会自动注册DefaultAnnotationHandlerMapping 与AnnotationMethodHandlerAdapter 这两个bean,所以就没有机会再给它注入interceptors属性,就无法指定拦截器。
当然我们可以通过人工配置上面的两个Bean,不使用 <mvc:annotation-driven />,就可以 给interceptors属性 注入拦截器了。
二、配置多个数据源切换访问
<1>:这是数据源和事务扫描注入的配置 访问多个数据源只需要建立多个数据源和事务这一套配置文件
这是第一个数据源
[html] view
plain copy
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
default-lazy-init="true">
<description>Spring公共配置 </description>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:resources.properties</value>
<!-- <value>classpath:memcached.properties</value> -->
</list>
</property>
</bean>
<!-- dubbo配置 -->
<!-- <dubbo:application name="xaUserRegPro" />
<dubbo:registry address="multicast://" />
<dubbo:reference id="userRegProService" interface="com.xinnet.xa.service.UserRegProService" timeout="6000"/> -->
<!-- **************** druid 监控连接池配置 ***************** -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${initialSize}" />
<property name="minIdle" value="${minIdle}" />
<property name="maxActive" value="${maxActive}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${maxWait}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<!-- 如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。分库分表较多的数据库,建议配置为false -->
<property name="poolPreparedStatements" value="${poolPreparedStatements}" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 对泄漏的连接 自动关闭 -->
<property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 打开removeAbandoned功能 -->
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 1800秒,也就是30分钟 -->
<property name="logAbandoned" value="${logAbandoned}" /> <!-- 关闭abanded连接时输出错误日志 -->
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="mergeStat" />
<!-- <property name="filters" value="stat" /> -->
<!-- 慢日志查询 缺省为3秒 修改为10秒 10000 -->
<property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" />
<!-- DruidDataSource各自独立 , 支持配置公用监控数据 -->
<!-- <property name="useGloalDataSourceStat" value="true" /> -->
</bean>
<!-- druid 监控 spring -->
<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor"/>
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
<property name="patterns">
<list>
<value>com.xinnet.*.service.*</value>
</list>
</property>
</bean>
<aop:config>
<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />
</aop:config>
<!-- MyBatis Mapper.XMl 配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:config/mybatis.xml" />
<property name="mapperLocations">
<list>
<!-- 自动匹配Mapper映射文件 -->
<value>classpath:mapper/**/*-mapper.xml</value>
</list>
</property>
<!-- 添加插件 -->
<property name="plugins">
<array>
<ref bean="pagePlugin" />
</array>
</property>
</bean>
<!-- 支持文件上传相关 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<!-- 分页插件,根据方言自动添加分页信息,默认要求 -->
<bean id="pagePlugin" class="com.xinnet.core.mybatis.plugin.PagePlugin">
<property name="properties">
<props>
<prop key="dialect">com.xinnet.core.mybatis.dialet.MySQLDialect</prop>
<prop key="pageSqlId">.*query.*</prop>
</props>
</property>
</bean>
<!-- redis客户端 -->
<!-- jedis pool配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="${redis.maxActive}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWait" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="usePool" value="true"></property>
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.pass}" />
<property name="timeout" value="${redis.timeout}" />
<property name="database" value="${redis.default.db}"></property>
<constructor-arg index="0" ref="jedisPoolConfig" />
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- ***************事务配置************** -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<aop:config>
<aop:advisor pointcut="execution(* com.xinnet..service..*.*(..))" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="load*" read-only="true" />
<tx:method name="select*" read-only="true" />
<tx:method name="count*" read-only="true" />
<tx:method name="search*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 开启注解事务 只对当前配置文件有效 -->
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.xinnet">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 隐式地向 Spring 容器注册 -->
<context:annotation-config/>
</beans>
<2>这是第二个数据源 和第一个数据源一样 需要有事务 扫描注解
不同的是数据源的 url username 和password 用的是第二个数据源的连接 用户名和密码
[html] view
plain copy
<?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:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
default-lazy-init="true">
<description>Spring公共配置 </description>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:resources.properties</value>
<!-- <value>classpath:memcached.properties</value> -->
</list>
</property>
</bean>
<!-- **************** druid 监控连接池配置 ***************** -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${url2}" />
<property name="username" value="${username2}" />
<property name="password" value="${password2}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${initialSize}" />
<property name="minIdle" value="${minIdle}" />
<property name="maxActive" value="${maxActive}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${maxWait}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="60000" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="300000" />
<property name="validationQuery" value="SELECT 'x'" />
<property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="false" />
<property name="testOnReturn" value="false" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
<!-- 如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。分库分表较多的数据库,建议配置为false -->
<property name="poolPreparedStatements" value="${poolPreparedStatements}" />
<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
<!-- 对泄漏的连接 自动关闭 -->
<property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 打开removeAbandoned功能 -->
<property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 1800秒,也就是30分钟 -->
<property name="logAbandoned" value="${logAbandoned}" /> <!-- 关闭abanded连接时输出错误日志 -->
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="mergeStat" />
<!-- <property name="filters" value="stat" /> -->
<!-- 慢日志查询 缺省为3秒 修改为10秒 10000 -->
<property name="connectionProperties" value="druid.stat.slowSqlMillis=5000" />
<!-- DruidDataSource各自独立 , 支持配置公用监控数据 -->
<!-- <property name="useGloalDataSourceStat" value="true" /> -->
</bean>
<!-- druid 监控 spring -->
<bean id="druid-stat-interceptor" class="com.alibaba.druid.support.spring.stat.DruidStatInterceptor"/>
<bean id="druid-stat-pointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut" scope="prototype">
<property name="patterns">
<list>
<value>com.xinnet.*.service.*</value>
</list>
</property>
</bean>
<aop:config>
<aop:advisor advice-ref="druid-stat-interceptor" pointcut-ref="druid-stat-pointcut" />
</aop:config>
<!-- MyBatis Mapper.XMl 配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:config/mybatis.xml" />
<property name="mapperLocations">
<list>
<!-- 自动匹配Mapper映射文件 -->
<value>classpath:mapper/**/*-mapper.xml</value>
</list>
</property>
<!-- 添加插件 -->
<property name="plugins">
<array>
<ref bean="pagePlugin" />
</array>
</property>
</bean>
<!-- 支持文件上传相关 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<!-- 分页插件,根据方言自动添加分页信息,默认要求 -->
<bean id="pagePlugin" class="com.xinnet.core.mybatis.plugin.PagePlugin">
<property name="properties">
<props>
<prop key="dialect">com.xinnet.core.mybatis.dialet.MySQLDialect</prop>
<prop key="pageSqlId">.*query.*</prop>
</props>
</property>
</bean>
<!-- redis客户端 -->
<!-- jedis pool配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxActive" value="${redis.maxActive}" />
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWait" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="usePool" value="true"></property>
<property name="hostName" value="${redis.host}" />
<property name="port" value="${redis.port}" />
<property name="password" value="${redis.pass}" />
<property name="timeout" value="${redis.timeout}" />
<property name="database" value="${redis.default.db}"></property>
<constructor-arg index="0" ref="jedisPoolConfig" />
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>
<!-- ***************事务配置************** -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<aop:config>
<aop:advisor pointcut="execution(* com.xinnet..service..*.*(..))" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="query*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="load*" read-only="true" />
<tx:method name="select*" read-only="true" />
<tx:method name="count*" read-only="true" />
<tx:method name="search*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 开启注解事务 只对当前配置文件有效 -->
<!-- 扫描注解Bean -->
<context:component-scan base-package="com.xinnet">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 隐式地向 Spring 容器注册 -->
<context:annotation-config/>
</beans>
<3>这个时候就可以用两个数据源进行切换注入 从而使用不同数据源的service
这是service里面的方法 该怎么写就是怎么写 该怎么注解就怎么注解 不用做特殊的步骤
[java] view
plain copy
@Service("partyService")
public class PartyServiceImpl implements PartyService {
@Autowired
private PartyDao partyDao;
@Override
public List<Emp> getAllEmp() throws SQLException {
return partyDao.getAllEmp();
}
}
Dao层也是一样 该怎么写就怎么写 该怎么注解就怎么注解
然后可以写一个测试类试一下连接
[java] view
plain copy
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring.xml" })//这里的spring.xml加载了第一个数据源 spring-commons.xml
public class DataSourceTest extends AbstractTransactionalJUnit4SpringContextTests {
/**
*
* 功能描述:xxxxx
*
* @throws SQLException
*
* @author xxx[973893384@163.com]
*
* @since 2014年3月12日
*
* @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
*/
@Test
@Rollback(true)
public void testGetAllEmp() throws SQLException {
ApplicationContext ac = new FileSystemXmlApplicationContext("classpath:config/hymanager/hymanager_spring.xml");//这里加载的是第二个数据源配置文件路径 使用的时候用application 读取第二个数据源的配置文件 就可以用getBean 获取注入的service 不用ac.getBean 用@Autowired自动注入的 则使用的是第一个数据源
PartyService partyService = (PartyService) ac.getBean("partyService");
List<Emp> list = partyService.getAllEmp();
for (Emp emp : list) {
System.out.println(emp.getEmpno());
}
}
这样就可以封装一个父类
[java] view
plain copy
public class DataSourceChange {
//第二个数据源数据源
public ApplicationContext otherDataSource=new FileSystemXmlApplicationContext("classpath:config/hymanager/hymanager_spring.xml");
//默认数据源
public ApplicationContext defaultDataSource=new FileSystemXmlApplicationContext("classpath:config/spring_commons.xml");
/**
*
* 功能描述:xxxx
*
* @param beanName
* @return
*
* @author xxx[973893384@163.com]
*
* @since 2014年3月12日
*
* @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
*/
public Object now(String beanName) {
return defaultDataSource.getBean(beanName);
}
public Object after(String beanName) {
return otherDataSource.getBean(beanName);
}
}
要使用多个数据源的类就可以继承这个父类
[java] view
plain copy
public class HyMangerEmpDataHandle extends DataSourceChange {
//用父类的after方法更换配置切换第二套数据源获取注入partyService
private PartyService partyService=(PartyService) after("partyService");
//<span style="font-family: Arial, Helvetica, sans-serif;">用父类的now方法</span>更换配置切换第一套数据源获取注入empService
private EmpService empService=(EmpService) now("empService");
private static Logger log=LoggerFactory.getLogger(PartyService.class);
/**
*
* 功能描述:xxxxx
*
* @throws SQLException
*
* @author xxx[973893384@163.com]
*
* @since 2014年3月12日
*
* @update:[变更日期YYYY-MM-DD][更改人姓名][变更描述]
*/
public void leadingAllEmp() throws SQLException {
List<Emp> partyList=partyService.getAllEmp();//第二个数据源注入的service
for(Emp emp:partyList) {
empService.addEmp(emp);//第一个数据源注入的service
}
}
}
相关文章推荐
- springMVC中使用ajax来接收Controller传输的数据demo
- 斯坦福iOS7公开课11笔记及演示Demo&访问HTTPS链接下载数据
- SpringMVC接收json数据的demo
- Sql Server使用链接服务器远程取数据!
- 精华的微软文章".NET 数据访问架构指南",特别是数据库连接的测试.即监视链接池化(1)
- HOW TO:打开“数据链接属性”对话框并返回连接字符串
- (7) R-Studio Demo 数据恢复好轻松(图)
- 精华的微软文章".NET 数据访问架构指南",特别是数据库连接的测试.即监视链接池化(1)
- 通用数据链接文件 (*.UDL) 的创建
- 在Delphi中调用"数据链接属性"对话框设置ConnectionString
- 通过编写3ds max插件导出模型数据的一个demo
- 通用数据链接文件 (*.UDL) 的创建
- 读取数据库(SQL 、Access)、数据类型转换(Convert.Tostring)、数据库链接
- 链接数据失败时候的连接方法
- SQL Server2000通过链接服务器更新数据时的问题及解决办法
- 请教asp中如何访问链接服务器中的数据?
- 在TOMCAT5.0.27 中利用数据链接缓冲池
- 精华的微软文章".NET 数据访问架构指南",特别是数据库连接的测试.即监视链接池化 (2)
- Sql Server使用链接服务器远程取数据!
- 20061023个人技术日志(mssql链接服务器链接到oracle,由于数据长度不定产生的问题)