文档章节

spring+ehcache实现的缓存查询参数。

龙之天空
 龙之天空
发布于 2015/04/21 13:21
字数 1368
阅读 166
收藏 0
点赞 0
评论 0

最近项目有一个需求,就是用户在查询界面,输入很多查询条件之后,查询出了需要的信息,然后点击查看详细之后,希望查询列表页面时还能保存上一次的查询条件。经过同事之间的简单讨论之后,确定了实现方案。

用spring的拦截器,拦截到用户的所有list.do请求,保存下list.do,把里面的request。paramaterMap转换成字符串(注意中文转码),以ip+username+功能模块url为key,保存下来,用户在详细信息页面点击返回时,返回连接需要带goback参数,拦截器监测到请求参数里包含goback时,就用ip+username+功能模块url把保存的值拿出来,之后response.sendRedirect(request.getRequestURL()+str).

上面只是大体实现的概括,下面看代码。

定义spring拦截器,项目的spring版本是2.5的,不支持mvc:interceptors标签定义拦截器。

Html代码 

  1. <util:list id="interceptors">  

  2.      <bean class="com.netqin.common.cache.SearchCacheInterceptor"/>    

  3. </util:list>  

  4.   

  5. <!-- 定义注解URL映射处理器 -->  

  6. <bean id="urlMapping"  

  7.     class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">  

  8.     <property name="interceptors" ref="interceptors" />  

  9.     <property name="order" value="1"></property>  

  10. </bean>  

使用的是DefaultAnnotationHandlerMapping这个spring默认的基于注解的请求拦截器类。

ehcache用的是1.72版本,配置文件ehcache.xml为:

Html代码 

  1. <?xml version="1.0" encoding="UTF-8"?>  

  2. <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

  3.     xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"  

  4.     monitoring="autodetect">  

  5.     <diskStore path="F:/appstore/ehcache"/>  

  6.     <defaultCache  

  7.             maxElementsInMemory="10000"  

  8.             eternal="false"  

  9.             timeToIdleSeconds="1800"  

  10.             timeToLiveSeconds="1800"  

  11.             overflowToDisk="true"  

  12.             maxElementsOnDisk="10000000"  

  13.             diskPersistent="false"  

  14.             diskExpiryThreadIntervalSeconds="120"  

  15.             memoryStoreEvictionPolicy="LRU"  

  16.             />  

  17.      <cache name="UrlCache"  

  18.            maxElementsInMemory="8000"  

  19.            maxElementsOnDisk="10000000"  

  20.            eternal="false"  

  21.            overflowToDisk="true"  

  22.            diskSpoolBufferSizeMB="20"  

  23.            memoryStoreEvictionPolicy="LFU"  

  24.             />  

  25. </ehcache>  

并且对ehcache进行了简单封装(不是我封装的):

Java代码 

  1. package com.netqin.common.cache;  

  2.   

  3. import java.net.URL;  

  4. import java.util.HashMap;  

  5. import java.util.Map;  

  6.   

  7. import net.sf.ehcache.Cache;  

  8. import net.sf.ehcache.CacheManager;  

  9. import net.sf.ehcache.Element;  

  10.   

  11. /** 

  12.  * cache管理器 

  13.  *  

  14.  * @author HANQUNFENG 

  15.  *  

  16.  */  

  17. public class CacheStore {  

  18.     private static CacheManager manager;  

  19.     private static Cache cache;  

  20.     static {  

  21.         CacheStore cs = new CacheStore();  

  22.         cs.init();  

  23.     }  

  24.   

  25.     /** 

  26.      * 初试化cache 

  27.      */  

  28.     private void init() {  

  29.         URL url = getClass().getResource("/config/context/ehcache.xml");  

  30.         manager = new CacheManager(url);  

  31.         cache = manager.getCache("UrlCache");  

  32.     }  

  33.   

  34.     /** 

  35.      * 清除cache 

  36.      */  

  37.     @SuppressWarnings("unused")  

  38.     private void destory() {  

  39.         manager.shutdown();  

  40.     }  

  41.   

  42.     /** 

  43.      * 得到某个key的cache值 

  44.      *  

  45.      * @param key 

  46.      * @return  

  47.      */  

  48.     public static Element get(String key) {  

  49.         return cache.get(key);  

  50.     }  

  51.   

  52.     /** 

  53.      * 清楚key的cache 

  54.      *  

  55.      * @param key 

  56.      */  

  57.     public static void remove(String key) {  

  58.         cache.remove(key);  

  59.     }  

  60.   

  61.     /** 

  62.      * 设置或更新某个cache值 

  63.      *  

  64.      * @param element 

  65.      */  

  66.     public static void put(Element element) {  

  67.         cache.put(element);  

  68.     }  

  69.       

  70.     public static void removeAll(){  

  71.         cache.removeAll();  

  72.     }  

  73.   

  74.       

  75.   

  76.     public static void main(String[] args) {  

  77.         Map m = new HashMap();  

  78.         m.put("1""1");  

  79.         m.put("2""2");  

  80.         m.put("3""3");  

  81.         Map m1 = new HashMap();  

  82.         m1.put("11""11");  

  83.         m1.put("21""21");  

  84.         m1.put("31""31");  

  85.         CacheStore.remove("1");  

  86.         System.out.println(CacheStore.get("1"));  

  87.         System.out.println(CacheStore.get("2"));  

  88.         System.out.println(CacheStore.get("2"));  

  89.         CacheStore.removeAll();  

  90.         System.out.println(CacheStore.get("2"));  

  91.         System.out.println(CacheStore.get("3"));  

  92.         System.out.println("------end-----");  

  93.     }  

  94. }  

