您的位置:首页 > 数据库 > Redis

spring+redis集成,策略设计,灵活配置,支持单机和集群

2017-05-06 14:36 761 查看

spring+redis集成,策略设计,支持单机和集群

前言

单JVM保证并发数据安全
1.线程同步锁,synchronized(this)或者Lock接口
2.数据表增加版本号字段,update where条件后面跟上版本号.这样就只会更新一次
3.利用数据库特性,悲观锁,性能较低,不推荐


这里主要用redis作缓存,实现分布式集群业务锁(多JVM环境)


环境准备

博主一惯基于自己ssm项目在做整合.可谓是大杂烩,后期还会逐步添加各种javaEE技术
目前是spring+springmvc+mybatis+redis+actvemq+dubbo+redis+log4j+quartz
还有很多细节未处理,大家见谅,项目可以运行,一切正常,已测试.
请注意本地需要activemq,redis环境.如果集成dubbo,还需要zookeeper作注册中心
技术交流可以加QQ757617714
github地址:https://github.com/15000814726/ssm.git


pom.xml导入依赖

<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>com.ssm.demo</groupId>
<artifactId>ssm</artifactId>
&l
4000
t;packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>ssm</name>
<url>http://maven.apache.org</url>
<properties>
<!-- spring版本号 -->
<spring.version>4.0.2.RELEASE</spring.version>
<!-- mybatis版本号 -->
<mybatis.version>3.2.6</mybatis.version>
<!-- log4j日志文件管理包版本 -->
<slf4j.version>1.7.7</slf4j.version>
<log4j.version>1.2.17</log4j.version>
<!-- activemq -->
<activemq_version>5.11.1</activemq_version>
<!-- quartz -->
<quartz.version>2.2.1</quartz.version>
<!-- dubbo -->
<dubbo.version>2.5.3</dubbo.version>
<!-- jedis -->
<jedis.version>2.8.1</jedis.version>
</properties>

<dependencies>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<!-- 表示开发的时候引入,发布的时候不会加载此包 -->
<scope>test</scope>
</dependency>

<!-- spring核心包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 添加扫描javabean的注解包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- web-mvc依赖web,不用导包 -->
<!-- <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency> -->

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
<version>${spring.version}</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- mybatis核心包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>

<!-- mybatis/spring包 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>

<!-- 导入java ee jar 包 -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>

<!-- 导入Mysql数据库链接jar包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.30</version>
</dependency>

<!-- 数据库连接池2选一,还有其余的 -->
<!-- dbcp连接池 -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
<exclusions>
<exclusion>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- c3p0连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>

<!-- JSTL标签类 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<!-- 日志文件管理包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>

<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.17</version>
</dependency>

<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>

<!-- 上传组件包 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>

<!-- StringUtils -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>

<!-- 集合工具类 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>

<!-- activeMQ -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-all</artifactId>
<version>${activemq_version}</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-pool</artifactId>
<version>${activemq_version}</version>
<!-- <exclusions>
<exclusion>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
</exclusion>
</exclusions> -->
</dependency>
<dependency>
<groupId>org.apache.xbean</groupId>
<artifactId>xbean-spring</artifactId>
<version>3.16</version>
</dependency>

<!-- Quartz 定时任务 -->
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>${quartz.version}</version>
<!-- 排除依赖 -->
<exclusions>
<exclusion>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz-jobs</artifactId>
<version>${quartz.version}</version>
</dependency>

<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
<exclusions>
<exclusion>
<artifactId>spring</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>

<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.7</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.9</version>
</dependency>

<!-- jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
<!-- <exclusions>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</exclusion>
</exclusions> -->
</dependency>

<!-- fst序列化工具 -->
<dependency>
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
<version>2.45</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
</exclusion>
</exclusions>
</dependency>

<!-- guava操作集合 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>21.0</version>
</dependency>

</dependencies>

<build>
<finalName>ssm</finalName>
<plugins>
<!-- 配置Tomcat插件 -->
<!-- <plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8082</port>
<path>/</path>
</configuration>
</plugin> -->
<!-- <plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<server>tomcat-local</server>
<port>8086</port>
<contextReloadable>true</contextReloadable>
<systemProperties>
<JAVA_OPTS>-Xms1024m -Xmx1024m -XX:PermSize=128M - XX:MaxPermSize=256m</JAVA_OPTS>
</systemProperties>
</configuration>
</plugin> -->
<!-- 资源文件拷贝插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>

</project>


Servlet容器入口web.xml

只在web.xml加载spring.xml.整合的XML在spring.xml引入.给人感觉赏心悦目,养成搭建习惯


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ssm</display-name>

<!-- 加载spring容器管理的所有bean -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring.xml</param-value>
</context-param>

<!-- 编码过滤器 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<async-supported>true</async-supported>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Spring监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- 防止Spring内存溢出监听器 -->
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>

<!-- Spring MVC servlet -->
<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:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<!-- 此处可以可以配置成*.do,对应struts的后缀习惯 -->
<url-pattern>/</url-pattern>
</servlet-mapping>

<welcome-file-list>
<welcome-file>/index.jsp</welcome-file>
</welcome-file-list>

</web-app>


spring容器核心配置文件和properties文件

spring.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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd ">

<!-- 自动扫描 -->
<context:component-scan base-package="com.ssm" />

<!-- 引入配置文件 -->
<bean id="propertyConfigurer"  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:redis.properties</value>
<value>classpath:jdbc.properties</value>
<value>classpath:log4j.properties</value>
</list>
</property>
</bean>

<!-- 引入activemq -->
<import resource="spring-active.xml"/>

<!-- 引入mvc -->
<import resource="spring-mvc.xml"/>

<!-- 引入mybatis -->
<import resource="spring-mybatis.xml"/>

<!-- 引入redis -->
<import resource="spring-redis.xml"/>

<!-- 引入定时任务 --><!-- job会不停的打日志,先注释掉,放开JOB就会跑 -->
<!-- <import resource="spring-quartz.xml"/> -->

</beans>


spring-mybatis.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:p="http://www.springframework.org/schema/p"
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.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> 
<!-- dbcp连接池 -->
<!-- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<property name="initialSize" value="${initialSize}"></property>
<property name="maxActive" value="${maxActive}"></property>
<property name="maxIdle" value="${maxIdle}"></property>
<property name="minIdle" value="${minIdle}"></property>
<property name="maxWait" value="${maxWait}"></property>
</bean> -->

<!-- C3P0连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}" />
<property name="jdbcUrl" value="${url}" />
<property name="user" value="${username}" />
<property name="password" value="${password}" />
<property name="initialPoolSize" value="${initialSize}" />
<property name="minPoolSize" value="${minIdle}" />
<property name="maxPoolSize" value="${maxActive}" />
<property name="testConnectionOnCheckin" value="false" />
<property name="idleConnectionTestPeriod" value="60" />
<property name="checkoutTimeout" value="30000" />
<property name="preferredTestQuery" value="select now()" />
</bean>

<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 自动扫描mapping.xml文件 -->
<property name="mapperLocations" value="classpath:com/ssm/mappings/*apper.xml"></property>
</bean>

<!-- DAO接口所在包名,Spring会自动查找其下的类 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.ssm.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>

<!-- 事务管理 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

</beans>


spring-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:p="http://www.springframework.org/schema/p"
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.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> 
<!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->
<context:component-scan base-package="com.ssm.web.controller" />

<!--避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>

<!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON转换器 -->
</list>
</property>
</bean>

<!-- 定义跳转的文件的前后缀 ,视图模式配置-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置视图解析的文件前缀后缀-->
<property name="prefix" value="/WEB-INF/page/" />
<property name="suffix" value=".jsp" />
</bean>

<!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 默认编码 -->
<property name="defaultEncoding" value="utf-8" />
<!-- 文件大小最大值 -->
<property name="maxUploadSize" value="10485760000" />
<!-- 内存中的最大值 -->
<property name="maxInMemorySize" value="40960" />
</bean>

</beans>


spring-quartz.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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd ">

<context:component-scan base-package="com.ssm.quartz.job" />

