Spring MVC Integration memcached use of annotation-based practices

Source: Internet
Author: User
Tags ibm developerworks

This article does not describe the installation and use of memcached, nor the long-winded cache framework for good performance. Instead, it is a combination of their own actual development, to talk about their own use.

One, configuration file Application-cache.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:jee="/HTTP/ Www.springframework.org/schema/jee "xmlns:tx=" Http://www.springframework.org/schema/tx " xmlns:context=" Http://www.springframework.org/schema/context "xmlns:jdbc=" Http://www.springframework.org/schema/jdbc "  xmlns:aop= "HTTP://WWW.SPRINGFRAMEWORK.ORG/SCHEMA/AOP" xmlns:cache= "Http://www.springframework.org/schema/cache" Xsi:schemalocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/ beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/ schema/tx/spring-tx-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org /schema/jee/spring-jee-3.1.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/ Schema/aop/spring-aop-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/jdbc http://www.springframework.org/schema/jdbc/ spring-jdbc-3.1.xsd http://www.springframework.org/schema/cache http://www.springframework.org/ Schema/cache/spring-cache-3.1.xsd "default-lazy-init=" true "><!--  Caching service  --><!--  Custom key generation strategy--><!-- <cache:annotation-driven key-generator= "Stringkeygenerator"  /> <bean id= "Stringkeygenerator"  class= "Cn.roomy.supply.metadata.cache.StringKeyGenerator"  / > --><!--spring 3.1  introduced a note-based (annotation) caching (cache) technology  --><cache: Annotation-driven cache-manager= "CacheManager"  /><bean id= "CacheManager"  class= " Cn.roomy.supply.metadata.cache.MemcacheCacheManager ">    <!--  Whether transactions surround, if true, If the transaction is rolled back, the cache is rolled back, and the default false -->    <p roperty name= "Transactionaware"  value= "true"  /><property name= "caches" ><set >                <bean  class= "Cn.roomy.supply.metadata.cache.MemcachedSpringCache" ><property name= "name"  value= "R"  /><property name= "Memcachedclient"  ref= "Memcachedclient4user"  /><!--  1 days  --><property name= "expiredduration"  value= "86400"  /></bean><bean  class= "Cn.roomy.supply.metadata.cache.MemcachedSpringCache" ><property name= "name"  value= "S"  /><property name= "Memcachedclient"  ref= "Memcachedclient4user"  /><!--  30 days  --><property name= "Expiredduration"  value= "2592000"  /></bean><bean  class= "Cn.roomy.supply.metadata.cache.MemcachedSpringCache" ><property name= "name"  value= "V"  /><prOperty name= "Memcachedclient"  ref= "Memcachedclient4user"  /><!-- 7 days  -->< Property name= "Expiredduration"  value= "604800"  /></bean></set></property> </bean>        <bean id= "MemcachedClient4User"   class= "Net.spy.memcached.spring.MemcachedClientFactoryBean" >         <property name= "Servers"  value= "${memcached.url}"/>         <!--  Specifies the protocol to use (Binary,text), which is text -->        by default  <property name= "Protocol"  value= "TEXT"/>         <!--  Set the default transcoding (default to Net.spy.memcached.transcoders.SerializingTranscoder)  -->         <property name= "Transcoder" >             <bean class= "Net.spy.memcached.transcoders.SerializingTranscoder" >                 <property name= "CompressionThreshold " value="/>            </bean>         </property>         <!--  Set the default operation time-out in milliseconds  -->        <property  name= "Optimeout"  value= "/>        <property"  name= "Timeoutexceptionthreshold"  value= "19980"/>         <!--  Set hash algorithm  -->        <property name= "HASHALG ">            <value type=" Net.spy.memcached.DefaultHashAlgoRithm ">KETAMA_HASH</value>        </property>         <!--  Set Locator type (array_mod,consistent), default is Array_mod -->         <property name= "Locatortype"  value= "CONSISTENT"/ >        <!--  Set failure mode (cancel, reassign, retry), default is reassign  -->          <property name= "Failuremode"  value= "Redistribute" />        <!--          <property name= "Failuremode"  value= "Retry"/>          -->         <!--  Set to True if you want to use the Nagle algorithm  -->        <property name= "UseNagleAlgorithm"   Value= "false"/> &nbSp;  </bean>        </beans> 

1. The configuration file has a key support cache configuration item: <cache:annotation-driven cache-manager= "CacheManager"/> This configuration item defaults to a name called CacheManager Cache Manager, we have customized a cache manager Memcachecachemanager, which needs to configure a property caches, which is a cache collection managed by this cache manager. The custom Memcachespringcache configures the effective time for each cache.