下载ehcache.jar

 


拦截器代码:

Java代码 

  1. package com.netqin.common.cache;  

  2.   

  3. import java.io.UnsupportedEncodingException;  

  4. import java.util.Arrays;  

  5. import java.util.Map;  

  6.   

  7. import javax.servlet.http.HttpServletRequest;  

  8. import javax.servlet.http.HttpServletResponse;  

  9.   

  10. import net.sf.ehcache.Element;  

  11.   

  12. import org.apache.log4j.Logger;  

  13. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;  

  14.   

  15. import com.netqin.common.util.AuthenticationUtils;  

  16.   

  17. /** 

  18.  * 查询条件缓存的拦截器 

  19.  *  

  20.  * @author KingViker 

  21.  *  

  22.  */  

  23. public class SearchCacheInterceptor extends HandlerInterceptorAdapter  

  24. {  

  25.     private static final Logger logger = Logger  

  26.             .getLogger(SearchCacheInterceptor.class);  

  27.   

  28.     @SuppressWarnings("unchecked")  

  29.     @Override  

  30.     public boolean preHandle(HttpServletRequest request,  

  31.             HttpServletResponse response, Object handler)throws Exception {  

  32.         logger.info("记录查询参数拦截器******begin");  

  33.         String url = request.getServletPath();  

  34.         String ip = request.getRemoteAddr();  

  35.         Map<String, String[]> paramsMap = request.getParameterMap();  

  36.         String userName = AuthenticationUtils.getUsername();  

  37.         if (url.indexOf("list.do") != -1) {  

  38.             if (paramsMap.get("goBack") != null) {  

  39.                 Element e = CacheStore.get(ip  

  40.                 + userName + url);  

  41.                 if (e != null) {  

  42.                     logger.info("取出缓存的查询参数,重定向连接");  

  43.                     response.sendRedirect(request.getRequestURL()+(String)e.getValue());  

  44.                     return false;  

  45.                 }  

  46.             } else {  

  47.                 logger.info("更新查询参数");  

  48.                 CacheStore.put(new Element(ip+ userName + url, changeMapToString(paramsMap)));  

  49.             }  

  50.         }  

  51.         logger.info("记录查询参数拦截器******begin");  

  52.         return true;  

  53.     }  

  54.   

  55.     private String changeMapToString(Map<String, String[]> paramsMap) {  

  56.         StringBuffer url = new StringBuffer();  

  57.         url.append("?");  

  58.         for(Map.Entry<String, String[]> entry :paramsMap.entrySet()){  

  59.             String key = entry.getKey();  

  60.             String [] value = entry.getValue();  

  61.             url.append(key+"="+encodeUrl(Arrays.toString(value)));  

  62.             url.append("&");  

  63.         }  

  64.         System.out.println(url);  

  65.         return url.toString();  

  66.     }  

  67.     private String encodeUrl(String value) {  

  68.         String result = "";  

  69.         result = value.replaceAll("\\[""").replaceAll("\\]""");  

  70.         try {  

  71.             byte temp[]=result.getBytes("UTF-8");  

  72.             result=new String(temp,"ISO-8859-1");      

  73.         } catch (UnsupportedEncodingException e) {  

  74.             e.printStackTrace();  

  75.         }      

  76.         return result;  

  77.     }  

  78. }  