<!-- 第一种:MethodInvokingJobDetailFactoryBean -->
<!-- 这种方式在你想要调用特定 bean 的一个方法的时候很是方便 -->
<bean id="simpleJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<!-- mySimpleJob 任务POJO -->
<property name="targetObject" ref="mySimpleJob" />
<!-- 执行run方法 -->
<property name="targetMethod" value="run" />
</bean>

<!-- 初始延迟1秒,每20秒运行一次 -->
<bean id="simpleTrigger"  class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
<property name="jobDetail" ref="simpleJobDetail" />
<property name="startDelay" value="1000" />
<property name="repeatInterval" value="20000" />
</bean>

<!-- 第二种:JobDetailFactoryBean -->
<!-- 如果你需要更高级的设置,需要给作业传递数据,想更加灵活的话就使用这种方式。 -->
<bean name="firstComplexJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.ssm.quartz.job.FirstScheduledJob" />
<property name="jobDataMap">
<map>
<entry key="anotherBean" value-ref="anotherBean" />
</map>
</property>
<property name="durability" value="true" />
</bean>
<!-- 每30秒运行一次 -->
<bean id="cronTrigger"  class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="firstComplexJobDetail" />
<!--<property name="cronExpression" value="0/5 * * ? * SAT-SUN" />-->
<property name="cronExpression" value="0/30 * * ? * *" />
</bean>

<bean name="secondComplexJobDetail"    class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
<property name="jobClass" value="com.ssm.quartz.job.SecondScheduledJob" />
<property name="durability" value="true" />
</bean>
<!-- 总是在18:19日常运行 -->
<bean id="secondCronTrigger"  class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
<property name="jobDetail" ref="secondComplexJobDetail" />
<property name="cronExpression" value="0 19 18 * * ? *" />
</bean>

<!-- 调度器工厂bean jobDetails粘合在一起并触发配置Quartz调度器 -->
<bean  class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="jobDetails">
<list>
<ref bean="simpleJobDetail" />
<ref bean="firstComplexJobDetail" />
<ref bean="secondComplexJobDetail" />
</list>
</property>

<property name="triggers">
<list>
<ref bean="simpleTrigger" />
<ref bean="cronTrigger" />
<ref bean="secondCronTrigger" />
</list>
</property>
</bean>

</beans>


spring-active.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:amq="http://activemq.apache.org/schema/core"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core-5.8.0.xsd"> 
<!-- 真正可以产生Connection的ConnectionFactory,由对应的 JMS服务厂商提供 -->
<bean id="targetConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">

<property name="brokerURL" value="tcp://127.0.0.1:61616" />

<!-- 将该值开启官方说法是可以取得更高的发送速度(5倍)。 -->
<property name="useAsyncSend" value="true" />

<!-- 对于一个connection如果只有一个session,该值有效,否则该值无效,默认这个参数的值为true。 -->
<property name="alwaysSessionAsync" value="true" />

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

</bean>

<!-- 发送消息的目的地(一个队列) -->
<bean id="destination" class="org.apache.activemq.command.ActiveMQQueue">
<!-- 设置消息队列的名字 -->
<constructor-arg value="dongyangyang--3?consumer.prefetchSize=100" />
<!-- consumer.prefetchSize则代表我们在此使用“消费者”预分配协议,在消费者内在足够时可以使这个值更大以获得更好的吞吐性能。 -->
</bean>

<!-- 申明对于destination这个队列的重发机制为间隔100毫秒重发一次。 -->
<amq:redeliveryPolicy id="activeMQRedeliveryPolicy" destination="#destination"
redeliveryDelay="100" maximumRedeliveries="1" />

<!-- 应答模式队列 -->
<bean id="destination-request" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="dongyangyang--4?consumer.prefetchSize=100" />
</bean>
<bean id="destination-response" class="org.apache.activemq.command.ActiveMQQueue">
<constructor-arg value="dongyangyang--4--reply" />
</bean>

</beans>


log4j.properties

#定义LOG输出级别
log4j.rootLogger=INFO,Console,File
#定义日志输出目的地为控制台
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out
#可以灵活地指定日志输出格式,下面一行是指定具体的格式
log4j.appender.Console.layout = org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c] - %m%n

#文件大小到达指定尺寸的时候产生一个新的文件
log4j.appender.File = org.apache.log4j.RollingFileAppender
#指定输出目录
log4j.appender.File.File = logs/ssm.log
#定义文件最大大小
log4j.appender.File.MaxFileSize = 10MB
# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志
log4j.appender.File.Threshold = ALL
log4j.appender.File.layout = org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern =[%p] [%d{yyyy-MM-dd HH\:mm\:ss}][%c]%m%n


jdbc.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
username=root
password=root
#定义初始连接数
initialSize=10
#定义最大连接数
maxActive=20
#定义最大空闲
maxIdle=20
#定义最小空闲
minIdle=1
#定义最长等待时间
maxWait=60000


spring整合redis

spring-redis.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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd ">

<!-- redis单机连接方案 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${maxIdle}" /> <!-- 最大能够保持idel状态的对象数  -->
<property name="maxTotal" value="${maxTotal}" /> <!-- 最大分配的对象数 -->
<property name="testOnBorrow" value="${testOnBorrow}" /> <!-- 当调用borrow Object方法时,是否进行有效性检查 -->
</bean>

<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1" value="${redis.host}" />
<constructor-arg index="2" value="${redis.port}" type="int" />
</bean>

<!-- redis集群连接方案 -->
<!-- <bean name="genericObjectPoolConfig" class="org.apache.commons.pool2.impl.GenericObjectPoolConfig">
<property name="maxWaitMillis" value="${cluster.maxWaitMillis}" />
<property name="maxTotal" value="${cluster.maxTotal}" />
<property name="minIdle" value="${cluster.minIdle}" />
<property name="maxIdle" value="${cluster.maxIdle}" />
</bean> -->

<!-- <bean id="jedisCluster" class="com.ssm.common.redis.JedisClusterFactory">
<property name="connectionTimeout" value="${cluster.connectionTimeout}" />
<property name="soTimeout" value="${cluster.soTimeout}" />
<property name="maxRedirections" value="${cluster.maxRedirections}" />
<property name="genericObjectPoolConfig" ref="genericObjectPoolConfig" />
<property name="jedisClusterNodes">
<set>
<value>${cluster.address1}</value>
<value>${cluster.address2}</value>
<value>${cluster.address3}</value>
</set>
</property>
</bean> -->

<!-- 真正的redis操作类,具体连接方式由jedisClient的ref属性决定 可选项为jedisClusterClient、jedisClient -->
<bean name="redisOperate" class="com.ssm.common.redis.RedisOperate">
<property name="jedisClient" ref="jedisClient" />
</bean>

</beans>


redis.properties

###redis单机连接配置----start
#最大能够保持idel状态的对象数
maxIdle=300
#最大分配的对象数
maxTotal=60000
#当调用borrow Object方法时,是否进行有效性检查
testOnBorrow=false
#redis单机连接IP
redis.host=127.0.0.1
#redis单机连接端口
redis.port=6379
###redis单机连接配置----end

###redis集群连接配置----start
#获取连接时的最大等待毫秒数(如果设置为阻塞时BlockWhenExhausted),如果超时就抛异常.小于零:阻塞不确定的时间,默认-1
cluster.clmaxWaitMillis=-1
#最大连接数,默认8个
cluster.maxTotal=8
#最小空闲连接数,默认0个
cluster.minIdle=0
#最大空闲连接数,默认8个
cluster.maxIdle=8
#连接超时时间
cluster.connectionTimeout=3000
#相应超时时间
cluster.soTimeout=3000
#最大重定向时间
cluster.maxRedirections=5
#redis集群地址
cluster.address1=127.0.0.1:6379
cluster.address2=127.0.0.1:6380
cluster.address3=127.0.0.1:6381
###redis集群连接配置----end


策略生成操作redis的客户端服务


package com.ssm.common.redis;

import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.jedis.Pipeline;

