OpenFire源码学习之二十二:openfie对用户的优化(下)
来源:互联网 发布:空气质量软件哪个好 编辑:程序博客网 时间:2024/05/16 13:51
用户名片
在预初始化中,贴出来用户名片的程序。这里也一样不在重复。
首先同样先修改系统属性:
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); } }@Overridepublic 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; }}@Overridepublic Element createVCard(String username, Element vCardElement)throws AlreadyExistsException {......}@Overridepublic Element updateVCard(String username, Element vCardElement)throws NotFoundException {......}@Overridepublic void deleteVCard(String username) {......}@Overridepublic boolean isReadOnly() {// TODO Auto-generated method stubreturn 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() {@Overridepublic 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); } @Overridepublic void initialize(XMPPServer server) { ...... } @Overridepublic void start() { ...... } @Overridepublic void stop() { // Remove this module as a user event listener UserEventDispatcher.removeListener(eventHandler); } public void reset() { //vcardCache.clear(); } @Overridepublic Iterator<String> getFeatures() {ArrayList<String> features = new ArrayList<String>(); features.add("redis-vcard-temp"); return features.iterator();}private class EventHandler extends UserEventAdapter { @Overridepublic 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);}@Overridepublic 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用户搜索这就只贴出一些比较关键性的代码。提供思路。代码贴多了搞了篇幅很长。
2 0
- OpenFire源码学习之二十二:openfie对用户的优化(下)
- OpenFire源码学习之二十一:openfie对用户的优化(上)
- OpenFire源码学习之二十八:与其他系统的用户整合
- OpenFire源码学习之二十三:关于消息的优化处理
- OpenFire源码学习之五:用户登录
- OpenFire源码学习之六:用户注册
- OpenFire源码学习之二十:在openfire中使用redis插件(下)
- OpenFire源码学习之十二:HttpBind&Script Syntax
- OpenFire源码学习之二:Mina基础知识
- OpenFire源码学习之二十九:openfire集群配置
- OpenFire源码学习之二十九:openfire集群配置
- OpenFire源码学习之三十二:使用Tsung测试openfire(下)
- OpenFire源码学习之二十七:Smack源码解析
- OpenFire源码学习之二十五:消息回执与离线消息(下)
- OpenFire源码学习之四:openfire的启动流程
- OpenFire源码学习之八:MUC用户聊天室
- OpenFire源码学习之二十六:Spark&Tinder
- OpenFire源码学习之十一:连接管理(下)
- 5个海盗,分100个金币
- Android应用测试实战与调试实践第5章:测试Android服务组件
- Leetcode_Reverse Integer(考虑了溢出情况)
- byte[]类型,blob类型装换
- Android发送dtmf键盘事件(模拟通话界面键盘事件)
- OpenFire源码学习之二十二:openfie对用户的优化(下)
- ZOJ 2108 Elevator (模拟题)
- CentOS/Linux 升级内核
- 解决SQLPlus中无法使用历史命令的问题
- debian 更换sh的默认链接为bash
- Android之Adapter用法总结
- OC类的扩展总结
- jvm 打印所有XX参数及值
- struct运用