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
原创粉丝点击