Spring 集成 Memcached 配置(二)

Memcached 客户端选择

上一篇文章 从零开始学 Java - Spring 集成 Memcached 配置(一)中我们讲到这篇要谈客户端的选择,在 Java 中一般常用的有三个:

  • Memcached Client for Java
  • SpyMemcached
  • XMemcached

他们的对比与性能我这里不讨论,想了解自己搜索查看,我这里使用的是 XMemcached ,据说它的并发效果更好一些。

地址:https://github.com/killme2008/xmemcached

一些基础的准备

首先,你要下载一个 memcached 服务端安装一下,这是他的网址:https://github.com/memcached/memcached/wiki/ReleaseNotes,如果是 Windows 系统,自己去找安装包安装一下即可。启动服务。

然后,你需要一个 xmemcached.jar 包,你可以直接通过我GitHub上的示例项目直接获取到,我贴一个地址:https://github.com/mafly/SpringDemo/blob/master/WebContent/WEB-INF/lib/xmemcached-1.3.8.jar

开试写代码吧

一、在src目录下建立memcached.properties配置文件
这个文件是用来存 memcached 服务器的地址、端口和权重的信息的

 
  1. memcached.connectionPoolSize=10
  2. memcached.failureMode=true
  3.  
  4. #server1
  5. server1.memcached.host=127.0.0.1
  6. server1.memcached.port=11211
  7. server1.memcached.weight=4
  8.  
  9. #server2
  10. server2.memcached.host=127.0.0.1
  11. server2.memcached.port=11212
  12. server2.memcached.weight=6

我这里是配置两台服务器用以测试,不同的权重。具体文件请访问https://github.com/mafly/SpringDemo/blob/memcached/src/memcached.properties 查看。

二、在applicationContext.xml文件中配置
打开applicationContext.xml文件,在下面加入 memcached 的配置:

 
  1. <!-- Memcached 配置 -->
  2. <bean id="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder"
  3. p:connectionPoolSize="${memcached.connectionPoolSize}" p:failureMode="${memcached.failureMode}">
  4. <!-- XMemcachedClientBuilder have two arguments.First is server list,and second is weights array. -->
  5. <constructor-arg>
  6. <list>
  7. <bean class="java.net.InetSocketAddress">
  8. <constructor-arg>
  9. <value>${server1.memcached.host}</value>
  10. </constructor-arg>
  11. <constructor-arg>
  12. <value>${server1.memcached.port}</value>
  13. </constructor-arg>
  14. </bean>
  15. <bean class="java.net.InetSocketAddress">
  16. <constructor-arg>
  17. <value>${server2.memcached.host}</value>
  18. </constructor-arg>
  19. <constructor-arg>
  20. <value>${server2.memcached.port}</value>
  21. </constructor-arg>
  22. </bean>
  23. </list>
  24. </constructor-arg>
  25. <constructor-arg>
  26. <list>
  27. <value>${server1.memcached.weight}</value>
  28. <value>${server2.memcached.weight}</value>
  29. </list>
  30. </constructor-arg>
  31. <property name="commandFactory">
  32. <bean class="net.rubyeye.xmemcached.command.TextCommandFactory" />
  33. </property>
  34. <property name="sessionLocator">
  35. <bean class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator" />
  36. </property>
  37. <property name="transcoder">
  38. <bean class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
  39. </property>
  40. </bean>
  41. <!-- Use factory bean to build memcached client -->
  42. <bean id="memcachedClient" factory-bean="memcachedClientBuilder"
  43. factory-method="build" destroy-method="shutdown" />

这里的地址及端口就是读取刚刚的memcached.properties配置文件。当然,你不能忘了把配置文件读取到 Spring 容器中管理。

三、建立cn.mayongfa.cache包,并新增MemcachedBasis.java基础类
1.新建cn.mayongfa.cache包我就说了,大家都会的,重要的是建完包之后要在applicationContext.xml文件中配置扫描包,完成 Bean 的注入 。就是下面:

 
  1. <context:component-scan base-package="cn.mayongfa.cache" />

2.新建MemcachedBasis.java类。

 
  1. @Component
  2. public class MemcachedBasis {
  3.  
  4. @Autowired
  5. protected MemcachedClient memcachedClient;
  6.  
  7. /**
  8. * 失效时间(秒)3600*24 一天
  9. */
  10. protected int Exptime = 3600 * 24;
  11.  
  12. /**
  13. * 基础数据失效时间(秒)3600*24*7 一周
  14. */
  15. protected int DataExptime = this.Exptime * 7;
  16.  
  17. protected String Prefix = "SPRINGDEMO:";
  18. }

都是我们需要用的基本信息,就是一个基类的概念,主要用于其他缓存类继承它,就不需要重复定义这些变量了。

