springmvc配置Ehcache实现缓存管理
项目源代码:http://download.csdn.net/detail/u013147600/9066943
工程介绍:
springmvc结合Ehcache实现缓存管理项目介绍:
通过在springmvc配置文件中配置oracle数据库连接信息实现JdbcTemplate连接数据库;
在dao和service层中实现查询用户信息方法;
添加Ehcache配置文件ehcache.xml,并在service.Impl中的类通过注释实现缓存管理(如: @Cacheable(value="myCache",key="'findByAccounterName'+#accountnumber"));
配置log日志管理,点击main.jsp中的链接,
1.第一次点击"ld信息"链接时,访问数据库日志打印为:@author lyx:-2015-08-31 10:36:51,681 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liudong]对应的用户名为[liudong]
2.当再点击"ld信息"链接时,不会打印日志,这是因为第二次查询时不会访问数据库,直接从缓存中读取数据,所以不会打印数据库
3.点击"更新"链接后,打印日志为:@author lyx:-2015-08-31 10:37:05,594 [INFO] -[com.service.impl.UserServiceImpl] --------移除缓存中此用户号[liudong]对应的用户名[liudong]的缓存
4.当再点击"ld信息"链接时,打印日志:@author lyx:-2015-08-31 10:37:09,046 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liudong]对应的用户名为[liudong]
5.点击"清空"链接时,打印日志为:@author lyx:-2015-08-31 10:37:12,112 [INFO] -[com.service.impl.UserServiceImpl] --------移除缓存中的所有数据!
6.点击"lyx信息"链接后打印日志:@author lyx:-2015-08-31 10:37:14,170 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liuyuxin]对应的用户名为[liuyuxin]
7.点击"ld信息"链接,打印日志为:@author lyx:-2015-08-31 10:37:16,246 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liudong]对应的用户名为[liudong]
5.点击"清空"链接时,打印日志为:@author lyx:-2015-08-31 10:37:12,112 [INFO] -[com.service.impl.UserServiceImpl] --------移除缓存中的所有数据!
6.点击"lyx信息"链接后打印日志:@author lyx:-2015-08-31 10:37:14,170 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liuyuxin]对应的用户名为[liuyuxin]
7.点击"ld信息"链接,打印日志为:@author lyx:-2015-08-31 10:37:16,246 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liudong]对应的用户名为[liudong]
Ehcache所需要的jar包:
ehcache-core-2.4.5.jar
ehcache-spring-annotations-1.2.0.jar
log日志需要的jar包:
slf4j-api-1.7.6.jar
slf4j-log4j12-1.7.6.jar
日志详细配置地址:http://blog.csdn.net/u013147600/article/details/47812811
ehcache.xml配置文件
<!-- 1)最好在ehcache.xml中声明不进行updateCheck -->
<!-- 2)为了配合BigMemory和Size Limit,原来的属性最好改名 -->
<!-- maxElementsInMemory->maxEntriesLocalHeap -->
<!-- maxElementsOnDisk->maxEntriesLocalDisk -->
<!--
name:Cache的唯一标识
maxElementsInMemory:内存中最大缓存对象数
maxElementsOnDisk:磁盘中最大缓存对象数,若是0表示无穷大
eternal:Element是否永久有效,一但设置了,timeout将不起作用
overflowToDisk:配置此属性,当内存中Element数量达到maxElementsInMemory时,Ehcache将会Element写到磁盘中
timeToIdleSeconds:设置Element在失效前的允许闲置时间。仅当element不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大
timeToLiveSeconds:设置Element在失效前允许存活时间。最大时间介于创建时间和失效时间之间。仅当element不是永久有效时使用,默认是0.,也就是element存活时间无穷大
diskPersistent:是否缓存虚拟机重启期数据
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒
diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)
-->
<ehcache name="lyxCache">
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"/>
<cache name="myCache"
maxElementsOnDisk="20000"
maxElementsInMemory="2000"
eternal="true"
overflowToDisk="true"
diskPersistent="true"/>
</ehcache>
springmvc-servlet.xml (springmvc的配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-3.2.xsd ">
<!-- default-autowire="byName" default-lazy-init="true" -->
<!-- springMVC比较详细注解 -->
<!-- 基本配置 -begin-->
<!-- 自动注入 -->
<context:annotation-config></context:annotation-config>
<!-- 自动扫描包 组件扫描-->
<context:component-scan base-package="com"></context:component-scan>
<!-- 注释驱动 -->
<mvc:annotation-driven/>
<!-- 配置不用DispatcherServlet 拦截的路径 -->
<mvc:resources location="/res/" mapping="/res/**"/>
<!-- 默认分发处理器不会拦截静态资源 -->
<!-- <mvc:default-servlet-handler/> -->
<!-- 默认地址栏访问跳转到首页 -->
<!-- <mvc:view-controller path="/" view-name="forward:/index"/> -->
<!-- 也可以利用<mvc:view-controller/>配置错误页面的跳转 -->
<!-- 避免IE执行AJAX时,返回JSON出现下载文件 -->
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 启动Spring MVC的注解功能,完成请求和注解POJO的映射 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJacksonHttpMessageConverter" /><!-- json转换器 -->
</list>
</property>
</bean>
<!-- 采用SpringMVC自带的JSON转换工具,支持@ResponseBody注解 -->
<!-- <bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
解析JSON数据,将json转换成java对象,避免IE执行AJAX时,返回JSON出现下载文件
<bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean> -->
<!-- 视图解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"></property>
</bean>
<!-- 基本配置 -end-->
<!-- 配置Ehcache缓存 -->
<!-- 启动缓存注解功能 -->
<cache:annotation-driven cache-manager="cacheManager"/>
<!-- Spring自己的基于java.util.concurrent.ConcurrentHashMap实现的缓存管理器(该功能是从Spring3.1开始提供的) -->
<!-- <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean name="myCache" class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"></bean>
</set>
</property>
</bean> -->
<!-- 若只想使用Spring自身提供的缓存器,则注释掉下面的两个关于Ehcache配置的bean,并启用上面的SimpleCacheManager即可 -->
<!-- Spring提供的基于的Ehcache实现的缓存管理器 -->
<bean id="ehCacheManagerFactoryBean" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="classpath:ehcache.xml"/>
</bean>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
<property name="cacheManager" ref="ehCacheManagerFactoryBean"></property>
</bean>
<!-- 功能配置 -begin-->
<!-- 配置springJDBC Template -->
<!-- 引入项目配置文件 方法一-->
<!-- <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:dbconfig.properties</value>
</list>
</property>
</bean> -->
<!-- 引入项目配置文件 方法二-->
<!-- <context:property-placeholder location="classpath:dbconfig.properties"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="${url}"></property>
<property name="driverClassName" value="${driverClassName}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
jdbcTemplate
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource">
</property>
</bean> -->
<!-- datasource 配置数据库 -->
<!-- datasource -->
<!-- destroy-method="close"的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用.-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"></property>
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
<property name="username" value="lyx"></property>
<property name="password" value="lyx"></property>
</bean>
<!-- jdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" >
<property name="dataSource" ref="dataSource">
</property>
</bean>
<!-- 文件上传配置 -->
<!-- <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8"></property> 默认编码
<property name="maxUploadSize" value="10000000"></property> 上传文件大小
</bean> -->
<!-- 拦截器 -->
<!--
<mvc:interceptors>
<mvc:interceptor>
拦截全部地址
<mvc:mapping path="/**"/>
登录拦截类
<bean id="loginInterceptor" class="com.sgcc.uds.fs.config.web.interceptor.LoginInterceptor">
</bean>
</mvc:interceptor>
</mvc:interceptors>
-->
<!-- 异常 -->
<!--
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
登录失败异常类
<prop key="com.sgcc.uds.fs.config.web.interceptor.UnLoginException">redirect:/toLogin</prop>
</props>
</property>
</bean>
-->
<!-- 功能配置 -end-->
</beans>
UserService.java
package com.service;
import java.util.List;
import java.util.Map;
import com.entity.MemberUser;
/**
* @author lyx
*
* 2015-8-19上午8:51:59
*
*service.UserService
* TODO
*/
public interface UserService {
public List<Map<String,Object>> queryAllInfo(int currentPage,int limitPage);
public int totalCount();
public List<Map<String, Object>> findByAccounterName(String accountnumber);
public void update(String accountnumber);
public void removeAll();
}
UserServiceImpl.java
package com.service.impl;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import com.dao.UserDao;
import com.dao.Impl.UserDaoImpl;
import com.entity.MemberUser;
import com.service.UserService;
/**
* @author lyx
*
* 2015-8-19上午8:52:16
*
*service.impl.UserServiceImpl
* TODO
*/
@Service("UserService")
public class UserServiceImpl implements UserService{
@Autowired
private UserDao dao;
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
public List<Map<String, Object>> queryAllInfo(int currentPage,int limitPage) {
// TODO Auto-generated method stub
return dao.queryAllInfo( currentPage, limitPage);
}
public int totalCount() {
// TODO Auto-generated method stub
return dao.totalCount();
}
//将查询到的数据缓存到myCache中,并使用方法名称加上参数中的userNo作为缓存的key
//通常更新操作只需刷新缓存中的某个值,所以为了准确的清除特定的缓存,故定义了这个唯一的key,从而不会影响其它缓存值
@Cacheable(value="myCache",key="'findByAccounterName'+#accountnumber")
public List<Map<String, Object>> findByAccounterName(String accountnumber) {
// TODO Auto-generated method stub/*dao.findByAccounterName(accountnumber).get(0).get("ACCOUNTNUMBER") */
System.out.println("数据库中查到此用户号[" + accountnumber + "]对应的用户名为[" +accountnumber + "]");
logger.info("-------数据库中查到此用户号[" + accountnumber + "]对应的用户名为[" +accountnumber + "]");
return dao.findByAccounterName(accountnumber);
}
@CacheEvict(value="myCache",key="'findByAccounterName'+#accountnumber")
public void update(String accountnumber)
{// dao.findByAccounterName(accountnumber).get(0).get("ACCOUNTNUMBER")
System.out.println("移除缓存中此用户号[" + accountnumber + "]对应的用户名[" + accountnumber+ "]的缓存");
logger.info("-------移除缓存中此用户号[" + accountnumber + "]对应的用户名[" + accountnumber+ "]的缓存");
}
//allEntries为true表示清除value中的全部缓存,默认为false
@CacheEvict(value="myCache",allEntries=true)
public void removeAll()
{
System.out.println("移除缓存中的所有数据!");
logger.info("-------移除缓存中的所有数据!");
}
}
UserController.java中方法:
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("/queryUserInfoByUsername")
public String queryUserInfoByUsername(HttpServletRequest request)
{
String username = request.getParameter("username");
List<Map<String, Object>> userlist = new ArrayList<Map<String,Object>>();
MemberUser user =new MemberUser();
if(username!=null)
{
userlist = service.findByAccounterName(username);
//user=(MemberUser) userlist.get(0);
for (Map<String, Object> map : userlist) {
for (String key : map.keySet()) {
user.setAccountNumber(map.get("ACCOUNTNUMBER").toString());
user.setMemberName(map.get("MEMBERNAME").toString());
System.out.print(key+":"+map.get(key));
}
}
if(user!=null)
{
request.setAttribute("memberUser", user);
return "/myInfo";
}
}
return null;
}
@RequestMapping(value="/update",method=RequestMethod.GET)
public String update(HttpServletRequest request)
{
String username = request.getParameter("username");
service.update(username);
request.setAttribute("accounterNumber", username);
return "/update";
}
@RequestMapping(value="/removeAll",method=RequestMethod.GET)
public String removeAll()
{
service.removeAll();
return "/removeAll";
}
}
main.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
request.setAttribute("home", path);
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>main</title>
<link rel="stylesheet" href="${home}/res/css/bootstrap.min.css" type="text/css"></link>
<link rel="stylesheet" href="${home}/res/css/allStyle.css" type="text/css"></link>
<style type="text/css">
.userTable{
font-size: 20px;
}
</style>
<script type="text/javascript">
var home ="${home}";
</script>
</head>
<body>
<div>
<h2 class="sub-header">管理列表</h2>
<ul>
<li> <a href="${home}/user/queryUserInfoByUsername?username=liuyuxin" target="_blank">lyx信息</a></li>
<li> <a href="${home}/user/queryUserInfoByUsername?username=liudong" target="_blank">ld信息</a></li>
<li> <a href="${home}/user/update?username=liudong" target="_blank">更新</a></li>
<li> <a href="${home}/user/removeAll" target="_blank">清空</a></li>
<li> <a href="${home}/index.jsp" target="_blank">全部信息</a></li>
</ul>
</div>
<script type="text/javascript" src="${home}/res/js/jquery-1.11.3.min.js"></script>
</body>
</html>
图片:
console控制台日志:
@author lyxx:-2015-08-31 10:36:51,681 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liudong]对应的用户名为[liudong]
@author lyxx:-2015-08-31 10:37:05,594 [INFO] -[com.service.impl.UserServiceImpl] --------移除缓存中此用户号[liudong]对应的用户名[liudong]的缓存
@author lyxx:-2015-08-31 10:37:09,046 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liudong]对应的用户名为[liudong]
@author lyxx:-2015-08-31 10:37:12,112 [INFO] -[com.service.impl.UserServiceImpl] --------移除缓存中的所有数据!
数据库中查到此用户号[liuyuxin]对应的用户名为[liuyuxin]
@author lyxx:-2015-08-31 10:37:14,170 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liuyuxin]对应的用户名为[liuyuxin]
@author lyxx:-2015-08-31 10:37:16,246 [INFO] -[com.service.impl.UserServiceImpl] --------数据库中查到此用户号[liudong]对应的用户名为[liudong]
文件打印日志:
2015-08-31 10:36:45 [ http-apr-8080-exec-8:26719 ] - [ INFO ] Loaded JDBC driver: oracle.jdbc.driver.OracleDriver
2015-08-31 10:36:51 [ http-apr-8080-exec-3:33050 ] - [ INFO ] -------数据库中查到此用户号[liudong]对应的用户名为[liudong]
2015-08-31 10:37:05 [ http-apr-8080-exec-8:46963 ] - [ INFO ] -------移除缓存中此用户号[liudong]对应的用户名[liudong]的缓存
2015-08-31 10:37:09 [ http-apr-8080-exec-3:50415 ] - [ INFO ] -------数据库中查到此用户号[liudong]对应的用户名为[liudong]
2015-08-31 10:37:12 [ http-apr-8080-exec-4:53481 ] - [ INFO ] -------移除缓存中的所有数据!
2015-08-31 10:37:14 [ http-apr-8080-exec-7:55539 ] - [ INFO ] -------数据库中查到此用户号[liuyuxin]对应的用户名为[liuyuxin]
2015-08-31 10:37:16 [ http-apr-8080-exec-8:57615 ] - [ INFO ] -------数据库中查到此用户号[liudong]对应的用户名为[liudong]