SSM 之 simple-spring-memcached 使用手册

Memcached是前台应用系统主要的分布式缓存工具。为了简化操作,引入了SSM(Simple-Spring-Memcached)工具。

SSM本身不提供任何缓存,是为了简化缓存操作而设计的。所以,在缓存的实现上使用了第三方的组件:spymemcached,xmemcached 和 aws-elasticache 。

SSM的源代码托管:https://github.com/ragnor/simple-spring-memcached

SSM的文档:https://code.google.com/p/simple-spring-memcached (非常遗憾,经常访问不了)

1、配置文件

1.1 依赖包

如果通过maven管理,引入非常简单。

<dependencies>
   <dependency>
     <groupId>com.google.code.simple-spring-memcached</groupId>
     <artifactId>xmemcached-provider</artifactId>
     <version>3.6.0</version>
   </dependency> 
</dependencies>


1.2 spring的配置文件

新增:

<!--把CacheBase注入到Advice中,默认使用自己jar包中的配置文件-->
<import resource="classpath:simplesm-context.xml"/>
<!--打开aop注解-->
<aop:aspectj-autoproxy/>
<!--定义缓存客户端-->
<bean name="defaultMemcachedClient" class="com.google.code.ssm.CacheFactory">
    <property name="cacheClientFactory">
        <!--可配置不同的客户端,比如sypMemcached等-->
        <bean class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl"/>
    </property>
    <property name="addressProvider">
        <!--缓存服务器集群地址,还可以使用JndiAddressProvider-->
        <bean class="com.google.code.ssm.config.DefaultAddressProvider">
            <!--缓存集群地址-->            
            <property name="address" value="${memcached.servers}"/>
        </bean>
    </property>
    <property name="configuration">
        <bean class="com.google.code.ssm.providers.CacheConfiguration">
            <property name="consistentHashing" value="true"/>
            <!--缓存操作超时时间-->
            <property name="operationTimeout" value="${memcached.timeout}"/>
            <!--3.3.0版本后,新增了keyName的前缀功能,可能是考虑到不同应用使用同一个集群,避免KEY覆盖的情况。useNameAsKeyPrefix keyPrefixSeparator-->
        </bean>
    </property>
</bean>
<!--加载properties文件->
<beans profile="zsc1">
    <context:property-placeholder location="classpath:zsc1/*.properties,classpath:*.properties" file-encoding="utf-8" />
</beans>
<beans profile="zsc2">
    <context:property-placeholder location="classpath:zsc2/*.properties,classpath:*.properties" file-encoding="utf-8" />
</beans>
<beans profile="pro">
    <context:property-placeholder location="classpath:pro/*.properties,classpath:*.properties" file-encoding="utf-8" />
</beans>

1.3 memcached.properties文件

#集群 主节点,备节点 主节点,备节点
#memcached.servers=172.16.20.1:11211,172.16.20.2:12211 172.16.20.3:11211,172.16.10.4:12211 172.16.10.5:11212,172.16.10.6:12211 172.16.10.7:11212,172.16.20.8:12211
memcached.servers=172.16.50.66:11211
memcached.timeout=1000

2、注解

SSM本质上是采用了AOP的方式来实现缓存的调用和管理,其核心组件声明了一些Advice,当遇到相应的切入点时,会执行这些Advice来对memcached加以管理。

切入点是通过注解的方式来进行声明的,在项目开发时,通常在方法上加以相应的注解描述,来表示组件对该方法的拦截。

组件所提供的切入点主要包括以下几种:

ReadThroughSingleCache、ReadThroughMultiCache、ReadThroughAssignCache

当遇到查询方法声明这些切入点时,组件首先会从缓存中读取数据,取到数据则跳过查询方法,直接返回。取不到数据在执行查询方法,并将查询结果放入缓存,以便下一次获取。

InvalidateSingleCache、InvalidateMultiCache、InvalidateAssignCache 

