spring+ehcache实现的缓存查询

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

用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="mon.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="-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 mon.cache;

2.

3.import .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 mon.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 mon.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. ("记录查询参数拦截器******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. ("取出缓存的查询参数,重定向连接");

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

44. return false;

45. }

46. } else {

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

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

49. }

50. }

51. ("记录查询参数拦截器******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各单位来实现功能。我个人提倡,用框架的时候多想想实现,别一味的用,要不然用到老,还是在用别人的框架,永远写不出自己的框架。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值