2, introduce the third party spy's client Mencacheclientfactorybean, set its related properties.

Second, Memcachecachemanager and Memcachespringcache

/* * copyright 2002-2012 the original author or authors. * *  Licensed under the Apache License, Version 2.0  (the  "License");  * you may not use this file except in compliance with  the license. * you may obtain a copy of the license  at * *      http://www.apache.org/licenses/license-2.0 *  * Unless required by applicable law or agreed to in  writing, software * distributed under the license is distributed  on an  "As is"  basis, * without warranties or conditions of  any kind, either express or implied. * see the license  for the specific language governing permissions and * limitations under the  license. */package cn.roomy.supply.metadata.cache;import java.util.collection;import  org.springframework.cache.cache;import  org.springframework.cache.transaction.abstracttransactionsupportingcachemanager;public class  memcachecachemanager extends abstracttransactionsupportingcachemanager {public  Memcachecachemanager ()  {}private Collection<? extends Cache> caches;     /**     * specify the collection of cache  instances to use for this CacheManager.     */     public void setcaches (collection<? extends cache> caches)  {        this.caches = caches;     }     @Override     protected Collection<? extends  Cache> loadcaches ()  {        return this.caches;     }}

   here the emphasis on inheriting the Abstracttransactionsupportingcachemanager abstract class, see the class name probably also knows its main function, support for spring affairs! That is, if the transaction is rolled back, the cache data is removed. See its source, it inherits the Abstractcachemanager, and Abstractcachemanager realized the CacheManager interface.

package cn.roomy.supply.metadata.cache;import java.io.serializable;import  java.util.concurrent.future;import java.util.concurrent.timeunit;import  net.spy.memcached.memcachedclient;import org.apache.commons.lang3.time.stopwatch;import  org.slf4j.logger;import org.slf4j.loggerfactory;import  org.springframework.beans.factory.initializingbean;import org.springframework.cache.cache;import  org.springframework.cache.support.simplevaluewrapper;import org.springframework.util.assert;/** *   Memcached cache implementation based on Spring cache abstract system  */public class memcachedspringcache implements  Cache, InitializingBean {private final static Logger logger =  Loggerfactory.getlogger (memcachedspringcache.class);p rivate string name;private memcachedclient  memcachedClient;/** *  default Maximum cache time is 1 hours  */private static final int max_ expired_duration&The maximum cache time for the Nbsp;= 60 * 60;/** null value  */private static final int null_ value_expiration = 60 * 60 * 24 * 7;/**  increment expiration allows setting the maximum value  */ private static final int delta_expiration_threshold = 60 * 60 *  24 * 30;/** *  Cache Data Time-out time  */private int expiredduration = max_ Expired_duration;private static final object null_holder = new nullholder () ;p rivate boolean allownullvalues = true; @Overridepublic  void afterpropertiesset ( )  throws exception {assert.notnull (memcachedclient,  "Memcachedclient must not  be null! ");} @Overridepublic  string getname ()  {return this.name;} @Overridepublic  memcachedclient getnativecache ()  {return this.memcachedclient;} /** *  is given a valuewrapper based on key and then calls its GEThe T method gets the value  */@Overridepublic  valuewrapper get (object key)  {string cachekey =  getcachekey (key); Try {stopwatch sw = new stopwatch (); Sw.start ();Object  Value = memcachedclient.get (CacheKey); Sw.stop ();if  (Sw.gettime ()  > 50)  { Logger.info ("read memcached spents {}, key={}",  sw.gettime (),  cachekey);} return  (Value != null ? new simplevaluewrapper (FromStoreValue (value))  :  null);}  catch  (exception e)  {logger.error ("read memcached cache exception,  key={}, server={}",  Cachekey,memcachedclient.getnodelocator (). Getprimary (CacheKey). Getsocketaddress (),  e.getcause ()); return  null;}} /** *  Gets the value   */@SuppressWarnings ("unchecked") directly based on the key, and the type of value @Overridepublic  <t> t get (Object key, class<t> type)  {ValueWrapper  Element = get (key); Object value =  (Element != null ? element.get ()  : null);if  (value ==  null) return null;if  (type != null && !type.isinstance (value))  {throw new illegalstateexception ("Cached value type specified error  ["  + type.getname ()  +  "] :  " + value);} return  (T)  value;} /** *  is credited to the cached key and is threaded by the cached area +key object value  *  @param  key key objects  *  @return    */private string getcachekey (Object key)  {return this.name +  Key.tostring ();} /** *  Store Data  *  Secure set method, return result in 3 seconds,  otherwise cancel operation.  */@Overridepublic  void put ( Object key, object value)  {string cachekey = getcachekey (key); Logger.debug ( "Put Cache key:{}, value:{}, storevalue:{}",  cachekey, value, tostorevalue (Value)); int  expiration = expiredDuration;if  (value ==&Nbsp;null)  {if  (allownullvalues)  {value = NULL_HOLDER; //  If you allow null values to be cached, Null is substituted for the occupied pit object, and null is not allowed directly because}if  (expiredduration > null_value_expiration) cannot be serialized  { expiration = null_value_expiration; //  shortens the expiration time for null values, with a maximum cache of 7 days}} else if  ( Expiredduration > delta_expiration_threshold)  {expiration +=  (int)   ( System.currenttimemillis ()  / 1000); //  modifies the expiration time of the UNIX timestamp type, enabling the ability to set an expiration time of more than 30 days//  Note: Timestamp calculation There are 2038 problems,// 2038-1-19 11:14:07  (gmt +8)  , the converted  int  will overflow, resulting in a negative value} Future<boolean> future = memcachedclient.set (cachekey, expiration, value); try  {future.get (3, timeunit.seconds);}  catch  (Exception e)  {future.cancel (false); Logger.error ("memcached write Cache exception,  key={},  server={} ",  cachekey,memcachedclient.getnodelocator (). Getprimary (CacheKey). Getsocketaddress (),  e);}} /** *  Remove the cache  *  secure evict method from the cache, and return the result,  or cancel the operation within 3 seconds.  */@Overridepublic  void evict ( Object key)  {string cachekey = getcachekey (key); Logger.debug ("Delete cached key:{}",  CacheKey); Future<boolean> future = memcachedclient.delete (CacheKey); Try {future.get (3,  Timeunit.seconds);}  catch  (Exception e)  {future.cancel (false); Logger.error ("memcached Clear Cache exception,  key={},  server={} ",  cachekey,memcachedclient.getnodelocator (). Getprimary (CacheKey). Getsocketaddress (),  e);}} @Overridepublic  void clear ()  {try {memcachedclient.flush ();}  catch  (exception e)  {logger.error ("Memcached performs flush exception",  e);}} Protected object fromstorevalue (Object storevalue)  {if  (this.allownullvalues  && storevalue instanceof nullholder)  {return null;} Return storevalue;} Private static class nulLholder implements serializable {private static final long serialversionuid  = -99681708140860560l;} Protected object tostorevalue (Object uservalue)  {if  (this.allownullvalues & & uservalue == null)  {return null_holder;} Return uservalue;} Public void setname (String name)  {this.name = name;} Public void setmemcachedclient (memcachedclient memcachedclient)  {this.memcachedClient  = memcachedclient;} Public void setexpiredduration (int expiredduration)  {this.expiredDuration =  Expiredduration;} Public void setallownullvalues (boolean allownullvalues)  {this.allowNullValues =  Allownullvalues;}}

This class implements the Cache API interface, overrides the save, remove, and remove methods, and does a null optimization. Therefore, the subsequent cache operation calls this custom method.

Iii. Custom Annotations

Customize @cacheable to Annotations @cacheablerelation@retention (retentionpolicy.runtime) @Target ({Elementtype.method}) @ cacheable (value = "R", key= "#distributId + ' _ ' + #supplierId") public @interface Cacheablerelation {}
Customize @cacheevict to Annotations @cacheevictrelation @Retention (retentionpolicy.runtime) @Target ({Elementtype.method}) @ Cacheevict (value = "R", key= "#relation. Distributor.id + ' _ ' + #relation. SupplierId") Public @interface Cacheevictrelation {}
Customize the @cacheput as a comment @cacheputrelation @Retention (retentionpolicy.runtime) @Target ({Elementtype.method}) @CachePut ( Value = "S", key= "#relation. Distributid + ' _ ' + #relation. SupplierId") public @interface Cacheputrelation {}

The use of annotations such as @cacheable, @CacheEvict, @CachePut, etc. is not covered here. The focus is on value and key, and you will find that this value appears in the config file, and then it has a valid time set! And the key setting can refer to Spel usage, of course, the attributes of its comments and condition and other conditions to judge, space is limited, please consult yourself.

Iv. Reference Articles

Open the Big God Blog article:Spring Cache abstract detailed

IBM Developerworks: Comment-driven Spring Cache cache Introduction

This article is from the "Learning and Thinking" blog, please be sure to keep this source http://linhongyu.blog.51cto.com/6373370/1677336

Spring MVC Integration memcached use of annotation-based practices

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.