View Javadoc
1   package com.foxinmy.weixin4j.cache;
2   
3   import java.util.ArrayList;
4   import java.util.Date;
5   import java.util.HashSet;
6   import java.util.List;
7   import java.util.Set;
8   
9   import com.whalin.MemCached.MemCachedClient;
10  import com.whalin.MemCached.SockIOPool;
11  
12  /**
13   * 用Memcache保存缓存对象(推荐使用)
14   *
15   * @className MemcacheCacheStorager
16   * @author jinyu(foxinmy@gmail.com)
17   * @date 2016年5月11日
18   * @since JDK 1.6
19   * @see
20   */
21  public class MemcacheCacheStorager<T extends Cacheable> implements
22  		CacheStorager<T> {
23  
24  	private final MemCachedClient mc;
25  
26  	public MemcacheCacheStorager() {
27  		this(new MemcachePoolConfig());
28  	}
29  
30  	public MemcacheCacheStorager(MemcachePoolConfig poolConfig) {
31  		mc = new MemCachedClient();
32  		poolConfig.initSocketIO();
33  		initializeKey();
34  	}
35  
36  	@SuppressWarnings("unchecked")
37  	private Set<String> initializeKey() {
38  		Set<String> all = (Set<String>) mc.get(ALLKEY);
39  		if (all == null) {
40  			all = new HashSet<String>();
41  			mc.set(ALLKEY, all);
42  		}
43  		return all;
44  	}
45  
46  	@SuppressWarnings("unchecked")
47  	@Override
48  	public T lookup(String key) {
49  		return (T) mc.get(key);
50  	}
51  
52  	@Override
53  	public void caching(String key, T cache) {
54  		if (cache.getCreateTime() > 0l) {
55  			mc.set(key,
56  					cache,
57  					new Date(cache.getCreateTime() + cache.getExpires() - CUTMS));
58  		} else {
59  			mc.set(key, cache);
60  		}
61  		Set<String> all = initializeKey();
62  		all.add(key);
63  		mc.set(ALLKEY, all);
64  	}
65  
66  	@Override
67  	public T evict(String key) {
68  		T cache = lookup(key);
69  		mc.delete(key);
70  		Set<String> all = initializeKey();
71  		all.remove(key);
72  		mc.set(ALLKEY, all);
73  		return cache;
74  	}
75  
76  	@Override
77  	public void clear() {
78  		Set<String> all = initializeKey();
79  		for (String key : all) {
80  			mc.delete(key);
81  		}
82  		mc.delete(ALLKEY);
83  	}
84  
85  	public static class MemcachePoolConfig {
86  		public final static String HOST = "127.0.0.1";
87  		public final static int PORT = 11211;
88  		public final static int WEIGHT = 1;
89  
90  		public static int minConn = 5;
91  		public static int initConn = 5;
92  		public static int maxConn = 100;
93  		public static int maxIdle = 300000;
94  		public static long maxBusyTime = 30000L;
95  		public static int socketTO = 3000;
96  		public static int socketConnectTO = 3000;
97  		public static boolean failover = true;
98  		public static boolean failback = true;
99  		public static boolean nagle = false;
100 		public static boolean aliveCheck = false;
101 		public static final int consistentHash = 3;
102 		public static final int mainSleep = 30000;
103 
104 		private static SockIOPool pool;
105 		static {
106 			pool = SockIOPool.getInstance();
107 			pool.setFailback(failback);
108 			pool.setFailover(failover);
109 			pool.setMaxBusyTime(maxBusyTime);
110 			pool.setMaxConn(maxConn);
111 			pool.setMaxIdle(maxIdle);
112 			pool.setMinConn(minConn);
113 			pool.setNagle(nagle);
114 			pool.setSocketConnectTO(socketConnectTO);
115 			pool.setSocketTO(socketTO);
116 			pool.setAliveCheck(aliveCheck);
117 			pool.setHashingAlg(consistentHash);
118 			pool.setInitConn(initConn);
119 			pool.setMaintSleep(maxBusyTime);
120 		}
121 
122 		private List<MemcacheConfig> configs;
123 		private String[] servers;
124 		private Integer[] weights;
125 
126 		/**
127 		 * {localhost:11211,1}
128 		 */
129 		public MemcachePoolConfig() {
130 			this(HOST, PORT, WEIGHT);
131 		}
132 
133 		/**
134 		 * {host:11211,1}
135 		 *
136 		 * @param host
137 		 *            主机
138 		 */
139 		public MemcachePoolConfig(String host) {
140 			this(host, PORT);
141 		}
142 
143 		/**
144 		 * {host:port,1}
145 		 *
146 		 * @param host
147 		 *            主机
148 		 * @param port
149 		 *            端口
150 		 */
151 		public MemcachePoolConfig(String host, int port) {
152 			this(host, port, WEIGHT);
153 		}
154 
155 		/**
156 		 * {host:port,weight}
157 		 *
158 		 * @param host
159 		 *            主机
160 		 * @param port
161 		 *            端口
162 		 * @param weight
163 		 *            权重
164 		 */
165 		public MemcachePoolConfig(String host, int port, int weight) {
166 			configs = new ArrayList<MemcacheConfig>();
167 			configs.add(new MemcacheConfig(host, port, weight));
168 		}
169 
170 		public MemcachePoolConfig addServer(String host) {
171 			return addServer(host, PORT, WEIGHT);
172 		}
173 
174 		public MemcachePoolConfig addServer(String host, int port) {
175 			return addServer(host, port, WEIGHT);
176 		}
177 
178 		public MemcachePoolConfig addServer(String host, int port, int weight) {
179 			configs.add(new MemcacheConfig(host, port, weight));
180 			return this;
181 		}
182 
183 		private void initConfig() {
184 			if (servers == null || weights == null) {
185 				servers = new String[configs.size()];
186 				weights = new Integer[configs.size()];
187 				for (int i = 0; i < configs.size(); i++) {
188 					servers[i] = configs.get(i).getServer();
189 					weights[i] = configs.get(i).getWeight();
190 				}
191 			}
192 		}
193 
194 		private void initSocketIO() {
195 			pool.setServers(getServers());
196 			pool.setWeights(getWeights());
197 			if (pool.isInitialized()) {
198 				pool.shutDown();
199 			}
200 			pool.initialize();
201 		}
202 
203 		public String[] getServers() {
204 			initConfig();
205 			return servers;
206 		}
207 
208 		public Integer[] getWeights() {
209 			initConfig();
210 			return weights;
211 		}
212 
213 		@Override
214 		public String toString() {
215 			return "MemcachePoolConfig [" + configs + "]";
216 		}
217 
218 		private static class MemcacheConfig {
219 			private String host;
220 			private int port;
221 			private int weight;
222 
223 			public MemcacheConfig(String host, int port, int weight) {
224 				this.host = host;
225 				this.port = port;
226 				this.weight = weight;
227 			}
228 
229 			public String getServer() {
230 				return String.format("%s:%d", host, port);
231 			}
232 
233 			public int getWeight() {
234 				return weight;
235 			}
236 
237 			@Override
238 			public String toString() {
239 				return String.format("{%s:%d,%d}", host, port, weight);
240 			}
241 		}
242 	}
243 }