Java Spring MVC-应用程序级缓存

Java Spring MVC-应用程序级缓存,java,spring-mvc,caching,request,single-page-application,Java,Spring Mvc,Caching,Request,Single Page Application,我将SpringMVC用于AngularJS开发的单页应用程序 第一个请求是登录服务,然后我调用服务A、B和C 生成客户端中构建页面所需的数据 在这些服务中的每一个服务A、B和C都需要调用一些DAO,这些DAO从数据库中带来数据。 DAO的名称是X 现在,当用户在应用程序中导航时,他会一次又一次地调用这些服务, 我不想每次都去DB。 在进行登录时,我只想进入数据库一次(对于matther-dao'X'),并将数据保存在一些缓存中 我的解决方案是将来自MAP中X的数据保存到某个bean中: @Co

我将SpringMVC用于AngularJS开发的单页应用程序

第一个请求是登录服务,然后我调用服务A、B和C 生成客户端中构建页面所需的数据

在这些服务中的每一个服务A、B和C都需要调用一些DAO,这些DAO从数据库中带来数据。 DAO的名称是X

现在,当用户在应用程序中导航时,他会一次又一次地调用这些服务, 我不想每次都去DB。 在进行登录时,我只想进入数据库一次(对于matther-dao'X'),并将数据保存在一些缓存中

我的解决方案是将来自MAP中X的数据保存到某个bean中:

@Component
public class XUtility {


    private Map<String, List<String>> xcache = new ArrayList<String>();


     // this method is being called only after login
    public void initX_Cache(String key) {
         if (xcache.containsKey(key)) {
             xcache.remove(key);
         }
    }
    // this method is called many times from service A,B,C..
    public List<String> getX(String key) {

        List<String> values = xcache.get(key);
        if (values != null) {
            return values;
        }
        List<String> vals = new ArrayList<String>();


        //daos = call the Database ... 

        for (DAOObeject dao : daos) {
            vals.add(dao.getKey());
        }
        xcache.put(key, vals); // save in cache the
        return vals;
    }


}
@组件
公共类效用{
私有映射xcache=newArrayList();
//只有在登录后才调用此方法
公共void initX_缓存(字符串键){
if(xcache.containsKey(键)){
xcache.remove(键);
}
}
//此方法在服务A、B、C中被多次调用。。
公共列表getX(字符串键){
列表值=xcache.get(键);
如果(值!=null){
返回值;
}
List vals=new ArrayList();
//daos=调用数据库。。。
for(daoobject-dao:daos){
add(dao.getKey());
}
xcache.put(key,vals);//保存在缓存中
返回VAL;
}
}
我的问题是这是正确的解决方案吗? 因为应用程序以这种方式将数据保存在内存中看起来像是糟糕的设计。。 有谁能提出更好的解决方案吗

希望我说得够清楚。 谢谢。

你可以去Ehcache。 检查简要介绍网页缓存的链接。
在您的案例中,您可以在web.xml中定义类似的内容,该内容将特定于登录-


SimplePageCachingFilter
/登录/*


因此,在web服务调用后加载网页后,它将被缓存。

您可以使用
@Cacheable
注释缓存方法的结果。这是一种简洁的优化机制,无需编写全部HashMap get()、put()逻辑

要使用它,需要定义
CacheManager
,并启用缓存。下面是一个使用基于Java的配置的自包含示例。更多信息请参阅

然而,鉴于您的结果最终来自DAOs,您可能应该使用EH缓存、Terracotta等,因为这可以在实体级别进行缓存,从而允许在整个应用程序中重用实体

public class CacheTest {
    public static class Service {
        @Cacheable("horseCache")
        public List<String> getX(String key) {
            System.out.println("Called for " + key);
            return Arrays.asList(key + "...");
        }
    }

    @Configuration
    @EnableCaching
    public static class Config {
        @Bean
        public CacheManager cacheManager() {
            SimpleCacheManager cacheManager = new SimpleCacheManager();
            cacheManager.setCaches(Arrays.asList(new ConcurrentMapCache("horseCache")));
            return cacheManager;
        }
    }

    public static void main(String[] args) {
        // Inline application context definition to support self-contained example
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(Service.class);
        GenericBeanDefinition configDefition = new GenericBeanDefinition();
        configDefition.setBeanClass(Config.class);
        context.registerBeanDefinition("bean", beanDefinition);
        context.registerBeanDefinition("config", configDefition);
        context.refresh();

        // actual example
        Service bean = context.getBean(Service.class);
        System.out.println(bean.getX("foo"));
        System.out.println(bean.getX("bar"));
        System.out.println(bean.getX("foo")); // demonstrate 2nd call is cached
    }

}

您正在将基础架构代码与业务逻辑混合在一起。这些应该完全分开。最简单的方法是使用spring提供的缓存抽象。根据您的spring版本,请参考相应的spring缓存示例。
Called for foo
[foo...]
Called for bar
[bar...]
[foo...]