Spring Framework 5和EhCache 3.5

8

我尝试在基于Spring Boot 2/Spring Framework 5的Web应用程序中使用EhCache 3.5缓存功能。

我添加了EHCache依赖:

    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>3.5.0</version>
    </dependency>
    <dependency>
        <groupId>javax.cache</groupId>
        <artifactId>cache-api</artifactId>
        <version>1.0.0</version>
    </dependency>

然后在src/main/resources文件夹中创建了ehcache.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
    monitoring="autodetect" dynamicConfig="true">

    <cache name="orders" maxElementsInMemory="100" 
        eternal="false" overflowToDisk="false" 
        memoryStoreEvictionPolicy="LFU" copyOnRead="true"
        copyOnWrite="true" />
</ehcache>

Spring 5参考指南没有提到EHCache的使用,而Spring 4参考指南则说明:"Ehcache 3.x完全符合JSR-107规范,不需要专门的支持。"

因此,我创建了OrderController控制器和REST端点:

@Cacheable("orders")
@GetMapping(path = "/{id}")
public Order findById(@PathVariable int id) {
    return orderRepository.findById(id);
}

Spring Boot配置:

@SpringBootApplication
@EnableCaching
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

但是,当我调用这个端点时,我会遇到一个异常:

找不到名称为“orders”的缓存,用于Builder[public org.Order org.OrderController.findById(int)] caches=[orders] | key='' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'

然后我尝试使用Spring Framework 4的示例:

@Bean
public CacheManager cacheManager() {
    return new EhCacheCacheManager(ehCacheCacheManager().getObject());
}

@Bean
public EhCacheManagerFactoryBean ehCacheCacheManager() {
    EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
    cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
    cmfb.setShared(true);
    return cmfb;
}

但是由于异常,它不能编译:

net.sf.ehcache.CacheManager类型无法解析。它是从所需的.class文件间接引用的。

请给予建议。

6个回答

13

这里有许多杂项。你正在使用的Ehcache 3是通过JCache与Spring一起使用的。

这就是为什么您需要使用spring.cache.jcache.config=classpath:ehcache.xml

然后,确实是一个Ehcache 2配置文件,EhCacheCacheManager也是如此。对于JCache,您应该使用JCacheCacheManager。但实际上,您甚至不需要它,只需一个ehcache.xml即可。

以下是使其正常工作的步骤:

步骤1:设置正确的依赖关系。请注意,您无需指定任何版本,因为它们由父POM依赖管理提供。javax.cache现在是1.1版本。

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
</dependency>
<dependency>
    <groupId>javax.cache</groupId>
    <artifactId>cache-api</artifactId>
</dependency>

步骤2:在src/main/resources中添加一个ehcache.xml文件。如下所示的一个示例。

<?xml version="1.0" encoding="UTF-8"?>
<config
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
    xmlns='http://www.ehcache.org/v3'
    xsi:schemaLocation="
        http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.5.xsd
        http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.5.xsd">

  <service>
    <jsr107:defaults enable-management="false" enable-statistics="true"/>
  </service>

  <cache alias="value">
    <resources>
      <heap unit="entries">2000</heap>
    </resources>
  </cache>
</config>

步骤3:需要一个包含此行的 application.properties 来找到 ehcache.xml

spring.cache.jcache.config=classpath:ehcache.xml
注意,由于类路径中找到了JCache,Spring Cache将选择它作为缓存提供程序。因此,无需指定spring.cache.type = jcache。
第4步:像您所做的那样启用缓存。
    @SpringBootApplication
    @EnableCaching
    public class Cache5Application {

        private int value = 0;

        public static void main(String[] args) {
            ApplicationContext context = SpringApplication.run(Cache5Application.class, args);
            Cache5Application app = context.getBean(Cache5Application.class);
            System.out.println(app.value());
            System.out.println(app.value());
        }

        @Cacheable("value")
        public int value() {
            return value++;
        }
    }

点赞。这在06/19中有效。我已经准备好了所有东西,除了javax.cache依赖项。 - Tirath

2
你需要强制使用ehcache版本2。
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.10.3</version>
</dependency>

要使用ehcache 3:

这是应用程序:

@SpringBootApplication
@EnableCaching
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

这里是application.yml文件。
spring:
  cache:
    ehcache:
      config: ehcache.xml

这里有一个带有计数器的测试服务。
@Service
public class OrderService {

    public static int counter=0;

    @Cacheable("orders")
    public Order findById(Long id) {
        counter++;
        return new Order(id, "desc_" + id);
    }
}

这里有一个测试来证明它正在使用缓存:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderServiceTest {

    @Autowired
    private OrderService orderService;

    @Test
    public void getHello() throws Exception {
        orderService.findById(1l);
        assertEquals(1, OrderService.counter);
        orderService.findById(1l);
        assertEquals(1, OrderService.counter);
        orderService.findById(2l);
        assertEquals(2, OrderService.counter);
    }
}

请查看此处的工作示例。


谢谢。是否有办法指定 ehcache.xml(而不是 jcache.xml)? - Sergiy

0
我进行了进一步的研究。Spring Boot(从application.properties)没有选择以下配置:
spring.cache.ehcache.config=classpath:ehcache.xml

所以我创建了jcache.xml文件,并将其放入src/main/resource文件夹中:

<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns='http://www.ehcache.org/v3'
    xsi:schemaLocation="
        http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd">

    <cache alias="orders">
        <key-type>org.springframework.cache.interceptor.SimpleKey</key-type>
        <value-type>java.util.Collections$SingletonList</value-type>
        <heap unit="entries">200</heap>
    </cache>
</config>

然后我在application.properties中更改了设置为

spring.cache.jcache.config=classpath:jcache.xml

现在Spring Caching运行正常。不过还有一个问题,就是如何获取ehcache.xml文件。


0

遇到了同样的问题。

  • 我的 ehcache.xml 文件如下:

    <config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
        xmlns='http://www.ehcache.org/v3'
        xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
        xsi:schemaLocation="
            http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
            http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">
      <service>
          <jsr107:defaults>
              <jsr107:cache name="vehicles" template="heap-cache" />
          </jsr107:defaults>
      </service>
      <cache-template name="heap-cache">
          <heap unit="entries">20</heap>
      </cache-template>
    </config>
    
  • application.properties 中配置了 spring.cache.jcache.config=classpath:ehcache.xml

  • 在我的应用程序类上使用了 @EnableCaching

  • 在我的服务实现上使用了 @CacheResult

@CacheResult(cacheName = "vehicles") public VehicleDetail getVehicle(@CacheKey String vehicleId) throws VehicleServiceException
请注意,我没有CacheManager bean。
如果有人能指出我错过了什么,那将非常有帮助。

0

嗯...将ehcache.xml更改为,就解决了问题..

<config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns='http://www.ehcache.org/v3'
    xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
    xsi:schemaLocation="
        http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
        http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">

    <service>
        <jsr107:defaults enable-management="true"
            enable-statistics="true" />
    </service>

    <cache alias="vehicles" uses-template="heap-cache" />

    <cache-template name="heap-cache">
        <heap unit="entries">20</heap>
    </cache-template>
</config>

0

在POM.XML中添加以下依赖项

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.6</version>
        <relativePath />
    </parent>
   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>3.10.8</version>
        </dependency>

请在Application.properties文件中添加以下行:
spring.cache.jcache.config=classpath:ehcache.xml

添加Ehcache.xml文件,然后在@SpringBootApplication文件中添加以下代码,并与@EnableCaching一起使用

@Bean
    public CacheManager cacheManager() {
      return new ConcurrentMapCacheManager("yourcacheName{must match with XML file}");
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接