用数据库读取和存储Smartfoxserver的好友列表(BuddyList)

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,搞定。

参考自官方文档

你可能还对下面的日志感兴趣:

相关标签: Development & Design and tagged , , .

15 Responses to 用数据库读取和存储Smartfoxserver的好友列表(BuddyList)

  1. SYW says:

    我试了不行,每次init的断点都进不去,是不是config.xml还要设置什么参数?

    • 唯枫 says:

      除了日志里说明的设置项,config.xml再不需要设置什么了,你需要检查一下java的类名和文件名以及config.xml里设置的类名是否一致

      另外注意这个类文件不是放在javaExtensions目录,而是sfs的Server目录中。

  2. SYW says:

    persisterclass你这个写错了,应该是persisterClass,这个我解决了,但是又有一个问题,如何在loadBuddys的时候设置好友的变量?

    • 唯枫 says:

      你看上面扩展中的代码,在设置好友是否在黑名单那行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;

  3. SYW says:

    还有如果好友不再线的,我怎么设置他的变量?

    • 唯枫 says:

      设置变量应该和在不在线无关吧?只要好友列表读出来,那就直接设置就可以了吧

  4. SYW says:

    我应该在什么时候把变量加上去?能给个例子吗?

    • 唯枫 says:

      肯定是在好友列表读取出来之后呀,否则怎么知道给哪个好友设置变量。

      在扩展中从数据库读取好友的同量,可以在循环中顺便把好友变量给设置进去。

  5. SYW says:

    如果我加好友时不像输入别人的登陆名,只想输入对方的昵称(只能在数据库取到),来找到对方,应该这么写?

  6. SYW says:

    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);

    我是这么写的,可是客户端获取不到变量,这是为什么?

  7. SYW says:

    而且getBuddyRoom会引发
    TypeError: Error #1095: XML 分析器失败: 属性未结束。
    服务端传过来的msg数据是这样的:

    有时候我用XML协议获得的数据也会不完整,会提示我根元素错误,这些是什么引起的?
    我现在打算用STR协议,自定义一个好友系统,你觉得这样会比他封装的BUDDY效率好吗?

发表评论

电子邮件地址不会被公开。 必填项已被标记为 *

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>