public interface IJedisClient {

/**
* 获取缓存
* @param key 键
* @return 值
*/

String get(String key);

/**
* 获取缓存
* @param key 键
* @return 值
*/
Object getObject(String key);

/**
* 设置缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
String set(String key, String value, int cacheSeconds);

/**
* 设置缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
String setObject(String key, Object value, int cacheSeconds);

/**
* 获取List缓存
* @param key 键
* @return 值
*/
List<String> getList(String key);

/**
* 获取List缓存
* @param key 键
* @return 值
*/
List<Object> getObjectList(String key);

/**
* 设置List缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
long setList(String key, List<String> value, int cacheSeconds);

/**
* 设置List缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
long setObjectList(String key, List<Object> value, int cacheSeconds);

/**
* 向List缓存中添加值
* @param key 键
* @param value 值
* @return
*/
long listAdd(String key, String... value);

/**
* 向List缓存中添加值
* @param key 键
* @param value 值
* @return
*/
long listObjectAdd(String key, Object... value);

/**
* 获取缓存
* @param key 键
* @return 值
*/
Set<String> getSet(String key);

/**
* 获取缓存
* @param key 键
* @return 值
*/
Set<Object> getObjectSet(String key);

/**
* 设置Set缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
long setSet(String key, Set<String> value, int cacheSeconds);

/**
* 设置Set缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
long setObjectSet(String key, Set<Object> value, int cacheSeconds);

/**
* 向Set缓存中添加值
* @param key 键
* @param value 值
* @return
*/
long setSetAdd(String key, String... value);

/**
* 向Set缓存中添加值
* @param key 键
* @param value 值
* @return
*/
long setSetObjectAdd(String key, Object... value);

/**
* 获取Map缓存
* @param key 键
* @return 值
*/
Map<String, String> getMap(String key);

/**
* 获取Map缓存
* @param key 键
* @return 值
*/
Map<String, Object> getObjectMap(String key);

/**
* 设置Map缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
String setMap(String key, Map<String, String> value, int cacheSeconds);

/**
* 设置Map缓存
* @param key 键
* @param value 值
* @param cacheSeconds 超时时间,0为不超时
* @return
*/
String setObjectMap(String key, Map<String, Object> value,int cacheSeconds);

/**
* 向Map缓存中添加值
* @param key 键
* @param value 值
* @return
*/
String mapPut(String key, Map<String, String> value);

/**
* 向Map缓存中添加值
* @param key 键
* @param value 值
* @return
*/
String mapObjectPut(String key, Map<String, Object> value);

/**
* 移除Map缓存中的值
* @param key 键
* @param value 值
* @return
*/
long mapRemove(String key, String mapKey);

/**
* 移除Map缓存中的值
* @param key 键
* @param value 值
* @return
*/
long mapObjectRemove(String key, String mapKey);

/**
* 判断Map缓存中的Key是否存在
* @param key 键
* @param value 值
* @return
*/
boolean mapExists(String key, String mapKey);

/**
*
2ca59
判断Map缓存中的Key是否存在
* @param key 键
* @param value 值
* @return
*/
boolean mapObjectExists(String key, String mapKey);

/**
* 删除缓存
* @param key 键
* @return
*/
long del(String key);

/**
* 删除缓存
* @param key 键
* @return
*/
long delObject(String key);

/**
* 缓存是否存在
* @param key 键
* @return
*/
boolean exists(String key);

/**
* 缓存是否存在
* @param key 键
* @return
*/
boolean existsObject(String key);

/**
* 模拟分布式锁
* @autho 董杨炀
* @time 2017年5月6日 上午10:24:44
* @param key
* @param value
* @return
*/
long setnx(String key,String value);

/**
* 为给定  key  设置生存时间,当  key  过期时(生存时间为  0  ),它会被自动删除。
* @autho 董杨炀
* @time 2017年5月6日 上午10:40:23
* @param key
* @param ttl
*/
void expire(String key, int ttl);

/**
* 批量解锁
* @autho 董杨炀
* @time 2017年5月6日 上午11:03:35
* @param array
*/
void del(String[] array);

/**
* 获取redis批量处理得对象
* @autho 董杨炀
* @time 2017年5月6日 上午11:08:58
* @return
*/
Pipeline pipelined();
}


package com.ssm.common.redis;

import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ssm.utils.SerializeUtil;
import com.ssm.utils.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.exceptions.JedisException;