当遇到删除方法声明这些切入点时,组件会删除缓存中的对应实体。

UpdateSingleCache、UpdateMultiCache、UpdateAssignCache 

当遇到更新方法声明这些切入点是,组件会更新缓存中对应的实体,以便下次从缓存中读取出的数据状态是最新的。

缓存的keyName,一般是由namespace 和 唯一性的值组合而成。

CacheKeyMethod、ParameterValueKeyProvider 生成缓存key。

以下是这些注解的详细使用说明:

@CacheName:指定缓存实例注解

@CacheKeyMethod:缓存key生成注解

---------------------------------            读取         --------------------------------- 

2.1 ReadThroughSingleCache

读取单个缓存

从缓存中读取value,如果缓存中没有,执行被注解的方法体,并将执行结果放倒缓存中。返回方法体的执行结果。

keyName的生成,通过 获取注解中的 namespace属性值以及ParameterValueKeyProvider 和  CacheKeyMethod注解的内容 获取。

ReadThroughSingleCache源码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@CacheOperation({CacheOperation.Type.READ, CacheOperation.Type.SINGLE})
public @interface ReadThroughSingleCache {
 
    /**
     * A namespace that is added to the key as it is stored in the distributed cache. This allows differing object that
     * may have the same ID to coexist. This value must be assigned.
     * 
     * @return the namespace for the objects cached in the given method.
     */
    String namespace() default AnnotationConstants.DEFAULT_STRING;
 
    /**
     * The exp value is passed along to memcached exactly as given, and will be processed per the memcached protocol
     * specification:
     * 
     * The actual value sent may either be Unix time (number of seconds since January 1, 1970, as a 32-bit value), or a
     * number of seconds starting from current time. In the latter case, this number of seconds may not exceed
     * 60*60*24*30 (number of seconds in 30 days); if the number sent by a client is larger than that, the server will
     * consider it to be real Unix time value rather than an offset from current time.
     * 
     * (Also note: a value of 0 means the given value should never expire. The value is still susceptible to purging by
     * memcached for space and LRU (least recently used) considerations.)
     * 
     * @return expiration of cached data
     */
    int expiration() default 0;
 
}

例子:

namespace:命名空间

expiration:缓存时间

/**
 * 获取银行列表接口查询结果,该结果获取后会被缓存。
 * KEY:CacheConstant.NAMESPACE_BANK_LIST_INFO 和 BankListIn 对象中getCacheKey() 方法的返回值的组合。 
 */
@ReadThroughSingleCache(namespace = CacheConstant.NAMESPACE_BANK_LIST_INFO, expiration = CacheConstant.EXP_SECONDS_BANK_LIST_INFO)
public UniResult<List<BankListOut>> getBankList(@ParameterValueKeyProvider BankListIn bankListIn)
      throws Throwable {
   // 序列化接口入参
   String url = InterfaceConfig.getInterface("/tianyimall/banklist");
   url = URLUtil.ObjectToURL(url, bankListIn);
   // 反序列化接口出参
       return excuteGet(url, new TypeReference<UniResult<List<BankListOut>>>() {});
}

BankListIn

public class BankListIn implements Serializable{
 
   private static final long serialVersionUID = 9168068757534717931L;
   /**
    * 类型
    */
   private String type;
   /**
    * 支付平台ID
    */
   private String paymentplatformid;
   /**
    * type.
    *
    * @return  the type
    * @since   
    */
   public String getType() {
      return type;
   }
   /**
    * type.
    *
    * @param   type    the type to set
    * @since   
    */
   public void setType(String type) {
      this.type = type;
   }
   /**
    * paymentplatformid.
    *
    * @return  the paymentplatformid
    * @since   
    */
   public String getPaymentplatformid() {
      return paymentplatformid;
   }
   /**
    * paymentplatformid.
    *
    * @param   paymentplatformid    the paymentplatformid to set
    * @since   
    */
   public void setPaymentplatformid(String paymentplatformid) {
      this.paymentplatformid = paymentplatformid;
   }
 
