Jpetstore是一个典型的web应用,其开发框架为struts(spring-web)+spring+ibatis,因此以它做为例子有很好的实际意义。
本篇的前提是memcached server已经安装并且启动,我们在此只是看看如何使用其java client进行数据的读取和更新,这里所用的client都是比较原始的,没有进行封装。
1.memcached client for java
1.1从whalin下载jar包,然后安装到nexus中,在jpetstore的pom.xml中增加如下依赖:
<dependency>
<groupId>com.danga</groupId>
<artifactId>memcached</artifactId>
<version>2.0.1</version>
<type>jar</type>
</dependency>
1.2配置
在dataAccessContext-local.xml中增加如下配置
<bean id="memcachedPool" class="com.danga.MemCached.SockIOPool" factory-method="getInstance"
init-method="initialize" destroy-method="shutDown">
<constructor-arg><value>eddyMemcachedPool</value></constructor-arg>
<property name="servers">
<list>
<value>127.0.0.1:11211</value>
</list>
</property>
<property name="initConn"><value>20</value></property>
<property name="minConn"><value>10</value></property>
<property name="maxConn"><value>50</value></property>
<property name="maintSleep"><value>30</value></property>
<property name="nagle"><value>false</value></property>
<property name="socketTO"><value>3000</value></property>
</bean>
<bean id="memcachedClient" class="com.danga.MemCached.MemCachedClient">
<constructor-arg><value>eddyMemcachedPool</value></constructor-arg>
<property name="compressEnable"><value>true</value></property>
<property name="compressThreshold"><value>4096</value></property>
</bean>
1.3在dao的实现中增加memcached支持,譬如SqlMapProductDao中作如下改动
增加注入
private MemCachedClient mmc;
public MemCachedClient getMmc() {
return mmc;
}
public void setMmc(MemCachedClient mmc) {
this.mmc = mmc;
}
修改实现代码
public Product getProduct(String productId) throws DataAccessException {
String key = "Product-"+productId;
Product p = (Product)mmc.get(key);
if(p==null){
p = (Product) getSqlMapClientTemplate().queryForObject("getProduct", productId);
mmc.set(key, p);
System.out.println("ddddddddddddddddddddddddddddddddddddddddddddd");
}else{
System.out.println("mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm");
}
return p;
}
1.4修改spring配置
<bean id="productDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapProductDao">
<property name="sqlMapClient" ref="sqlMapClient"/>
<property name="mmc" ref="memcachedClient"/>
</bean>
修改完毕,第一次访问,可以看到后台打印出
ddddddddddddddddddddddddddddddddddddddddddddd
后面的访问都打印出
mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
2。spymemcached
http://code.google.com/p/spymemcached
- An improved Java API maintained by Dustin Sallings.
- Aggressively optimised, ability to run async, supports binary protocol, etc. See site for details.
参考simple-spring-memcachedhttp://code.google.com/p/simple-spring-memcached/
2.1为项目增加spymemcached依赖,修改pom.xml,增加:
<dependency>
<groupId>spy</groupId>
<artifactId>memcached</artifactId>
<version>2.3.1</version>
</dependency>
2.2添加memcached client factory和memcached helper bean
package org.springframework.samples.jpetstore.util;
public class MemcachedConnectionBean {
private String nodeList;
private boolean consistentHashing;
public String getNodeList() {
return nodeList;
}
public void setNodeList(final String nodeList) {
this.nodeList = nodeList;
}
public boolean isConsistentHashing() {
return consistentHashing;
}
public void setConsistentHashing(final boolean consistentHashing) {
this.consistentHashing = consistentHashing;
}
}
package org.springframework.samples.jpetstore.util;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.List;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.ConnectionFactory;
import net.spy.memcached.DefaultConnectionFactory;
import net.spy.memcached.KetamaConnectionFactory;
import net.spy.memcached.MemcachedClient;
import net.spy.memcached.MemcachedClientIF;
public class MemcachedClientFactory {
private MemcachedConnectionBean bean;
public void setBean(MemcachedConnectionBean bean) {
this.bean = bean;
}
public MemcachedClientIF createMemcachedClient() throws IOException{
if (this.bean == null) {
throw new RuntimeException("The MemcachedConnectionBean must be defined!");
}
final List<InetSocketAddress> addrs = AddrUtil.getAddresses(this.bean.getNodeList());
final ConnectionFactory connectionFactory = this.bean.isConsistentHashing() ?
new KetamaConnectionFactory() : new DefaultConnectionFactory();
final MemcachedClientIF client = new MemcachedClient(connectionFactory, addrs);
return client;
}
}
2.3 修改dataAccessContext-local.xml,增加如下
<bean id="memcachedConnectionBean" class="org.springframework.samples.jpetstore.util.MemcachedConnectionBean">
<property name="consistentHashing" value="true" />
<property name="nodeList" value="127.0.0.1:11211 127.0.0.1:11311" />
</bean>
<bean id="memcachedClientFactory" class="org.springframework.samples.jpetstore.util.MemcachedClientFactory" >
<property name="bean" ref="memcachedConnectionBean" />
</bean>
<bean id="memcachedSpyClient" factory-bean="memcachedClientFactory" factory-method="createMemcachedClient" />
同时修改其中的
<bean id="productDao" class="org.springframework.samples.jpetstore.dao.ibatis.SqlMapProductDao">
<property name="sqlMapClient" ref="sqlMapClient"/>
<property name="mmc" ref="memcachedClient"/>
</bean>
将mmc换成memcachedSpyClient
2.4修改SqlMapProductDao,将spymemcached client注入
private MemcachedClientIF mmc;
public MemcachedClientIF getMmc() {
return mmc;
}
public void setMmc(MemcachedClientIF mmc) {
this.mmc = mmc;
}
2.5修改客户端调用方式
public Product getProduct(String productId) throws DataAccessException {
String key = "Product-"+productId;
Product p = (Product)mmc.get(key);
if(p==null){
p = (Product) getSqlMapClientTemplate().queryForObject("getProduct", productId);
mmc.set(key, 3600, p);
System.out.println("ddddddddddddddddddddddddddddddddddddddddddddd");
}else{
System.out.println("mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm");
}
return p;
}
修改完毕,其实从这个改动来看,主要是获取memcached client有所区别。
总结:
从上面的两个例子可以看出,两种缓存的方式都对代码进行了侵入,所以在更换memcached client时需要修改不少的代码。因此要让缓存客户端对我们的代码透明,就需要做自己的cache接口和cache client以及其factory。
这两种客户端对于使用各自的set/get没有问题,对于对象为string的互相set/get也没有问题,但是对于复杂object的互相set/get是不行的。譬如,对于对象Product,如下:
import java.io.Serializable;
public class Product implements Serializable {
/* Private Fields */
private String productId;
private String categoryId;
private String name;
private String description;
/* JavaBeans Properties */
public String getProductId() { return productId; }
public void setProductId(String productId) { this.productId = productId.trim(); }
public String getCategoryId() { return categoryId; }
public void setCategoryId(String categoryId) { this.categoryId = categoryId; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
/* Public Methods*/
public String toString() {
return getName();
}
}
使用第一个客户端set,
Product obj = new Product();
obj.setName("test");
obj.setProductId("1-2-3");
mcc.set("P-1-2-3", obj);
使用第二个客户端get,
Product bar = (Product)mcc.get( "P-1-2-3" );
就会产生如下异常:
Exception in thread "main" java.lang.ClassCastException: java.lang.Byte
at TestMemcached.objexamples(TestMemcached.java:95)
at TestMemcached.main(TestMemcached.java:112)
从异常来看是类型转换错误,分别打印出
System.out.println("mcc|"+mcc.get( "P-1-2-3" )+"|");
和
System.out.println("spy|"+getSpy().get( "P-1-2-3" )+"|");
结果是
mcc|Product@dd5b|
和
spy|?? Product??w
categoryIdtxx
Ljava/lang/String;Lxx
descriptionqxx
nameq productIdqxx
xppptxx ========name========txx
1-2-3|
xx代表一些特殊字符。
很明显,这两个client不兼容,至今没找到解决方案。(?????)
分享到:
相关推荐
jpetstore的版本号为3-1-1,这表明它可能经过了多次更新和改进,以适应不断发展的技术和最佳实践。 该应用的核心是Java Servlet和JavaServer Pages(JSP)技术,它们是Java EE平台的重要组成部分,用于创建动态网页...
《Spring框架学习:以JpetStore为例》 Spring框架是Java企业级应用开发中的核心框架,它为开发者提供了丰富的功能,简化了开发流程,提高了代码的可测试性和可维护性。JpetStore作为Spring的经典示例项目,是学习...
Struts框架在jpetstore系统中扮演了重要的角色,它不仅简化了Web应用的开发过程,还提供了强大的表单处理、页面导航以及国际化支持等功能。在系统架构图中,ActionServlet作为Struts框架的核心组件,负责接收客户端...
jpetstore项目是一个示例应用,它展示了如何在实际环境中运用多种设计模式,为学习J2EE提供了一个生动的实践场景。 J2EE,即Java企业版,是Java平台的一部分,专为开发和部署分布式企业级应用程序而设计。它提供了...
JPetStore-5.0是一个著名的开源项目,它基于iBatis数据持久层框架,为开发者提供了一个完整的电子商务应用程序示例。这个项目由Apache Software Foundation维护,是学习和理解Java Web开发、MVC设计模式以及iBatis...
标题 "spring例子: jpetstore" 提到的是一个基于Spring框架的应用示例——JPetStore。这个项目是Spring官方提供的一个经典示例,用于展示如何使用Spring框架来构建Web应用程序。它是一个小型的在线宠物商店,包含了...
这个项目不仅提供了一个可直接运行的实例,还为初学者提供了深入理解这些框架之间协作的绝佳平台。 首先,让我们详细了解一下Spring框架。Spring是Java企业级应用开发的核心框架,它提供了依赖注入(Dependency ...
《基于Spring、Struts和iBatis的jpetstore4.0详解》 jpetstore4.0是一款经典的电子商务示例应用,它采用Spring、Struts和iBatis这三个核心框架构建,展示了如何在Java环境下实现一个完整的MVC(Model-View-...
jpetstore设计为部署在Tomcat的`webapps`目录下,启动Tomcat后,应用将自动加载并可供访问。 5. **文件结构** `rightjpetstore` 是项目的主要压缩包,解压后通常会包含以下几个部分: - `WEB-INF` 目录:包含了...
在这个改造版中,iBatis替换为MyBatis,意味着数据访问层的实现方式发生了变化,但整体业务逻辑和架构设计依然沿用了jpetstore的思路。 【压缩包子文件的文件名称列表】"org.springframework.samples.jpetstore...
JPetStore是基于iBATIS实现的一个在线宠物商店示例,它的设计和实现为开发者提供了学习数据库驱动应用开发的良好实践。 首先,让我们深入了解一下iBATIS框架。iBATIS的核心理念是将SQL与Java代码分离,通过XML或...
AJAX开发。在JSP/Servlet实现的JPetStore项目基础上,在表单验证、表单输入、订单更新等环节增加AJAX技术,改善项目的用户体验。以下三个任务为必须完成部分,还可自行添加其他改进用户体验的功能。
使用了mybatis的jpetstore-6
1. **项目导入**:首先,你需要下载JPetStore的源码压缩包,这在你提供的文件列表中已经包含,名为"JPetStore"。在MyEclipse中,选择“File” -> “Import” -> “Existing Projects into Workspace”,然后在弹出的...
项目可能包含了多语言支持,通过`.properties`文件提供不同语言的文本资源。 7. **单元测试**: 为了保证代码质量,`jpetstore`源码通常会包含JUnit测试用例,用于测试各个组件的功能和行为。 8. **部署与运行**...
这个版本相较于之前的JPetStore5.0,进行了重要的技术升级,主要体现在将数据持久层的Ibatis替换为更强大的Hibernate,并引入了Spring框架来增强应用程序的模块化和管理。 **Struts框架:** Struts是Apache基金会的...
**Java Web应用:JPetStore静态页面** JPetStore是一个基于Java技术的示例Web应用程序,主要用于教学目的,让学生和开发者了解如何使用Java进行Web开发。这个项目通常出现在Java课程设计中,它提供了构建电子商务...
使用MyEclipse创建一个新的Web项目,命名为`jpetstore`。 **3. 复制文件** - 将解压文件夹中的`web`目录下的所有文件复制并粘贴到新建项目的`WebRoot`目录下。 - 将解压文件夹中的`src`目录下的所有文件复制并粘贴...