/**
* 单机方式redis客户端操作
* @author 353654
*
*/
@Service("jedisClient")
public class JedisClient implements IJedisClient {

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

@Resource
private JedisPool jedisPool;

/**
* 获取缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:16:19
* @param key
* @return
*/
public  String get(String key) {
String value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)) {
value = jedis.get(key);
value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
logger.debug("get {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("get {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 获取缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:16:15
* @param key
* @return
*/
public  Object getObject(String key) {
Object value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))) {
value = toObject(jedis.get(getBytesKey(key)));
logger.debug("getObject {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObject {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 设置缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:16:10
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  String set(String key, String value, int cacheSeconds) {
String result = null;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.set(key, value);
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("set {} = {}", key, value);
} catch (Exception e) {
logger.warn("set {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 设置缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:16:03
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  String setObject(String key, Object value, int cacheSeconds) {
String result = null;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.set(getBytesKey(key), toBytes(value));
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("setObject {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObject {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 获取List缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:57
* @param key
* @return
*/
public  List<String> getList(String key) {
List<String> value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)) {
value = jedis.lrange(key, 0, -1);
logger.debug("getList {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getList {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 获取List缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:52
* @param key
* @return
*/
public  List<Object> getObjectList(String key) {
List<Object> value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))) {
List<byte[]> list = jedis.lrange(getBytesKey(key), 0, -1);
value = Lists.newArrayList();
for (byte[] bs : list){
value.add(toObject(bs));
}
logger.debug("getObjectList {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObjectList {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 设置List缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:47
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  long setList(String key, List<String> value, int cacheSeconds) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)) {
jedis.del(key);
}
result = jedis.rpush(key, (String[])value.toArray());
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("setList {} = {}", key, value);
} catch (Exception e) {
logger.warn("setList {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 设置List缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:41
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  long setObjectList(String key, List<Object> value, int cacheSeconds) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))) {
jedis.del(key);
}
List<byte[]> list = Lists.newArrayList();
for (Object o : value){
list.add(toBytes(o));
}
result = jedis.rpush(getBytesKey(key), (byte[][])list.toArray());
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("setObjectList {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObjectList {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 向List缓存中添加值
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:35
* @param key
* @param value
* @return
*/
public  long listAdd(String key, String... value) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.rpush(key, value);
logger.debug("listAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("listAdd {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 向List缓存中添加值
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:29
* @param key
* @param value
* @return
*/
public  long listObjectAdd(String key, Object... value) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
List<byte[]> list = Lists.newArrayList();
for (Object o : value){
list.add(toBytes(o));
}
result = jedis.rpush(getBytesKey(key), (byte[][])list.toArray());
logger.debug("listObjectAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("listObjectAdd {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 获取缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:24
* @param key
* @return
*/
public  Set<String> getSet(String key) {
Set<String> value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)) {
value = jedis.smembers(key);
logger.debug("getSet {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getSet {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 获取缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:18
* @param key
* @return
*/
public  Set<Object> getObjectSet(String key) {
Set<Object> value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))) {
value = Sets.newHashSet();
Set<byte[]> set = jedis.smembers(getBytesKey(key));
for (byte[] bs : set){
value.add(toObject(bs));
}
logger.debug("getObjectSet {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObjectSet {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 设置Set缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:12
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  long setSet(String key, Set<String> value, int cacheSeconds) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)) {
jedis.del(key);
}
result = jedis.sadd(key, (String[])value.toArray());
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("setSet {} = {}", key, value);
} catch (Exception e) {
logger.warn("setSet {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 设置Set缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:07
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  long setObjectSet(String key, Set<Object> value, int cacheSeconds) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))) {
jedis.del(key);
}
Set<byte[]> set = Sets.newHashSet();
for (Object o : value){
set.add(toBytes(o));
}
result = jedis.sadd(getBytesKey(key), (byte[][])set.toArray());
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("setObjectSet {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObjectSet {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 向Set缓存中添加值
* @autho 董杨炀
* @time 2017年5月6日 上午11:15:02
* @param key
* @param value
* @return
*/
public  long setSetAdd(String key, String... value) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.sadd(key, value);
logger.debug("setSetAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("setSetAdd {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 向Set缓存中添加值
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:57
* @param key
* @param value
* @return
*/
public  long setSetObjectAdd(String key, Object... value) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
Set<byte[]> set = Sets.newHashSet();
for (Object o : value){
set.add(toBytes(o));
}
result = jedis.rpush(getBytesKey(key), (byte[][])set.toArray());
logger.debug("setSetObjectAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("setSetObjectAdd {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 获取Map缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:46
* @param key
* @return
*/
public  Map<String, String> getMap(String key) {
Map<String, String> value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)) {
value = jedis.hgetAll(key);
logger.debug("getMap {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getMap {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 获取Map缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:41
* @param key
* @return
*/
public  Map<String, Object> getObjectMap(String key) {
Map<String, Object> value = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))) {
value = Maps.newHashMap();
Map<byte[], byte[]> map = jedis.hgetAll(getBytesKey(key));
for (Map.Entry<byte[], byte[]> e : map.entrySet()){
value.put(new String(e.getKey()), toObject(e.getValue()));
}
logger.debug("getObjectMap {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObjectMap {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return value;
}

/**
* 设置Map缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:36
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  String setMap(String key, Map<String, String> value, int cacheSeconds) {
String result = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)) {
jedis.del(key);
}
result = jedis.hmset(key, value);
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("setMap {} = {}", key, value);
} catch (Exception e) {
logger.warn("setMap {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 设置Map缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:29
* @param key
* @param value
* @param cacheSeconds
* @return
*/
public  String setObjectMap(String key, Map<String, Object> value, int cacheSeconds) {
String result = null;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))) {
jedis.del(key);
}
Map<byte[], byte[]> map = Maps.newHashMap();
for (Map.Entry<String, Object> e : value.entrySet()){
map.put(getBytesKey(e.getKey()), toBytes(e.getValue()));
}
result = jedis.hmset(getBytesKey(key), (Map<byte[], byte[]>)map);
if (cacheSeconds != 0) {
jedis.expire(key, cacheSeconds);
}
logger.debug("setObjectMap {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObjectMap {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 向Map缓存中添加值
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:24
* @param key
* @param value
* @return
*/
public  String mapPut(String key, Map<String, String> value) {
String result = null;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.hmset(key, value);
logger.debug("mapPut {} = {}", key, value);
} catch (Exception e) {
logger.warn("mapPut {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 向Map缓存中添加值
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:19
* @param key
* @param value
* @return
*/
public  String mapObjectPut(String key, Map<String, Object> value) {
String result = null;
Jedis jedis = null;
try {
jedis = getResource();
Map<byte[], byte[]> map = Maps.newHashMap();
for (Map.Entry<String, Object> e : value.entrySet()){
map.put(getBytesKey(e.getKey()), toBytes(e.getValue()));
}
result = jedis.hmset(getBytesKey(key), (Map<byte[], byte[]>)map);
logger.debug("mapObjectPut {} = {}", key, value);
} catch (Exception e) {
logger.warn("mapObjectPut {} = {}", key, value, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 移除Map缓存中的值
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:11
* @param key
* @param mapKey
* @return
*/
public  long mapRemove(String key, String mapKey) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.hdel(key, mapKey);
logger.debug("mapRemove {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapRemove {}  {}", key, mapKey, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 移除Map缓存中的值
* @autho 董杨炀
* @time 2017年5月6日 上午11:14:04
* @param key
* @param mapKey
* @return
*/
public  long mapObjectRemove(String key, String mapKey) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.hdel(getBytesKey(key), getBytesKey(mapKey));
logger.debug("mapObjectRemove {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapObjectRemove {}  {}", key, mapKey, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 判断Map缓存中的Key是否存在
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:58
* @param key
* @param mapKey
* @return
*/
public  boolean mapExists(String key, String mapKey) {
boolean result = false;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.hexists(key, mapKey);
logger.debug("mapExists {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapExists {}  {}", key, mapKey, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 判断Map缓存中的Key是否存在
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:52
* @param key
* @param mapKey
* @return
*/
public  boolean mapObjectExists(String key, String mapKey) {
boolean result = false;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.hexists(getBytesKey(key), getBytesKey(mapKey));
logger.debug("mapObjectExists {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapObjectExists {}  {}", key, mapKey, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 删除缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:47
* @param key
* @return
*/
public  long del(String key) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(key)){
result = jedis.del(key);
logger.debug("del {}", key);
}else{
logger.debug("del {} not exists", key);
}
} catch (Exception e) {
logger.warn("del {}", key, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 删除缓存
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:42
* @param key
* @return
*/
public  long delObject(String key) {
long result = 0;
Jedis jedis = null;
try {
jedis = getResource();
if (jedis.exists(getBytesKey(key))){
result = jedis.del(getBytesKey(key));
logger.debug("delObject {}", key);
}else{
logger.debug("delObject {} not exists", key);
}
} catch (Exception e) {
logger.warn("delObject {}", key, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 缓存是否存在
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:37
* @param key
* @return
*/
public  boolean exists(String key) {
boolean result = false;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.exists(key);
logger.debug("exists {}", key);
} catch (Exception e) {
logger.warn("exists {}", key, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 缓存是否存在
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:27
* @param key
* @return
*/
public  boolean existsObject(String key) {
boolean result = false;
Jedis jedis = null;
try {
jedis = getResource();
result = jedis.exists(getBytesKey(key));
logger.debug("existsObject {}", key);
} catch (Exception e) {
logger.warn("existsObject {}", key, e);
} finally {
returnResource(jedis);
}
return result;
}

/**
* 获取资源
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:19
* @return
* @throws JedisException
*/
public  Jedis getResource() throws JedisException {
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//          logger.debug("getResource.", jedis);
} catch (JedisException e) {
logger.warn("getResource.", e);
returnBrokenResource(jedis);
throw e;
}
return jedis;
}

/**
* 归还资源
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:13
* @param jedis
*/
@SuppressWarnings("deprecation")
public  void returnBrokenResource(Jedis jedis) {
if (jedis != null) {
jedisPool.returnBrokenResource(jedis);
}
}

/**
* 释放资源
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:06
* @param jedis
*/
@SuppressWarnings("deprecation")
public  void returnResource(Jedis jedis) {
if (jedis != null) {
jedisPool.returnResource(jedis);
}
}

/**
* 获取byte[]类型Key
* @autho 董杨炀
* @time 2017年5月6日 上午11:13:01
* @param object
* @return
*/
public static byte[] getBytesKey(Object object){
if(object instanceof String){
return StringUtils.getBytes((String)object);
}else{
return SerializeUtil.serialize(object);
}
}

/**
* Object转换byte[]类型
* @autho 董杨炀
* @time 2017年5月6日 上午11:12:55
* @param object
* @return
*/
public static byte[] toBytes(Object object){
return SerializeUtil.serialize(object);
}

/**
* byte[]型转换Object
* @param key
* @return
*/
public static Object toObject(byte[] bytes){
return SerializeUtil.deserialize(bytes);
}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午10:25:16
* @param key
* @param value
* @return
*/
@Override
public long setnx(String key, String value) {
return this.getResource().setnx(key,value);
}

/**
*
* @autho 董杨炀
* @time 2017年5月6日 上午11:03:52
* @param key
* @param ttl
*/
@Override
public void expire(String key, int ttl) {
this.getResource().expire(key,ttl);
}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午11:03:52
* @param array
*/
@Override
public void del(String[] array) {
this.getResource().del(array);
}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午11:09:28
* @return
*/
@Override
public Pipeline pipelined() {
return this.getResource().pipelined();
}

}


package com.ssm.common.redis;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.ssm.utils.SerializeUtil;
import com.ssm.utils.StringUtils;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.Pipeline;

/**
* 集群方式redis客户端操作
* @author 353654
*
*/
//集群环境才开启Service,在spring注入
//@Service("jedisClusterClient")
public class JedisClusterClient implements IJedisClient{

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

@Resource
private JedisCluster jedisCluster;

@Override
public  String get(String key) {
String value = null;
try {
if (jedisCluster.exists(key)) {
value = jedisCluster.get(key);
value = StringUtils.isNotBlank(value) && !"nil".equalsIgnoreCase(value) ? value : null;
logger.debug("get {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("get {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return value;
}

@Override
public   Object getObject(String key) {
Object value = null;
try {
if (jedisCluster.exists(getBytesKey(key))) {
value = toObject(jedisCluster.get(getBytesKey(key)));
logger.debug("getObject {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObject {} = {}", key, value, e);
} finally {
//returnResource(jedis);
//          try {
//              jedisCluster.close();
//          } catch (IOException e) {
//              e.printStackTrace();
//          }
}
return value;
}

@Override
public   String set(String key, String value, int cacheSeconds) {
String result = null;

try {

result = jedisCluster.set(key, value);
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("set {} = {}", key, value);
} catch (Exception e) {
logger.warn("set {} = {}", key, value, e);
} finally {
//returnResource(jedis);
}
return result;
}

@Override
public   String setObject(String key, Object value, int cacheSeconds) {
String result = null;

try {
result = jedisCluster.set(getBytesKey(key), toBytes(value));
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("setObject {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObject {} = {}", key, value, e);
} finally {
//returnResource(jedis);
}
return result;
}

@Override
public  List<String> getList(String key) {
List<String> value = null;
try {
if (jedisCluster.exists(key)) {
value = jedisCluster.lrange(key, 0, -1);
logger.debug("getList {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getList {} = {}", key, value, e);
} finally {
//returnResource(jedis);
}
return value;
}

@Override
public   List<Object> getObjectList(String key) {
List<Object> value = null;
try {
if (jedisCluster.exists(getBytesKey(key))) {
List<byte[]> list = jedisCluster.lrange(getBytesKey(key), 0, -1);
value = Lists.newArrayList();
for (byte[] bs : list){
value.add(toObject(bs));
}
logger.debug("getObjectList {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObjectList {} = {}", key, value, e);
} finally {
//returnResource(jedis);
}
return value;
}

@Override
public   long setList(String key, List<String> value, int cacheSeconds) {
long result = 0;
try {
if (jedisCluster.exists(key)) {
jedisCluster.del(key);
}
result = jedisCluster.rpush(key, (String[])value.toArray());
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("setList {} = {}", key, value);
} catch (Exception e) {
logger.warn("setList {} = {}", key, value, e);
} finally {
//returnResource(jedis);
}
return result;
}

@Override
public   long setObjectList(String key, List<Object> value, int cacheSeconds) {
long result = 0;
try {
if (jedisCluster.exists(getBytesKey(key))) {
jedisCluster.del(key);
}
List<byte[]> list = Lists.newArrayList();
for (Object o : value){
list.add(toBytes(o));
}
result = jedisCluster.rpush(getBytesKey(key), (byte[][])list.toArray());
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("setObjectList {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObjectList {} = {}", key, value, e);
} finally {
//returnResource(jedis);
}
return result;
}

@Override
public   long listAdd(String key, String... value) {
long result = 0;
try {
result = jedisCluster.rpush(key, value);
logger.debug("listAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("listAdd {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long listObjectAdd(String key, Object... value) {
long result = 0;
try {
List<byte[]> list = Lists.newArrayList();
for (Object o : value){
list.add(toBytes(o));
}
result = jedisCluster.rpush(getBytesKey(key), (byte[][])list.toArray());
logger.debug("listObjectAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("listObjectAdd {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   Set<String> getSet(String key) {
Set<String> value = null;
try {
if (jedisCluster.exists(key)) {
value = jedisCluster.smembers(key);
logger.debug("getSet {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getSet {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return value;
}

@Override
public Set<Object> getObjectSet(String key) {
Set<Object> value = null;
try {
if (jedisCluster.exists(getBytesKey(key))) {
value = Sets.newHashSet();
Set<byte[]> set = jedisCluster.smembers(getBytesKey(key));
for (byte[] bs : set){
value.add(toObject(bs));
}
logger.debug("getObjectSet {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObjectSet {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return value;
}

@Override
public   long setSet(String key, Set<String> value, int cacheSeconds) {
long result = 0;
try {
if (jedisCluster.exists(key)) {
jedisCluster.del(key);
}
result = jedisCluster.sadd(key, (String[])value.toArray());
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("setSet {} = {}", key, value);
} catch (Exception e) {
logger.warn("setSet {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long setObjectSet(String key, Set<Object> value, int cacheSeconds) {
long result = 0;
try {
if (jedisCluster.exists(getBytesKey(key))) {
jedisCluster.del(key);
}
Set<byte[]> set = Sets.newHashSet();
for (Object o : value){
set.add(toBytes(o));
}
result = jedisCluster.sadd(getBytesKey(key), (byte[][])set.toArray());
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("setObjectSet {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObjectSet {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long setSetAdd(String key, String... value) {
long result = 0;
try {
result = jedisCluster.sadd(key, value);
logger.debug("setSetAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("setSetAdd {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long setSetObjectAdd(String key, Object... value) {
long result = 0;
try {
Set<byte[]> set = Sets.newHashSet();
for (Object o : value){
set.add(toBytes(o));
}
result = jedisCluster.rpush(getBytesKey(key), (byte[][])set.toArray());
logger.debug("setSetObjectAdd {} = {}", key, value);
} catch (Exception e) {
logger.warn("setSetObjectAdd {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   Map<String, String> getMap(String key) {
Map<String, String> value = null;
try {
if (jedisCluster.exists(key)) {
value = jedisCluster.hgetAll(key);
logger.debug("getMap {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getMap {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return value;
}

@Override
public   Map<String, Object> getObjectMap(String key) {
Map<String, Object> value = null;
try {
if (jedisCluster.exists(getBytesKey(key))) {
value = Maps.newHashMap();
Map<byte[], byte[]> map = jedisCluster.hgetAll(getBytesKey(key));
for (Map.Entry<byte[], byte[]> e : map.entrySet()){
value.put(new String(e.getKey()), toObject(e.getValue()));
}
logger.debug("getObjectMap {} = {}", key, value);
}
} catch (Exception e) {
logger.warn("getObjectMap {} = {}", key, value, e);
} finally {
}
return value;
}

@Override
public   String setMap(String key, Map<String, String> value, int cacheSeconds) {
String result = null;
try {
if (jedisCluster.exists(key)) {
jedisCluster.del(key);
}
result = jedisCluster.hmset(key, value);
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("setMap {} = {}", key, value);
} catch (Exception e) {
logger.warn("setMap {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   String setObjectMap(String key, Map<String, Object> value, int cacheSeconds) {
String result = null;
try {
if (jedisCluster.exists(getBytesKey(key))) {
jedisCluster.del(key);
}
Map<byte[], byte[]> map = Maps.newHashMap();
for (Map.Entry<String, Object> e : value.entrySet()){
map.put(getBytesKey(e.getKey()), toBytes(e.getValue()));
}
result = jedisCluster.hmset(getBytesKey(key), (Map<byte[], byte[]>)map);
if (cacheSeconds != 0) {
jedisCluster.expire(key, cacheSeconds);
}
logger.debug("setObjectMap {} = {}", key, value);
} catch (Exception e) {
logger.warn("setObjectMap {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   String mapPut(String key, Map<String, String> value) {
String result = null;
try {
result = jedisCluster.hmset(key, value);
logger.debug("mapPut {} = {}", key, value);
} catch (Exception e) {
logger.warn("mapPut {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   String mapObjectPut(String key, Map<String, Object> value) {
String result = null;
try {
Map<byte[], byte[]> map = Maps.newHashMap();
for (Map.Entry<String, Object> e : value.entrySet()){
map.put(getBytesKey(e.getKey()), toBytes(e.getValue()));
}
result = jedisCluster.hmset(getBytesKey(key), (Map<byte[], byte[]>)map);
logger.debug("mapObjectPut {} = {}", key, value);
} catch (Exception e) {
logger.warn("mapObjectPut {} = {}", key, value, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long mapRemove(String key, String mapKey) {
long result = 0;
try {
result = jedisCluster.hdel(key, mapKey);
logger.debug("mapRemove {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapRemove {}  {}", key, mapKey, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long mapObjectRemove(String key, String mapKey) {
long result = 0;
try {
result = jedisCluster.hdel(getBytesKey(key), getBytesKey(mapKey));
logger.debug("mapObjectRemove {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapObjectRemove {}  {}", key, mapKey, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   boolean mapExists(String key, String mapKey) {
boolean result = false;
try {
result = jedisCluster.hexists(key, mapKey);
logger.debug("mapExists {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapExists {}  {}", key, mapKey, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   boolean mapObjectExists(String key, String mapKey) {
boolean result = false;
try {
result = jedisCluster.hexists(getBytesKey(key), getBytesKey(mapKey));
logger.debug("mapObjectExists {}  {}", key, mapKey);
} catch (Exception e) {
logger.warn("mapObjectExists {}  {}", key, mapKey, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long del(String key) {
long result = 0;
try {
if (jedisCluster.exists(key)){
result = jedisCluster.del(key);
logger.debug("del {}", key);
}else{
logger.debug("del {} not exists", key);
}
} catch (Exception e) {
logger.warn("del {}", key, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   long delObject(String key) {
long result = 0;
try {
if (jedisCluster.exists(getBytesKey(key))){
result = jedisCluster.del(getBytesKey(key));
logger.debug("delObject {}", key);
}else{
logger.debug("delObject {} not exists", key);
}
} catch (Exception e) {
logger.warn("delObject {}", key, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   boolean exists(String key) {
boolean result = false;
try {
result = jedisCluster.exists(key);
logger.debug("exists {}", key);
} catch (Exception e) {
logger.warn("exists {}", key, e);
} finally {
//          returnResource(jedis);
}
return result;
}

@Override
public   boolean existsObject(String key) {
boolean result = false;
try {
result = jedisCluster.exists(getBytesKey(key));
logger.debug("existsObject {}", key);
} catch (Exception e) {
logger.warn("existsObject {}", key, e);
} finally {
//          returnResource(jedis);
}
return result;
}

/**
* 获取byte[]类型Key
* @param key
* @return
* @throws UnsupportedEncodingException
*/
public static  byte[] getBytesKey(Object object){
if(object instanceof String){
return StringUtils.getBytes((String)object);
}else{
return SerializeUtil.serialize(object);
}
}

/**
* Object转换byte[]类型
* @param key
* @return
*/
public static  byte[] toBytes(Object object){
return SerializeUtil.serialize(object);
}

/**
* byte[]型转换Object
* @param key
* @return
*/
public static Object toObject(byte[] bytes){
return SerializeUtil.deserialize(bytes);
}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午11:03:58
* @param key
* @param value
* @return
*/
@Override
public long setnx(String key, String value) {
return jedisCluster.setnx(key,value);
}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午11:03:58
* @param key
* @param ttl
*/
@Override
public void expire(String key, int ttl) {
jedisCluster.expire(key, ttl);
}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午11:03:58
* @param array
*/
@Override
public void del(String[] array) {
jedisCluster.del(array);

}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午11:09:24
* @return
*/
@Override
public Pipeline pipelined() {
//TODO redis集群环境获取管道模式执行批量操作
return null;
//TODO redis集群环境批量操作待续
}

}


package com.ssm.common.redis;

import java.util.HashSet;
import java.util.Set;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.expression.ParseException;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

public class JedisClusterFactory implements FactoryBean<JedisCluster>,InitializingBean{

private GenericObjectPoolConfig genericObjectPoolConfig;
private JedisCluster jedisCluster;
private int connectionTimeout;
private int soTimeout;
private int maxRedirections;
private Set<String> jedisClusterNodes;

@Override
public void afterPropertiesSet() throws Exception {
//判断地址是否为空
if(jedisClusterNodes == null || jedisClusterNodes.size() == 0){
throw new NullPointerException("jedisClusterNodes is null");
}
//构造结点
Set<HostAndPort> haps = new HashSet<HostAndPort>();
for(String node:jedisClusterNodes){
String[] arr = node.split(":");
if(arr.length != 2){
throw new ParseException(0, "node address error!");
}
haps.add(new HostAndPort(arr[0],Integer.valueOf(arr[1])));
}

jedisCluster = new JedisCluster(haps, connectionTimeout, soTimeout, maxRedirections, genericObjectPoolConfig);
}

@Override
public JedisCluster getObject() throws Exception {
return jedisCluster;
}

@Override
public Class<?> getObjectType() {
return (this.jedisCluster != null ? this.jedisCluster.getClass()
: JedisCluster.class);
}

@Override
public boolean isSingleton() {
return true;
}

public GenericObjectPoolConfig getGenericObjectPoolConfig() {
return genericObjectPoolConfig;
}

public void setGenericObjectPoolConfig(
GenericObjectPoolConfig genericObjectPoolConfig) {
this.genericObjectPoolConfig = genericObjectPoolConfig;
}

public JedisCluster getJedisCluster() {
return jedisCluster;
}

public void setJedisCluster(JedisCluster jedisCluster) {
this.jedisCluster = jedisCluster;
}

public int getConnectionTimeout() {
return connectionTimeout;
}

public void setConnectionTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
}

public int getSoTimeout() {
return soTimeout;
}

public void setSoTimeout(int soTimeout) {
this.soTimeout = soTimeout;
}

public int getMaxRedirections() {
return maxRedirections;
}

public void setMaxRedirections(int maxRedirections) {
this.maxRedirections = maxRedirections;
}

public Set<String> getJedisClusterNodes() {
return jedisClusterNodes;
}

public void setJedisClusterNodes(Set<String> jedisClusterNodes) {
this.jedisClusterNodes = jedisClusterNodes;
}
}


package com.ssm.common.redis;

import java.util.List;
import java.util.Map;
import java.util.Set;

import redis.clients.jedis.Pipeline;

/**
*
* 操作redis时真正使用的类
* 具体连接方式由spring注入的客户端类型决定
* @author 353654
*
*/
public class RedisOperate implements IJedisClient{

IJedisClient jedisClient;
public IJedisClient getJedisClient() {
return jedisClient;
}

public void setJedisClient(IJedisClient jedisClient) {
this.jedisClient = jedisClient;
}

@Override
public String get(String key) {
return jedisClient.get(key);
}

@Override
public Object getObject(String key) {
return jedisClient.getObject(key);
}

@Override
public String set(String key, String value, int cacheSeconds) {
return jedisClient.set(key, value, cacheSeconds);
}

@Override
public String setObject(String key, Object value, int cacheSeconds) {
return jedisClient.setObject(key, value, cacheSeconds);
}

@Override
public List<String> getList(String key) {
return jedisClient.getList(key);
}

@Override
public List<Object> getObjectList(String key) {
return jedisClient.getObjectList(key);
}

@Override
public long setList(String key, List<String> value, int cacheSeconds) {
return jedisClient.setList(key, value, cacheSeconds);
}

@Override
public long setObjectList(String key, List<Object> value, int cacheSeconds) {
return jedisClient.setObjectList(key, value, cacheSeconds);
}

@Override
public long listAdd(String key, String... value) {
return jedisClient.listAdd(key, value);
}

@Override
public long listObjectAdd(String key, Object... value) {
return jedisClient.listObjectAdd(key, value);
}

@Override
public Set<String> getSet(String key) {
return jedisClient.getSet(key);
}

@Override
public Set<Object> getObjectSet(String key) {
return jedisClient.getObjectSet(key);
}

@Override
public long setSet(String key, Set<String> value, int cacheSeconds) {
return jedisClient.setSet(key, value, cacheSeconds);
}

@Override
public long setObjectSet(String key, Set<Object> value, int cacheSeconds) {
return jedisClient.setObjectSet(key, value, cacheSeconds);
}

@Override
public long setSetAdd(String key, String... value) {
return jedisClient.setSetAdd(key, value);
}

@Override
public long setSetObjectAdd(String key, Object... value) {
return jedisClient.setSetObjectAdd(key, value);
}

@Override
public Map<String, String> getMap(String key) {
return jedisClient.getMap(key);
}

@Override
public Map<String, Object> getObjectMap(String key) {
return jedisClient.getObjectMap(key);
}

@Override
public String setMap(String key, Map<String, String> value, int cacheSeconds) {
return jedisClient.setMap(key, value, cacheSeconds);
}

@Override
public String setObjectMap(String key, Map<String, Object> value,
int cacheSeconds) {
return jedisClient.setObjectMap(key, value, cacheSeconds);
}

@Override
public String mapPut(String key, Map<String, String> value) {
return jedisClient.mapPut(key, value);
}

@Override
public String mapObjectPut(String key, Map<String, Object> value) {
return jedisClient.mapObjectPut(key, value);
}

@Override
public long mapRemove(String key, String mapKey) {
return jedisClient.mapRemove(key, mapKey);
}

@Override
public long mapObjectRemove(String key, String mapKey) {
return jedisClient.mapObjectRemove(key, mapKey);
}

@Override
public boolean mapExists(String key, String mapKey) {
return jedisClient.mapExists(key, mapKey);
}

@Override
public boolean mapObjectExists(String key, String mapKey) {
return jedisClient.mapObjectExists(key, mapKey);
}

@Override
public long del(String key) {
return jedisClient.del(key);
}

@Override
public long delObject(String key) {
return jedisClient.delObject(key);
}

@Override
public boolean exists(String key) {
return jedisClient.exists(key);
}

@Override
public boolean existsObject(String key) {
return jedisClient.existsObject(key);
}

/**
* 分布式锁模拟
* @autho 董杨炀
* @time 2017年5月6日 上午10:38:35
* @param key
* @param value
* @return
*/
@Override
public long setnx(String key, String value) {
return jedisClient.setnx(key,value);
}

/**
* 为给定  key  设置生存时间,当  key  过期时(生存时间为  0  ),它会被自动删除。
* @autho 董杨炀
* @time 2017年5月6日 上午10:38:35
* @param key
* @param ttl
*/
@Override
public void expire(String key, int ttl) {
jedisClient.expire(key,ttl);
}

/**
* 批量解锁
* @autho 董杨炀
* @time 2017年5月6日 上午11:02:32
* @param array
*/
@Override
public void del(String[] array) {
jedisClient.del(array);
}

/**
* 获取redis批量提交的对象
* @autho 董杨炀
* @time 2017年5月6日 上午11:08:15
* @return
*/
public Pipeline pipelined() {
return jedisClient.pipelined();
}

}


redis的缓存策略如上,这里使用单机,博主没有搭建redis集群,Jedis对集群的支持也不是很好,管道批量操作比较复杂.测试例子可以去源码看,下面简单贴一下代码,如何使用

package com.ssm.service.impl;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.ssm.common.exception.BusinessException;
import com.ssm.common.redis.RedisOperate;
import com.ssm.common.redis.sync.IBusinessLockService;
import com.ssm.common.redis.sync.MutexElement;
import com.ssm.common.redis.sync.MutexElementType;
import com.ssm.dao.UserDao;
import com.ssm.domain.UserEntity;
import com.ssm.service.UserService;

@Service("userService")
public class UserServiceImpl implements UserService {

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

@Resource
private UserDao userDao;

@Resource
private RedisOperate redisOperate;

@Resource
private IBusinessLockService businessLockService;

public UserEntity getUserById(int userId) {
if(userId < 0){
throw new BusinessException("userID不合法");
}
UserEntity user = null;
user = (UserEntity)redisOperate.getObject(String.valueOf(userId));
if(user!=null){
logger.info(user.toString());
return user;
}else{
user = this.userDao.selectByPrimaryKey(userId);
if(user != null){
redisOperate.setObject(String.valueOf(userId), user, 0);
}
return user;
}
}

/**
* @autho 董杨炀
* @time 2017年5月6日 下午12:18:49
* @param user
* @return
*/
@Override
public int updateUser(UserEntity user) {
if(user == null || StringUtils.isBlank(String.valueOf(user.getId())) || user.getId()<0){
throw new BusinessException("userId不合法");
}
//获取互斥对象
MutexElement mutexElement = new MutexElement(String.valueOf(user.getId()), "修改用户资料", MutexElementType.USER_UPDATE);
boolean lock = businessLockService.lock(mutexElement, 0);
System.out.println(lock);
if(!lock){
throw new BusinessException("此用户已被锁定,请稍后重试");
}
try {
return userDao.updateByPrimaryKey(user);
} finally {
businessLockService.unlock(mutexElement);//释放锁
}
}

}








redis实现业务锁

package com.ssm.common.redis.sync;

/**
* 互斥对象
* @autho 董杨炀
* @time 2017年5月6日 上午9:18:30
*/
public class MutexElement {

/**
* 业务标记
* 比如运单号,订单号,或者唯一ID
*/
private String businessNo;

/**
* 业务对象描述,如并发更新订单,运单,结清货款,签收等等业务
*/
private String businessDesc;

/**
* 锁定业务对象类型
*/
private MutexElementType type;

/**
* 锁定时间,默认一分钟
*/
private int ttl = 60;

/**
* 构造函数
* @autho 董杨炀
* @time 2017年5月6日 上午9:18:35
* @param businessNo
* @param businessDesc
* @param type
*/
public MutexElement(String businessNo, String businessDesc,MutexElementType type) {
this.businessNo = businessNo;
this.businessDesc = businessDesc;
this.type = type;
}

/**
* 获取业务标记  比如运单号订单号或者唯一ID
* @return 业务标记  比如运单号订单号或者唯一ID
*/
public String getBusinessNo() {
return businessNo;
}

/**
* 设置业务标记  比如运单号订单号或者唯一ID
* @param businessNo 业务标记  比如运单号订单号或者唯一ID
*/
public void setBusinessNo(String businessNo) {
this.businessNo = businessNo;
}

/**
* 获取业务对象描述,如并发更新订单运单结清货款签收等等业务
* @return 业务对象描述,如并发更新订单运单结清货款签收等等业务
*/
public String getBusinessDesc() {
return businessDesc;
}

/**
* 设置业务对象描述,如并发更新订单运单结清货款签收等等业务
* @param businessDesc 业务对象描述,如并发更新订单运单结清货款签收等等业务
*/
public void setBusinessDesc(String businessDesc) {
this.businessDesc = businessDesc;
}

/**
* 获取锁定业务对象类型
* @return 锁定业务对象类型
*/
public MutexElementType getType() {
return type;
}

/**
* 设置锁定业务对象类型
* @param type 锁定业务对象类型
*/
public void setType(MutexElementType type) {
this.type = type;
}

/**
* 获取锁定时间默认一分钟
* @return 锁定时间默认一分钟
*/
public int getTtl() {
return ttl;
}

/**
* 设置锁定时间默认一分钟
* @param ttl 锁定时间默认一分钟
*/
public void setTtl(int ttl) {
this.ttl = ttl;
}

/**
* @autho 董杨炀
* @time 2017年5月6日 上午9:58:56
* @return
*/
@Override
public String toString() {
return "MutexElement [businessNo=" + businessNo + ", businessDesc=" + businessDesc + ", type=" + type + ", ttl="
+ ttl + "]";
}

}


package com.ssm.common.redis.sync;

/**
* 锁定业务类型
* @autho 董杨炀
* @time 2017年5月6日 上午10:00:00
*/
public enum MutexElementType {

REPAYMENT_NO("LockRepaymentNo_","结清货款"),
RFC_SIGN("LockRfcSign_","签收"),
WABYILL_SUBMIT("LockWS_", "运单提交"),
ORDER_UPDATE("LockOrder_", "订单更改"),
USER_UPDATE("LockUser_","用户更改");

/**
* 业务前缀
*/
private String prefix;

/**
* 具体业务操作描述
*/
private String name;

private MutexElementType(String prefix, String name) {
this.prefix = prefix;
this.name = name;
}

/**
* 获取业务前缀
* @return 业务前缀
*/
public String getPrefix() {
return prefix;
}

/**
* 设置业务前缀
* @param prefix 业务前缀
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}

/**
* 获取具体业务操作描述
* @return 具体业务操作描述
*/
public String getName() {
return name;
}

/**
* 设置具体业务操作描述
* @param name 具体业务操作描述
*/
public void setName(String name) {
this.name = name;
}

}


package com.ssm.common.redis.sync;

import java.util.List;

/**
* 业务互斥锁服务
* @autho 董杨炀
* @time 2017年5月6日 上午9:11:21
*/
public interface IBusinessLockService {

/**
* 锁定某个业务对象
* timeout = 0 时,非阻塞调用,如果对象已锁定立刻返回失败
* timeout > 0 时,阻塞调用,如果对象已锁定,会等待直到1)获取锁并返回成功 2)超时并返回失败
* @author 董杨炀
* @date 2017年5月6日 上午9:11:21
* @param mutex 互斥对象
* @param timeout 超时时间,单位:秒
* @return true:锁定成功,false:锁定失败
*/
boolean lock(MutexElement mutex, int timeout);

/**
* 解除某个业务对象锁定
* @author 董杨炀
* @date 2017年5月6日 上午9:11:21
* @param mutex 互斥对象
*/
void unlock(MutexElement mutex);

/**
* 批量锁定多个业务对象
* timeout = 0 时,非阻塞调用,如果任意对象已锁定立刻返回失败
* timeout > 0 时,阻塞调用,如果任意对象已锁定,会等待直到1)获取锁并返回成功 2)超时并返回失败
* @author 董杨炀
* @date 2017年5月6日 上午9:11:21
* @param mutexes 多个互斥对象
* @param timeout 超时时间,单位:秒
* @return true:锁定成功,false:锁定失败
*/
boolean lock(List<MutexElement> mutexes, int timeout);

/**
* 批量解除多个业务对象锁定
* @author 董杨炀
* @date 2017年5月6日 上午9:11:21
* @param mutexes
*/
void unlock(List<MutexElement> mutexes);

}


package com.ssm.common.redis.sync;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.ssm.common.exception.BusinessException;
import com.ssm.common.redis.RedisOperate;
import com.ssm.utils.CollectionUtils;
import com.ssm.utils.StringUtils;

import redis.clients.jedis.Pipeline;

/**
* 业务互斥锁服务
* 根据redis setnx命令模拟实现集群锁
* @autho 董杨炀
* @time 2017年5月6日 上午10:05:35
*/
@Service("businessLockService")
public class BusinessLockService implements IBusinessLockService {

private static final Logger LOGGER = LoggerFactory.getLogger(BusinessLockService.class);

@Resource
private RedisOperate redisOperate;

/**
* 锁定某个业务对象
* timeout = 0 时,非阻塞调用,如果对象已锁定立刻返回失败
* timeout > 0时,阻塞调用,如果对象已锁定,会等待直到1)获取锁并返回成功 2)超时并返回失败
* @autho 董杨炀
* @time 2017年5月6日 上午10:05:35
* @param mutex  互斥对象
* @param timeout 超时时间,单位:秒
* @return true:锁定成功,false:锁定失败
*/
@Override
public boolean lock(MutexElement mutex, int timeout) {
if (mutex == null || mutex.getType() == null
|| StringUtils.isEmpty(mutex.getBusinessNo())) {
throw new BusinessException("The mutex parameter is empty");
}
String key = mutex.getType().getPrefix() + mutex.getBusinessNo();
String value = mutex.getBusinessDesc();
long nano = System.nanoTime();
try {
do {
LOGGER.debug("try lock key: " + key);
// 使用setnx模拟锁
Long i = redisOperate.setnx(key, value);
if (i == 1) {   // setnx成功,获得锁
redisOperate.expire(key, mutex.getTtl());
LOGGER.debug("get lock, key: " + key + " , expire in " + mutex.getTtl() + " seconds.");
return true;
} else {    // 存在锁
if (LOGGER.isDebugEnabled()) {
String desc = redisOperate.get(key);
LOGGER.debug("key: " + key + " locked by another business:" + desc);
}
}
if (timeout == 0) { // 非阻塞调用,则退出
break;
}
Thread.sleep(1000); // 每秒访问一次
} while ((System.nanoTime() - nano) < timeout * 1000 * 1000 * 1000);
// 得不到锁,返回失败
return false;
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
// 锁不再作为业务的的强制必要条件
// 发生REDIS异常,则不再处理锁
return true;
}

/**
* 解除某个业务对象锁定
* @autho 董杨炀
* @time 2017年5月6日 上午10:05:35
* @param mutex
*/
@Override
public void unlock(MutexElement mutex) {
if (mutex == null || mutex.getType() == null
|| StringUtils.isEmpty(mutex.getBusinessNo())) {
throw new BusinessException("The mutex parameter is empty");
}
String key = mutex.getType().getPrefix() + mutex.getBusinessNo();
try {
redisOperate.del(key);
LOGGER.debug("release lock, key :" + key);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}

/**
* 批量锁定多个业务对象
* @autho 董杨炀
* @time 2017年5月6日 上午10:05:35
* @param mutexes
* @param timeout
* @return
*/
@Override
public boolean lock(List<MutexElement> mutexes, int timeout) {
if (CollectionUtils.isEmpty(mutexes)) {
throw new BusinessException("The mutex parameter is empty");
}
// 定义并构造所有锁MAP
LinkedHashMap<String, MutexElement> map = new LinkedHashMap<String, MutexElement>();
for (MutexElement mutex : mutexes) {
if (mutex == null || mutex.getType() == null
|| StringUtils.isEmpty(mutex.getBusinessNo())) {
throw new BusinessException("The mutex parameter is empty");
}
String key = mutex.getType().getPrefix() + mutex.getBusinessNo();
map.put(key, mutex);
}
try {
List<String> locking = new ArrayList<String>(); // 要锁定的KEY集合
List<String> locked = new ArrayList<String>();  // 已锁定的KEY集合
locking.addAll(map.keySet());
long nano = System.nanoTime();
do {
LOGGER.debug("try lock keys: " + locking);
// 构建pipeline,批量提交
Pipeline pipeline = redisOperate.pipelined();
for (String key : locking) {
// 使用setnx模拟锁
pipeline.setnx(key, map.get(key).getBusinessDesc());
}
// 提交redis执行计数
List<Object> results = pipeline.syncAndReturnAll();
for (int i = 0; i < results.size(); ++i) {
Long result = (Long) results.get(i);
String key = locking.get(i);
if (result == 1) {  // setnx成功,获得锁
redisOperate.expire(key, map.get(key).getTtl());
locked.add(key);
}// 存在锁
}
locking.removeAll(locked);  // 已锁定资源去除
if (CollectionUtils.isEmpty(locking)) { // 得到所有锁资源
return true;
} else {    // 部分资源未能锁住
LOGGER.debug("keys: " + locking + " locked by another business:");
}
if (timeout == 0) { // 非阻塞调用,则退出
break;
}
Thread.sleep(1000); // 每秒访问一次

} while ((System.nanoTime() - nano) < timeout*10001*10001*10001);

// 得不到锁,释放锁定的部分对象,并返回失败
if (CollectionUtils.isNotEmpty(locked)) {
redisOperate.del(locked.toArray(new String[0]));
}
return false;
}catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
// 锁不再作为业务的的强制必要条件
// 发生REDIS异常,则不再处理锁
return true;
}

/**
* 批量解锁
* @autho 董杨炀
* @time 2017年5月6日 上午10:05:35
* @param mutexes
*/
@Override
public void unlock(List<MutexElement> mutexes) {
if (CollectionUtils.isEmpty(mutexes)) {
throw new BusinessException("The mutex parameter is empty");
}
List<String> keys = new ArrayList<String>();
for (MutexElement mutex : mutexes) {
if (mutex == null || mutex.getType() == null
|| StringUtils.isEmpty(mutex.getBusinessNo())) {
throw new BusinessException("The mutex parameter is empty");
}
String key = mutex.getType().getPrefix() + mutex.getBusinessNo();
keys.add(key);
}
try {
redisOperate.del(keys.toArray(new String[0]));
LOGGER.debug("release lock, keys :" + keys);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}

}


redis的高级特性.队列,发布/订阅待续.博主也不清楚,多见谅

github地址:https://github.com/15000814726/ssm.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: