通过spring 拦截,实现颗粒度比较细,容易控制的缓存。了解了下,spring 3.0 以后,应该从3.1
以后吧,注解方式的缓存就已经实现,下面是我自己做的例子,分享给大家:
例子内容介绍:
1.没用数据库,用的集合里面的数据,也就没事务之类的,完成的一个CRUD操作
2.主要测试内容,包括第一次查询,和反复查询,缓存是否生效,更新之后数据同步的问题
3.同时含有一些常用参数绑定等东西
4.为了内容简单,我没有使用接口,就是User,UserControl,UserServer,UserDao 几个类,以及xml 配置文件
直接看类吧,源码文件,以及jar 都上传,方便大家下载:
Java代码
- package com.se;
- public class User {
- public Integer id;
- public String name;
- public String password;
- // 这个需要,不然在实体绑定的时候出错
- public User(){}
- public User(Integer id, String name, String password) {
- super();
- this.id = id;
- this.name = name;
- this.password = password;
- }
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- @Override
- public String toString() {
- return "User [id=" + id + ", name=" + name + ", password=" + password
- + "]";
- }
- }
Java代码
- package com.se;
- import java.util.ArrayList;
- import java.util.List;
- import org.springframework.stereotype.Repository;
- /**
- * 静态数据,模拟数据库操作
- */
- @Repository("userDao")
- public class UserDao {
- List<User> users = initUsers();
- public User findById(Integer id){
- User user = null;
- for(User u : users){
- if(u.getId().equals(id)){
- user = u;
- }
- }
- return user;
- }
- public void removeById(Integer id){
- User user = null;
- for(User u : users){
- if(u.getId().equals(id)){
- user = u;
- break;
- }
- }
- users.remove(user);
- }
- public void addUser(User u){
- users.add(u);
- }
- public void updateUser(User u){
- addUser(u);
- }
- // 模拟数据库
- private List<User> initUsers(){
- List<User> users = new ArrayList<User>();
- User u1 = new User(1,"张三","123");
- User u2 = new User(2,"李四","124");
- User u3 = new User(3,"王五","125");
- users.add(u1);
- users.add(u2);
- users.add(u3);
- return users;
- }
- }
Java代码
- package com.se;
- import java.util.List;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cache.annotation.CacheEvict;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.stereotype.Service;
- /**
- * 业务操作,
- */
- @Service("userService")
- public class UserService {
- @Autowired
- private UserDao userDao;
- // 查询所有,不要key,默认以方法名+参数值+内容 作为key
- @Cacheable(value = "serviceCache")
- public List<User> getAll(){
- printInfo("getAll");
- return userDao.users;
- }
- // 根据ID查询,ID 我们默认是唯一的
- @Cacheable(value = "serviceCache", key="#id")
- public User findById(Integer id){
- printInfo(id);
- return userDao.findById(id);
- }
- // 通过ID删除
- @CacheEvict(value = "serviceCache", key="#id")
- public void removeById(Integer id){
- userDao.removeById(id);
- }
- public void addUser(User u){
- if(u != null && u.getId() != null){
- userDao.addUser(u);
- }
- }
- // key 支持条件,包括 属性condition ,可以 id < 10 等等类似操作
- // 更多介绍,请看参考的spring 地址
- @CacheEvict(value="serviceCache", key="#u.id")
- public void updateUser(User u){
- removeById(u.getId());
- userDao.updateUser(u);
- }
- // allEntries 表示调用之后,清空缓存,默认false,
- // 还有个beforeInvocation 属性,表示先清空缓存,再进行查询
- @CacheEvict(value="serviceCache",allEntries=true)
- public void removeAll(){
- System.out.println("清除所有缓存");
- }
- private void printInfo(Object str){
- System.out.println("非缓存查询----------findById"+str);
- }
- }
Java代码
- package com.se;
- import java.util.List;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.Model;
- import org.springframework.web.bind.annotation.ModelAttribute;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- @Controller
- public class UserControl {
- @Autowired
- private UserService userService;
- // 提前绑定视图,提前绑定数据,方便查看数据变化
- @ModelAttribute("users")
- public List<User> cityList() {
- return userService.getAll();
- }
- // 根据ID查询
- @RequestMapping("/get/{id}")
- public String getUserById(Model model,@PathVariable Integer id){
- User u = userService.findById(id);
- System.out.println("查询结果:"+u);
- model.addAttribute("user", u);
- return "forward:/jsp/edit";
- }
- // 删除
- @RequestMapping("/del/{id}")
- public String deleteById(Model model,@PathVariable Integer id){
- printInfo("删除-----------");
- userService.removeById(id);
- return "redirect:/jsp/view";
- }
- // 添加
- @RequestMapping("/add")
- public String addUser(Model model,@ModelAttribute("user") User user){
- printInfo("添加----------");
- userService.addUser(user);
- return "redirect:/jsp/view";
- }
- // 修改
- @RequestMapping("/update")
- public String update(Model model,@ModelAttribute User u){
- printInfo("开始更新---------");
- userService.updateUser(u);
- model.addAttribute("user", u);
- return "redirect:/jsp/view";
- }
- // 清空所有
- @RequestMapping("/remove-all")
- public String removeAll(){
- printInfo("清空-------------");
- userService.removeAll();
- return "forward:/jsp/view";
- }
- // JSP 跳转
- @RequestMapping("/jsp/{jspName}")
- public String toJsp(@PathVariable String jspName){
- System.out.println("JSP TO -->>" +jspName);
- return jspName;
- }
- private void printInfo(String str){
- System.out.println(str);
- }
- }
XML 配置:
Java代码
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
- <display-name>springEhcache</display-name>
- <servlet>
- <servlet-name>spring</servlet-name>
- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
- <init-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:com/config/springmvc-context.xml</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>spring</servlet-name>
- <url-pattern>/</url-pattern>
- </servlet-mapping>
- </web-app>
Java代码
- <?xml version="1.0" encoding="UTF-8"?>
- <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
- <!-- service 缓存配置 -->
- <cache name="serviceCache"
- eternal="false"
- maxElementsInMemory="100"
- overflowToDisk="false"
- diskPersistent="false"
- timeToIdleSeconds="0"
- timeToLiveSeconds="300"
- memoryStoreEvictionPolicy="LRU" />
- </ehcache>
Java代码
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:oxm="http://www.springframework.org/schema/oxm"
- xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:cache="http://www.springframework.org/schema/cache"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/mvc
- http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
- http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context-3.2.xsd
- http://www.springframework.org/schema/cache
- http://www.springframework.org/schema/cache/spring-cache.xsd">
- <!-- 默认扫描 @Component @Repository @Service @Controller -->
- <context:component-scan base-package="com.se" />
- <!-- 一些@RequestMapping 请求和一些转换 -->
- <mvc:annotation-driven />
- <!-- 前后缀 -->
- <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/"/>
- <property name="suffix" value=".jsp"/>
- </bean>
- <!-- 静态资源访问 的两种方式 -->
- <!-- <mvc:default-servlet-handler/> -->
- <mvc:resources location="/*" mapping="/**" />
- <!-- 缓存 属性-->
- <bean id="cacheManagerFactory" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
- <property name="configLocation" value="classpath:com/config/ehcache.xml"/>
- </bean>
- <!-- 支持缓存注解 -->
- <cache:annotation-driven cache-manager="cacheManager" />
- <!-- 默认是cacheManager -->
- <bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
- <property name="cacheManager" ref="cacheManagerFactory"/>
- </bean>
- </beans>
JSP 配置:
Java代码
- <%@ page language="java" contentType="text/html; charset=Utf-8" pageEncoding="Utf-8"%>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>Insert title here</title>
- </head>
- <script type="text/javascript" src="<%=request.getContextPath()%>/js/jquery-1.4.3.js"></script>
- <body>
- <strong>用户信息</strong><br>
- 输入编号:<input id="userId">
- <a href="#" id="edit">编辑</a>
- <a href="#" id="del" >删除</a>
- <a href="<%=request.getContextPath()%>/jsp/add">添加</a>
- <a href="<%=request.getContextPath()%>/remove-all">清空缓存</a><br/>
- <p>所有数据展示:<p/>
- ${users }
- <p>静态图片访问测试:</p>
- <img style="width: 110px;height: 110px" src="<%=request.getContextPath()%>/img/404cx.png"><br>
- </body>
- <script type="text/javascript">
- $(document).ready(function(){
- $(‘#userId‘).change(function(){
- var userId = $(this).val();
- var urlEdit = ‘<%=request.getContextPath()%>/get/‘+userId;
- var urlDel = ‘<%=request.getContextPath()%>/del/‘+userId;
- $(‘#edit‘).attr(‘href‘,urlEdit);
- $(‘#del‘).attr(‘href‘,urlDel);
- });
- });
- </script>
- </html>
Java代码
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- </head>
- <script type="text/javascript" src="../js/jquery-1.4.3.js"></script>
- <body>
- <strong>编辑</strong><br>
- <form id="edit" action="<%=request.getContextPath()%>/update" method="get">
- 用户ID:<input id="id" name="id" value="${user.id}"><br>
- 用户名:<input id="name" name="name" value="${user.name}"><br>
- 用户密码:<input id="password" name="password" value="${user.password}"><br>
- <input value="更新" id="update" type="submit">
- </form>
- </body>
- </html>
Java代码
- <%@ page language="java" contentType="text/html; charset=UTF-8"
- pageEncoding="UTF-8"%>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>Insert title here</title>
- </head>
- <script type="text/javascript" src="../js/jquery-1.4.3.js"></script>>
- <body>
- <strong>添加</strong>
- <form action="<%=request.getContextPath()%>/add" method="post">
- 用户ID:<input name="id" ><br>
- 用户名:<input name="name" ><br>
- 用户密码:<input name="password"><br>
- <input value="添加" id="add" type="submit">
- </form>
- ${users }
- </body>
- </html>
关于测试方式:
输入地址:http://localhost:8081/springEhcache/jsp/view
然后根据ID 进行查询编辑, 还有添加,以及删除等操作,这里仅仅做简单实例,更多的需要大家自己做写。测试用例的我也导入了,业务可以自己写。
里面用到了很多参考资料:
比如:
这个是google 弄的例子,实例项目类似,就不上传了
http://blog.goyello.com/2010/07/29/quick-start-with-ehcache-annotations-for-spring/
这个是涛ge,对spring cache 的一些解释
http://jinnianshilongnian.iteye.com/blog/2001040
还有就是spring 官网的一些资料,我是自己下的src ,里面文档都有,会上传
自己路径的文件地址/spring-3.2.0.M2/docs/reference/htmlsingle/index.html
关于Ehcache 的介绍,可以参考
官网:http://www.ehcache.org/documentation/get-started/cache-topologies
还有我缓存分类里面转的文章,关于几个主流缓存分类 以及区别的。
小结:
1.现在aop 和DI
用得很多了,也特别的方便,但是框架太多了,但是要核心源码搞清楚了才行
2.上面的缓存机制还可以运用到类上,和事务差不多,反正里面东西挺多了,
我就不一一介绍了,可以自己进行扩展研究。
3.感觉spring
的缓存,颗粒度还可以再细,精确到元素,或者可以提供对指定方法,指定内容的时间控制,而不是只能通过xml,也可以在方法上直接加参数,细化元素的缓存时间,关于这点的作用来说,我项目中,比如A
结果集,我想缓存10秒,B结果集想缓存50秒,就不用再次去配置缓存了。而且ehcache 是支持元素级的颗粒控制,各有想法吧。当然看自己喜欢用xml
方式拦截呢,还是注解使用,这里仅提供了注解方式,我比较喜欢~。~
4.有问题的地方欢迎大家,多指正!
不能超过10M,就分开传的,包括项目,以及文档介绍
spring3.2+ehcache 注解使用,布布扣,bubuko.com