- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java Cache详解及简单实现由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
Java Cache详解及简单实现 。
概要:
最近在做spring的项目,想做一个缓存,访问数据库,定期来做数据更新 。
要实现两个功能 。
通过Controller来做 。
因为需要通过http来刷新缓存,所以第一个想法就是把缓存做成一个Controller 。
Controller的实现 。
Controller最大的优势,就是可以通过Spring的配置,注入很多依赖,比如对Service的依赖,对数据库的依赖等.
大量的访问数据库跟服务层的代码,都可以进行复用 。
定义一个Cache接口如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
interface
Cache {
/**
* Refresh the cache. If succeed, return true, else return false;
*
* @return
*/
boolean
refresh();
/**
* How much time it will refresh the cache.
*
* @return
*/
long
interval();
}
|
但是这里碰到了问题,自己写的Controller可以通过注入的方式轻而易举的与Http服务跟Service层,数据库层连接,但是如果CacheController实现Cache接口,会发现很难调用interval函数来找到间隔的时间.
因为CacheController也是一个Bean,需要通过Spring找到这个bean来调用。无法找到Bean,就不能调用Interval,也就不能够顺势通过另外的线程来控制缓存刷新。为了获取这个Bean可以将所有的CacheController都Autowired到一个CacheManagerController之中 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Controller
public
class
CacheManagerController {
@Autowired
private
CacheController cache;
private
static
ScheduledExecutorService executor = Executors
.newScheduledThreadPool(
1
);
public
CacheManagerController() {
executor.scheduleAtFixedRate(() -> cache.refresh(),
0
, cache.interval(),
TimeUnit.MILLISECONDS);
}
}
|
曾经考虑这么做,但是发现一个问题,这样做,CacheManagerController在初始化的时候,也就是构造Bean的时候,各种的Cache还没有被注入CacheController,而如果不将方法放入构造函数,那么CacheManagerController是无法自动的调用调度服务的。需要手动调用才行。但是程序的入口不一定从哪一个Controller进入,如果写拦截器,也是很繁琐,而且每次调用都会执行.
这个时候,就通过一个CacheService来实现这个问题 。
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
|
public
class
CacheService {
public
static
final
long
ONE_MINUTE =
60
*
1000
;
private
static
ScheduledExecutorService executor = Executors
.newScheduledThreadPool(
1
);
public
static
void
register(Cache cache) {
executor.scheduleAtFixedRate(() -> cache.refresh(),
0
, cache.interval(),
TimeUnit.MILLISECONDS);
}
}
@Controller
public
class
CacheController
implements
Cache {
// autowire 各种不同的service,或者是repo连接数据库
@Autowired
private
Service service;
public
CacheController() {
CacheService.register(
this
);
}
// cache interface
@Override
public
long
interval() {
return
1000
;
}
@Override
public
boolean
refresh() {
return
true
;
}
}
|
因为具体的CacheController是通过反射构造成Bean由Spring管理的,所以可以直接通过无参构造函数来注册一下,这样就没有问题了,当Spring在加载CacheController的时候,就会直接调用CacheService的注册方法,将缓存注册到CacheService中定义的线程池当中,然后立刻执行刷新方法,同时还会根据时间间隔来自动的刷新.
至于获取指定的Cache,更简单了,因为Cache本身是一个Controller,所以可以通过Autowire自动注册到需要使用的其他Controller之中.
当然了,目前这么写是没有什么问题,但是当refresh为立刻调用的时候,会无法拿到Autowired注入的那些Service。因为Spring是统一全部实例化,然后再进行装载的,所以,如果refresh函数中调用了service,那么显然,程序肯定会报空指针异常的。这也是使用Controller来做Cache的问题。如果要获得全部的Spring装载的实例,那么肯定就都要修改构造函数来将实例注入到统一的集合当中了,那样就跟前文提到的问题一样了,也就是获取Bean。如果能够获取Bean,那直接就能调用实例方法,也就没有这么多事情了.
总结 。
使用Controller的特点如下:
通过Listener来做 。
Listener有一个优势,就是可以通过一个写一个PreloadListener 实现ServletContextListener,这样就能够利用Tomcat加载web.xml的时候,将代码提前进行初始化了.
Listener的实现 。
1
2
3
4
5
6
7
8
9
10
11
|
public
class
PreloadListener
implements
ServletContextListener {
@Override
public
void
contextInitialized(ServletContextEvent servletContextEvent) {
CacheFactory.init();
}
@Override
public
void
contextDestroyed(ServletContextEvent servletContextEvent) {
}
}
|
下面是web.xml的代码 。
1
2
3
4
|
// web.xml
<listener>
<listener-
class
>com.sapphire.listener.PreloadListener</listener-
class
>
</listener>
|
当然了,有优势肯定会存在劣势,因为使用Listener的方式来提前加载,也会因为Web的声明周期,产生问题.
Tomcat在加载Web.xml的时候,Listener的初始化,会在Spring容器启动之前,这样也就碰到一个问题。PreloadListener中可以调用的代码,肯定是无法Autowire到任何的Bean的。这也就是对比Controller碰到的一个巨大的劣势了,需要自己重写那些Service.
除此以外, 还需要单独写一个Controller来刷新指定的缓存.
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
|
public
class
CacheFactory {
private
static
ConcurrentHashMap<String, Cache> caches =
new
ConcurrentHashMap<>();
private
static
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(
1
);
private
static
void
register(Cache cache) {
caches.put(cache.category(), cache);
}
private
static
void
registerAll() {
register(
new
StockCache());
}
public
static
void
init() {
registerAll();
for
(Cache cache : caches.values()) {
executorService.scheduleAtFixedRate(
new
Runnable() {
@Override
public
void
run() {
cache.refresh();
}
},
0
, cache.interval(), TimeUnit.MILLISECONDS);
}
}
public
static
Cache getCache(String key) {
if
(caches.contains(key)) {
return
caches.get(key);
}
return
null
;
}
}
// cache接口除了需要提供interval和refresh以外,还需要提供一个category来区分不同的Cache
public
interface
Cache {
/**
* Refresh the cache. If succeed, return true, else return false;
*
* @return
*/
boolean
refresh();
/**
* How much time it will refresh the cache.
*
* @return
*/
long
interval();
/**
* Cache's category. Each cache has distinct category.
*
* @return
*/
String category();
}
|
这样完成的CacheFactory,可以在PreloadListener之中调用init方法来初始化所有的Cache,来完成Cache的启动。可以看出,所有的CacheFactory之中的方法都是静态方法,可以直接由Controller层随便调用.
之后,不同的Cache就需要单独来写init方法,放到各自实现的refresh方法之中。跟数据库的链接等,都需要建立。不同的Cache都需要重写各自的初始化方法,还需要写一个读取文件配置的东西读取数据库的一些配置信息。总之,感觉很麻烦.
总结 。
通过Listener来实现,更加灵活,可以在容器启动之前就将需要的信息加载到内存之中,但是很多业务代码都需要重新来写,数据库的链接,解析Property,灵活刷新的CacheController.
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持! 。
原文链接:http://blog.csdn.net/ethanwhite/article/details/51278133 。
最后此篇关于Java Cache详解及简单实现的文章就讲到这里了,如果你想了解更多关于Java Cache详解及简单实现的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 8 年前。 Improve t
我卡在了一个点上,我无法进步,很抱歉这个愚蠢的问题。我为此进行了很多搜索,但我不知道我错过了什么。请帮助我。 我研究了 python 中的模块和类。现在我想使用 python 和 apt 进行一些操作
我在 Kong 有服务,我已经为该服务设置了代理缓存插件。 curl -X POST http://localhost:8001/plugins --data "name=proxy-cache"--
ASP.NET Core 提供内存缓存和响应缓存。 假设该应用程序是 ASP.NET Core WebAPI,它通过配置的响应缓存中间件将 SQL 数据库中的数据传送给用户。 在什么情况下也使用内存缓
我最近遇到了以下面试问题: You need to design a system to provide answers to factorials for between 1 and 100. Yo
我的 Javascript (JS) 代码遇到了一些麻烦,因为我有时需要在同一个函数中多次访问相同的 DOM 元素。还提供了一些推理here . 从性能的角度来看,是一次性创建一个 jQuery 对象
仅使用 Cache 终端,我使用或查看什么实用程序函数或 Global 来查找存在于 Cache 数据库中的所有 Globals 的列表? 再次仅在缓存终端中使用,我使用或查看什么实用程序功能或全局以
我的 Javascript (JS) 代码遇到了一些麻烦,因为有时我需要在同一个函数中多次访问同一个 DOM 元素。还提供了一些推理here . 从性能的角度来看,是先创建一个jQuery对象然后缓存
来自 RFC 2616 http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1 no-cache If the no-cach
大多数 CDN 服务器对经常访问的内容使用缓存。 场景:假设有人上传了一张非常热门的图片,并且来自同一位置的许多用户 (1000) 试图访问该图片。 问题:假设网络服务器收到一个请求,首先检查它的缓存
我的 Javascript (JS) 代码遇到了一些麻烦,因为有时我需要在同一个函数中多次访问同一个 DOM 元素。还提供了一些推理here . 从性能的角度来看,是先创建一个jQuery对象然后缓存
如果我将服务器响应设置为:Cache-Control: private,no-cache,max-age=900 ? 如果标题是这样的,会发生什么:Cache-Control: public,no-c
我有一个类需要在缓存中存储数据。最初我在 ASP.NET 应用程序中使用它,所以我使用了 System.Web.Caching.Cache。 现在我需要在 Windows 服务中使用它。现在,据我了解
我遇到了和这个人一样的问题:X-Drupal-Cache for Drupal 7 website always hits MISS ,并且找不到出路。 我正在运行 Drupal 7 - 新闻流 和
我已将 Laravel 设置为使用 Redis 作为缓存。当我使用 Cache::('my_var', 'my_val'); 然后通过 CLI 检查 Redis 以查看 key 是否已创建时,我可以验
我在 Windows Azure 云上有一个应用程序,并且正在使用 Windows Azure 共置缓存。 有时,当我发布网站/web服务时,调用DataCacheFactory.GetCache方法
我正在阅读 documentation for Apollo server-side caching ,但看不到任何关于缓存通常如何加密的内容。 我需要的是一个以响应中包含的对象 ID 为键的缓存,而
Hibernate\Grails 中最好的缓存策略是什么?是否缓存所有实体和查询以及如何找到最佳解决方案? 这是我的 hibernate 配置。 hibernate { cache.use_sec
我收到错误 'Nuget.Proxy Cache' 的类型初始化器抛出异常 尝试连接到 Nuget 官方包源时。我在公司网络后面,但是我怀疑问题是连接性。 有任何想法吗? 最佳答案 我有同样的问题。我
我是一名优秀的程序员,十分优秀!