使用maven简单搭建Spring mvc + redis缓存
注:此文参考并整合了网上的文章
《spring缓存机制》:http://blog.csdn.net/sidongxue2/article/details/30516141
《配置 Spring4.0 注解Cache+Redis缓存》:http://blog.csdn.net/ouyhong123/article/details/52162951
《spring整合redis缓存,以注解(@Cacheable、@CachePut、@CacheEvict)形式使用》: http://blog.csdn.net/aqsunkai/article/details/51758900
因为是自己简单搭建的例子,所以一个高级配置(如缓存规则)都没有加。
整个目录的结构如下:
几个重点的文件代码如下:
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zjf</groupId>
<artifactId>springmvc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.0.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
</dependencies>
</project>
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/spring-servlet.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>
spring-servlet.xml:
<?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:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 配置扫描的包 -->
<context:component-scan base-package="com.zjf.*" />
<!-- 注册HandlerMapper、HandlerAdapter两个映射类 -->
<mvc:annotation-driven />
<!-- 访问静态资源 -->
<mvc:default-servlet-handler />
<!-- 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>
applicationContext.xml:
<?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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-4.2.xsd">
<!-- 应用spring cache注解功能 -->
<cache:annotation-driven />
<context:property-placeholder location="classpath:redis.properties" />
<!-- jedis 配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<!--<property name="maxWaitMillis" value="${redis.maxWait}" />-->
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<!-- redis服务器中心 -->
<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="poolConfig" />
<property name="port" value="${redis.port}" />
<property name="hostName" value="${redis.hostname}" />
<!-- <property name="password" value="${redis.password}" /> -->
<property name="timeout" value="${redis.timeout}"></property>
</bean>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory" />
<property name="keySerializer">
<bean
class="org.springframework.data.redis.serializer.StringRedisSerializer" />
</property>
<property name="valueSerializer">
<bean
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
</property>
</bean>
<!-- 创建spring cache bean -->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<bean
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean"
p:name="default" />
<bean class="com.zjf.util.RedisCache">
<property name="redisTemplate" ref="redisTemplate" />
<property name="name" value="data"/>
<!-- common名称要在类或方法的注解中使用 -->
</bean>
</set>
</property>
</bean>
<!-- 创建User Dao bean -->
<bean id="userDao" class="com.zjf.spring.cache.dao.impl.UserDaoImpl" ></bean>
<!-- 创建User Service bean -->
<bean id="userService" class="com.zjf.spring.cache.service.impl.UserServiceImpl" >
<property name="userDao" >
<ref bean="userDao"></ref>
</property>
</bean>
</beans>
UserServiceImpl.java:
package com.zjf.spring.cache.service.impl;
import java.util.Map;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import com.zjf.spring.cache.dao.UserDao;
import com.zjf.spring.cache.model.User;
import com.zjf.spring.cache.service.UserService;
public class UserServiceImpl implements UserService {
private UserDao userDao;
/**
* JVM加载spring配置文件时, 通过set方法注入本类的依赖.
* @param userDao
*/
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
/**
* 对数据进行增删改时清空缓存, 查询时使用缓存, 其中value为缓存区,
* allEntries表示清空缓存中所有的数据.
*/
@CacheEvict(value = "data", allEntries = true)
public void add(User user) {
System.out.println("UserService: method- add(User user)" );
userDao.add(user);
}
@CacheEvict(value = "data", allEntries = true)
public void delete(String id) {
System.out.println("UserService: method-delete(String id)" );
userDao.delete(id);
}
@CacheEvict(value = "data", allEntries = true)
public void update(User user) {
System.out.println("UserService: method-update(User user)" );
userDao.update(user);
}
@Cacheable(value = "data")
public User find(String id) {
System.out.println("UserService: method-find(String id)" );
return userDao.find(id);
}
@Cacheable(value = "data")
public Map<String, User> getAll() {
System.out.println("UserService: method-getAll()" );
return userDao.getAll();
}
}
redis.properties
#redis config
#redis.hostname=192.168.242.131
redis.hostname=192.168.1.101
redis.port=6379
redis.timeout=2000
redis.usePool=true
redis.default.db=0
#\u6700\u5927\u5206\u914D\u7684\u5BF9\u8C61\u6570
redis.maxTotal=600
#\u6700\u5927\u80FD\u591F\u4FDD\u6301idel\u72B6\u6001\u7684\u5BF9\u8C61\u6570
redis.maxIdle=300
#\u591A\u957F\u65F6\u95F4\u68C0\u67E5\u4E00\u6B21\u8FDE\u63A5\u6C60\u4E2D\u7A7A\u95F2\u7684\u8FDE\u63A5
redis.timeBetweenEvictionRunsMillis=30000
#\u7A7A\u95F2\u8FDE\u63A5\u591A\u957F\u65F6\u95F4\u540E\u4F1A\u88AB\u6536\u56DE
redis.minEvictableIdleTimeMillis=30000
#\u5F53\u8C03\u7528borrow Object\u65B9\u6CD5\u65F6\uFF0C\u662F\u5426\u8FDB\u884C\u6709\u6548\u6027\u68C0\u67E5
redis.testOnBorrow=true
########reids\u7F16\u7801\u683C\u5F0F
redis.encode=utf-8
######\u7F13\u5B58\u8FC7\u671F\u65F6\u95F4 \u79D2 1000*60*60*24*7 \u4E03\u5929
redis.expire=604800000
####\u662F\u5426\u5F00\u542FRedis\u670D\u52A1\u5E94\u7528
redis.unlock=false
DemoController.java:
package com.zjf.spring.cache;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.zjf.spring.cache.model.User;
import com.zjf.spring.cache.service.UserService;
@Controller
public class DemoController {
@Autowired
private UserService userService;
@RequestMapping("/finduser")
public String finduser() {
User user = userService.find("2");
System.out.println(user);
return "finduser";
}
@RequestMapping("/adduser")
public String adduser() {
userService.add(new User("2", "Ilucky1", "pwd1"));
return "adduser";
}
}
执行结果:
tomcat服务启动后,先进入http://localhost:8080/springmvc/adduser页面,这时候会在dao层插入一个user。
然后进入http://localhost:8080/springmvc/finduser页面,因为第一次进入,还没有缓存,这时候会进入service和dao。
再次进入http://localhost:8080/springmvc/finduse 页面,这个时候发现,没有进入service。直接取了redis缓存。
控制台打印的结果如下:
UserService: method- add(User user)
UserDao method- add(User user)
UserService: method-find(String id)
UserDao method- find(String id)
2-Ilucky1-pwd1
2-Ilucky1-pwd1
注意:第二次打印2-Ilucky1-pwd1的时候,前面没有进入UserService和UserDao的打印。
这个时候我们去redis服务器上看redis的缓存。
127.0.0.1:6379> keys *
1) "2"
注意:keys*命令可以获取所有的key。这里我们看到key为2.因为我们执行UserService: method-find(String id)方法的时候,传入的参数是2.这样来看,spring是通过参数来作为key的,如果有两个不同的方法,参数一样,那么缓存会冲突才对。所以还是定义@Cacheable注解的时候,还是把key也加上。
@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存
@Cacheable 主要的参数 | ||
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 | 例如: @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”} |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | 例如: @Cacheable(value=”testcache”,key=”#userName”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 | 例如: @Cacheable(value=”testcache”,condition=”#userName.length()>2”) |
------------------------------------------------------------
表 2. @CachePut 作用和配置方法
@CachePut 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存,和 @Cacheable 不同的是,它每次都会触发真实方法的调用
@CachePut 主要的参数 | ||
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 | 例如: @Cacheable(value=”mycache”) 或者 @Cacheable(value={”cache1”,”cache2”} |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | 例如: @Cacheable(value=”testcache”,key=”#userName”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才进行缓存 | 例如: @Cacheable(value=”testcache”,condition=”#userName.length()>2”) |
//////////////////////////////////////////////////////
表 3. @CacheEvict 作用和配置方法
@CachEvict 的作用 主要针对方法配置,能够根据一定的条件对缓存进行清空
@CacheEvict 主要的参数 | ||
value | 缓存的名称,在 spring 配置文件中定义,必须指定至少一个 | 例如: @CachEvict(value=”mycache”) 或者 @CachEvict(value={”cache1”,”cache2”} |
key | 缓存的 key,可以为空,如果指定要按照 SpEL 表达式编写,如果不指定,则缺省按照方法的所有参数进行组合 | 例如: @CachEvict(value=”testcache”,key=”#userName”) |
condition | 缓存的条件,可以为空,使用 SpEL 编写,返回 true 或者 false,只有为 true 才清空缓存 | 例如: @CachEvict(value=”testcache”, condition=”#userName.length()>2”) |
allEntries | 是否清空所有缓存内容,缺省为 false,如果指定为 true,则方法调用后将立即清空所有缓存 | 例如: @CachEvict(value=”testcache”,allEntries=true) |
beforeInvocation | 是否在方法执行前就清空,缺省为 false,如果指定为 true,则在方法还没有执行的时候就清空缓存,缺省情况下,如果方法执行抛出异常,则不会清空缓存 | 例如: @CachEvict(value=”testcache”,beforeInvocation=true) |
整个代码的下载:
http://download.csdn.net/detail/xiaolang8762400/9857058