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

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

2015-02-03 22:01 525 查看

用户名片

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

首先同样先修改系统属性:

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