拦截器类继承自HandlerInterceptorAdapter,重写了prehandle方法。prehandle是在请求前执行,还可以重写afterCompletion和postHandle两个方法,分别是请求后和请求前后执行。


我的拦截器的代码原先的逻辑不是这样。我原先的逻辑是利用反射直接更改request的parameterMap保存的值,不需要其他的操作很简单,也不需要重定向。但是这个思路有两个问题:

1.我用ehcache保存时直接保存的是parameterMap的引用,每次请求过来之后spring都会清空并且重新初始化这个map,导致ehcache未能缓存到真正的数据。

2.在测试时发现,spring框架从请求接受参数后并且封装到了bean里面之后请求才能拦截到,也就是说我更改了parameterMap的值,controller收到的请求还是未更改的数据。

所以我改变了思路,把每次请求的parameterMap对象封装成字符串然后在缓存,需要使用缓存时,直接取出并重定向sendredirectt。

但是sendreditect是get方式的请求,浏览器一般会把请求连接中的中文参数进行转码,转成ISO-8859-1,产生了乱码问题,所以需要在链接后面拼接参数时需要对中文转码。这也就是上面的encodeUrl函数的作用。


写这篇文章的目的只是介绍一下实现思路和用到的一些现有框架,以及其中遇到的一些问题。给一些需要实现类似功能的道友一个实现思路而已。这里不提供源码,我个人是很不喜欢伸手党的。就是因为编程界有太多的伸手党,导致了很多人能做一些项目,但是出现问题就不知道怎么改,或者明明性能上只需要1各单位,偏偏不知所以然的用了10各单位来实现功能。我个人提倡,用框架的时候多想想实现,别一味的用,要不然用到老,还是在用别人的框架,永远写不出自己的框架。


© 著作权归作者所有

共有 人打赏支持
龙之天空
粉丝 7
博文 77
码字总数 18140
作品 0
宁波
ehcache 能取得缓存内容么?

问大家一个问题? 环境:mybatis +spring+ehcache 1.如何取得缓存后的内容呢? 2.如果缓存的对象(表) 在后台改变了数据 那怎么通过系统呢?

唐代de豆腐 ⋅ 2012/05/22 ⋅ 4

关于Spring的缓存问题

项目中应用了Spring的Cacheable,按照Spring的文档配置的,怎么就不起作用了呢?大家都Spring的缓存有什么看法,用着怎么样?文档说可以与ehcache整合到一起用,有用过的话,谈谈你的想法。如...

IT_小翼 ⋅ 2012/09/29 ⋅ 2

spring+ehcache+注解的使用

spring+ehcache+注解的使用 为了提高系统的运行效率,引入缓存机制,减少数据库访问和磁盘IO。下面说明一下ehcache和spring整合配置。 总共需要四步,引入包,添加ehcache.xml文件,在sprin...

风中帆 ⋅ 2015/11/04 ⋅ 0

《深入理解mybatis原理》 MyBatis的一级缓存实现详解 及使用注意事项

MyBatis是一个简单,小巧但功能非常强大的ORM开源框架,它的功能强大也体现在它的缓存机制上。MyBatis提供了一级缓存、二级缓存 这两个缓存机制,能够很好地处理和维护缓存,以提高系统的性能...

java梦想家01 ⋅ 2016/01/11 ⋅ 1

Hibernate查询缓存

查询缓存中的key是根据查询的语句、查询的条件、查询的参数和查询的页数等信息组成的。而数据的存储则会使用两种方式,使用SELECT语句只查询实体 对象的某些列或者某些实体对象列的组合时,会...

markGao ⋅ 2014/01/03 ⋅ 0

Solr1.3的核心机制

内核调用机制 从图3-3可以看出Solr1.3服务器包含一个实现基本功能的核心API,也可称之为内核。所有功能的实现都通过对内核API的调用来实现。Solr1.3的内核API提供的接口具有高内聚低耦合的特...

