最近项目有一个需求,就是用户在查询界面,输入很多查询条件之后,查询出了需要的信息,然后点击查看详细之后,希望查询列表页面时还能保存上一次的查询条件。经过同事之间的简单讨论之后,确定了实现方案。
用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标签定义拦截器。
- <util:list id="interceptors">
- <bean class="com.netqin.common.cache.SearchCacheInterceptor"/>
- </util:list>
-
-
- <bean id="urlMapping"
- class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
- <property name="interceptors" ref="interceptors" />
- <property name="order" value="1"></property>
- </bean>
使用的是DefaultAnnotationHandlerMapping这个spring默认的基于注解的请求拦截器类。
ehcache用的是1.72版本,配置文件ehcache.xml为:
- <?xml version="1.0" encoding="UTF-8"?>
- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
- monitoring="autodetect">
- <diskStore path="F:/appstore/ehcache"/>
- <defaultCache
- maxElementsInMemory="10000"
- eternal="false"
- timeToIdleSeconds="1800"
- timeToLiveSeconds="1800"
- overflowToDisk="true"
- maxElementsOnDisk="10000000"
- diskPersistent="false"
- diskExpiryThreadIntervalSeconds="120"
- memoryStoreEvictionPolicy="LRU"
- />
- <cache name="UrlCache"
- maxElementsInMemory="8000"
- maxElementsOnDisk="10000000"
- eternal="false"
- overflowToDisk="true"
- diskSpoolBufferSizeMB="20"
- memoryStoreEvictionPolicy="LFU"
- />
- </ehcache>
并且对ehcache进行了简单封装(不是我封装的):
- package com.netqin.common.cache;
-
- import java.net.URL;
- import java.util.HashMap;
- import java.util.Map;
-
- import net.sf.ehcache.Cache;
- import net.sf.ehcache.CacheManager;
- import net.sf.ehcache.Element;
-
-
-
-
-
-
-
- public class CacheStore {
- private static CacheManager manager;
- private static Cache cache;
- static {
- CacheStore cs = new CacheStore();
- cs.init();
- }
-
-
-
-
- private void init() {
- URL url = getClass().getResource("/config/context/ehcache.xml");
- manager = new CacheManager(url);
- cache = manager.getCache("UrlCache");
- }
-
-
-
-
- @SuppressWarnings("unused")
- private void destory() {
- manager.shutdown();
- }
-
-
-
-
-
-
-
- public static Element get(String key) {
- return cache.get(key);
- }
-
-
-
-
-
-
- public static void remove(String key) {
- cache.remove(key);
- }
-
-
-
-
-
-
- public static void put(Element element) {
- cache.put(element);
- }
-
- public static void removeAll(){
- cache.removeAll();
- }
-
-
-
- public static void main(String[] args) {
- Map m = new HashMap();
- m.put("1", "1");
- m.put("2", "2");
- m.put("3", "3");
- Map m1 = new HashMap();
- m1.put("11", "11");
- m1.put("21", "21");
- m1.put("31", "31");
- CacheStore.remove("1");
- System.out.println(CacheStore.get("1"));
- System.out.println(CacheStore.get("2"));
- System.out.println(CacheStore.get("2"));
- CacheStore.removeAll();
- System.out.println(CacheStore.get("2"));
- System.out.println(CacheStore.get("3"));
- System.out.println("------end-----");
- }
- }
下载ehcache.jar
拦截器代码:
- package com.netqin.common.cache;
-
- import java.io.UnsupportedEncodingException;
- import java.util.Arrays;
- import java.util.Map;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import net.sf.ehcache.Element;
-
- import org.apache.log4j.Logger;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
-
- import com.netqin.common.util.AuthenticationUtils;
-
-
-
-
-
-
-
- public class SearchCacheInterceptor extends HandlerInterceptorAdapter
- {
- private static final Logger logger = Logger
- .getLogger(SearchCacheInterceptor.class);
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean preHandle(HttpServletRequest request,
- HttpServletResponse response, Object handler)throws Exception {
- logger.info("记录查询参数拦截器******begin");
- String url = request.getServletPath();
- String ip = request.getRemoteAddr();
- Map<String, String[]> paramsMap = request.getParameterMap();
- String userName = AuthenticationUtils.getUsername();
- if (url.indexOf("list.do") != -1) {
- if (paramsMap.get("goBack") != null) {
- Element e = CacheStore.get(ip
- + userName + url);
- if (e != null) {
- logger.info("取出缓存的查询参数,重定向连接");
- response.sendRedirect(request.getRequestURL()+(String)e.getValue());
- return false;
- }
- } else {
- logger.info("更新查询参数");
- CacheStore.put(new Element(ip+ userName + url, changeMapToString(paramsMap)));
- }
- }
- logger.info("记录查询参数拦截器******begin");
- return true;
- }
-
- private String changeMapToString(Map<String, String[]> paramsMap) {
- StringBuffer url = new StringBuffer();
- url.append("?");
- for(Map.Entry<String, String[]> entry :paramsMap.entrySet()){
- String key = entry.getKey();
- String [] value = entry.getValue();
- url.append(key+"="+encodeUrl(Arrays.toString(value)));
- url.append("&");
- }
- System.out.println(url);
- return url.toString();
- }
- private String encodeUrl(String value) {
- String result = "";
- result = value.replaceAll("\\[", "").replaceAll("\\]", "");
- try {
- byte temp[]=result.getBytes("UTF-8");
- result=new String(temp,"ISO-8859-1");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- return result;
- }
- }
拦截器类继承自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各单位来实现功能。我个人提倡,用框架的时候多想想实现,别一味的用,要不然用到老,还是在用别人的框架,永远写不出自己的框架。
分享到:
相关推荐
spring + ehcache + redis两级缓存
Spring+EhCache缓存实例
1.通过google ehcache-spring-annotatios.jar自动注解方式实现整合Spring+Ehcache。 2.Action里通过struts2-spring-plugin.jar插件自动根据名字注入。 3.Ajax无刷新异步调用Struts2,返回Json数据,以用户注册为例。...
Spring4.1+ehcache2.10.2实现缓存功能!
需要使用Spring来实现一个Cache简单的解决方案,具体需求如下:使用任意一个现有开源Cache Framework,要求可以Cache系统中Service或则DAO层的get/find等方法返回结果,如果数据更新(使用Create/update/delete方法...
基于公司的项目在Spring中集成Ehcache,并提供EhcaheUtils工具类,并通过Spring的AOP编程实现方法缓存注解话,先奉献出核心代码,需要的朋友可以参考哦!
spring+springMVC+hibernate+cxf+quartz(定时器)+ehcache(缓存)
NULL 博文链接:https://liuyunlong1229.iteye.com/blog/2081421
【B1】Spring+SpringMVC+Ehcache+Shiro+BootStrap企业级开发平台源码下载 内置功能 用户管理 角色管理 菜单管理 字典管理 部门管理 附件管理 参数管理 连接池监视 日志管理 技术选型 1、后端 核心框架...
自己项目的开发包集合,其中包括:缓存处理ehcache相关jar,spring MVC4.0 jar,ehcache依赖jar,以及其他jar(图像处理thumbnailator-0.4.2),包虽然不是很新但可用。实际使用时找包较为麻烦,现在整理出来,希望...
此项目有shiro验证码的实现,更改用户userState状态可以实现用户锁定,密码次数过多未写(异常类型为ExcessiveAttemptsException),自己累计次数吧。 五: 此例子是给一哥们理解的,一些注释和代码未做删减。
积分最低,Spring MVC+Mybatis+Ehcache+Apache Shiro+Bootstrap整合开发java仓库管理系统源码 开发环境:Eclipse ,JDK 1.8 ,Tomcat7 技术选型 后端技术 SpringMVC MVC框架 Spring Framework 容器 Apache ...
springMVC+Ehcache的各级缓存(包括页面缓存)
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider。 Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。它具有内存和磁盘存储,...
缘起需求:需要使用Spring来实现一个Cache简单的解决方案,具体需求如下:使用任意一个现有开源Cache Framework,要求可以Cache系统中Service或者DAO层的get/find等方法返回结果,如果数据更新(使用Create/update/...
spring+springmvc+hibernate+ehcache JavaWeb后台框架,不仅提高了开发程序的速度,且其中还是用到hibernate和ehcache缓存的使用,加快了程序运行的数据,该框架亲测好用。值得注意的是该种框架现在还算是用的比较多...
主要为大家详细介绍了Spring+EHcache缓存实例,EhCache是一个纯Java的进程内缓存框架,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
J2EE基础平台,包括Spring管理Bean,Struts管理Action,数据库链接池Proxool,内存数据库,页面缓存等与一体的基础开发环境
3.Ehcache方法缓存及页面缓存。见applicationContext-cache.xml及web.xml的pageEhCacheFilter 4.MyBatis+Maven代码生成工具。见bin目录 5.作为项目或者技术研究的基础架构。必要的jar包依赖都已配置好,基本都采用较...