001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.components.cache.j2cache; 017 018import com.jfinal.log.Log; 019import com.jfinal.plugin.ehcache.IDataLoader; 020import io.jboot.components.cache.JbootCacheBase; 021import io.jboot.components.cache.JbootCacheConfig; 022import io.jboot.exception.JbootException; 023import net.oschina.j2cache.CacheChannel; 024import net.oschina.j2cache.CacheObject; 025import net.oschina.j2cache.J2Cache; 026 027import java.lang.reflect.Method; 028import java.util.ArrayList; 029import java.util.Collection; 030import java.util.List; 031import java.util.stream.Collectors; 032 033/** 034 * @author Michael Yang 杨福海 (fuhai999@gmail.com) 035 * @version V1.0 036 */ 037public class J2cacheImpl extends JbootCacheBase { 038 039 private static final Log LOG = Log.getLog(J2cacheImpl.class); 040 041 public J2cacheImpl(JbootCacheConfig config) { 042 super(config); 043 } 044 045 @Override 046 public <T> T get(String cacheName, Object key) { 047 cacheName = buildCacheName(cacheName); 048 CacheObject cacheObject = J2Cache.getChannel().get(cacheName, key.toString(), false); 049 if (cacheObject != null) { 050 Object value = cacheObject.getValue(); 051 if (config.isDevMode()) { 052 println("J2cache GET: cacheName[" +cacheName+ "] cacheKey["+key+"] value:" + value); 053 } 054 return (T) value; 055 } else { 056 return null; 057 } 058 } 059 060 @Override 061 public void put(String cacheName, Object key, Object value) { 062 cacheName = buildCacheName(cacheName); 063 J2Cache.getChannel().set(cacheName, key.toString(), value); 064 065 if (config.isDevMode()) { 066 println("J2cache PUT: cacheName[" +cacheName+ "] cacheKey["+key+"] value:" + value); 067 } 068 } 069 070 @Override 071 public void put(String cacheName, Object key, Object value, int liveSeconds) { 072 cacheName = buildCacheName(cacheName); 073 J2Cache.getChannel().set(cacheName, key.toString(), value, liveSeconds); 074 075 if (config.isDevMode()) { 076 println("J2cache PUT: cacheName[" +cacheName+ "] cacheKey["+key+"] value:" + value); 077 } 078 } 079 080 081 @Override 082 public void remove(String cacheName, Object key) { 083 cacheName = buildCacheName(cacheName); 084 J2Cache.getChannel().evict(cacheName, key.toString()); 085 086 if (config.isDevMode()) { 087 println("J2cache REMOVE: cacheName[" +cacheName+ "] cacheKey["+key+"]"); 088 } 089 } 090 091 @Override 092 public void removeAll(String cacheName) { 093 cacheName = buildCacheName(cacheName); 094 J2Cache.getChannel().clear(cacheName); 095 096 if (config.isDevMode()) { 097 println("J2cache REMOVEALL: cacheName[" +cacheName+ "]"); 098 } 099 } 100 101 @Override 102 public <T> T get(String cacheName, Object key, IDataLoader dataLoader) { 103 Object value = get(cacheName, key); 104 if (value == null) { 105 value = dataLoader.load(); 106 if (value != null) { 107 put(cacheName, key, value); 108 } 109 } 110 111 if (config.isDevMode()) { 112 println("J2cache GET: cacheName[" + buildCacheName(cacheName) + "] cacheKey[" + key + "] value:" + value); 113 } 114 115 return (T) value; 116 } 117 118 @Override 119 public <T> T get(String cacheName, Object key, IDataLoader dataLoader, int liveSeconds) { 120 if (liveSeconds <= 0) { 121 return get(cacheName, key, dataLoader); 122 } 123 124 Object data = get(cacheName, key); 125 if (data == null) { 126 data = dataLoader.load(); 127 put(cacheName, key, data, liveSeconds); 128 } 129 130 if (config.isDevMode()) { 131 println("J2cache GET: cacheName[" +buildCacheName(cacheName)+ "] cacheKey["+key+"] value:" + data); 132 } 133 return (T) data; 134 } 135 136 private Method sendEvictCmdMethod; 137 138 @Override 139 public synchronized void refresh(String cacheName, Object key) { 140 cacheName = buildCacheName(cacheName); 141 if (sendEvictCmdMethod == null) { 142 sendEvictCmdMethod = getSendEvictCmdMethod(); 143 } 144 try { 145 if (sendEvictCmdMethod != null) { 146 sendEvictCmdMethod.invoke(J2Cache.getChannel(), cacheName, key); 147 } 148 } catch (Exception e) { 149 LOG.error("refresh error!", e); 150 } 151 } 152 153 154 private Method sendClearCmdMethod; 155 156 @Override 157 public synchronized void refresh(String cacheName) { 158 cacheName = buildCacheName(cacheName); 159 if (sendClearCmdMethod == null) { 160 sendClearCmdMethod = getSendClearCmdMethod(); 161 } 162 try { 163 if (sendClearCmdMethod != null) { 164 sendClearCmdMethod.invoke(J2Cache.getChannel(), cacheName); 165 } 166 } catch (Exception e) { 167 LOG.error("refresh error!", e); 168 } 169 } 170 171 @Override 172 public List getNames() { 173 Collection<CacheChannel.Region> regions = J2Cache.getChannel().getL1Provider().regions(); 174 return regions != null && !regions.isEmpty() 175 ? regions.stream().map(CacheChannel.Region::getName).collect(Collectors.toList()) 176 : null; 177 } 178 179 180 @Override 181 public List getKeys(String cacheName) { 182 cacheName = buildCacheName(cacheName); 183 Collection keys = J2Cache.getChannel().keys(cacheName); 184 return keys != null ? new ArrayList(keys) : null; 185 } 186 187 188 private Method getSendEvictCmdMethod() { 189 try { 190 Method method = CacheChannel.class.getDeclaredMethod("sendEvictCmd", String.class, String[].class); 191 method.setAccessible(true); 192 return method; 193 } catch (Exception e) { 194 e.printStackTrace(); 195 } 196 return null; 197 } 198 199 200 private Method getSendClearCmdMethod() { 201 try { 202 Method method = CacheChannel.class.getDeclaredMethod("sendClearCmd", String.class); 203 method.setAccessible(true); 204 return method; 205 } catch (Exception e) { 206 e.printStackTrace(); 207 } 208 return null; 209 } 210 211 212 @Override 213 public Integer getTtl(String cacheName, Object key) { 214 throw new JbootException("getTtl not support in j2cache"); 215 } 216 217 @Override 218 public void setTtl(String cacheName, Object key, int seconds) { 219 throw new JbootException("setTtl not support in j2cache"); 220 } 221}