首页 > 代码库 > 采用Spring实现在容器启动时把用ConcurrentHashMap实现的并发缓存加载到ServletContext中

采用Spring实现在容器启动时把用ConcurrentHashMap实现的并发缓存加载到ServletContext中

1.ConstantDataDTO.java,一定要重写hashcode和equals方法

import java.io.Serializable;
import java.util.Date;

/**
 * ConstantDataDTO.java
 * 
 * @author steveguoshao
 * @created 2014年07月10日 下午6:15:55
 * @version 1.0
 */
public class ConstantDataDTO implements Serializable {

	/**
	 * serialVersionUID:TODO
	 * 
	 * @since 1.0.0
	 */
	private static final long serialVersionUID = -504215100856069620L;

	private String codeSet;

	private String code;

	private String codeContent;

	private String parentCode;

	private Integer seqNum;

	private Date cjsj;

	private Date xgsj;

	public String getCodeSet() {
		return codeSet;
	}

	public void setCodeSet(String codeSet) {
		this.codeSet = codeSet;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getCodeContent() {
		return codeContent;
	}

	public void setCodeContent(String codeContent) {
		this.codeContent = codeContent;
	}

	public String getParentCode() {
		return parentCode;
	}

	public void setParentCode(String parentCode) {
		this.parentCode = parentCode;
	}

	public Integer getSeqNum() {
		return seqNum;
	}

	public void setSeqNum(Integer seqNum) {
		this.seqNum = seqNum;
	}

	public Date getCjsj() {
		return cjsj;
	}

	public void setCjsj(Date cjsj) {
		this.cjsj = cjsj;
	}

	public Date getXgsj() {
		return xgsj;
	}

	public void setXgsj(Date xgsj) {
		this.xgsj = xgsj;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((code == null) ? 0 : code.hashCode());
		result = prime * result + ((codeSet == null) ? 0 : codeSet.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		ConstantDataDTO other = (ConstantDataDTO) obj;
		if(other.getCode().equals(code) && other.getCodeSet().equals(codeSet)) {
			return true;
		} 
		return false;
	}

	
}

2.用ConcurrentHashMap实现缓存ConstantDataCache,刚开始虽然用的是ConcurrentHashMap当数据容器,但是各方法里面的操作并不是采用ConcurrentMap接口里面的方法,而是采用Map接口里面的方法,而且各操作并不是原子的,所以并不能实现并发,还是会出现ConcurrentModificationException,要实现并发必须要用ConcurrentMap接口里面的方法。

ConcurrentMap代码如下,注意接口里面每个方法的注释,里面写了等同于原先采用Map接口里面的方法实现代码

public interface ConcurrentMap<K, V> extends Map<K, V> {
    /**
     * If the specified key is not already associated
     * with a value, associate it with the given value.
     * This is equivalent to
     * <pre>
     *   if (!map.containsKey(key))
     *       return map.put(key, value);
     *   else
     *       return map.get(key);</pre>
     *
     */
    V putIfAbsent(K key, V value);

    /**
     * Removes the entry for a key only if currently mapped to a given value.
     * This is equivalent to
     * <pre>
     *   if (map.containsKey(key) && map.get(key).equals(value)) {
     *       map.remove(key);
     *       return true;
     *   } else return false;</pre>
     */
    boolean remove(Object key, Object value);

    /**
     * Replaces the entry for a key only if currently mapped to a given value.
     * This is equivalent to
     * <pre>
     *   if (map.containsKey(key) && map.get(key).equals(oldValue)) {
     *       map.put(key, newValue);
     *       return true;
     *   } else return false;</pre>
     */
    boolean replace(K key, V oldValue, V newValue);

    /**
     * Replaces the entry for a key only if currently mapped to some value.
     * This is equivalent to
     * <pre>
     *   if (map.containsKey(key)) {
     *       return map.put(key, value);
     *   } else return null;</pre>
     */
    V replace(K key, V value);
}

ConstantDataCache.java

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * ConstantDataCache.java
 * @author 	  steveguoshao	
 * @created   2014年07月10日 下午2:54:46
 * @version   1.0
 */
@Component
@Scope(value=http://www.mamicode.com/"singleton")>
3.实现InitializingBean接口让Spring容器在启动的时候能够加载数据,实现ServletContextAware接口能够通过AOP获取ServletContext,从而实现把缓存放到application中。

SystemDataBean.java


import javax.servlet.ServletContext;
import javax.sql.DataSource;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.ServletContextAware;

/**
 * CacheBean.java
 * @author    steveguoshao	
 * @created   2014年07月10日 下午3:36:13
 * @version   1.0
 */
@Component
public class SystemDataBean implements InitializingBean,ServletContextAware {

	private ServletContext servletContext;
	@Override
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}
	
	@Autowired
	private ConstantDataCache dataCache;
	
	@Autowired
	private DataSource dataSource;
	
	@Override
	public void afterPropertiesSet() throws Exception {
		// 把缓存放入到servletcontext
		servletContext.setAttribute(Constants.CACHE, dataCache.getCache());
		servletContext.setAttribute(Constants.DATA_SOURCE, dataSource);
	}

}