标签:openfire+nosql openfire redis插件 openfire用户优化
在预初始化中,贴出来用户名片的程序。这里也一样不在重复。
首先同样先修改系统属性:
provider.vcard.className |
org.jivesoftware.util.redis.expand.RedisVCardProvider |
然后需要修改VCardManager名片管理这个类。
RedisVCardProvider:
import redis.clients.jedis.Jedis; public class RedisVCardProvider implements VCardProvider { private static final Logger Log = LoggerFactory.getLogger(RedisVCardProvider.class); private static final String DELETE_PROPERTIES = "DELETE FROM ofVCard WHERE username=?"; private static final String UPDATE_PROPERTIES = "UPDATE ofVCard SET vcard=? WHERE username=?"; private static final String INSERT_PROPERTY = "INSERT INTO ofVCard (username, vcard) VALUES (?, ?)"; private static final int POOL_SIZE = 10; private BlockingQueue<SAXReader> xmlReaders = new LinkedBlockingQueue<SAXReader>(POOL_SIZE); public RedisVCardProvider() { super(); // Initialize the pool of sax readers for (int i=0; i<POOL_SIZE; i++) { SAXReader xmlReader = new SAXReader(); xmlReader.setEncoding("UTF-8"); xmlReaders.add(xmlReader); } } @Override public Element loadVCard(String username) { synchronized (username.intern()) { Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis(); Element vCardElement = null; SAXReader xmlReader = null; try { // Get a sax reader from the pool xmlReader = xmlReaders.take(); String usercard = jedis.get("OFVCARD:" + username); if (usercard == null || "".equals(usercard)) { return XMPPServer.getInstance().getJedisConfDao().getVCardProvider().loadVCard(username); } vCardElement = xmlReader.read(new StringReader(usercard)).getRootElement(); } catch (Exception e) { Log.error("Error loading vCard of username: " + username, e); } finally { if (xmlReader != null) { xmlReaders.add(xmlReader); } XMPPServer.getInstance().getUserJedis().returnRes(jedis); } return vCardElement; } } @Override public Element createVCard(String username, Element vCardElement) throws AlreadyExistsException { ...... } @Override public Element updateVCard(String username, Element vCardElement) throws NotFoundException { ...... } @Override public void deleteVCard(String username) { ...... } @Override public boolean isReadOnly() { // TODO Auto-generated method stub return false; } }
VCardManager
/** * Manages VCard information for users. * * @author Matt Tucker */ public class VCardManager extends BasicModule implements ServerFeaturesProvider { private static final Logger Log = LoggerFactory.getLogger(VCardManager.class); private VCardProvider provider; private static VCardManager instance; private EventHandler eventHandler; private static HmThreadPool threadPool = new HmThreadPool(5); public static VCardManager getInstance() { return instance; } public static VCardProvider getProvider() { return instance.provider; } public VCardManager() { super("VCard Manager"); //String cacheName = "VCard"; //vcardCache = CacheFactory.createCache(cacheName); this.eventHandler = new EventHandler(); // Keeps the cache updated in case the vCard action was not performed by VCardManager VCardEventDispatcher.addListener(new VCardListener() { public void vCardCreated(String username, Element vCard) { // Since the vCard could be created by the provider, add it to the cache. //vcardCache.put(username, vCard); Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis(); try { jedis.set("OFVCARD:" + username, vCard.asXML()); } finally { XMPPServer.getInstance().getUserJedis().returnRes(jedis); } } public void vCardUpdated(String username, Element vCard) { // Since the vCard could be updated by the provider, update it to the cache. //vcardCache.put(username, vCard); vCardCreated(username, vCard); } public void vCardDeleted(String username, Element vCard) { // Since the vCard could be delated by the provider, remove it to the cache. //vcardCache.remove(username); Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis(); try { jedis.del("OFVCARD:" + username); } finally { XMPPServer.getInstance().getUserJedis().returnRes(jedis); } } }); } public String getVCardProperty(String username, String name) { ...... } public void setVCard(String username, Element vCardElement) throws Exception { boolean created = false; boolean updated = false; if (provider.isReadOnly()) { throw new UnsupportedOperationException("VCard provider is read-only."); } //Element newvCard = null; Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis(); try { boolean exists = jedis.exists("OFVCARD:" + username); if (exists) { threadPool.execute(createTaskByUpdateVCard(provider, username, vCardElement)); updated = true; } else { threadPool.execute(createTaskByCreateVCard(provider, username, vCardElement)); created = true; } }finally { XMPPServer.getInstance().getUserJedis().returnRes(jedis); } // Dispatch vCard events if (created) { // Alert listeners that a new vCard has been created VCardEventDispatcher.dispatchVCardCreated(username, vCardElement); } else if (updated) { // Alert listeners that a vCard has been updated VCardEventDispatcher.dispatchVCardUpdated(username, vCardElement); } } private Runnable createTaskByCreateVCard(final VCardProvider provider, final String username, final Element vCardElement) { return new Runnable() { public void run() { try { provider.createVCard(username, vCardElement); } catch (AlreadyExistsException e) { Log.error("AlreadyExistsException: username=" + username + ", vCardElement=" + vCardElement); } } }; } private Runnable createTaskByUpdateVCard(final VCardProvider provider, final String username, final Element vCardElement) { return new Runnable() { public void run() { try { provider.updateVCard(username, vCardElement); } catch (NotFoundException e) { Log.error("NotFoundException: username=" + username + ", vCardElement=" + vCardElement); } } }; } public void deleteVCard(String username) { if (provider.isReadOnly()) { throw new UnsupportedOperationException("VCard provider is read-only."); } final String vusername = username; threadPool.execute(new Runnable() { @Override public void run() { provider.deleteVCard(vusername); } }); VCardEventDispatcher.dispatchVCardDeleted(username, null); } public Element getVCard(String username) { Element vCardElement = getOrLoadVCard(username); return vCardElement == null ? null : vCardElement.createCopy(); } private Element getOrLoadVCard(String username) { return provider.loadVCard(username); } @Override public void initialize(XMPPServer server) { ...... } @Override public void start() { ...... } @Override public void stop() { // Remove this module as a user event listener UserEventDispatcher.removeListener(eventHandler); } public void reset() { //vcardCache.clear(); } @Override public Iterator<String> getFeatures() { ArrayList<String> features = new ArrayList<String>(); features.add("redis-vcard-temp"); return features.iterator(); } private class EventHandler extends UserEventAdapter { @Override public void userDeleting(User user, Map params) { try { deleteVCard(user.getUsername()); } catch (UnsupportedOperationException ue) { /* Do Nothing */ } } } public UserCardEnity getUserCardByUserName (String username) { Element element = getVCard(username); UserCardEnity uce = new UserCardEnity(); if (element != null) { String myName = element.elementText("MYNAME"); String sex = element.elementText("SEX"); String oname = element.elementText("ONAME"); String moblie = element.elementText("MOBILE"); String landline = element.elementText("LANDLINE"); String address = element.elementText("ADDRESS"); String workUnit = element.elementText("WORKUNIT"); String birthday = element.elementText("BIRTHDAY"); String photo = element.elementText("PHOTO"); String userType = element.elementText("USERTYPE"); uce.setMyName( myName); uce.setSex(sex); uce.setOname(oname); uce.setMoblie( moblie) ; uce.setLandline(landline); uce.setAddress(address); uce.setWorkUnit(workUnit) ; uce.setBirthday(birthday); uce.setPhoto(photo); if (userType == null) { uce.setUserType(""); } else if (1 == Integer.valueOf(userType)) { uce.setUserType("student"); } else if (2 == Integer.valueOf(userType)) { uce.setUserType("teacher"); } else if (3 == Integer.valueOf(userType)) { uce.setUserType("Guardian"); } else if (4 == Integer.valueOf(userType)) { uce.setUserType("edusun admin"); } else if (5 == Integer.valueOf(userType)) { uce.setUserType("Agents"); } else { uce.setUserType("Other locations"); } } return uce; } }
用户名片就到这了。
搜索用户的时候,在openfire中都是重新查找关系数据库的。因为我们已经将用户预加载到了redis中。那么这里只需要对用户做一些分词存储检索即可。
本人在这里做了比较简单的分词处理。比如用户名,手机号码等。
首先要做的就是制作用户分词了。然后要做的就是需要修修改搜索的handler处理类。Openfire上提供了一个search搜索插件。查询消息最后提交给SearchPlugin这个类的handler方法。本人这里就不做描述。重点要说的就是如何在redis中分词存储。
客户端发送用户查找请求如下:
<iq id="E6l1b-43" to="test@search.hytest240" type="get"><query xmlns="jabber:iq:search"></query></iq>
请看代码清单:
RedisSearchManager:
public class RedisSearchManager extends BasicModule{ private static final Logger LOG = LoggerFactory.getLogger(RedisSearchManager.class); private static final Integer timeout = 1000*10; private static final int maxActive = 5000 * 10; private static final int maxIdle = 5; private static final long maxWait = (1000 * 100); private static JedisPool pool; private static XMPPServer loaclserver; private static JedisPoolConfig config; public RedisSearchManager() { super("Redis search manager"); } private static JedisPoolConfig createConfig() { ...... } private static void createJedisPool() { ......//创建连接池 } private static synchronized void poolInit() { boolean enabled = JiveGlobals.getBooleanProperty("plugin.userservice.enabled"); if (enabled) { if (pool == null) createJedisPool(); } } public Jedis getSearchJedis() { if (pool == null) poolInit(); Jedis jedis = pool.getResource(); jedis.select(3); return jedis; } public void returnSearchJedis(Jedis jedis) { pool.returnResource(jedis); } @Override public void initialize(XMPPServer server) { ..... } //创建用户的搜索关键词数据 public void createSearchAllUserData() { Collection<User> userList = XMPPServer.getInstance().getUserJedis().getAllUser(); for (User user : userList) { createSearchUserData(user); } System.out.println("Initialize the user search data is completed...(the end)"); } //这里根据string长度切分。按照“|”分割 public void createSearchUserData(User user) { Jedis jedis = getSearchJedis(); IndexWriter iw = new IndexWriter(jedis); String username = user.getUsername(); String keyword = ""; if (username.length() >= 4) { int index = 4; for (int i=0; i<=username.length()-4; i++) { String usernameKey = username.substring(0, index++) + "|"; keyword += usernameKey; } } else { keyword = username + "|"; } if (user.getName() != null && !"".equals(user.getName())) { keyword += user.getName() + "|"; } if (user.getEmail() != null && !"".equals(user.getEmail())) { keyword += user.getEmail() + "|"; } if (user.getMoblie() != null && !"".equals(user.getMoblie())) { keyword += user.getMoblie(); } if ("|".equals(keyword.substring(keyword.length()-1))) { keyword = keyword.substring(0, keyword.length()-1); } iw.addIdAndIndexItem(username, keyword); iw.addNeedSortItem("USERNAME",username); iw.addNeedSortItem("CREATIONDATE",user.getCreationDate() != null ? user.getCreationDate() : StringUtils.dateToMillis(new Date())); iw.addNeedSortItem("MODIFICATIONDATE",user.getModificationDate() != null ? user.getModificationDate() : StringUtils.dateToMillis(new Date())); iw.writer(); System.out.println("create user search data, id:" + username + ", keyword:" + keyword); LOG.info("create user search data, id:" + username + ", keyword:" + keyword); returnSearchJedis(jedis); } }
IndexWriter写入索引
public class IndexWriter { private Jedis jedis; private String id; private Map<String, String> items = new HashMap<String, String>(); private String contentItems[]; public IndexWriter(Jedis jedis) { if (!jedis.isConnected()) { jedis.connect(); } this.jedis = jedis; } /** * @param id * 必须有 * @param content * 是分词程序切分后的内容,每个词中间必须用用“|”分隔,如:中国|中国人|2012 */ public void addIdAndIndexItem(String id, String content) { this.id = id; contentItems = content.split("\\|"); } public void addNeedSortItem(String name, String value) { items.put(name, value); } public void writer() { indexWriter(); itemWriter(); } private void indexWriter() { if (!id.equals("") && contentItems.length != 0) { for (int i = 0; i < contentItems.length; i++) { jedis.sadd(contentItems[i].trim(), id); } } } private void itemWriter() { if (items.size() != 0) { Iterator<Entry<String, String>> it = items.entrySet().iterator(); while (it.hasNext()) { Entry<String, String> entry = (Entry<String, String>) it.next(); jedis.set(entry.getKey().toString() + ":" + id, entry .getValue().toString()); } } } }
IndexSearch:查找索引
public class IndexSearch { public static int ALPHA = 0; public static int DESC = 1; public static int ASC = 2; private Jedis jedis; private int limit = 100; private String itemName = null; private int pager = 0; public IndexSearch(Jedis jedis) { if (!jedis.isConnected()) { jedis.connect(); } this.jedis = jedis; } private SortingParams getSP(String item, int sort) { SortingParams sp = new SortingParams(); sp.limit(pager, limit); if (null == item || "".equals(item)) { switch (sort) { case 1: sp.desc(); break; case 2: sp.asc(); break; case 0: default: sp.alpha(); break; } } else { switch (sort) { case 1: sp.by(itemName + ":*").desc(); break; case 2: sp.by(itemName + ":*").asc(); break; case 0: default: sp.by(itemName + ":*").alpha(); break; } } return sp; } private List<String> isearch(int sort, String... query) { jedis.sinterstore("tempKey", query); return jedis.sort("tempKey", this.getSP(itemName, sort)); } public List<String> search(String... query) { return this.isearch(0, query); } public List<String> search(int sort, String... query) { return this.isearch(sort, query); } public List<String> search(String itemName, int sort, String... query) { this.itemName = itemName; return this.isearch(sort, query); } public List<String> search(String itemName, int sort, int limit, String... query) { this.itemName = itemName; this.limit = limit; return this.isearch(sort, query); } public List<String> search(String itemName, int sort, int pager, int limit, String... query) { this.itemName = itemName; this.limit = limit; this.pager = pager; return this.isearch(sort, query); } }
Ok用户搜索这就只贴出一些比较关键性的代码。提供思路。代码贴多了搞了篇幅很长。
OpenFire源码学习之二十二:openfie对用户的优化(下)
标签:openfire+nosql openfire redis插件 openfire用户优化
原文地址:http://blog.csdn.net/huwenfeng_2011/article/details/43458885