SFS最新的Buddy List 2.0不再只支持文件存储好友列表,也可以支持数据库存储好友列表,提供更好的速度和安全性,每个Zone都可以配置自己的数据库。
我们可以通过一个Java类来负责好友列表的加载、保存,代码如下:
import it.gotoandplay.smartfoxserver.SmartFoxServer; import it.gotoandplay.smartfoxserver.data.buddylist.StorableBuddyItem; import it.gotoandplay.smartfoxserver.data.buddylist.StorableBuddyList; import it.gotoandplay.smartfoxserver.data.buddylist.persistence.AbstractBuddyPersister; import it.gotoandplay.smartfoxserver.data.*; import it.gotoandplay.smartfoxserver.db.*; import it.gotoandplay.smartfoxserver.extensions.*; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; public class BuddyPersiter extends AbstractBuddyPersister { private ExtensionHelper helper; private Zone currentZone; private DbManager db; @Override public void init(Object param) { helper = ExtensionHelper.instance(); this.currentZone = helper.getZone(this.zoneName); info("CUSTOM Persister initialized."); } @Override public void destroy(Object param) { info("CUSTOM Persister shutting down."); } @Override public StorableBuddyList loadList(String userName) { return loadBuddys(userName); } // 从数据库读取好友列表 @SuppressWarnings("unchecked") private StorableBuddyList loadBuddys(String userName) { db = this.currentZone.dbManager; StorableBuddyList buddyList = new StorableBuddyList(userName); buddyList.buddies = new ArrayList<storablebuddyitem>(); if (userName.length() > 0) { String sql = "SELECT BUDDYNAME,ISBLACK FROM BUDDYS WHERE USERNAME='"+userName+"'"; ArrayList<datarow> buddys = db.executeQuery(sql); if (buddys.size() > 0) { DataRow dr; for (int i = 0; i < buddys.size(); i++) { dr = buddys.get(i); StorableBuddyItem buddyItem = new StorableBuddyItem(dr.getItem("BUDDYNAME")); buddyItem.isBlocked = (dr.getItem("ISBLACK").equals("1")) ? true : false; buddyList.buddies.add(buddyItem); } } } info("Buddy List loaded for user: " + userName); return buddyList; } @Override public boolean saveList(String userName, StorableBuddyList buddyList) { db = this.currentZone.dbManager; // 删除所有好友 String sql = "DELETE FROM BUDDYS WHERE USERNAME='" + userName + "'"; db.executeCommand(sql); db.executeCommand("commit"); int isBlack = 0; info("Saving buddy list for user: " + userName); for (StorableBuddyItem buddyItem : buddyList.buddies) { System.out.println("\t> " + buddyItem.name); isBlack = buddyItem.isBlocked ? 1 : 0; db.executeCommand("INSERT INTO BUDDYS(ISBLACK, USERNAME, BUDDYNAME) VALUES("+isBlack+",'"+userName+"','"+buddyItem.name+"')"); db.executeCommand("commit"); } return true; } @Override public Map<string , String> getOfflineVariables(String userName) { info("getOfflineVariables called for user: " + userName); return new HashMap</string><string , String>(); } @Override public boolean removeOfflineBuddy(String owner, String buddyName) { // Called when removing a buddy that is currently offline // and the mutualRemove is active return true; } private void info(String msg) { SmartFoxServer.log.info(msg); } } </string></datarow></storablebuddyitem> |
写完后,将BuddyPersiter.class文件复制到SFS的Server目录中(不是javaExtensions),然后在SFS配置文件的相应zone中加入如下buddylist配置(注意persisterClass标签内的类名):
<BuddyList active="true">
<size>100</size>
<maxBuddyVariables>5</maxBuddyVariables>
<mode>advanced</mode>
<!-- Apply only for advanced mode -->
<addBuddyPermission>true</addBuddyPermission>
<offLineBuddyVariables>true</offLineBuddyVariables>
<permissionTimeOut>10</permissionTimeOut>
<mutualAddBuddy>true</mutualAddBuddy>
<mutualRemoveBuddy>true</mutualRemoveBuddy>
<persisterClass>BuddyPersiter</persisterClass>
</BuddyList>
最后重启一下SFS,搞定。
参考自官方文档
我试了不行,每次init的断点都进不去,是不是config.xml还要设置什么参数?
除了日志里说明的设置项,config.xml再不需要设置什么了,你需要检查一下java的类名和文件名以及config.xml里设置的类名是否一致
另外注意这个类文件不是放在javaExtensions目录,而是sfs的Server目录中。
persisterclass你这个写错了,应该是persisterClass,这个我解决了,但是又有一个问题,如何在loadBuddys的时候设置好友的变量?
你看上面扩展中的代码,在设置好友是否在黑名单那行buddyItem.isBlocked 之后设置变量,难道下面代码:
Map variables = new HashMap ();
variables.put(“$img”, dr.getItem(“img”));
variables.put(“$gold”, dr.getItem(“gold”));
variables.put(“$mark”, dr.getItem(“mark”));
variables.put(“$sex”, dr.getItem(“sex”));
buddyItem.variables=variables;
还有如果好友不再线的,我怎么设置他的变量?
设置变量应该和在不在线无关吧?只要好友列表读出来,那就直接设置就可以了吧
我应该在什么时候把变量加上去?能给个例子吗?
肯定是在好友列表读取出来之后呀,否则怎么知道给哪个好友设置变量。
在扩展中从数据库读取好友的同量,可以在循环中顺便把好友变量给设置进去。
如果我加好友时不像输入别人的登陆名,只想输入对方的昵称(只能在数据库取到),来找到对方,应该这么写?
你可以在输入对方昵称后,根据昵称去数据库得到登陆名,然后再做加好友操作。
给你个sfs交流QQ群:33506994
dr = buddys.get(i);
StorableBuddyItem buddyItem = new StorableBuddyItem(dr.getItem(“buddyName”));
buddyItem.isBlocked = (dr.getItem(“isBlack”).equals(“1″)) ? true : false;
Map variables = new HashMap();
variables.put(“$bName”, dr.getItem(“name”));
variables.put(“$img”, dr.getItem(“img”));
variables.put(“$gold”, dr.getItem(“gold”));
variables.put(“$mark”, dr.getItem(“mark”));
variables.put(“$sex”, dr.getItem(“sex”));
buddyItem.variables=variables;
//helper.set(dr.getItem(“buddyName”), variables);
buddyList.buddies.add(buddyItem);
我是这么写的,可是客户端获取不到变量,这是为什么?
不清楚,建议看看官方手册
而且getBuddyRoom会引发
TypeError: Error #1095: XML 分析器失败: 属性未结束。
服务端传过来的msg数据是这样的:
有时候我用XML协议获得的数据也会不完整,会提示我根元素错误,这些是什么引起的?
我现在打算用STR协议,自定义一个好友系统,你觉得这样会比他封装的BUDDY效率好吗?
我用xmlSocket获取的数据也会不完整,估计应该是sfs的bug吧。。