    @CacheKeyMethod
    public String getCacheKey(){
        return type+"_"+paymentplatformid;
    }
    
}

2.2 ReadThroughMultiCache

@ReadThroughMultiCache(option = @ReadThroughMultiCacheOption(generateKeysFromResult = true)):读取多个缓存

@ReadThroughMultiCacheOption(generateKeysFromResult = true) 读取多个缓存操作generateKeysFromResult 通过结果生成key

例子:ReadThroughMultiCache

@ReadThroughMultiCache(namespace = CacheConstant.NAMESPACE_BASIC_INFO, expiration = CacheConstant.EXP_SECONDS_BASIC_INFO)
   public List<SPProductInfo> getProductBasicInfoByPids(@ParameterValueKeyProvider List<String> salesPids) throws Throwable {
       List<SPProductInfo> list = new ArrayList<>();
       for (String salesPid : salesPids) {
           list.add(getProductBasicInfoByPid(salesPid));
       }
       return list;
   }

2.3 ReadThroughAssignCache

这个注解在没有参数,也就是没有@ParameterValueKeyProvider 的时候,会指定key,比如下面的SomePhatKey

@ReadThroughAssignCache(assignedKey = "SomePhatKey", namespace = "Echo", expiration = 3000): 读取指定key缓存

例子:ReadThroughtAssignCache

@ReadThroughAssignCache(assignedKey = "userKey", namespace = "test", expiration = 3000)
public List getAllUser(){  
      System.out.println("没有缓存命中");  
      List l = new  ArrayList(3);  
      l.add("1");  
      return l;  
}

---------------------------------           失效           --------------------------------- 

InvalidateSingleCache

@InvalidateSingleCache(namespace = SINGLE_NS):失效单个缓存

InvalidateMultiCache

@InvalidateMultiCache(namespace = "Delta") : 失效多个缓存

InvalidateAssignCache

@InvalidateAssignCache(assignedKey = "SomePhatKey", namespace = "Echo") : 指定key失效缓存

InvalidateAssignCache

@InvalidateAssignCache(assignedKey = "userKey", namespace = "test")  
   // assignedKey 也是不可缺少的,参数和返回值 不是必须的  
   public User delete() throws Exception{  
       User user = new User();  
       return user;  
}

 ---------------------------------           更新          --------------------------------- 

UpdateSingleCache

@UpdateSingleCache(namespace = SINGLE_NS, expiration = 2): 更新单个缓存(namespace 命名空间, expiration 失效时间单位秒)

 

UpdateMultiCache

@UpdateMultiCache(namespace = "Bravo", expiration = 300): 更新多个缓存

UpdateAssignCache

@UpdateAssignCache(assignedKey = "SomePhatKey", namespace = "Echo", expiration = 3000): 指定key更新缓存

UpdateMultiCacheOption

---------------------------------           参数          --------------------------------- 

ParameterDataUpdateContent

@ParameterDataUpdateContent: 标记方法的参数作为更新内容。这个注解应结合Update*Cache注解使用

ParameterValueKeyProvider 

@ParameterValueKeyProvider: 标记将方法的参数做为计算缓存key.如果方法被注解的对象标记CacheKeyMethod的方法将会用来生成缓存key否则调用toString()生成

@ParameterValueKeyProvider(order=0): 属性表示如果多个参数做为key时需提供参数顺序

与@ParameterValueKeyProvider类似的注解有:

{

  @ReturnValueKeyProvider: 返回值对象中计算key

}

ReturnDataUpdateContent

 

spring xmemcached 注解介绍  

  http://greemranqq.iteye.com/blog/2169594

 simple-spring-memcached那些事三

  http://my.oschina.net/orgsky/blog/424727?fromerr=bme8sZfS

赞(52) 打赏
未经允许不得转载:优客志 » JAVA开发
分享到:

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