`

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麻烦了

相关推荐

    SpringBoot整合Shiro完整源码(含sql脚本).rar

    2.1 添加依赖:在项目pom.xml文件中,引入Spring Boot的Shiro Starter和Shiro的相关依赖,如`spring-boot-starter-shiro`、`shiro-redis-session-manager`等。 2.2 配置Shiro:创建一个`ShiroConfig`类,配置Shiro...

    Spring Boot整合Shiro搭建权限管理系统

    编写处理用户请求的Controller,使用Shiro的注解`@RequiresAuthentication`、`@RequiresRoles`和`@RequiresPermissions`进行权限控制。 ### 4. 实现细节 - **认证**:Shiro通过`Subject`对象进行用户认证,`...

    SpringBoot2整合shiro

    在Controller方法上使用Shiro的注解,如`@RequiresAuthentication`、`@RequiresPermissions`等,实现基于注解的权限控制。 ```java @RestController @RequestMapping("/api") public class UserController { @...

    shiro视频教程-最全,通俗易懂

    - **3.3 集成Spring MVC**:介绍如何将Shiro与Spring MVC框架进行整合,实现基于注解的权限控制。 - **3.4 整合MyBatis**:通过示例演示如何在MyBatis中实现用户数据的增删改查操作,并与Shiro进行集成。 #### 四、...

    shiro用户教程pdf

    这一章通常会通过一个具体的例子来展示如何在实际项目中使用Shiro。这包括了如何配置Shiro、实现登录认证、实现权限控制等。 ### 第十七章:OAuth2集成 #### 17.1 服务器端 OAuth2是一种开放标准授权协议,用于...

    SpringBoot-Shiro:这是最简单的SpringBoot与Shiro整合的框架

    在 SpringBoot 应用中,可以通过 Shiro 提供的注解来控制方法或 URL 的访问权限。例如,使用 `@RequiresRoles` 和 `@RequiresPermissions` 注解限制只有特定角色或权限的用户才能访问。 ```java @RestController @...

    2017年尚学堂Java培训课程大纲.docx

    - **Spring MVC简介及基本使用**:了解Spring MVC框架的基本概念和使用方法。 - **Spring MVC注解开发**:学习基于注解的控制器开发方式。 - **处理器映射和处理器适配器**:掌握处理器映射和适配器的工作原理。 - *...

    基于springboot财务管理系统.zip

    系统应具备用户注册、登录功能,可能使用了Spring Security或Shiro等框架实现权限控制,确保数据的安全性。 5.2 账务管理 包括收支记录、预算设定、费用报销等功能,通过MyBatis与数据库交互,实现数据的增删改查...

    物联网基础框架设计说明书.docx

    * 提供拦截器组件(Jboot、Spring)在登录后调用RPC接口实现对权限信息的拦截,把用户的菜单、权限、基地、地块信息提取后整合到缓存中,内部调用使用方法或缓存获取,不再通过RPC调用获取 2. 系统架构 2.1 数据...

Global site tag (gtag.js) - Google Analytics