3

我想使用来自网络服务的数据并将其放入骆驼 eh-cache 中。后来我想通过CacheManager在骆驼上下文之外使用这个缓存。我没有找到任何方法来做到这一点。

在下面的代码中,我跳过了 Web 服务的使用,并使用了 Map 中的数据并将其提供给 eh-cache,但我无法使用CacheManager访问此缓存。

CamelRouter 类

package com.camel;


import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.ehcache.EhcacheConstants;
import org.apache.camel.main.Main;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.Configuration;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.xml.XmlConfiguration;

public class Test {

    private static Main main;

    public static void main(String[] args) throws Exception {

        main = new Main();
        main.addRouteBuilder(new RouteBuilder() {

            @Override
            public void configure() throws Exception {
                from("timer:foo?period=5s&repeatCount=1")
                .process(exchange ->{
                    Map<String, String> inputMap = new HashMap<>();
                    inputMap.put("name", "murli");
                    inputMap.put("lastname", "hiware");
                    inputMap.put("city", "pune");
                    exchange.getIn().setBody(inputMap);
                    exchange.getIn().setHeader("CamelEhcacheAction", EhcacheConstants.ACTION_PUT_ALL);
                })
                .to("ehcache://testCache?configUri=ehcache.xml&keyType=java.lang.String&valueType=java.lang.String")
                .process(exchange -> {
                    URL myUrl = getClass().getResource("/ehcache.xml"); 
                    Configuration xmlConfig = new XmlConfiguration(myUrl); 
                    CacheManager myCacheManager = CacheManagerBuilder.newCacheManager(xmlConfig); 
                    myCacheManager.init();
                    //here I want to access already created testCache component but it is creating new one.
                    Cache<String, String> cache = myCacheManager.getCache("testCache", String.class, String.class);
                    System.out.println("Cache Element:"+cache.get("name"));
                    System.out.println("Exchange Message:"+exchange.getIn().getBody());

                });
            }
        });

         main.run();
    }

}

ehcache 配置文件

<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.xsd">

  <cache alias="testCache"> 
    <key-type>java.lang.String</key-type> 
    <value-type>java.lang.String</value-type> 
    <resources>
      <heap unit="entries">2000</heap> 
      <offheap unit="MB">100</offheap> 
    </resources>
  </cache>

  <cache-template name="myDefaults"> 
    <key-type>java.lang.Long</key-type>
    <value-type>java.lang.String</value-type>
    <heap unit="entries">200</heap>
  </cache-template>

  <cache alias="bar" uses-template="myDefaults"> 
    <key-type>java.lang.Number</key-type>
  </cache>

  <cache alias="simpleCache" uses-template="myDefaults" /> 

</config>

请让我知道我试图实现的用例是否可以使用camel eh-cache?

4

4 回答 4

4

您通常应该能够使用from("ehcache://...).

但是,我假设您确实想要访问缓存或缓存管理器。

这是这样做的方法:

public static void main(String[] args) throws Exception {
    URL url = App.class.getResource("/ehcache.xml");
    Configuration xmlConfig = new XmlConfiguration(url);

    CacheManager cacheManager = CacheManagerBuilder.newCacheManager(xmlConfig);
    cacheManager.init();

    Main main = new Main();
    main.bind("cacheManager", cacheManager);

    main.addRouteBuilder(new RouteBuilder() {

        @Override
        public void configure() throws Exception {
            from("timer:foo?period=5s&repeatCount=1")
                .process(exchange ->{
                    Map<String, String> inputMap = new HashMap<>();
                    inputMap.put("name", "murli");
                    inputMap.put("lastname", "hiware");
                    inputMap.put("city", "pune");
                    exchange.getIn().setBody(inputMap);
                    exchange.getIn().setHeader("CamelEhcacheAction", EhcacheConstants.ACTION_PUT_ALL);
                })
                .to("ehcache://testCache?cacheManager=#cacheManager&keyType=java.lang.String&valueType=java.lang.String")
                .process(exchange -> {
                    //here I want to access already created testCache component but it is creating new one.
                    Cache<String, String> cache = cacheManager.getCache("testCache", String.class, String.class);
                    System.out.println("Cache Element:"+cache.get("name"));
                    System.out.println("Exchange Message:"+exchange.getIn().getBody());

                });
        }
    });

    main.run();
}
于 2017-05-15T17:26:48.850 回答
3

您正在寻找的是:

  • CacheManager您可以从任何地方访问的存储库,包括从骆驼上下文
  • 或者你需要找到一种方法来暴露CacheCacheManager脱离上下文。

第一个是 Ehcache 2.x 的默认设置,它被设计为从 Ehcache 3.x 中删除。遗憾的是,我不太了解 Camel,因此无法推荐任何一种方式作为最佳方法。

于 2017-05-11T16:08:42.867 回答
2

您可以使用和 uri 设置缓存管理器,例如:

    to("ehcache:myCache?cacheManager=#myCacheManager")

其中 myCacheManager 是您在骆驼注册表上的 bean 的引用,作为示例,请查看:

于 2017-05-16T09:26:03.297 回答
0

当从 Spring Boot 到达 Camel-context 缓存时,我想分享这种方法@Service。因此,REST API 可以检索通过路由流式传输的最新值:

首先,我们确实将缓存添加为路由的附加目标点,但是,我们将传入的数据转换为显式地使其成为 String 对象,这是在最后一个之前的过程部分中完成的to()

  from(
                getMqttRouteConfiguration(
                        sourceId, mqttHost, mqttTopic, mqttPort, mqttProtocol, authenticated,
                        username, password, mqttVersion, maxReadRate, qualityOfService
                )
        )
                .to("log:camel.proxy?level=INFO&groupInterval=500000")
                .to(String.format("kafka:%s?brokers=%s", sourceId, kafkaBrokerUrls))
                .process(new Processor() {
                    @Override
                    public void process(Exchange exchange) throws Exception {
                     exchange.getIn().setBody(exchange.getIn().getBody(String.class));
                     exchange.getIn().setHeader("CamelCacheKey",sourceId);
                     exchange.getIn().setHeader("CamelCacheOperation","Update");
                    }
                })
                .to(String.format("cache://%s?maxElementsInMemory=10&eternal=true", sourceId))
                .routeId(sourceId);

@Service我们调用camelContext,然后使用“缓存”值检索所需的组件:

public Optional<String> cachedLastValue(String key) {
        CacheManager cacheManager = ((CacheComponent) camelContext.getComponent("cache")).getCacheManagerFactory().getInstance();
        Cache cache = cacheManager.getCache(key);
        if (cache != null) {
            Element valueElement = cache.
                    get(key);
            if (valueElement != null) {
                String value = (String) (valueElement.
                        getObjectValue());
                return Optional.of(value);
            } else {
                logger.warn("Cached value for {} topic was requested, but can not be retrieved from the cache: {} with key: {}", key, key, key);
            }
        } else {
            logger.info("Cached value for {} topic was requested, but not yet recorded from the source", key);
        }
        return Optional.empty();
    }

因此我们到达了 CacheManager 和 Cache 对象,这使我们能够查看所需的缓存名称并检索此处留下的最后一个值。

在这个解决方案之后仍然不清楚,我们是否可以使用相同的方法在缓存中存储大约 10 个值并检索所有这些值。此外,尚不清楚为什么如果没有明确调用

                     exchange.getIn().setBody(exchange.getIn().getBody(String.class));
                     exchange.getIn().setHeader("CamelCacheKey",sourceId);
                     exchange.getIn().setHeader("CamelCacheOperation","Update");

在将 String 对象放入缓存之前,我手动放置了交换主体,并明确设置了标头(我相信默认情况下它们应该由 Apache Camel Ehcache 添加,但我必须显式添加它们)。

于 2020-11-03T20:41:08.530 回答