应用场景:在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载。缓存是解决这个问题的好办法。但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是不够灵活。此时Memcached或许是你想要的。
一. 什么是Memcached
Memcached 是一个高性能的分布式内存 对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象 来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。
Memcached基于一 个存储键/值对的hashmap。其守护进程是用C写的,但是客户端可以用任何语言来编写(本文使用JAVA作为例子),并通过memcached协议与守护进程通信。
二. Memcached 特征
(1) 协议简单: 不使用复杂的xml格式,而是使用文本格式
(2) 基于libevent的事件处理机制
(3) 内置内存存储方式: 数据存在在内存中,所以重启机器会导致数据丢失
(4)Memcached相互不通信的分布式: Memcached 服务器之间不会进行通信,数据都是通过客户端的分布式算法存储到各个服务器中
三.Memcached的安装(windows)
下载Memcached 服务端: http://memcached.org/ (官网寻找适用的版本)
1 解压缩文件到D:\memchche\memcached-win32-1.4.4-14
2 命令行输入 D:\memchche\memcached-win32-1.4.4-14\memcached.exe -d install
3 命令行输入 D:\memchche\memcached-win32-1.4.4-14\memcached.exe -d start,该命令启动 Memcached ,默认监听端口为 11211
四.Memcached在java在java项目中的应用
(一)StaticValue 类中设置常量
package com.jssso.htgl.util; public class StaticValue { public static final String COOKIES_ROLE_KKEY = "COOKIES_ROLE_KKEY"; public static final Long MEMCAED_ROLE_KKEY = 120l; //分钟 }
(二)MyCache 为一个单例模式,这样会更加安全,每次调用的时候会创建一个私有实例
1.add方法为向memcached中添加查到的集合,在方法中
MEMCAED_ROLE_KKEY为设置的分钟数,可以从类StaticValue 中取到设置的值(注意此处设置的时间为120分钟:120l)
2.getCache方法为从memcached中取出缓存的数据
package com.zxrytj.netty; import java.util.Date; import java.util.List; import com.danga.MemCached.MemCachedClient; import com.danga.MemCached.SockIOPool; import com.jssso.htgl.util.StaticValue; public class MyCache { private static MemCachedClient client=new MemCachedClient(); private static MyCache myCache=new MyCache(); private MyCache(){}; public static MyCache getinstance() { return myCache; } static { String [] addr ={"127.0.0.1:11211"}; Integer [] weights = {3}; SockIOPool pool = SockIOPool.getInstance(); pool.setServers(addr); pool.setWeights(weights); pool.setInitConn(5); pool.setMinConn(5); pool.setMaxConn(200); pool.setMaxIdle(1000*30*30); pool.setMaintSleep(30); pool.setNagle(false); pool.setSocketTO(30); pool.setSocketConnectTO(0); pool.initialize(); } public boolean add(String key,List list)//add { /** * date为memcached过期时间 * MEMCAED_ROLE_KKEY,分钟 */ Date date = new Date(StaticValue.MEMCAED_ROLE_KKEY * 60 * 1000);//2小时,单位毫秒 // System.out.println( "XXXXXXXX"+(List)client.get(key)); return client.add(key, list,date); } public List getCache(String key) { List list=null; boolean b=client.keyExists(key); if(b==true) { list=(List) client.get(key); //System.out.println( "XXXXXXXXlist.size()"+list.size()); } return list; } }
二,在Servlet中的调用add,getCache方法
通过判断cookie是否过期向memcached中取数据,为说明问题把关键部分摘出来加以说明
1.cookie存在就直接向memcached中取数据
2.cookie不存在就调用add方法向memcached中添加数据集合
Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组 String ckvalue="";//声明一个cookie的value,判断cookie是否存在 List listcahe=null;//这里声明一个集合存放数据
//该for循环判断cookie是否存在 for(Cookie cookie : cookies) { if(cookie.getName().equalsIgnoreCase(StaticValue.COOKIES_ROLE_KKEY))//cookie的key值存在,ckvalue存在,直接从memcache中取值 { ckvalue=cookie.getValue(); System.out.println("ckvalue存在"+ckvalue); MyCache cache=MyCache.getinstance(); listcahe=cache.getCache(ckvalue);//从memcached中取值赋值给listcache } }
//cookie不存在 if("".equals(ckvalue))//ckvalue不存在 { System.out.println("ckvalue不存在"+ckvalue); MyCache cache=MyCache.getinstance(); String uuid = UUID.randomUUID().toString(); /** * COOKIES_ROLE_KKEY为cookie的key */ Cookie ck=new Cookie(StaticValue.COOKIES_ROLE_KKEY,uuid); ck.setMaxAge(-1);//过期时间,单位为秒,-1关闭浏览器cookie消失 ck.setPath("/js_sso_server/"); response.addCookie(ck); listcahe = roleService.getApp(rname, rdes, pageIndex, pageSize);//cookie不存在,从数据库获取数据 cache.add(uuid,listcahe); }
下面是Servlet中的完整代码,可以不看(自己可以练手的可以复制试试)
package com.jssso.htgl.action; import java.io.IOException; import java.io.PrintWriter; import java.net.URLDecoder; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import com.jssso.htgl.entity.Role; import com.jssso.htgl.service.RoleService; import com.jssso.htgl.service.impl.RoleServiceImpl; import com.jssso.htgl.util.GetChche; import com.jssso.htgl.util.StaticValue; import com.zxrytj.netty.MyCache; @SuppressWarnings("serial") public class RoleServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); }; @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String option = request.getParameter("option"); if (option != null) { if ("selectApp".equals(option)) { selectApp(request, response); } else if ("saveApp".equals(option)) { saveApp(request, response); } else if ("updateApp".equals(option)) { updateApp(request, response); } else if ("deleteApp".equals(option)) { deleteApp(request, response); } else if ("index".equals(option)) { goView("/WEB-INF/view/jsp/htgl/role.jsp", request, response); return; } else if("jsonRole".equals(option)){ jsonRole(request, response); } } } /** * 删除应用地址 * * @param request * @param response * @throws IOException */ private void deleteApp(HttpServletRequest request, HttpServletResponse response) throws IOException { String urlId = request.getParameter("rid"); RoleService roleService = new RoleServiceImpl(); boolean flag = roleService.deleteApp(urlId); PrintWriter out = response.getWriter(); if (flag) { out.print("success"); } else { out.print("error"); } out.flush(); out.close(); } /** * 修改应用地址 * * @param request * @param response * @throws IOException */ private void updateApp(HttpServletRequest request, HttpServletResponse response) throws IOException { String urlId = request.getParameter("rid"); String name = request.getParameter("rname"); String url = request.getParameter("des"); Long rid = null; if (urlId != null) { rid = Long.parseLong(urlId); } Role role = new Role(rid, name, url); RoleService roleService = new RoleServiceImpl(); boolean flag = roleService.updateApp(role); PrintWriter out = response.getWriter(); if (flag) out.print("success"); else out.print("error"); out.flush(); out.close(); } /** * 添加应用地址 * * @param request * @param response * @throws IOException */ private void saveApp(HttpServletRequest request, HttpServletResponse response) throws IOException { String rname = request.getParameter("rname"); String rdes = request.getParameter("des"); RoleService roleService = new RoleServiceImpl(); boolean flag = roleService.saveApp(rname, rdes); PrintWriter out = response.getWriter(); if (flag) out.print("success"); else out.print("error"); out.flush(); out.close(); } /** * 查询应用地址 * * @param request * @param response * @throws IOException */ private void selectApp(HttpServletRequest request, HttpServletResponse response) throws IOException { String rname = request.getParameter("rname"); String rdes = request.getParameter("des"); if(rname!=null && !"".equals(rname.trim())){ try { rname = URLDecoder.decode(rname, "utf-8"); } catch (Exception e) { e.printStackTrace(); } } Long pageIndex = 1L; if (request.getParameter("page") != null) { pageIndex = Long.parseLong(request.getParameter("page")); if (pageIndex == null || pageIndex == 0) { pageIndex = 1L; } } Integer pageSize = 10; if (request.getParameter("rows") != null) { pageSize = Integer.parseInt(request.getParameter("rows")); if (pageSize == null) { pageSize = 10; } } RoleService roleService = new RoleServiceImpl(); Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组 String ckvalue=""; List listcahe=null; for(Cookie cookie : cookies) { if(cookie.getName().equalsIgnoreCase(StaticValue.COOKIES_ROLE_KKEY))//cookie的key值存在,ckvalue存在,直接取值listcacahe { ckvalue=cookie.getValue(); System.out.println("ckvalue存在"+ckvalue); MyCache cache=MyCache.getinstance(); listcahe=cache.getCache(ckvalue); } } if("".equals(ckvalue))//ckvalue不存在 { System.out.println("ckvalue不存在"+ckvalue); MyCache cache=MyCache.getinstance(); String uuid = UUID.randomUUID().toString(); /** * COOKIES_ROLE_KKEY为cookie的key */ Cookie ck=new Cookie(StaticValue.COOKIES_ROLE_KKEY,uuid); ck.setMaxAge(-1);//过期时间,单位为秒,-1关闭浏览器cookie消失 /** * 获取web-inf路径 */ //String path=request.getSession().getServletContext().getRealPath("/WEB-INF/cookie"); // System.out.println("&&&&&&&&&&&&&&&&&path:"+path); ck.setPath("/js_sso_server/"); response.addCookie(ck); listcahe = roleService.getApp(rname, rdes, pageIndex, pageSize); cache.add(uuid,listcahe); } //GetChche get=new GetChche(); // get.getCache(request); Long count = roleService.pageCount(rname, rdes); Long pageCount = count % pageSize == 0 ? count / pageSize : (count / pageSize) + 1; Map<String, Object> jsonMap = new HashMap<String, Object>();// 定义map jsonMap.put("total", count); jsonMap.put("rows", listcahe); jsonMap.put("pages", pageCount); jsonMap.put("from", (pageIndex - 1) * pageSize + 1); jsonMap.put("to", pageIndex * pageSize); PrintWriter out = response.getWriter(); out.print(JSONObject.fromObject(jsonMap).toString()); out.flush(); out.close(); } /** * 查询应用地址 * * @param request * @param response * @throws IOException */ private void jsonRole(HttpServletRequest request, HttpServletResponse response) throws IOException { Long pageIndex = 1L; if (request.getParameter("page") != null) { pageIndex = Long.parseLong(request.getParameter("page")); if (pageIndex == null || pageIndex == 0) { pageIndex = 1L; } } Integer pageSize = 10; if (request.getParameter("rows") != null) { pageSize = Integer.parseInt(request.getParameter("rows")); if (pageSize == null) { pageSize = 10; } } RoleService roleService = new RoleServiceImpl(); List<Role> json = roleService.getApp(null,null, pageIndex, pageSize); PrintWriter out = response.getWriter(); out.print(JSONArray.fromObject(json).toString()); out.flush(); out.close(); } private void goView(String url, HttpServletRequest request, HttpServletResponse response) { RequestDispatcher dispatcher = request.getRequestDispatcher(url); try { dispatcher.forward(request, response); } catch (ServletException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }