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
相关文章推荐
- redis集群的Cluster方式配置以及spring的集成
- java代码中操作Redis:单机redis、集群redis(spring+redis集成)
- Spring集成Jedis(不依赖spring-data-redis)(单机/集群模式)(待实践)
- Spring集成Jedis(不依赖spring-data-redis)(单机/集群模式)(待实践)
- Redis客户端之Spring整合Jedis,ShardedJedisPool集群配置
- Java + Redis3.0.2集群的应用(二)——Spring集成Jedis
- Spring Data Redis 单节点和集群配置和RedisTemplate用法
- Spring集成Redis集群
- Redis 一二事 - 在spring中使用jedis 连接调试单机redis以及集群redis
- Redis-3.2.4集群配置(RedisCluster+SpringBoot+Jedis)
- spring boot下JedisCluster方式连接Redis集群的配置
- windows本地安装redis单机和集群配置
- Spring Boot Redis 集成配置
- spring 使用redis集群配置
- CentOS7 redis-3.2.8 从单机到主从再到集群配置
- spring整合redis集群遇到的问题及MyEclipse下Maven的安装配置
- 使用spring-data-redis配置集群错误
- 玩转nodeJS系列:使用原生API实现简单灵活高效的路由功能(支持nodeJs单机集群),nodeJS本就应该这样轻快
- Spring集成quartz集群配置总结
- SpringBoot集成redis集群存储字符串和对象