用户名片
在预初始化中,贴出来用户名片的程序。这里也一样不在重复。
首先同样先修改系统属性:
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用户搜索这就只贴出一些比较关键性的代码。提供思路。代码贴多了搞了篇幅很长。