OpenFire源码学习之二十:在openfire中使用redis插件(下)

Redis插件实现

首先来看下插件目录:

OpenFire源码学习之二十:在openfire中使用redis插件(下)

RedisServicePlugin

源码清单:

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.jivesoftware.database.DbConnectionManager;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.PropertyEventDispatcher;
import org.jivesoftware.util.PropertyEventListener;
import org.jivesoftware.util.redis.enity.RedisConfig;
import org.jivesoftware.util.redis.enity.User;
import org.jivesoftware.util.redis.enity.UserVcard;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;

public class RedisServicePlugin implements Plugin, PropertyEventListener{
	
	private static final Logger log = LoggerFactory.getLogger(RedisServicePlugin.class);
	
	private static final String OF_REDIS_CONFIG_DELETE = "delete from redisConfiguration";
	private static final String OF_REDIS_CONFIG_INSERT = "INSERT INTO redisConfiguration (name, ip, port, auto) VALUES (?, ?, ?, ?)";

	private XMPPServer server;
	private boolean enabled;
	
	@Override
	public void propertySet(String property, Map<String, Object> params) {
		if (property.equals("plugin.redis.enabled")) {
            this.enabled = Boolean.parseBoolean((String)params.get("value"));
        }
	}
......
	public boolean isEnabled() {
        return enabled;
    }
	
	public void setEnabled(boolean enabled) {
        this.enabled = enabled;
        JiveGlobals.setProperty("plugin.redis.enabled",  enabled ? "true" : "false");
    }

	@Override
	public void initializePlugin(PluginManager manager, File pluginDirectory) {
		enabled = JiveGlobals.getBooleanProperty("plugin.redis.enabled", true);
		server = XMPPServer.getInstance();
		PropertyEventDispatcher.addListener(this);
	}

	@Override
	public void destroyPlugin() {
		enabled = JiveGlobals.getBooleanProperty("plugin.redis.enabled", false);
		PropertyEventDispatcher.removeListener(this);
	}

	public void initializeAllData () {
		Collection<RedisConfig> crcfs = getAllRedisConfig();
		if (!crcfs.isEmpty()) {
			for (RedisConfig rcf : crcfs) {
				if ("REDIS_USER".equals(rcf.getName())) {
					setRedisByUserInfo();
				}
			}
		}
	}
	
	public void saveRedisConfig(Collection<RedisConfig> object) {
		PreparedStatement pstmt = null;
		Connection con = null;
		try {
			con = (Connection) DbConnectionManager.getConnection();
			if (object != null) {
				pstmt = con.prepareStatement(OF_REDIS_CONFIG_DELETE);
				pstmt.execute();
				pstmt = (PreparedStatement) con.prepareStatement(OF_REDIS_CONFIG_INSERT);
				for (RedisConfig cr : object) {
					pstmt.setString(1, cr.getName());
					pstmt.setString(2, cr.getIp());
					pstmt.setString(3, cr.getPort());
					pstmt.setString(4, cr.getAuto());
					pstmt.executeUpdate();
				}
			}
		} catch (Exception e) {
			 log.info(e.getMessage());
			 e.printStackTrace();
		}
		finally {
			 DbConnectionManager.closeConnection(pstmt, con);
		}
	}
	
	public Collection<RedisConfig> getAllRedisConfig() {
		if (server == null)
			server = XMPPServer.getInstance();
		return server.getJedisConfDao().getAllRedisConfig();
	}
	
	public void setRedisOfflineMessage() {
		XMPPServer.getInstance().getChatMessageJedisPoolManager().initDataByOfflineMessage();
	}
	
	public void destroyOfflineMessage() {
		Jedis jedis = server.getChatMessageJedisPoolManager().getJedis();
		jedis.flushDB();
		server.getChatMessageJedisPoolManager().returnRes(jedis);
	}
	
	public void setRedisUserSearch() {
		XMPPServer.getInstance().getRedisSearchManager().createSearchAllUserData();
	}
	
	public void destroyUserSearch() {
		Jedis jedis = server.getRedisSearchManager().getSearchJedis();
		jedis.flushDB();
		XMPPServer.getInstance().getUserJedis().returnRes(jedis);
	}
	
