Spring 整合 Spring Cache + Redis + Java Config

1.安装redis

  a.由于官方是没有Windows版的,所以我们需要下载微软开发的redis,网址:https://github.com/MicrosoftArchive/redis/releases

  b.解压后,在redis根目录打开cmd界面,输入:redis-server.exe redis.windows.conf,启动redis(关闭cmd窗口即停止)

 

 

2.使用

  a.导入 maven 依赖

  <properties>

    ......

    <!-- spring -->
    <spring.version>5.1.1.RELEASE</spring.version>
    <!-- jackson-json -->
    <jackson.version>2.9.4</jackson.version>
    <!-- log4j -->
    <slf4j.version>1.7.18</slf4j.version>
    <log4j.version>1.2.17</log4j.version>
  </properties>

  <dependencies>
    <!-- spring -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-oxm</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context-support</artifactId>
      <version>${spring.version}</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>${spring.version}</version>
    </dependency>

    <!-- Jackson -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>${jackson.version}</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>${jackson.version}</version>
    </dependency>

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- AOP -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.8.6</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.6</version>
    </dependency>

    <!-- 日志相关 -->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>${log4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>${slf4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>${slf4j.version}</version>
    </dependency>

    <!-- redis -->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>2.1.1.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.10.0</version>
    </dependency>

    <!-- servlet -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.2</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

 

 

  b.创建 spring.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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 自动扫描的包名 -->
    <context:component-scan base-package="com.wode" />

    <!-- 开启AOP代理 -->
    <aop:aspectj-autoproxy proxy-target-class="true" />

    <!--开启注解处理器 -->
    <context:annotation-config>
    </context:annotation-config>

    <context:property-placeholder location="classpath:redis.properties"/>
    <!-- Spring中引入其他配置文件 -->
    <import resource="classpath*:/spring-redis.xml" />

</beans>

 

 

  c.创建 spring-redis.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">

    <!-- jedis配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最大空闲数:空闲连接数大于maxIdle时,将进行回收 -->
        <property name="maxIdle" value="${redis.maxIdle}" />
        <!-- 最大连接数:能够同时建立的最大连接个数 -->
        <property name="maxTotal" value="${redis.maxTotal}" />
        <!-- 最大等待时间:单位ms -->
        <property name="maxWaitMillis" value="${redis.maxWait}" />
        <!-- 使用连接时,检测连接是否成功 -->
        <property name="testOnBorrow" value="${redis.testOnBorrow}" />
    </bean>

    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
          p:host-name="${redis.ip}" p:port="${redis.port}" p:password="${redis.password}" p:pool-config-ref="jedisPoolConfig"/>

    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="jedisConnectionFactory" />
        <!-- 配置Serializer -->
        <property name="keySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="hashKeySerializer">
            <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
        </property>
        <property name="valueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
        <property name="hashValueSerializer">
            <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/>
        </property>
    </bean>

</beans>

 

 

  d.创建 spring-mvc.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: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/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
    <!-- 开启SpringMVC注解模式 -->
    <mvc:annotation-driven />

    <!-- 扫描web相关的bean -->
    <context:component-scan base-package="com.wode.controller" />

    <!-- 静态资源默认servlet配置 -->
    <mvc:default-servlet-handler/>

    <!-- 配置jsp 显示ViewResolver -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/page/" />
        <property name="suffix" value=".jsp" />
    </bean>

</beans>

 

 

  e.创建 redis.properties 配置文件

redis.ip=localhost
redis.port=6379
redis.password=
redis.maxIdle=5
redis.maxWait=60000
redis.maxTotal=500
redis.testOnBorrow=true

 

 

  f.创建 RedisConfig 缓存配置类

@Configuration
@EnableCaching  //开启缓存
@ImportResource("classpath:spring-redis.xml")
public class RedisConfig {

    @Autowired
    private RedisConnectionFactory jedisConnectionFactory;

    /**
     * 缓存管理器
     * @return
     */
    @Bean
    public RedisCacheManager cacheManager() {
        // 生成一个默认配置,通过config对象即可对缓存进行自定义配置
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
        // 设置缓存的默认过期时间,也是使用Duration设置
        config = config.entryTtl(Duration.ofMinutes(30))
                // 设置 key为string序列化
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
                // 设置value为json序列化
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
                // 不缓存空值
                .disableCachingNullValues();

        // 对每个缓存空间应用不同的配置
        Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
        configMap.put("userCache", config.entryTtl(Duration.ofSeconds(60)));

        // 使用自定义的缓存配置初始化一个cacheManager
        RedisCacheManager cacheManager = RedisCacheManager.builder(jedisConnectionFactory)
                //默认配置
                .cacheDefaults(config)
                // 特殊配置(一定要先调用该方法设置初始化的缓存名,再初始化相关的配置)
                .initialCacheNames(configMap.keySet())
                .withInitialCacheConfigurations(configMap)
                .build();
        return cacheManager;
    }

    /**
     * json序列化
     * @return
     */
    private RedisSerializer<Object> jackson2JsonRedisSerializer() {
        //使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
        Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        //json转对象类,不设置默认的会将json转成hashmap
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);
        return serializer;
    }

}

     注:1.由于高版本的 Spring-Data-Redis 中的 RedisCacheManager 无法用 RedisTemplate 初始化,故需使用 Java-Config 的方式配置

       2.低版本可将下面代码加到 spring-redis.xml 中

    <!--cacheManager-->
    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
        <constructor-arg ref="redisTemplate"/>
    </bean>

 

 

  g.创建 SpringConfig 整合Spring配置类

@Configuration
@ImportResource("classpath:spring.xml")
@Import(RedisConfig.class)
public class SpringConfig {
}

 

 

  h.配置 WEB-INF 下的 web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>springMVC</display-name>

  <!-- 欢迎界面 -->
  <welcome-file-list>
    <welcome-file>/WEB-INF/page/test.jsp</welcome-file>
  </welcome-file-list>

  <!-- 通过@Configuration注解加载Spring配置 -->
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
  </context-param>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>com.wode.config.SpringConfig</param-value>
  </context-param>

  <!-- SpringMvc监听Spring配置 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <!-- 通过xml加载SpringMvc的DispatcherServlet -->
  <servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

  <!-- 编码过滤器 -->
  <filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>
      org.springframework.web.filter.CharacterEncodingFilter
    </filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

 

 

  i.创建entity实体类

public class User implements Serializable {

    private int id;
    private String userName;
    private String userPwd;

    public User(){}

    public User(int id, String userName, String userPwd) {
        this.id = id;
        this.userName = userName;
        this.userPwd = userPwd;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getUserPwd() {
        return userPwd;
    }

    public void setUserPwd(String userPwd) {
        this.userPwd = userPwd;
    }

}

 

 

  j.创建 Service

@Service
public class UserService {

    //查询:先查缓存是是否有,有则直接取缓存中数据,没有则运行方法中的代码并缓存
    @Cacheable(value = "userCache", key = "'user:' + #userId")
    public User getUser(int userId) {
        System.out.println("执行此方法,说明没有缓存");
        return new User(userId, "用户名(get)_" + userId, "密码_" + userId);
    }

    //添加:运行方法中的代码并缓存
    @CachePut(value = "userCache", key = "'user:' + #user.id")
    public User addUser(User user){
        int userId = user.getId();
        System.out.println("添加缓存");
        return new User(userId, "用户名(add)_" + userId, "密码_" + userId);
    }

    //删除:删除缓存
    @CacheEvict(value = "userCache", key = "'user:' + #userId")
    public boolean deleteUser(int userId){
        System.out.println("删除缓存");
        return true;
    }

    @Cacheable(value = "common", key = "'common:user:' + #userId")
    public User getCommonUser(int userId) {
        System.out.println("执行此方法,说明没有缓存(测试公共配置是否生效)");
        return new User(userId, "用户名(common)_" + userId, "密码_" + userId);
    }

}

 

 

  k.创建 Controller

@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;

    @RequestMapping("/getUser")
    public User getUser(int userId) {
        return userService.getUser(userId);
    }

    @RequestMapping("/addUser")
    public User addUser(User user){
        return userService.addUser(user);
    }

    @RequestMapping("/deleteUser")
    public boolean deleteUser(int userId){
        return userService.deleteUser(userId);
    }

    @RequestMapping("/getCommonUser")
    public User getCommonUser(int userId) {
        return userService.getCommonUser(userId);
    }

}

 

 

  l.在 WEB-INF 中的 page 文件夹下创建 test.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html lang="en">
<head>
    <base href="<%=basePath%>">
    <meta charset="UTF-8">
    <title>test</title>
    <style type="text/css">
        .row{
            margin:10px 0px;
        }
        .col{
            display: inline-block;
            margin:0px 5px;
        }
    </style>
</head>
<body>
<div>
    <h1>测试</h1>
    <div class="row">
        <label>用户ID:</label><input id="userid-input" type="text" name="userid"/>
    </div>
    <div class="row">
        <div class="col">
            <button id="getuser-btn">获取用户</button>
        </div>
        <div class="col">
            <button id="adduser-btn">添加用户</button>
        </div>
        <div class="col">
            <button id="deleteuser-btn">删除用户</button>
        </div>
        <div class="col">
            <button id="getcommonuser-btn">获取用户(common)</button>
        </div>
    </div>
    <div class="row" id="result-div"></div>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
    $(function() {
        $("#getuser-btn").on("click",function(){
            var userId = $("#userid-input").val();
            $.ajax({
                url: "user/getUser",
                data: {
                    userId: userId
                },
                dataType: "json",
                success: function(data){
                    $("#result-div").text("id[" + data.id + ", userName[" + data.userName + "], userPwd[" + data.userPwd + "]");
                },
                error: function(e){
                    $("#result-div").text("系统错误!");
                },
            })
        });
        $("#adduser-btn").on("click",function(){
            var userId = $("#userid-input").val();
            $.ajax({
                url: "user/addUser",
                data: {
                    id: userId
                },
                dataType: "json",
                success: function(data){
                    $("#result-div").text("id[" + data.id + ", userName[" + data.userName + "], userPwd[" + data.userPwd + "]");
                },
                error: function(e){
                    $("#result-div").text("系统错误!");
                },
            })
        });
        $("#deleteuser-btn").on("click",function(){
            var userId = $("#userid-input").val();
            $.ajax({
                url: "user/deleteUser",
                data: {
                    userId: userId
                },
                dataType: "json",
                success: function(data){
                    $("#result-div").text(data);
                },
                error: function(e){
                    $("#result-div").text("系统错误!");
                },
            })
        });
        $("#getcommonuser-btn").on("click",function(){
            var userId = $("#userid-input").val();
            $.ajax({
                url: "user/getCommonUser",
                data: {
                    userId: userId
                },
                dataType: "json",
                success: function(data){
                    $("#result-div").text("id[" + data.id + ", userName[" + data.userName + "], userPwd[" + data.userPwd + "]");
                },
                error: function(e){
                    $("#result-div").text("系统错误!");
                },
            })
        });
    });
</script>
</html>

 

 

3.测试

  a.访问 http://localhost:8080/项目名/,添加删除缓存

  b.结合控制台和RedisDesktopManager 查看Redis缓存情况

 

posted @ 2019-12-11 15:52  晨M风  阅读(680)  评论(0编辑  收藏  举报