四、新增UserBasisCache.java缓存类,继承于MemcachedBasis.java

 
  1. @Component
  2. public class UserBasisCache extends MemcachedBasis {
  3.  
  4. private Logger log = Logger.getLogger(UserBasisCache.class);
  5. @Autowired
  6. private UserBasisDao userBasisDao;
  7.  
  8. /**
  9. * 设置缓存
  10. *
  11. * @param model
  12. * 用户model
  13. * @return
  14. */
  15. public Boolean set(UserBasis model) {
  16. Boolean result = false;
  17. try {
  18. result = memcachedClient.set(getCacheKey(model.getId()), super.Exptime, model);
  19. } catch (TimeoutException | InterruptedException | MemcachedException e) {
  20. log.error("", e);
  21. }
  22. return result;
  23. }
  24.  
  25. /**
  26. * 获取缓存
  27. *
  28. * @param id
  29. * 用户ID
  30. * @return
  31. */
  32. public UserBasis get(long id) {
  33. UserBasis entity = new UserBasis();
  34. try {
  35. entity = memcachedClient.get(getCacheKey(id));
  36. if (entity == null || entity.getId() <= 0) {
  37. entity = userBasisDao.getEntity(id);
  38. this.set(entity);
  39. }
  40. } catch (TimeoutException | InterruptedException | MemcachedException e) {
  41. log.error("", e);
  42. entity = userBasisDao.getEntity(id);
  43. }
  44. return entity;
  45. }
  46.  
  47. /**
  48. * 删除缓存
  49. *
  50. * @param id
  51. * 用户ID
  52. * @return
  53. */
  54. public Boolean delete(long id) {
  55. try {
  56. return memcachedClient.delete(getCacheKey(id));
  57. } catch (TimeoutException | InterruptedException | MemcachedException e) {
  58. log.error("", e);
  59. }
  60. return false;
  61. }
  62.  
  63. /**
  64. * 获取缓存 Key
  65. *
  66. * @param id
  67. * 用户ID
  68. * @return
  69. */
  70. private String getCacheKey(long id) {
  71. return super.Prefix + "UserBasis:" + id;
  72. }
  73. }

这个就是具体的业务逻辑的缓存的获取、增加、修改和删除的处理了,这里是以每个用户来添加到缓存,只是用来演示的,具体的情况你们自己处理。

还记不记得上篇文章说:我们怎么做到缓存对代码的侵入性,以及我们怎么更方便或者说不需要改代码就实现缓存。其实这个时候,我们会发现我们项目架构是分层的,分层的意义不就是为了分配职责、减小耦合和定义标准嘛。那这个时候我们如果都在实现层(Service.Imp)来实现缓存的增删改查,那是不是 Controller 层的调用就不需要任何改动了,也不需要考虑缓存怎么实现的了,不需要去执行缓存的增删改查了,还是像原来那样直接调用实现层的方法就行了。

五、修改UserBasisServiceImp.java类,实现缓存的增删改查
最开始这个类其中的方法是这样的:

 
  1. @Override
  2. public long Save(UserBasis entity) {
  3. return UserBasisdao.Save(entity);
  4. }
  5.  
  6. @Override
  7. public Boolean Delete(long ID) {
  8. return UserBasisdao.Delete(ID);
  9. }
  10.  
  11. @Override
  12. public UserBasis getEntity(long ID) {
  13. return UserBasisdao.getEntity(ID);
  14. }

我们改成了这样的:

 
  1. @Autowired
  2. private UserBasisCache UserBasiscache;
  3.  
  4. @Override
  5. public long Save(UserBasis entity) {
  6. long id = UserBasisdao.Save(entity);
  7. if (id > 0) {
  8. UserBasiscache.set(entity);
  9. }
  10. return id;
  11. }
  12.  
  13. @Override
  14. public Boolean Delete(long ID) {
  15. boolean result = UserBasisdao.Delete(ID);
  16. if (result) {
  17. UserBasiscache.delete(ID);
  18. }
  19. return result;
  20. }
  21.  
  22. @Override
  23. public UserBasis getEntity(long ID) {
  24. return UserBasiscache.get(ID);
  25. }

看出来区别了吧,就是我们在实现层处理了缓存的操作,并不需要去最外层的调用处处理了。

总结一下

上一篇文章我讲了整个选择缓存的心路历程,虽然没有干货,但都是值得思考的东西,这篇文章就有了干货,可以让你用「最原始版」方式来灵活在项目中实现缓存。希望我的分享对你有所帮助吧,所有这些配置及代码都可以在我的 GitHub 上关于 Spring 的示例项目看到:https://github.com/mafly/SpringDemo

又写到凌晨一点,我睡了。

 

http://blog.mayongfa.cn/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值