折腾了2天。
看spring in action看到一半,觉得搭一套这个东西,只是书上的很多描述并不具体,而且它的spring是2.0的......因此各种搜索.....最后终于完成。
spring里面的ehcache是通过aop实现的,而aop又是通过委托实现的,委托简单说是通过组合来实现的;因此这里就会存在一个问题,通过组合得到的一个新类型是没有类型信息的;因此,想要引用这个委托出来的新类,必须通过接口,在这里折腾了一下午,各种看源码才发现....
说一下总体思路:
1. 建立数据库表
2. 根据数据库表结构构造一个数据类,通过这个类和hibernate来进行交互,使用注解的方式避免过多的xml文件
3. 构建数据交互接口,用于描述和数据库交互的方式
4. 通过expends HibernateDaoSupport 构造hibernate处理类
5. 在4构造的类中添加对ehcache的支持,避免直接操作数据库
1. webx-spring.xml 主xml,配置spring的各种必须信息
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ehcache="http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd ;
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd ;
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd ;
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ;
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring
http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.1.xsd"
default-autowire="byName">
<ehcache:annotation-driven />
<ehcache:config cache-manager="cacheManager">
<ehcache:evict-expired-elements interval="60" />
</ehcache:config>
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
<property name="configLocation" value="spring/test/hello/ehcache.xml"/>
</bean>
<bean id="AopUpdate" class="spring.test.hello.AopUpdate"></bean>
<bean id="aopTest" class="spring.test.hello.AopTest"></bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://127.0.0.1:3306/test" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>spring.test.hello.User</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="hiberTest" class="spring.test.hello.HiberTest">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:aspectj-autoproxy/>
</beans>
2. ehcache.xml。缓存描述xml文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<defaultCache eternal="true" maxElementsInMemory="100" overflowToDisk="false" />
<cache name="userCache" maxElementsInMemory="10" eternal="true" overflowToDisk="false" />
</ehcache>
3. DataIn.java 数据调用接口
package spring.test.hello;
import java.util.List;
public interface DataIn
{
public void update(User user);
public List query(String id);
public void delete(String id);
}
4. HiberTest.java。spring提供的hibernate支持类实现。
package spring.test.hello;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.googlecode.ehcache.annotations.Cacheable;
import com.googlecode.ehcache.annotations.TriggersRemove;
import com.googlecode.ehcache.annotations.When;
import java.util.*;
public class HiberTest extends HibernateDaoSupport
implements DataIn
{
@TriggersRemove
(cacheName = "userCache", when = When.BEFORE_METHOD_INVOCATION, removeAll = true)
public void update(User user)
{
getHibernateTemplate().save(user);
}
@Cacheable(cacheName = "userCache")
public List query(String id)
{
return getHibernateTemplate().find("from User where id=?", id);
}
@TriggersRemove
(cacheName = "userCache", when = When.BEFORE_METHOD_INVOCATION, removeAll = true)
public void delete(String id)
{
getHibernateTemplate().delete(getHibernateTemplate().get(User.class, id));
}
}
5. User.java。使用这个类映射数据库表
package spring.test.hello;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "vip_info")
public class User
{
String id;
String name;
String password;
User(String id, String name,
String password)
{
this.id = id;
this.name = name;
this.password = password;
}
//needed by hibernate
User() {}
@Id
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}
6. HelloApp.java 测试文件
package spring.test.hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.*;
public class HelloApp
{
public static void main(String[] args) throws Exception
{
ApplicationContext ctx =
new ClassPathXmlApplicationContext("spring/test/hello/webx-spring.xml");
System.out.println("start");
ctx.getBean(DataIn.class).update(new User("1.266", "test", "123"));
List lis = ctx.getBean(DataIn.class).query("124");
for (Object tmp : lis)
{
User user = (User) tmp;
System.out.println(user.getId() + " "
+ user.getName() + " " + user.getPassword());
}
lis = ctx.getBean(DataIn.class).query("124");
for (Object tmp : lis)
{
User user = (User) tmp;
System.out.println(user.getId() + " "
+ user.getName() + " " + user.getPassword());
}
ctx.getBean(DataIn.class).update(new User("1.28", "test", "123"));
lis = ctx.getBean(DataIn.class).query("124");
for (Object tmp : lis)
{
User user = (User) tmp;
System.out.println(user.getId() + " "
+ user.getName() + " " + user.getPassword());
}
//ctx.getBean(DataIn.class).delete("13");
}
}
7. maven 依赖文件
<dependency>
<groupId>com.googlecode.ehcache-spring-annotations</groupId>
<artifactId>ehcache-spring-annotations</artifactId>
<version>1.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>transaction-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.1.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.2.0.ga</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjlib</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.5.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.22</version>
</dependency>
8. 数据库建表语句
/*
Navicat MySQL Data Transfer
Source Server : localhost_3306_1
Source Server Version : 50520
Source Host : localhost:3306
Source Database : test
Target Server Type : MYSQL
Target Server Version : 50520
File Encoding : 65001
Date: 2013-01-05 19:51:34
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for `vip_info`
-- ----------------------------
DROP TABLE IF EXISTS `vip_info`;
CREATE TABLE `vip_info` (
`id` varchar(50) NOT NULL,
`name` varchar(50) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of vip_info
-- ----------------------------
INSERT INTO `vip_info` VALUES ('1', '2', '24242');
总结,java中的工具,框架确实很多,很强大,只是用起来并不是那么轻松,无论是版本问题还是配置的便利性上,都很麻烦。不过搭建这么一套东西还是蛮有成就感的。
maven更新依赖时速度很慢,各种卡顿,不响应,用着不给力啊。
原文地址:http://wenku.baidu.com/link?url=pSFVrVSTwflCG4h3vxY75XX0-N-1Ge5Ix-vPh1WYxOjIiJ3CMpfd_9-ZTpo4oOgW6UHhOCHixB510bvzOpjzvTzmZmXsIj35AKxLP5-s0MG
|
ehcache 有几种方式集群 ,rmi,jgroup还有jms;这里讲一下ehcache的使用
ehcache 使用rmi方式复制缓存是可取的,原因如下:
1、rmi是java 默认的远程机制
3、Elements因为要存到磁盘,所以肯定是早已序列化。所以不需要借助xml格式化什么的
4、通过配置可以通过防火墙
Ehcache的rmi方式是一种点对点的协议,因此它会产生很多局域网的内部通信,当然Ehcache会通过一种异步批处复制理机制类解决
如果要配置ehcache 需要配置一下元素
PeerProvider
CacheManagerPeerListener
配置Provider,这里有两种方式:自动发现、手动配置
自动方式:自动发现方式使用tcp广播来建立和包含一个广播组,它的特征是最小配置和对成员组的自动添加和管理。没有那个服务器是有优先级的。对等点每一秒中向广播组发送心跳,如果一个对等点在五秒钟内没发送过来,则此对等点将会被删除,如果有新的,则会被加入集群
cacheManagerPeerProviderFactory 的properties有以下配置:
peerDiscovery=automatic
multicastGroupAddress=230.0.0.1
multicastGroupPort=40001
timeToLive=0-255
hostName=hostname
peerDiscovery 方式:atutomatic 为自动 ;mulicastGroupAddress 广播组地址:230.0.0.1;mulicastGroupPort 广播组端口:40001;timeToLive是指搜索范围:0是同一台服务器,1是同一个子网,32是指同一站点,64是指同一块地域,128是同一块大陆,还有个256,我就不说了;hostName:主机名或者ip,用来接受或者发送信息的接口
在我这次试验中具体如下:
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32,hostName=192.168.1.101" />
当然还有一种方式就是手动配置,贴上例子,但不作叙述了
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server2:40001/sampleCache11|//server2:40001/sampleCache12"/>
server2
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,
rmiUrls=//server1:40001/sampleCache11|//server1:40001/sampleCache12"/>
将方式配好之后需要配置listener才会有用,接下来讲讲:Listener
Listener是用来监听从集群发送过来的信息
Listenner有两个属性:class和propertis
class 一个完整的工厂类名
properties 都好分割的对facotory有用的属性
此次实验具体配置如下:
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=192.168.1.101, port=40001,
socketTimeoutMillis=2000" />
hostName指的是本机,这里注意如果使用的localhost,则只会对本机有效,请使用子网内的ip地址或者主机名,port端口 40001,socketTimeoutMillis是指socket子模块的超时时间,默认是2000ms,注意port两台主机可以相同可以不同。最好相同,个人建议
然后配置缓存的复制 Replicators:
本机配置如下:
<cache name="myCache" maxEntriesLocalHeap="10" eternal="false"
timeToIdleSeconds="10000" timeToLiveSeconds="10000" overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=false, replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"
/>
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
</cache>
name为cache制定名字,maxEntriesLocalHeap:内存中可驻留最大Element数量,timeToLiveSeconds 生存周期 10000s;overflowToDisk:当内存不足,是否启用磁盘:这里为false;给myCache价格监听,然后是异步方式,在put,update,copy,remove操作是否复制,然后同步时间1s,bootstrapCacheLoaderFactory 工厂是指启动是指一启动就同步数据
以下是完整的配置
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"
monitoring="autodetect" dynamicConfig="true">
<diskStore path="D:/ehcache/diskStore" />
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=automatic, multicastGroupAddress=230.0.0.1,
multicastGroupPort=4446, timeToLive=32,hostName=192.168.1.101" />
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=192.168.1.101, port=40001,
socketTimeoutMillis=2000" />
<cache name="myCache" maxEntriesLocalHeap="10" eternal="false"
timeToIdleSeconds="10000" timeToLiveSeconds="10000" overflowToDisk="false">
<cacheEventListenerFactory
class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true, replicatePuts=true, replicateUpdates=true,
replicateUpdatesViaCopy=false, replicateRemovals=true,asynchronousReplicationIntervalMillis=1000"
/>
<bootstrapCacheLoaderFactory
class="net.sf.ehcache.distribution.RMIBootstrapCacheLoaderFactory"/>
</cache>
</ehcache>
在server2 也就是 192.168.1.116 在hostName配置成此地址,就行了
下面是测试代码
package com.ehcache;
import java.io.IOException;
import java.io.InputStream;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
public class Test2 {
public static void main(String[] args) throws InterruptedException {
InputStream is=null;
CacheManager manager=null;
try {
is = Test2.class.getResourceAsStream("/ehcache.xml");
manager = CacheManager.newInstance(is);
} catch (CacheException e1) {
try {
if(is!=null){
is.close();
is=null;
}
} catch (IOException e) {
e.printStackTrace();
}
e1.printStackTrace();
}
Cache cache = manager.getCache("myCache");
Element element = new Element("client3" + System.currentTimeMillis(), "client3");
cache.put(element);
int i=0;
while (true)
{
Element element2 = new Element("client-3-"+i,i);
cache.put(element2);
Thread.sleep(3000);
System.out.println("\n");
for (Object key : cache.getKeys())
{
System.out.println(key + ":" + cache.get(key).getObjectValue());
}
i++;
}
}
}
server2 的测试代码将 element那里改成client-2-即可
client3 同步到client2的数据了
另外附叙述ehcache的淘汰缓存的算法:
LRU是Least Recently Used 近期最少使用算法;
FIFO 以一种队列方式谁先进谁先出
LFU least frequently used 即最不经常使用页置换算法
这是工程文件的下载地址:点击打开链接
备注:作者水平有限,并且这些配置只在局域网的实践过,如果有错误,请指出。
前面也写了并且试验了局域网内的,负载均衡,tomcat集群,session回话的分离并且双机热备,希望以后有机会让来亲自架构一下大规模的集群。
<!-- Begin 先支持 ehcache 集群内存双机热备份 demo ,售后整理筛选重复的jar版本 lguo -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-web</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<!-- End 先支持 ehcache 集群内存双机热备份 demo ,售后整理筛选重复的jar版本 lguo -->
spring 3.2.1
hibernate 3.2
原文地址:http://www.tuicool.com/articles/MJzYZbR
|