	public void destroyRedisByUserInfo () {
		Jedis jedis = server.getUserJedis().getJedis();
		Map<String, String > user = jedis.hgetAll("OFUSER:admin");
		jedis.flushAll();
		jedis.hmset("OFUSER:admin", user);
		XMPPServer.getInstance().getUserJedis().returnRes(jedis);
	}
	
	public void setRedisByUserInfo () {
		Jedis jedis = server.getUserJedis().getJedis();
		int i = 1;
		
		Collection<User> users = server.getUserJedis().getAllUser();
		if (!users.isEmpty()) {
			for (User user : users) {
				Map<String,String> map = new HashMap<String, String>();
				map.put("PASSWORD", user.getPassword());
				if (user.getName() != null )
					map.put("NAME", user.getName());
				if (user.getMoblie() != null )
					map.put("MOBILE", user.getMoblie().trim());
				if (user.getEmail() != null)
					map.put("EMAIL", user.getEmail().trim());
				map.put("CREATIONDATE",user.getCreationDate().trim());
				map.put("MODIFICATIONDATE",user.getModificationDate().trim());
				jedis.hmset("OFUSER:" + user.getUsername(), map);
				
				System.out.println("The " + i++ + "user generation=> username:" + user.getUsername() + ", name:" + user.getName());
			}
			System.out.println("the end:user base info generated...");
			i = 1;
			
			for (User user : users) {
				if (user.getMoblie() != null && !"".equals(user.getMoblie())) {
					jedis.set("MOBILE:" + user.getMoblie(), user.getUsername());
					System.out.println("The" + i++ + "user,mobile relation generation=> mobile:" + user.getMoblie() + ", username:" + user.getUsername());
				}
			}
			System.out.println("the end:user and mobile relation generated...");
			i = 1;
		}
		
		Collection<UserVcard> uservcards = server.getUserJedis().getUserVcard();
		if (!uservcards.isEmpty()) {
			for (UserVcard uv : uservcards) {
				if (uv.getVcard() != null && !"".equals(uv.getVcard())) {
					jedis.set("OFVCARD:" + uv.getUsername(), uv.getVcard());
					System.out.println("The" + i++ + "user vcard generation=> username:" + uv.getUsername());
				}
			}
			i = 1;
			System.out.println("the end:user vcard generated...");
 		}
		
		server.getUserJedis().returnRes(jedis);
	}
}

RedisUserInfoOpt:

import java.util.HashMap;
import java.util.Map;

import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.util.redis.enity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;

public class RedisUserInfoOpt {

	private static final Logger Log = LoggerFactory.getLogger(RedisUserInfoOpt.class);
	
	public void setBaseUserInfo(User user) {
		if (user != null) {
			Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();
			
			try {
				Map<String,String> map = new HashMap<String, String>();
				map.put("PASSWORD", user.getPassword());
				if (user.getName() != null )
					map.put("NAME", user.getName());
				if (user.getMoblie() != null )
					map.put("MOBILE", user.getMoblie().trim());
				if (user.getEmail() != null)
					map.put("EMAIL", user.getEmail().trim());
				map.put("CREATIONDATE",user.getCreationDate().trim());
				map.put("MODIFICATIONDATE",user.getModificationDate().trim());
				jedis.hmset("OFUSER:" + user.getUsername(), map);
				Log.info("user generation=> username:" + user.getUsername() + ", name:" + user.getName());
			} finally{
				XMPPServer.getInstance().getUserJedis().returnRes(jedis);
			}
		}
	}
	
	public void setUserMobile(User user) {
		if (user != null) {
			Jedis jedis = XMPPServer.getInstance().getUserJedis().getJedis();
			try {
				
			} finally {
				XMPPServer.getInstance().getUserJedis().returnRes(jedis);
			}
			
		}
	}
}

redis-service.jsp

<%@ page import="java.util.*,
                 org.jivesoftware.openfire.XMPPServer,
                 org.jivesoftware.util.*,
                 com.montnets.redis.plugin.RedisServicePlugin,
                 org.jivesoftware.util.redis.enity.RedisConfig"
    errorPage="error.jsp"
%>

<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jstl/fmt_rt" prefix="fmt" %>

