Spring MVC - 应用程序级缓存
Spring MVC - caching at application level
我正在使用 Spring MVC 开发在 AngularJS 中开发的单页应用程序。
第一个请求是登录服务,然后我调用服务 A、B 和 C
生成我在客户端构建页面所需的数据。
在这些服务 A、B 和 C 中的每一个中,都需要调用一些 DAO - 从数据库中获取数据。
DAO 名称是 X.
现在,当用户在应用程序中导航时,他一次又一次地调用这些服务,
而且我不会每次都去数据库。
我只想在登录时访问数据库一次(就此而言 - 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;
}
}
我的问题是这是正确的解决方案吗?
因为应用程序以这种方式将数据保存在内存中看起来像是糟糕的设计..
谁能提出更好的解决方案?
希望我说得够清楚了。
谢谢
你可以去Ehcache。
检查 this link,其中简要介绍了网页缓存。
在您的情况下,您可以在 web.xml 中定义类似的内容,这将特定于登录 -
<filter-mapping>
<filter-name>SimplePageCachingFilter</filter-name>
<url-pattern>/login/*</url-pattern>
</filter-mapping>
因此,一旦您的网页被加载 post 网络服务调用,它就会被缓存。
您可以缓存来自使用 @Cacheable
注释的方法的结果。这是一种简洁的优化机制,无需编写整个负载的 HashMap get()、put() 逻辑。
要使用它,您需要定义 CacheManager
并启用缓存。这是一个使用基于 Java 的配置的独立示例。 Spring documentation.
中的更多信息
但是,鉴于您的结果最终来自 DAO,您可能应该使用 EH-cache、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
}
}
输出
Called for foo
[foo...]
Called for bar
[bar...]
[foo...]
我正在使用 Spring MVC 开发在 AngularJS 中开发的单页应用程序。
第一个请求是登录服务,然后我调用服务 A、B 和 C 生成我在客户端构建页面所需的数据。
在这些服务 A、B 和 C 中的每一个中,都需要调用一些 DAO - 从数据库中获取数据。 DAO 名称是 X.
现在,当用户在应用程序中导航时,他一次又一次地调用这些服务, 而且我不会每次都去数据库。 我只想在登录时访问数据库一次(就此而言 - 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;
}
}
我的问题是这是正确的解决方案吗? 因为应用程序以这种方式将数据保存在内存中看起来像是糟糕的设计.. 谁能提出更好的解决方案?
希望我说得够清楚了。 谢谢
你可以去Ehcache。
检查 this link,其中简要介绍了网页缓存。
在您的情况下,您可以在 web.xml 中定义类似的内容,这将特定于登录 -
<filter-mapping>
<filter-name>SimplePageCachingFilter</filter-name>
<url-pattern>/login/*</url-pattern>
</filter-mapping>
因此,一旦您的网页被加载 post 网络服务调用,它就会被缓存。
您可以缓存来自使用 @Cacheable
注释的方法的结果。这是一种简洁的优化机制,无需编写整个负载的 HashMap get()、put() 逻辑。
要使用它,您需要定义 CacheManager
并启用缓存。这是一个使用基于 Java 的配置的独立示例。 Spring documentation.
但是,鉴于您的结果最终来自 DAO,您可能应该使用 EH-cache、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
}
}
输出
Called for foo
[foo...]
Called for bar
[bar...]
[foo...]