ehcache + spring 整合以及配置说明 ,附带整合问题 (已解决)

新做的项目,因为流量不大 就是一个征信平台,高峰流量不多,但缓存是必须的,cache到server上就可以,不需要额外的memcache、redis之类的东西。

但是遇到一个大坑,事情是这样的:

通过阅读大量教程,官方文档所知,该缓存框架是java进程内的缓存,开发便捷,缺点就是java kill掉后缓存就消失了,不会想其他缓存框架可以独立于JAVA程序外。

总结起来就是以下几点,特此记录

1:我配置好ehcache缓存框架,如下所示:重点就是cache name 

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="es">

    <diskStore path="java.io.tmpdir"/>
    <!--1 timeToIdleSeconds ,多长时间不访问该缓存,那么ehcache 就会清除该缓存.

    2 timeToLiveSeconds ,缓存的存活时间,从开始创建的时间算起.

    3 eternal 缓存是否持久

    4 overflowToDisk 是否保存到磁盘,当系统宕机时 -->

    <defaultCache
            maxEntriesLocalHeap="1000"
            eternal="false"
            timeToIdleSeconds="3600"
            timeToLiveSeconds="3600"
            overflowToDisk="false">
    </defaultCache>

    <cache name="cisReportRoot"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           overflowToDisk="false"
           statistics="true">
    </cache>

    <cache name="user"
           maxEntriesLocalHeap="2000"
           eternal="false"
           timeToIdleSeconds="600"
           timeToLiveSeconds="600"
           overflowToDisk="false"
           statistics="true">
    </cache>

</ehcache>

2: 开始配置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:cache="http://www.springframework.org/schema/cache"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"

       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/cache
        http://www.springframework.org/schema/cache/spring-cache-4.3.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">

    <context:component-scan base-package="com.xxxx.credit.*"/>
    <cache:annotation-driven/>
    <!-- 使用全注释事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <!-- cacheManager, 指定ehcache.xml的位置 -->
    <bean id="ehcacheManager" 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="ehcacheManager"/>
        <property name="transactionAware" value="true"/>
    </bean>

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:jdbc.properties"/>
    </bean>

    <!-- 数据源配置, 使用应用中的DBCP数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
          destroy-method="close">
        <!-- Connection Info -->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>

        <!-- Connection Pooling Info -->
        <property name="maxActive" value="${dbcp.maxActive}"/>
        <property name="maxIdle" value="${dbcp.maxIdle}"/>
        <property name="defaultAutoCommit" value="false"/>

        <!-- 连接Idle一个小时后超时 -->
        <property name="timeBetweenEvictionRunsMillis" value="3600000"/>
        <property name="minEvictableIdleTimeMillis" value="3600000"/>
    </bean>

    <!-- spring和MyBatis整合 -->
    <bean id="sqlSessionFactory"
          class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!-- 自动扫描Mapper.xml文件 -->
        <property name="mapperLocations" value="classpath:mybatis/*Mapper.xml"/>
    </bean>

    <!-- DAO接口所在包名,Spring会自动查找其下的类 -->
    <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.pingan.credit.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory"/>
    </bean>

    <!-- 事务管理 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- 懒加载 -->
    <bean id="jacksonObjectMapper" class="com.pingan.credit.model.MyJsonMapper" />

</beans>

 

4:然后写一个简单的bean,service 做测试验证配置是否正确:

Bean

package com.pingan.credit.model;

import java.io.Serializable;

public class User implements Serializable {
    private Long id;
    private String username;
    private String email;

    public User() {
    }
    public User(Long id, String username, String email){
        this.id = id;
        this.username = username;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (id != null ? !id.equals(user.id) : user.id != null) return false;

        return true;
    }

    @Override
    public int hashCode() {
        return id != null ? id.hashCode() : 0;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", email='" + email + '\'' +
                '}';
    }
}
View Code

Service:

package com.xxxx.credit.service;


import com.xxxx.credit.model.User;
import org.apache.log4j.Logger;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;


@Service("userService")
public class UserService {

    private static Logger logger = Logger.getLogger(UserService.class);
    Set<User> users = new HashSet<User>();

    @CachePut(value = "user", key = "#user.id")
    public User save(User user) {
        users.add(user);
        logger.info(user.toString());
        return user;
    }

    @CachePut(value = "user", key = "#user.id")
    public User update(User user) {
        users.remove(user);
        users.add(user);
        return user;
    }

    @CacheEvict(value = "user", key = "#user.id")
    public User delete(User user) {
        users.remove(user);
        return user;
    }

    @CacheEvict(value = "user", allEntries = true)
    public void deleteAll() {
        users.clear();
    }

    @Cacheable(value = "user", key = "#id")
    public User findById(final Long id) {
        System.out.println("cache miss, invoke find by id, id:" + id);
        for (User user : users) {
            if (user.getId().equals(id)) {
                return user;
            }
        }
        return null;
    }

}

然后开始测试:

    @Test
    public void testCacheUser() {
        System.out.println("test cache()");
        Long id = 1L;
        User user = new User(id, "zhang333", "zhang@gmail.com");
        User save = userService.save(user);
        junit.framework.TestCase.assertEquals(true,user==save);
        System.out.println("123");
        User result = userService.findById(id);
    }

通过验证:  缓存正常输出  ,也理解通过UserService中@Cacheable注解后,不会进入方法体内,也就是说不会有sysout.out.println()这句输出

直接返回save方法中 save() 方法return的值

也就是说 save方法 会缓存 return的那个user

好了 道理都懂了 junit也测过了 差不许多可以开始上测试服务器了

这个时候,折磨了我4个小时的问题来了,

我在本地一切问题都没有,但是通过post man(http 请求工具)就是拿不到缓存数据,当时总觉得是缓存框架配置的有问题,但恰恰并不是

原因在这:spring-mvc.xml

<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-4.3.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context-4.3.xsd
                        http://www.springframework.org/schema/mvc
                        http://www.springframework.org/schema/mvc/spring-mvc.xsd">


    <!--自动扫描,注解控制器 -->
    <context:component-scan base-package="com.xxxx.credit.*"/>

    <!--注解驱动 -->
    <mvc:annotation-driven/>

    <!--静态资源映射-->
    <!--本项目把静态资源放在了WEB-INF的statics目录下,资源映射如下-->
    <mvc:resources mapping="/css/**" location="/WEB-INF/statics/css/"/>
    <mvc:resources mapping="/js/**" location="/WEB-INF/statics/js/"/>
    <mvc:resources mapping="/image/**" location="/WEB-INF/statics/image/"/>

    <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀(如果最后一个还是表示文件夹,则最后的斜杠不要漏了) 使用JSP-->
    <!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- -->
    <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/"/><!--设置JSP文件的目录位置-->
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- springMvc文件上传需要配置的节点-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="20971500"/><!--设置JSP文件的目录位置-->
        <property name="defaultEncoding" value="UTF-8"/><!--设置默认编码-->
        <property name="resolveLazily" value="true"/><!--启用是为了推迟文件解析,以便捕获文件大小异常-->
    </bean>


</beans>

但是更改成:

<context:component-scan base-package="com.pingan.xxxx.controller"/>

就没有问题了,擦 折腾了我4个小时的问题终于找到了,魔鬼细节啊 魔鬼细节啊  魔鬼细节啊 还是马虎造成的,如次简单的问题又耗费了大量的时间

谨记

 

posted @ 2017-08-23 11:34  showme1942  阅读(205)  评论(0编辑  收藏  举报