`

Spring3.1中使用缓存注解及Shiro的缓存联合

 
阅读更多

Spring最近释出了3.1的REALEASE版本,到我写这篇日志的时候已经是3.1.2.REALEASE版本了,该版本直接内置了Ehcache的缓存注解,比起以前配置上是容易了许多,但是shiro官方却并没有为此3.1版本的注解缓存更新其最新的实现方式,为了能够用上最新版本的spring和shiro(1.2.1),特别针对缓存部分做了一些修改。

首先Spring 3.1及以后版本的cache功能位于spring-context包中,要使用spring3.1的缓存注解,只需要在spring的主配置xml文件中添加schema:

1
xmlns:cache="http://www.springframework.org/schema/cache"

记得在xsi:schemaLocation中增加:

1
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.1.xsd

注意:cache的schemaLocation暂时不支持不写版本号的xsd,也就是说,现在还必须写上spring-cache-3.1.xsd

然后写上

1
<cache:annotation-driven/>

就可以使用注解@Cacheable和@CacheEvict了

@Cacheable:要缓存的方法或者类,属性:value、key、condition,value是最主要的,对应ehcache.xml中声明的cache的name;key的主要作用我认为是给局部更新缓存使用的,并且支持SpEL;condition是触发条件,空表示全部增加,也支持SpEL。

@CacheEvict:要进行清空缓存的方法或者类,属性:value、key、condition、allEntries、beforeInvocation,前三者与@Cacheable类似,allEntries为true表示清空全部缓存,默认为false;beforeInvocation为true表示在方法执行以前清理缓存,默认为false

当然,如果想要详细的配置,就需要在xml中添加一些东西了:

1
2
3
4
5
6
7
8
9
10
11
12
13
<cache:annotation-driven cache-manager="cacheManager"/>

<bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">

<property name="configLocation" value="classpath:/config/ehcache.xml" />

</bean>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">

<property name="cacheManager" ref="cacheManagerFactory" />

</bean>

以上Spring 3.1的缓存注解就已经OK了,接下去就是Shiro的部分。

shiro目前还不支持直接使用上述Spring 3.1的配置,但是我们可以改造一下:

首先得写两个类进行注入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/**
*
*/

package org.apache.shiro.cache.ehcacheSpring3_1;

import java.io.IOException;
import java.io.InputStream;

import org.apache.shiro.ShiroException;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.config.ConfigurationException;
import org.apache.shiro.io.ResourceUtils;
import org.apache.shiro.util.Destroyable;
import org.apache.shiro.util.Initializable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.ehcache.EhCacheCacheManager;

/**
* @author Yockii
*
*/

public class EhCacheManager implements CacheManager, Initializable, Destroyable {

private static final Logger log = LoggerFactory.getLogger(EhCacheManager.class);

protected org.springframework.cache.ehcache.EhCacheCacheManager manager;

private boolean cacheManagerImplicitlyCreated = false;

private String cacheManagerConfigFile = "classpath:org/apache/shiro/cache/ehcache/ehcache.xml";

public EhCacheManager(){}

public org.springframework.cache.ehcache.EhCacheCacheManager getCacheManager(){
return manager;
}

public void setCacheManager(org.springframework.cache.ehcache.EhCacheCacheManager manager){
this.manager = manager;
}

public String getCacheManagerConfigFile(){
return this.cacheManagerConfigFile;
}

public void setCacheManagerConfigFile(String classpathLocation){
this.cacheManagerConfigFile = classpathLocation;
}

protected InputStream getCacheManagerConfigFileInputStream(){
String configFile = getCacheManagerConfigFile();
try{
return ResourceUtils.getInputStreamForPath(configFile);
} catch (IOException e) {
throw new ConfigurationException("Unable to obtain input stream for cacheManagerConfigFile [" +
configFile + "]", e);
}
}

/* (non-Javadoc)
* @see org.apache.shiro.util.Destroyable#destroy()
*/

@Override
public void destroy() throws Exception {
// TODO Auto-generated method stub

}

/* (non-Javadoc)
* @see org.apache.shiro.util.Initializable#init()
*/

@Override
public void init() throws ShiroException {
// TODO Auto-generated method stub

}

/* (non-Javadoc)
* @see org.apache.shiro.cache.CacheManager#getCache(java.lang.String)
*/

@Override
public final <K, V> Cache<K, V> getCache(String name) throws CacheException {
if(log.isTraceEnabled()){
log.trace("Acquiring EhCache instance named [" + name + "]");
}

try{
org.springframework.cache.Cache cache = manager.getCache(name);
if(cache == null){
if(log.isInfoEnabled()){
log.info("Cache with name '{}' does not yet exist. Creating now.", name);
}
this.manager.getCacheManager().addCache(name);
cache = manager.getCache(name);
if(log.isInfoEnabled()){
log.info("Added EhCache named [" + name + "]");
}
} else {
if(log.isInfoEnabled()){
log.info("Using existing EHCache named [" + cache.getName() + "]");
}
}
return new EhCache&lt;K, V&gt;(cache);
} catch (Exception e) {
throw new CacheException(e);
}
}

private EhCacheCacheManager ensureCacheManager(){
try{
if(this.manager == null){
if(log.isDebugEnabled()){
log.debug("cacheManager property not set. Constructing CacheManager instance... ");
}

this.manager = new org.springframework.cache.ehcache.EhCacheCacheManager();
manager.setCacheManager(new net.sf.ehcache.CacheManager(getCacheManagerConfigFileInputStream()));
if(log.isTraceEnabled()){
log.trace("instantiated Ehcache CacheManager instance WITH SPRING EhCacheCacheManager");
}
cacheManagerImplicitlyCreated = true;
if(log.isDebugEnabled()){
log.debug("implicit cacheManager created WITH SPRING EhCacheCacheManager successfully.");
}
}
return this.manager;
} catch (Exception e) {
throw new CacheException(e);
}
}
}

这个是主要的缓存管理类,还有一个缓存类hack类Ehcache

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
*
*/

package org.apache.shiro.cache.ehcacheSpring3_1;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import net.sf.ehcache.Ehcache;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache.ValueWrapper;

/**
* @author Yockii
*
*/

public class EhCache<K, V> implements Cache<K, V> {

private static final Logger log = LoggerFactory.getLogger(EhCache.class);

private org.springframework.cache.Cache cache;

public EhCache(org.springframework.cache.Cache cache) {
if (cache == null) {
throw new IllegalArgumentException("Cache argument cannot be null.");
}
this.cache = cache;
}

@Override
public V get(K key) throws CacheException {
try {
if (log.isTraceEnabled()) {
log.trace("Getting object from cache [" + cache.getName() + "] for key [" + key + "]");
}
if (key == null) {
return null;
} else {
ValueWrapper vw = cache.get(key);
if (vw == null) {
if (log.isTraceEnabled()) {
log.trace("ValueWrapper for [" + key + "] is null.");
}
return null;
} else {
return (V) vw.get();
}
}
} catch (Throwable t) {
throw new CacheException(t);
}
}

@Override
public V put(K key, V value) throws CacheException {
if (log.isTraceEnabled()) {
log.trace("Putting object in cache [" + cache.getName() + "] for key [" + key + "]");
}
try {
V previous = get(key);
cache.put(key, value);
return previous;
} catch (Throwable t) {
throw new CacheException(t);
}
}

@Override
public V remove(K key) throws CacheException {
if (log.isTraceEnabled()) {
log.trace("Removing object from cache [" + cache.getName() + "] for key [" + key + "]");
}
try {
V previous = get(key);
cache.evict(key);
return previous;
} catch (Throwable t) {
throw new CacheException(t);
}
}

@Override
public void clear() throws CacheException {
if (log.isTraceEnabled()) {
log.trace("Clearing all objects from cache [" + cache.getName() + "]");
}
try {
cache.clear();
} catch (Throwable t) {
throw new CacheException(t);
}
}

@Override
public int size() {
try {
return ((Ehcache) cache.getNativeCache()).getSize();
} catch (Throwable t) {
throw new CacheException(t);
}
}

@Override
public Set<K> keys() {
try {
Ehcache ehcache = (Ehcache) cache.getNativeCache();
@SuppressWarnings("unchecked")
List<K> keys = ehcache.getKeys();
if (!CollectionUtils.isEmpty(keys)) {
return Collections.unmodifiableSet(new LinkedHashSet<K>(keys));
} else {
return Collections.emptySet();
}
} catch (Throwable t) {
throw new CacheException(t);
}
}

@Override
public Collection<V> values() {
try {
Ehcache ehcache = (Ehcache) cache.getNativeCache();
@SuppressWarnings("unchecked")
List<K> keys = ehcache.getKeys();
if (!CollectionUtils.isEmpty(keys)) {
List<V> values = new ArrayList<V>(keys.size());
for (K key : keys) {
V value = get(key);
if (value != null) {
values.add(value);
}
}
return Collections.unmodifiableList(values);
} else {
return Collections.emptyList();
}
} catch (Throwable t) {
throw new CacheException(t);
}
}

public long getMemoryUsage() {
try {
return ((Ehcache) cache.getNativeCache()).calculateInMemorySize();
} catch (Throwable t) {
return -1;
}
}

public long getMemoryStoreSize() {
try {
return ((Ehcache) cache.getNativeCache()).getMemoryStoreSize();
} catch (Throwable t) {
throw new CacheException(t);
}
}

public long getDiskStoreSize() {
try {
return ((Ehcache) cache.getNativeCache()).getDiskStoreSize();
} catch (Throwable t) {
throw new CacheException(t);
}
}

public String toString() {
return "EhCache [" + cache.getName() + "]";
}
}

 

然后再在spring配置文件中加入shiro的spring配置信息,可以参考之前的博客或者官方的spring联合部分

注意这里shiro部分缓存cacheManage使用上面Spring的cacheManager,而注入到shiro缓存中的类要使用上面的org.apache.shiro.cache.ehcacheSpring3_1.EhCacheManager

改造这样就应该可以了,暂时未验证!

分享到:
评论
1 楼 yangguo 2014-02-24  
太j8麻烦了

相关推荐

Global site tag (gtag.js) - Google Analytics