<%-- Define Administration Bean --%>
<jsp:useBean   />
<c:set var="admin" value="${admin.manager}" />
<% admin.init(request, response, session, application, out ); %>

<%  // Get parameters
    boolean save = request.getParameter("save") != null;
	String initdata = request.getParameter("initdata");
	String deldata = request.getParameter("deldata");
    boolean success = request.getParameter("success") != null;
    RedisServicePlugin rsp = new RedisServicePlugin();
    Collection<RedisConfig> rcList = rsp.getAllRedisConfig();
    
    // Handle a save
    Map errors = new HashMap();
    Collection<RedisConfig> rcColl = new ArrayList<RedisConfig>();
	
    if ("REDIS_USER".equals(initdata)) {
    	rsp.initializeAllData();
        response.sendRedirect("redis-service.jsp?success=true");
        return;
    }
    else if ("REDIS_USER".equals(deldata)) {
    	rsp.destroyRedisByUserInfo();
    	response.sendRedirect("redis-service.jsp?success=true");
        return;
    }
    ......
    if (save) {
    	String uname = request.getParameter("REDIS_USER");
    	String r_user_name = request.getParameter("REDIS_USER_IP").trim();
    	String r_user_port = request.getParameter("REDIS_USER_PORT").trim();
    	String r_user_auto = request.getParameter("REDIS_USER_AUTO").trim();
    	if (r_user_name == null || r_user_port == null) {
    		errors.put("uname", "Redis-User is error!");
    	}
    	else {
    		RedisConfig rc = new RedisConfig();
        	rc.setName(uname);
        	rc.setIp(r_user_name);
        	rc.setPort(r_user_port);
        	rc.setAuto(r_user_auto);
        	rcColl.add(rc);
    	}
    	......
    	String mmname = request.getParameter("REDIS_MUC_MESSAGE");
    	String r_mm_name = request.getParameter("REDIS_MUC_MESSAGE_IP").trim();
    	String r_mm_port = request.getParameter("REDIS_MUC_MESSAGE_PORT").trim();
    	String r_mm_auto = request.getParameter("REDIS_MUC_MESSAGE_AUTO").trim();
    	if (r_mm_name == "" || r_mm_port == "") {
    		errors.put("mname", "Redis-MUC MESSAGE is error!");
    	}
    	else {
    		RedisConfig rc = new RedisConfig();
        	rc.setName(mmname);
        	rc.setIp(r_mm_name);
        	rc.setPort(r_mm_port);
        	rc.setAuto(r_mm_auto);
        	rcColl.add(rc);
    	}
    	
    	String omname = request.getParameter("REDIS_OFFLINE_MESSAGE");
    	......
        if (errors.size() == 0) {
        	rsp.saveRedisConfig(rcColl);
            response.sendRedirect("redis-service.jsp?success=true");
            return;
        }
    }
    
%>

<html>
    <head>
        <title>Redis Service Properties</title>
        <meta name="pageID" content="redis-service"/>
    </head>
    <body>
<%  if (!errors.isEmpty()) { %>

    <div class="jive-error">
    <table cellpadding="0" cellspacing="0" border="0">
    <tbody>
        <tr>
            <td class="jive-icon"><img src="images/error-16x16.gif" width="16" height="16" border="0" alt=""/></td>
            <td class="jive-icon-label">

            <% if (errors.get("uname") != null) { %>
                <%=errors.get("uname") %>
            <% } else if (errors.get("gname") != null) { %>
                <%=errors.get("gname") %>
            <% } else if (errors.get("rname") != null) { %>
                <%=errors.get("rname") %>
            <% } else if (errors.get("mname") != null) { %>
                <%=errors.get("mname") %>
            <% } else if (errors.get("mmname") != null) { %>
                <%=errors.get("mmname") %>
            <% } else if (errors.get("omname") != null) { %>
                <%=errors.get("omname") %>
            <% } else if (errors.get("cmname") != null) { %>
                <%=errors.get("cmname") %>
            <% } %>
            </td>
        </tr>
    </tbody>
    </table>
    </div><br>

<%  } %>

<p>
This is redis plugin
</p>

