• memcached与spring集成


    一、背景

    销售CRM(项目A)将负责管理项目信息系统(项目B)的支付与权限

    上级要求为避免频繁调用CRM接口,中间放一级缓存,但要做到缓存中保证最新数据

    因项目B已使用memcache作缓存,所以决定使用memcache

    二、设计

    1、统一系统交互方式,确保系统与系统间调用只有一个接口,接口参数为(String action, String data),以action区别调用是什么方法

    2、封装简单的memcache工具类,可执行简单的增删改查

    3、memcache单独一个日志文件,方便查找原因

    4、项目A,采用AOP拦截,在对数据进行增删改时,对缓存中数据进行同步操作

    5、为项目B再次封装memcache工具类的查询方法,确保在缓存查不到数据时,调用项目A的接口,将数据放于缓存

    本文主要讲解memcache与spring的集成,这些设计不在讲解范围内(貌似讲了一堆废话,哈哈)

    三、memcache与Spring集成

     memcache决定使用memcached client java客户端,原因是其使用较为广泛,单纯求稳妥

    在项目/src/main/resources/property下有三个配置文件,分别对应开发环境、预上线、正式线

    修改配置文件,增加

    #######################设置Memcached服务器参数#######################
    #设置服务器地址
    memcached.server=172.16.231.230:11211
    #容错
    memcached.failOver=true
    #设置初始连接数
    memcached.initConn=20
    #设置最小连接数
    memcached.minConn=10
    #设置最大连接数
    memcached.maxConn=250
    #设置连接池维护线程的睡眠时间
    memcached.maintSleep=3000
    #设置是否使用Nagle算法(Socket的参数),如果是true在写数据时不缓冲,立即发送出去
    memcached.nagle=false
    #设置socket的读取等待超时时间
    memcached.socketTO=3000
    #设置连接心跳监测开关
    memcached.aliveCheck=true
    #######################设置Memcached服务器参数#######################

    因预上线、与线上环境为封闭环境,memcache服务器地址在不同配置文件中各有不同

    可直接在spring的配置文件中增加memcache的配置,在这选择在/src/main/resources中增加memcached-context.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:task="http://www.springframework.org/schema/task"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://code.alibabatech.com/schema/dubbo    
        http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
        http://www.springframework.org/schema/task  
        http://www.springframework.org/schema/task/spring-task-3.1.xsd">
        
         <!-- 加载初始化配置文件 
         <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
            <property name="locations">
                <list>
                    <value>classpath:property/init.properties</value>
                </list>
            </property>
        </bean>-->
    
        <!-- Memcached配置 -->  
        <bean id="memcachedPool" class="com.whalin.MemCached.SockIOPool"  
            factory-method="getInstance" init-method="initialize" destroy-method="shutDown">  
            <property name="servers">  
                <list>  
                    <value>${memcached.server}</value>  
                </list>  
            </property>  
            <property name="initConn">  
                <value>${memcached.initConn}</value>  
            </property>  
            <property name="minConn">  
                <value>${memcached.minConn}</value>  
            </property>  
            <property name="maxConn">  
                <value>${memcached.maxConn}</value>  
            </property>  
            <property name="maintSleep">  
                <value>${memcached.maintSleep}</value>  
            </property>  
            <property name="nagle">  
                <value>${memcached.nagle}</value>  
            </property>  
            <property name="socketTO">  
                <value>${memcached.socketTO}</value>  
            </property>  
        </bean>
    </beans>

    因在spring配置文件中已加载了初始化配置文件,所以在这不需要再加载,如果没有加载过,应放开注释

    修改web.xml,增加memcached-content.xml

    <!-- spring配置文件 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath*:applicationContext.xml,classpath*:memcached-content.xml</param-value>
        </context-param>
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <listener>
            <listener-class>com.glodon.gcxx.common.ServletContextInit</listener-class>
        </listener>

    至此,配完了。。。。 是的,配完了,下面是工具类的代码

    package com.glodon.gcxx.Interaction.memcached;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.StringWriter;
    import java.util.Date;
    
    import org.apache.log4j.Logger;
    import org.springframework.stereotype.Component;
    
    import com.whalin.MemCached.MemCachedClient;
    public class MemcachedUtil { private static final Logger logger = Logger.getLogger(MemcachedUtil.class); private static MemCachedClient cachedClient; static { if (cachedClient == null) cachedClient = new MemCachedClient(); } /** * @Description 添加新的键值对,默认最少使用算法淘汰。如果键已经存在,则之前的值将被替换。 * @author liuy-8 * @date 2015年5月29日 下午2:09:17 * @param key 键 * @param value 值 * @return 是否成功 */ public static boolean set(String key, Object value) { return setExp(key, value, null); } /** * @Description 添加新的键值对。如果键已经存在,则之前的值将被替换。 * @author liuy-8 * @date 2015年5月29日 下午2:10:08 * @param key 键 * @param value 值 * @param time 过期时间,单位ms * @return 是否成功 */ public static boolean set(String key, Object value, int time) { return setExp(key, value, new Date(time)); } /** * @Description 添加新的键值对。如果键已经存在,则之前的值将被替换。 * @author liuy-8 * @date 2015年5月29日 下午2:13:18 * @param key 键 * @param value 值 * @param expire 例:New Date(1000*10):十秒后过期 * @return 是否成功 */ private static boolean setExp(String key, Object value, Date expire) { boolean flag = false; try { flag = cachedClient.set(key, value, expire); } catch (Exception e) { // 记录Memcached日志 logger.error("Memcached set方法报错,key值:" + key + " " + exceptionWrite(e)); } return flag; } /** * @Description 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对,默认最少使用算法淘汰 * @author liuy-8 * @date 2015年5月29日 下午2:13:50 * @param key 键 * @param value 值 * @return 是否成功 */ public static boolean add(String key, Object value) { return addExp(key, value, null); } /** * @Description 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对 * @author liuy-8 * @date 2015年5月29日 下午2:27:40 * @param key 键 * @param value 值 * @param time 过期时间,单位毫秒 * @return 是否成功 */ public static boolean add(String key, Object value, int time) { return addExp(key, value, new Date(time)); } /** * @Description 仅当缓存中不存在键时,add 命令才会向缓存中添加一个键值对 * @author liuy-8 * @date 2015年5月29日 下午2:30:29 * @param key 键 * @param value 值 * @param expire 例:New Date(1000*10):十秒后过期 * @return 是否成功 */ private static boolean addExp(String key, Object value, Date expire) { boolean flag = false; try { flag = cachedClient.add(key, value, expire); } catch (Exception e) { // 记录Memcached日志 logger.error("Memcached add方法报错,key值:" + key + " " + exceptionWrite(e)); } return flag; } /** * @Description 仅当键已经存在时,replace 命令才会替换缓存中的键,默认最少使用算法淘汰 * @author liuy-8 * @date 2015年5月29日 下午2:42:22 * @param key 键 * @param value 值 * @return 是否成功 */ public static boolean replace(String key, Object value) { return replaceExp(key, value, null); } /** * @Description 仅当键已经存在时,replace 命令才会替换缓存中的键。 * @author liuy-8 * @date 2015年5月29日 下午3:07:51 * @param key 键 * @param value 值 * @param time 过期时间,单位毫秒 * @return 是否成功 */ public static boolean replace(String key, Object value, int time) { return replaceExp(key, value, new Date(time)); } /** * @Description 仅当键已经存在时,replace 命令才会替换缓存中的键。 * @author liuy-8 * @date 2015年5月29日 下午3:09:22 * @param key 键 * @param value 值 * @param expire 过期时间 例:New Date(1000*10):十秒后过期 * @return 是否成功 */ private static boolean replaceExp(String key, Object value, Date expire) { boolean flag = false; try { flag = cachedClient.replace(key, value, expire); } catch (Exception e) { logger.error("Memcached replace方法报错,key值:" + key + " " + exceptionWrite(e)); } return flag; } /** * @Description 命令用于检索与之前添加的键值对相关的值 * @author liuy-8 * @date 2015年5月29日 下午3:09:45 * @param key 键 * @return 得到与键对应的值 */ public static Object get(String key) { Object obj = null; try { obj = cachedClient.get(key); } catch (Exception e) { logger.error("Memcached get方法报错,key值:" + key + " " + exceptionWrite(e)); } return obj; } /** * @Description 删除 memcached 中的任何现有值。 * @author liuy-8 * @date 2015年5月29日 下午3:10:57 * @param key 键 * @return 是否成功 */ public static boolean delete(String key) { return deleteExp(key, null); } /** * @Description 删除 memcached 中的任何现有值。 * @author liuy-8 * @date 2015年5月29日 下午3:33:39 * @param key 键 * @param time 阻塞时间,单位ms,禁止使用同样的键保存新数据,set方法除外 * @return 是否成功 */ public static boolean delete(String key, int time) { return deleteExp(key, new Date(time)); } /** * @Description 方法描述说明 * @author liuy-8 * @date 2015年5月29日 下午3:37:52 * @param key 键 * @param expire 阻塞时间,单位ms,禁止使用同样的键保存新数据,set方法除外 * @return 是否成功 */ private static boolean deleteExp(String key, Date expire) { boolean flag = false; try { flag = cachedClient.delete(key, expire); } catch (Exception e) { logger.error("Memcached delete方法报错,key值:" + key + " " + exceptionWrite(e)); } return flag; } /** * @Description 清理缓存中的所有键/值对 * @author liuy-8 * @date 2015年5月29日 下午3:38:26 * @return 是否成功 */ public static boolean flushAll() { boolean flag = false; try { flag = cachedClient.flushAll(); } catch (Exception e) { logger.error("Memcached flashAll方法报错 " + exceptionWrite(e)); } return flag; } /** * @Description 返回异常栈信息,String类型 * @author liuy-8 * @date 2015年5月29日 下午3:38:52 * @param e 异常 * @return 异常信息 */ private static String exceptionWrite(Exception e) { StringWriter sw = null; PrintWriter pw = null; String errorInfo = ""; try { sw = new StringWriter(); pw = new PrintWriter(sw); e.printStackTrace(pw); pw.flush(); errorInfo = sw.toString(); } finally { //关闭PrintWriter if(pw != null) pw.close(); //关闭StringWriter if(sw != null){ try { sw.close(); } catch (IOException e1) { e1.printStackTrace(); } } } return errorInfo; } }
  • 相关阅读:
    23、mybatis学习——mybatis的二级缓存
    22、mybatis学习——mybatis的一级缓存
    21、mybatis学习——mybatis动态sql之<sql>抽取sql语句
    20、mybatis学习——<bind>绑定
    19、mybatis学习——mybatis的动态sql之<foreach>遍历传入的数组,集合和map
    18、mybatis学习——mybatis的动态sql之通过{<set>和<if>结合}或者{<trim>和<if>的结合}实现部分字段更新
    17、mybatis学习——mybatis的动态sql之<choose><when><otherwise>选择唯一条件
    16、mybatis学习——mybatis的动态sql之<if>、<where>和<trim>
    15、mybatis学习——鉴别器discriminator的使用
    [20181108]with temp as 建立临时表吗.txt
  • 原文地址:https://www.cnblogs.com/xjyh/p/4545856.html
Copyright © 2020-2023  润新知