超人学院 ⋅ 2015/06/09 ⋅ 0

hibernate 基础

一、Hibernate工作原理: 读取并解析配置文件 读取并解析映射信息,创建SessionFactory 打开Sesssion 创建事务Transation 持久化操作 提交事务 关闭Session 关闭SesstionFactory 二、Hiberna...

scofi06 ⋅ 2010/09/01 ⋅ 0

hibernate面试题

一、Hibernate工作原理: 读取并解析配置文件 读取并解析映射信息,创建SessionFactory 打开Sesssion 创建事务Transation 持久化操作 提交事务 关闭Session 关闭SesstionFactory 二、Hiberna...

序写人生 ⋅ 2010/06/13 ⋅ 1

mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache

大 中 小 mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache 一、 查询缓存 1.1 什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。 mybaits提供...

LYQ1990 ⋅ 2016/05/26 ⋅ 0

Spring Cache 介绍

Spring Cache 是实际工作中非常常用的一种提高性能的方法, 我们会在许多场景下来使用缓存。 本文通过一个简单的例子进行展开,通过对比我们原来的自定义缓存和 spring 的基于注释的 cache 配...

嘻哈开发者 ⋅ 2016/09/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

MySQL主从复制原理、半同步操作步骤及原理

1.1 企业Linux运维场景数据同步方案 1.1.1 文件级别的异机同步方案 1、scp/sftp/nc 命令可以实现远程数据同步。 2、搭建ftp/http/svn/nfs 服务器,然后在客户端上也可以把数据同步到服务器。...

xiaomin0322 ⋅ 19分钟前 ⋅ 0

Oracle10g 数据及文件迁移过程[原]

QL*Plus: Release 10.2.0.1.0 - Production on 星期三 5月 11 10:22:35 2011 Copyright (c) 1982, 2005, Oracle. All rights reserved. 连接到: Oracle Database 10g Enterprise Edition Re......

harrypotter ⋅ 25分钟前 ⋅ 0

nginx安装

1:安装工具包 wget、vim和gcc yum install -y wget yum install -y vim-enhanced yum install -y make cmake gcc gcc-c++ 2:下载nginx安装包 wget http://nginx.org/download/nginx-1......

壹丶贰 ⋅ 28分钟前 ⋅ 0

ideaVim安装及配置

1.安装插件 File-Settings-Plugins,Browse Repositories,输入ideavim,安装。 重启后,在Tools-Vim Emulator启用。 2.快捷键设置 ideaViim键与idea快捷键有冲突,可以在Settings-Other Se...

Funcy1122 ⋅ 32分钟前 ⋅ 0

MySQL中B+Tree索引原理

B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引。B+树中的B代表平衡(balance),而不是二叉(binary),因为B+树是从最早的平衡二叉树演化而来的。在讲B...

浮躁的码农 ⋅ 46分钟前 ⋅ 0

两道面试题,带你解析Java类加载机制

在许多Java面试中,我们经常会看到关于Java类加载机制的考察,例如下面这道题: class Grandpa{ static { System.out.println("爷爷在静态代码块"); }} cl...

1527 ⋅ 51分钟前 ⋅ 0

SpringCloud(Data Flow)

dataflow-server

赵-猛 ⋅ 今天 ⋅ 0

深入理解Java虚拟机

这本书我读到第8章,之后就是在读不下去了。 读到后面是一种痛苦的体验,太多的东西是不全面的,大量的专有名词是没有解释的,读到最后很多东西仅仅是一个侧面,所以我觉得,这本书不适合初学...

颖伙虫 ⋅ 今天 ⋅ 0

NanoPi NEO core/ Ubuntu16.04单网卡配置3个IP地址(2个静态,1个动态)

配置 root@NanoPi-NEO-Core:/etc/network# cat interfacesauto loiface lo inet loopbackallow-hotplug eth0iface eth0 inet static address 172.31.188.249 netmask 255.......

SamXIAO ⋅ 今天 ⋅ 0

三步为你的App集成LivePhoto功能

摘要:LivePhoto是iOS9新推出的一种拍照方式,类似于拍摄Gif图或录制视频片段生成图片。如果没有画面感,可以联想《哈利波特》霍格沃茨城堡的壁画,哈哈,很炫酷有木有,但坑爹的是只有iphone6S以...

壹峰 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部