<%  if (success) { %>

    <div class="jive-success">
    <table cellpadding="0" cellspacing="0" border="0">
    <tbody>
        <tr><td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16" border="0"></td>
        <td class="jive-icon-label">
            redis service properties edited successfully.
        </td></tr>
    </tbody>
    </table>
    </div><br>
<% } %>

<form action="redis-service.jsp?save=true" method="post">

<fieldset>
    <legend>Redis Service</legend>
    <div>
    <ul>
    <%if (rcList.size() < 1) { %>
        <label for="r_user">REDIS_USER:</label>
		<input type="hidden" />
        <input type="text" />
		<label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_USER_AUTO" size="10" value=""/>
		<br><br>
		
		<label for="r_user">REDIS_GROUP:</label>
		<input type="hidden" />
        <input type="text" />
        <label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_GROUP_AUTO" size="10" value=""/>
		<br><br>
		
		<label for="r_user">REDIS_ROSTER:</label>
		<input type="hidden" />
        <input type="text" />
        <label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_ROSTER_AUTO" size="10" value=""/>
		<br><br>
		
		<label for="r_user">REDIS_MUC:</label>
		<input type="hidden" />
        <input type="text" />
        <label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_MUC_AUTO" size="10" value=""/>
		<br><br>
		
		<label for="r_user">REDIS_MUC_MESSAGE:</label>
		<input type="hidden" />
        <input type="text" />
        <label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_MUC_MESSAGE_AUTO" size="10" value=""/>
		<br><br>
		
		<label for="r_user">REDIS_OFFLINE_MESSAGE:</label>
		<input type="hidden" />
        <input type="text" />
        <label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_OFFLINE_MESSAGE_AUTO" size="10" value=""/>
		<br><br>
		
		<label for="r_user">REDIS_CHAT_MESSAGE:</label>
		<input type="hidden" />
        <input type="text" />
        <label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_CHAT_MESSAGE_AUTO" size="10" value=""/>
		<br><br>
		
		<label for="r_user">REDIS_SEARCH:</label>
		<input type="hidden" />
        <input type="text" />
        <label for="r_port">port:</label>
		<input type="text" />
		<label for="r_auto">auto:</label>
		<input type="text" name="REDIS_SEARCH_AUTO" size="10" value=""/>
		<br><br>
		
		<% } %>
		<% if (rcList.size() >= 1) { %>
			<% for (RedisConfig cr : rcList) { %>
				<label for="r_user"><%=cr.getName() %></label>
				<input type="hidden" name="<%=cr.getName() %>" value="<%=cr.getName() %>"/>
        		<input type="text" name="<%=cr.getName() %>_IP" size="20" value="<%=cr.getIp() %>"/>
        		<label for="r_port">port:</label>
				<input type="text" name="<%=cr.getName() %>_PORT" size="5" value="<%=cr.getPort() %>"/>
				<label for="r_auto">auto:</label>
				<input type="text" name="<%=cr.getName() %>_AUTO" size="10" value="<%=cr.getAuto() %>"/>
				<br>
				<input type="button" value="initialize data" onclick="window.location.href='redis-service.jsp?initdata=<%=cr.getName() %>'; return false;"/>
				<input type="button" value="destroy data" onclick="window.location.href='redis-service.jsp?deldata=<%=cr.getName() %>'; return false;"/>
				<br><br>
			<%} %>
		<% } %>
    </ul>
    </div>
</fieldset>

<br><br>

<input type="submit" value="Save Settings">
<input type="hidden" name="initdata" value=""/>
</form>

</body>
</html>

Plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
    <class>com.montnets.redis.plugin.RedisServicePlugin</class>
    <name>Redis Service</name>
    <description>Redis distributed cache</description>
    <author>HuWenFeng</author>
    <version>1.3.3</version>
    <date>17/1/2014</date>
    <minServerVersion>3.8.2</minServerVersion>
    
    <adminconsole>		
        <tab >
            <sidebar  >
                <item 
                     description="Redis distributed cache" />
            </sidebar>
        </tab>
    </adminconsole>
</plugin>

这里只简单贴出了用户这类的相关数据的预加载。

下面开始具体讲讲基于Redis数据的几大分类。这里这里主要拿用户和消息这两大块具体来说说openfire基于redis的优化。