引用:
JBoss Cache is a tree-structured, clustered, transactional cache. It can be used in a standalone, non-clustered environment, to cache frequently accessed data in memory thereby removing data retrieval or calculation bottlenecks while providing "enterprise" features such as JTA [http://java.sun.com/products/jta] compatibility, eviction and persistence.
JBoss Cache is also a clustered cache, and can be used in a cluster to replicate state providing a high degree of failover. A variety of replication modes are supported, including invalidation and buddy replication, and network communications can either be synchronous or asynchronous.
When used in a clustered mode, the cache is an effective mechanism of building high availability, fault tolerance and even load balancing into custom applications and frameworks. For example, the JBoss Application Server [http://www.jboss.org/projects/jbossas/] and Red Hat's Enterprise Application Platform [http://www.jboss.com] make extensive use of JBoss Cache to cluster services such as HTTP and EJB [http://java.sun.com/products/ejb/] sessions, as well as providing a distributed entity cache for JPA [http://en.wikipedia.org/wiki/Java_Persistence_API].
JBoss Cache can - and often is - used outside of JBoss AS, in other Java EE environments such as Spring, Tomcat, Glassfish, BEA WebLogic, IBM WebSphere, and even in standalone Java programs thanks to its minimal dependency set.
示例:
jboss-cache-config-single.xml
<span style="font-size:12px;"><?xml version="1.0" encoding="UTF-8"?> <!-- ===================================================================== --> <!-- Sample TreeCache Service Configuration --> <!-- ===================================================================== --> <server> <!-- ==================================================================== --> <!-- Defines TreeCache configuration --> <!-- ==================================================================== --> <mbean code="org.jboss.cache.jmx.CacheJmxWrapper" name="jboss.cache:service=TreeCache"> <depends>jboss:service=Naming</depends> <depends>jboss:service=TransactionManager</depends> <!-- Configure the TransactionManager --> <attribute name="TransactionManagerLookupClass">org.jboss.cache.transaction.GenericTransactionManagerLookup </attribute> <!-- Isolation level : SERIALIZABLE REPEATABLE_READ (default) READ_COMMITTED READ_UNCOMMITTED NONE --> <attribute name="IsolationLevel">REPEATABLE_READ</attribute> <!-- Valid modes are LOCAL REPL_ASYNC REPL_SYNC INVALIDATION_ASYNC INVALIDATION_SYNC --> <attribute name="CacheMode">LOCAL</attribute> <!-- Just used for async repl: use a replication queue --> <attribute name="UseReplQueue">false</attribute> <!-- Replication interval for replication queue (in ms) --> <attribute name="ReplQueueInterval">0</attribute> <!-- Max number of elements which trigger replication --> <attribute name="ReplQueueMaxElements">0</attribute> <!-- Name of cluster. Needs to be the same for all TreeCache nodes in a cluster in order to find each other. --> <attribute name="ClusterName">JBossCache-Cluster</attribute> <!-- Whether or not to fetch state on joining a cluster NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive. --> <attribute name="FetchInMemoryState">true</attribute> <!-- The max amount of time (in milliseconds) we wait until the state (ie. the contents of the cache) are retrieved from existing members in a clustered environment --> <attribute name="StateRetrievalTimeout">15000</attribute> <!-- Number of milliseconds to wait until all responses for a synchronous call have been received. --> <attribute name="SyncReplTimeout">15000</attribute> <!-- Max number of milliseconds to wait for a lock acquisition --> <attribute name="LockAcquisitionTimeout">10000</attribute> <!-- Indicate whether to use region based marshalling or not. Set this to true if you are running under a scoped class loader, e.g., inside an application server. Default is "false". --> <attribute name="UseRegionBasedMarshalling">true</attribute> </mbean> </server></span>
CacheManager.java
package shuai.study.jbossCache; import java.io.Serializable; import java.util.logging.Level; import java.util.logging.Logger; import org.jboss.cache.Cache; import org.jboss.cache.DefaultCacheFactory; import org.jboss.cache.Fqn; import org.jboss.cache.Node; import org.jboss.cache.config.Configuration; import org.jboss.cache.config.Configuration.CacheMode; import org.jboss.cache.util.CachePrinter; /** * CacheManager. * * @author Zhou Shengshuai * @since 10-Mar-2015 */ public class CacheManager { private static final Logger LOGGER = Logger.getLogger(CacheManager.class.getName()); private static CacheManager cacheManager = null; private static Cache<String, Serializable> cache = null; private static final String CONFIGURATION_FILE = "jboss-cache-config-single.xml"; private static final String CLUSTER_NAME = "JBossCacheDemo"; private static Node<String, Serializable> rootNode = null; private static final String NODE_NAME = "Node Name"; private static final String LOCAL = "LOCAL"; private static final String KEY = "Key"; private static final String VALUE = "Value"; private static final int MAX_RETRY_COUNT = 5; /** * Creates a cache if it is not existing. */ private CacheManager() { if (cache == null) { cache = new DefaultCacheFactory<String, Serializable>().createCache(CONFIGURATION_FILE, false); initCache(); } } /** * Singleton for CacheManager * * @return */ public static CacheManager getInstance() { if (cacheManager == null) { cacheManager = new CacheManager(); } return cacheManager; } /** * Creates a cache */ private void initCache() { Cache<String, Serializable> cache = getCache(); Configuration configuration = cache.getConfiguration(); configuration.setCacheMode(CacheMode.valueOf(LOCAL)); configuration.setClusterName(CLUSTER_NAME); LOGGER.log(Level.INFO, "Created Cache with Name : {0} :: Mode :: {1} ", new Object[] { configuration.getClusterName(), configuration.getCacheMode() }); cache.start(); rootNode = cache.getRoot(); } /** * Gets the cache instance. * * @return instance of cache. */ Cache<String, Serializable> getCache() { return cache; } /** * Gets the value from the cache for the specified key. * * @param qualifiedNodeName * the complete node name from which you want to fetch * the value for a given key * @param key * the key * @return the value associated for the key */ public Serializable get(String qualifiedNodeName, String key) { nullCheck(KEY, key); Node<String, Serializable> node = getNode(qualifiedNodeName); if (node == null) { return null; } return node.get(key); } /** * Put key value pair in the cache. * * @param qualifiedNodeName * the complete node name against which you want to put * the key-value pair * @param key * the key * @param value * the value * @param overwrite * true if the value can be overwritten otherwise * false. */ public void put(String qualifiedNodeName, String key, Serializable value, boolean overwrite) { nullCheck(KEY, key); nullCheck(VALUE, value); nullCheck(NODE_NAME, qualifiedNodeName); put(qualifiedNodeName, key, value, 1, overwrite); } /** * method to find out whether a node exists or not. * * @param qualifiedNodeName * node name * @return boolean indicating whether node exists or not. */ public boolean nodeExists(String qualifiedNodeName) { nullCheck(NODE_NAME, qualifiedNodeName); return rootNode.hasChild(Fqn.fromString(qualifiedNodeName)); } /** * Gets the node of specified name. * * @param qualifiedNodeName * the fqn. * @return the node. */ public Node<String, Serializable> getNode(String qualifiedNodeName) { return rootNode.getChild(Fqn.fromString(qualifiedNodeName)); } /** * Deletes the specified node * * @param node * to be deleted */ public void removeNode(String qualifiedNodeName) { nullCheck(NODE_NAME, qualifiedNodeName); removeNode(qualifiedNodeName, 1); } /** * Puts the value to the given qualifiedNodeName * * @param qualifiedNodeName * @param key * @param value * @param attemptNumber * @param overwrite */ private void put(String qualifiedNodeName, String key, Serializable value, int attemptNumber, boolean overwrite) { try { Node<String, Serializable> node = getNode(qualifiedNodeName); if (node == null) { node = createNode(qualifiedNodeName); } if (overwrite) { node.put(key, value); } else { node.putIfAbsent(key, value); } } catch (RuntimeException runtimeException) { if (attemptNumber == MAX_RETRY_COUNT) { LOGGER.log(Level.SEVERE, "Exception occured while storing value: " + value + " with key: " + key + " at node " + qualifiedNodeName + " due to " + runtimeException.getMessage(), runtimeException); return; } LOGGER.log(Level.WARNING, "Retry [{0}] for storing value: {1} with key: {2} at node {3} due to {4}", new Object[] { attemptNumber, value, key, qualifiedNodeName, runtimeException.getMessage() }); put(qualifiedNodeName, key, value, attemptNumber++, overwrite); } } /** * Removes the node * * @param qualifiedNodeName * @param attemptNumber */ private void removeNode(String qualifiedNodeName, int attemptNumber) { nullCheck(NODE_NAME, qualifiedNodeName); try { rootNode.removeChild(Fqn.fromString(qualifiedNodeName)); } catch (RuntimeException runtimeException) { if (attemptNumber == MAX_RETRY_COUNT) { LOGGER.log(Level.SEVERE, "Exception occured while removing node: " + qualifiedNodeName + " due to " + runtimeException.getMessage(), runtimeException); return; } LOGGER.log(Level.WARNING, "Retry [{0}] for removing node: {1} due to {2}", new Object[] { attemptNumber, qualifiedNodeName, runtimeException.getMessage() }); removeNode(qualifiedNodeName, attemptNumber++); } } /** * Creates a new node * * @param qualifiedNodeName * @return */ private Node<String, Serializable> createNode(String qualifiedNodeName) { return rootNode.addChild(Fqn.fromString(qualifiedNodeName)); } /** * Used to check if the node exists or not * * @param msg * @param obj */ private void nullCheck(String msg, Object obj) { if (obj == null || obj.toString().trim().length() == 0) { IllegalArgumentException e = new IllegalArgumentException(msg + " needs to be specified"); LOGGER.log(Level.SEVERE, e.getMessage(), e); throw e; } } /** * Reset the cache reference. SHOULD BE USED ONLY IN JUNITS. */ static void resetCache() { cache = null; } /** * Prints the contents of the cache (nodes + data) to a string * * @return a String representation of the cache */ public String printCacheDetails() { return CachePrinter.printCacheDetails(cache); } }
Main.java
package shuai.study.jbossCache; import java.util.logging.Level; import java.util.logging.Logger; public class Main { private static final Logger LOGGER = Logger.getLogger(Main.class.getName()); public static void main(String[] args) { CacheManager cacheManager = CacheManager.getInstance(); cacheManager.put("NAME", "cnName", "Shuai", false); cacheManager.put("NAME", "enName", "Tom", true); LOGGER.log(Level.INFO, cacheManager.get("NAME", "cnName").toString()); LOGGER.log(Level.INFO, cacheManager.get("NAME", "enName").toString()); } }