[JavaWeb]_[初级]_[jfinal集成ehcache缓存]
Posted infoworld
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaWeb]_[初级]_[jfinal集成ehcache缓存]相关的知识,希望对你有一定的参考价值。
场景
-
开发网站的时候,有些页面在后台
SQL
查询时间比较慢(比如需要集成多个表的数据),如果页面内容不常变化,那么能否设置页面缓存,让用户访问的时候能直接显示已经查询过的数据,快速显示页面? -
Java
生态里就有这一个产品ehcache
, 可以做到缓存的功能. 那么它如何集成进JFinal
框架里?
说明
-
集成
ehcache
步骤:1.1 在项目
maven
文件pom.xml
里增加ehcache
的依赖, 注意目前jfinal
只支持2.x
版本的ehcache
.<dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.11</version> </dependency>
1.2 在启动文件
DemoConfig
(它继承自JFinalConfig
,用于全局配置)的configPlugin()
方法里加载EhCachePlugin
插件.me.add(new EhCachePlugin());
1.3 新建
ehcache.xml
文件到项目结构目录src/main/resources
下.<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false" monitoring="autodetect" dynamicConfig="true"> <diskStore path="java.io.tmpdir"/> <defaultCache eternal="false" maxElementsInMemory="100" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="600" timeToLiveSeconds="0" memoryStoreEvictionPolicy="LRU" /> <cache name="local" eternal="false" maxElementsInMemory="500" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="1800" timeToLiveSeconds="0" memoryStoreEvictionPolicy="LRU" /> </ehcache>
name
: 缓存名称,可以建多个缓存名,注意这个是存储你自己的缓存数据的容器名称,-所有你需要缓存的Java
对象都存在这个容器里,也是从这个容器里取出存储对象. 可以任意名称.eternal
: 如果为true
就是永不过期,timeToIdleSeconds
和timeToLiveSeconds
就会失效.maxElementsInMemory
:最大的存储对象数,比如需要存储某个页面,url
作为key
,页面内容作为value
. 那么这里设置的就是key
的数量。overflowToDisk
: 是否在缓存过大时,内存容不下时存储到磁盘。diskPersistent
:Server
重启时将缓存序列化到本地,后再加载,保证缓存在重启后依然有效。timeToIdleSeconds
: 超过设置的秒数后没有访问这个key
,那么这个key
就会失效,会被移除缓存.timeToLiveSeconds
: 超过这个设置的秒数就会失效,无论是否有访问. 如果为0
时就永不失效,失效控制交给timeToIdleSeconds
和其他因素,比如内存不够。memoryStoreEvictionPolicy
: 内存不够或最大元素达到后的失效策略,这里配置使用LRU
, 最近最少使用的key
先移除.
1.4 使用
jfinal
自带的CacheKit
工具类来操作缓存. 主要是使用它以下的3
个方法,里面封装了对ehcache
的调用。 注意,ehcache
的方法是线程安全的, 所以不用担心多线程访问的问题.get()
: 获取缓存put()
: 添加缓存remove()
: 移除缓存
1.5 在
jfinal
官方文档[4]里,推荐使用的是缓存jfinal enjoy
模板使用的Java
变量,而不是缓存整个html
页面。应该是整个页面需要的内存会更多的原因,而enjoy
模板本身也有编译后的缓存,所以这种做法性能也是比较高的.public void list() List<Blog> blogList = CacheKit.get("local", "blogList"); if (blogList == null) blogList = Blog.dao.find("select * from blog"); CacheKit.put("local", "blogList", blogList); setAttr("blogList", blogList); render("blog.html");
1.6 在缓存的时候就,通过从
ehcache
里取出来放到Controller.request
的属性里, 可以调用Controller.setAttr
或request.setAttribute
设置request
属性,在渲染enjoy
模板时就会拿到这些变量值. 无缓存的做法是,第一次查询数据库后得到的数据,会放到request
的属性里,之后调用Controller
的render
方法进行渲染模板。这时候如果不想缓存整个页面,可以通过读取request
的属性,把所有的属性值都封装到一个Map
里,之后再把这个Map
存到CacheKit
里即可. 我这里封装了一个工具类CacheUtils
的applyViewCache
用于做这些工作,它的Supplier
返回值是一个Pair<Boolean,String>
, 如果k
为true
时,说明是正常返回,v
就是这个enjoy
模板文件的路径. 注意当想让缓存失效时,调用CacheKit
的remove()
方法移除缓存,那么调用就会重新查询数据库。
例子
调用
boolean result = CacheUtils.applyViewCache(kLocalCacheName,subUrlPath,oc,
()->
...
return new Pair<>(true,"/public/_home.enjoy");
);
Pair
public class Pair<K,V>
public K k;
public V v;
public Pair(K k, V v)
this.k = k;
this.v = v;
CacheUtils
import com.alibaba.fastjson.JSONObject;
import com.jfinal.core.Controller;
import com.jfinal.plugin.ehcache.CacheKit;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.function.Supplier;
public class CacheUtils
public static final String kLocalCacheName = "local";
private static final String kViewPath = "CACHE_VIEW_PATH";
public static final String kCacheRootKey = "/";
public static JSONObject applyJsonCache(String cacheName, String cacheKey,
Supplier<Pair<Boolean,String>> func)
JSONObject cache = getJsonCache(cacheName, cacheKey);
if(cache == null)
Pair<Boolean, String> pair = func.get();
if(pair.k && !isEmpty(pair.v))
cache = (JSONObject)JSONObject.parse(pair.v);
if(cache != null)
CacheKit.put(cacheName, cacheKey, cache);
return cache;
public static boolean applyViewCache(String cacheName, String cacheKey,Controller oc,
Supplier<Pair<Boolean,String>> func)
Map<String, Object> cache = getCache(cacheName, cacheKey);
boolean result;
if(cache == null)
Pair<Boolean, String> pair = func.get();
if(pair.k && !isEmpty(pair.v))
cache = cacheAttribute(cacheName, cacheKey, oc);
cache.put(kViewPath,pair.v);
oc.render(pair.v);
result = pair.k;
else
useCacheAttribute(cache,oc);
oc.render((String)cache.get(kViewPath));
result = true;
return result;
public static JSONObject getJsonCache(String cacheName, String cacheKey)
return CacheKit.get(cacheName,cacheKey);
public static Map<String, Object> getCache(String cacheName, String cacheKey)
return CacheKit.get(cacheName,cacheKey);
public static Map<String, Object> cacheAttribute(String cacheName, String cacheKey, Controller controller)
HttpServletRequest request = controller.getRequest();
Map<String, Object> cacheData = new HashMap<String, Object>();
for (Enumeration<String> names = request.getAttributeNames(); names.hasMoreElements();)
String name = names.nextElement();
cacheData.put(name, request.getAttribute(name));
CacheKit.put(cacheName, cacheKey, cacheData);
return cacheData;
public static void useCacheAttribute(Map<String, Object> cacheData, Controller controller)
HttpServletRequest request = controller.getRequest();
Set<Map.Entry<String, Object>> set = cacheData.entrySet();
for (Iterator<Map.Entry<String, Object>> it = set.iterator(); it.hasNext();)
Map.Entry<String, Object> entry = it.next();
request.setAttribute(entry.getKey(), entry.getValue());
参考
以上是关于[JavaWeb]_[初级]_[jfinal集成ehcache缓存]的主要内容,如果未能解决你的问题,请参考以下文章
[JavaWeb]_[初级]_[Jfinal使用时的常见错误]*持续更新*
[JavaWeb]_[初级]_[Jfinal使用时的常见错误]*持续更新*
[JavaWeb]_[初级]_[搭建jfinal_4.9.15_demo_for_maven开发环境]
[JavaWeb]_[初级]_[搭建jfinal_4.9.15_demo_for_maven开发环境]