您的位置:首页 > 运维架构

OpenFire源码学习之二十二:openfie对用户的优化(下)

2018-02-05 10:57 513 查看


用户名片

在预初始化中,贴出来用户名片的程序。这里也一样不在重复。

首先同样先修改系统属性:
provider.vcard.className
org.jivesoftware.util.redis.expand.RedisVCardProvider
然后需要修改VCardManager名片管理这个类。

RedisVCardProvider:

[java] view
plain copy

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

[java] view
plain copy

/**

* 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中分词存储。

客户端发送用户查找请求如下:

[html] view
plain copy

<iq id="E6l1b-43" to="test@search.hytest240" type="get"><query xmlns="jabber:iq:search"></query></iq>

请看代码清单:

RedisSearchManager:

[java] view
plain copy

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

}

&nb
20000
sp;

@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写入索引

[java] view
plain copy

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:查找索引

[java] view
plain copy

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用户搜索这就只贴出一些比较关键性的代码。提供思路。代码贴多了搞了篇幅很长。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: