openfire插件二次开发(扩展用户注册功能添加了用户省份信息)

一、插件开发的目录结构设计 

        我们先看一下openfire源码的插件开发目录结构: 


二、插件开发

        我们知道openfire插件开发主要有3种方式注册方式:

1)IQHandler(IQ handlers respond to IQ packets with a particular element name and namespace);

2)Interceptor(PacketInterceptor to receive all packets being send through the system and optionally reject them);

3)Component(Components receive all packets addressed to a particular sub-domain)。

        今天来讲IQHandler涉及到的一种设计模式——模板方法(Template Method)模式。

        模板方法最标志性的特点是它需要一个抽象类。在java设计模式中,其实很少用到抽象类,更多地还是用到接口。

        我们如果要做自己的IQ包处理,可以自定义类如TestTemplateMethodHandler:class TestTemplateMethodHandler extends IQHandler,然后在public IQHandlerInfo getInfo()方法中写上自己想要注册的元素名及命名空间,在public IQ handlerIQ(IQ packet)方法中写上自己想要对丢进来的IQ包做什么样的处理(注意IQ包是基于问答形式的,所以应该有IQ包的reply)。

1、创建plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
  Plugin configuration for the areabroadcast plugin.
-->
<plugin>
    <class>org.jivesoft.openfire.plugin.AreaBroadcastPlugin</class>   <!--此处为自己添加的插件的类路径 -->
    <name>areabroadcast</name> <!-- 插件名称这里最好都是小写否则jsp的java代码里面会出现获取不到的问题 -->
    <description>Broadcasts messages to users.</description>
    <author>authorname</author>
    <version>1.7.0</version>
    <date>11/16/2007</date>
    <url>http://www.igniterealtime.org</url>
    <minServerVersion>3.4.1</minServerVersion>
    
    <!-- UI extension 以下为对后台管理界面的扩展在tab-session下添加了一个siderbar-->
    <adminconsole>
<tab id="tab-session"> <!--这里这个名称请参照admin-sidebar.xml-->
<sidebar id="sidebar-areaBroadcast" name="areaBroadcast">
<item id="areaBroadcast" name="areaBroadcast"
url="areaBroadcast.jsp"
description="broadcast messages to users in specific area" />
</sidebar>
        </tab>
    </adminconsole>
</plugin>

2、实现Plugin 类和IQHandler

        Plugin 类主要起到的作用是初始化和释放资源,在初始化的过程中,最重要的的注册一批IQHandlerIQHander 的作用有点类似于Spark 中的IQProvider,其实就是解析XML 文件之后,生成一些有用的实例,以供处理。下面分别给出一个扩展用户注册信息字段(增加了一个province省份字段)的Plugin 类的实例和IQProvider 的实例。
说明:下面这个例子是按province给用户发消息的例子,先为用户扩展了一个省份字段,然后在管理员控制台界面添加一个页面用来给不同省份的用户发消息。
步骤:1,UserInfoIQHander 构造方法中初始化拦截请求消息info; 2,AreaBroadcastPlugin 构造方法中注册拦截器; 3,UserInfoIQHander 重写handleIQ请求处理方法获取请求数据,读写数据库,构造返回协议,返回。

AreaBroadcastPlugin 类:
public class AreaBroadcastPlugin implements Plugin {
private XMPPServer server;
private MessageRouter msgRouter;
private UserInfoDao userInfoDao;
private String domain;
UserInfoIQHander userInfoIQHander = null;

@Override
public void destroyPlugin() {
System.out.println("destroy AreaBroadcastPlugin");
/*移除注册用户信息拦截器 */
if (userInfoIQHander != null)
 {
  server.getIQRouter().removeHandler(userInfoIQHander);
  userInfoIQHander = null;
  }
}

/**
* 拦截包含http://jivesoft.org/protocol/userRegister查询的特定请求,如下:
* 例:
 * 
<iq id="g0G4m-1" to="zhanglj" type="set">
 *   <query xmlns="http://jivesoft.org/protocol/userRegister">
 * <username>re</username>
 * <email>username@test.com</email>
 * <name>username</name>
 * <password>1</password>
 * <province>北京</province>
 *    </query>
 * </iq>
*/
@Override
public void initializePlugin(PluginManager manager, File pluginDirectory) {
System.out.println("initialize AreaBroadcastPlugin");
server = XMPPServer.getInstance();
/*
注册用户注册请求拦截器*/
userInfoIQHander = new UserInfoIQHander("UserInfoIQHander");
server.getIQRouter().addHandler(userInfoIQHander);   
domain = server.getServerInfo().getXMPPDomain();
msgRouter = server.getMessageRouter();
}

/**
 * 管理员给特定区域用户发消息,这里这个方法没用到,发消息是从管理员控制台jsp页面中直接调用的
 * 
 * 1.发消息
 * <message id="j0Dw7-59" from="zhouds@zhanglj" to="zhang@zhanglj"><body>sdfsdf</body></message>
 *
 * 2.收消息——离线也能收到
 * <message id="j0Dw7-59" to="zhang@zhanglj" from="zhouds@zhanglj/Spark 2.6.3"><body>sdfsdf</body></message>
 *
 * 1.发通知
 * <message id="j0Dw7-61" to="zhang@zhanglj" type="headline"><body>通知</body></message>
 *
 *2.收通知——离线无法收到区别在于发消息中有发送人
 * <message id="j0Dw7-61" to="zhang@zhanglj" type="headline" from="zhouds@zhanglj/Spark 2.6.3"><body>通知</body></message>
 *
*/
public boolean sendMsg(String province, String message){
try{
userInfoDao = new UserInfoDao();
List<String> ls = new ArrayList<String>();
ls = userInfoDao.getUsernameByProvince(URLDecoder.decode(province, "UTF-8"));
for(String username : ls){
Message Msg = new Message();
Msg.setFrom("admin@" + domain);  /*有此为发消息,无为发通知*/
Msg.setTo(username + "@" + domain);
Msg.setSubject("新闻");
Msg.addChildElement("body", "").addText(URLDecoder.decode(message, "UTF-8"));
msgRouter.route(Msg);
}
return true;
}catch(Exception e){
e.printStackTrace();
return false;
}
}

}

UserInfoIQHander 类:
public class UserInfoIQHander extends IQHandler {
private IQHandlerInfo info;
private UserInfoDao userInfoDao;
private XMPPServer server;
private String domain;
private UserManager userManager;

/**
* 初始化查询用户信息请求和服务器域
*/
public UserInfoIQHander(String moduleName) {
super(moduleName);
/*
初始化用户注册请求*/
info = new IQHandlerInfo("query", "http://jivesoft.org/protocol/userRegister");
/*获取服务器域*/
server = XMPPServer.getInstance();
domain = server.getServerInfo().getXMPPDomain();
userManager = server.getUserManager();
}

/**
* 用户注册,从xml中解析用户信息并插入数据库,返回如下信息:
* 1.用户名已存在:
* <iq type="error" id="g0G4m-1" from="zhanglj" to="zhang@zhanglj/Spark 2.6.3">
*   <query xmlns=" http:// jivesoft .org/protocol/userRegister">
*    <register xmlns="" result="Username 're' already exists"/>
*   </query>
* </iq>
*
* 2.注册成功:
* <iq type="result" id="g0G4m-1" from="zhanglj" to="zhang@zhanglj/Spark 2.6.3">
*   <query xmlns=" http:// jivesoft .org/protocol/userRegister">
*    <register xmlns="" result="success"/>
*   </query>
* </iq>

*/
@Override
public IQ handleIQ(IQ iq) throws UnauthorizedException {
IQ reply = IQ.createResultIQ(iq);
try {
userInfoDao = new UserInfoDao();
Element childElement = iq.getChildElement();
String namespace = childElement.getNamespaceURI();
if (IQ.Type.set.equals(iq.getType())){
String username = null;
           String password = null;
           String email = null;
           String name = null;
           String province = null;
Element iqElement = iq.getChildElement();
username = iqElement.elementText("username");

           password = iqElement.elementText("password");
           email = iqElement.elementText("email");
           name = iqElement.elementText("name");
           province = iqElement.elementText("province");
       userManager = server.getUserManager();
boolean isRegisteredUser = userManager.isRegisteredUser(username);
if(isRegisteredUser){
   // The user already exists since no exception, so:
//throw new UserAlreadyExistsException("Username " + username + " already exists");
reply.setType(IQ.Type.error);
Element query = new DefaultElement("query");
query.addElement("register").addAttribute("result", "Username '" + username + "' already exists");
query.addNamespace("", "http://qnsoft/protocol/registerAreaUser");
reply.setChildElement(query);
return reply;

}
/* 插入用户信息 */
userInfoDao.createUser(username,password,name,email,province);
}
/* 构造信息并返回 */
if ("http://jivesoft.org/protocol/userRegister".equals(namespace)) {
reply.setType(IQ.Type.result);
Element query = new DefaultElement("query");
query.addElement("register").addAttribute("result", "success");
query.addNamespace("", "http://jivesoft.org/protocol/userRegister");
reply.setChildElement(query);
}
} catch (Exception e) {
e.printStackTrace();
}
return reply;
}
}

UserInfoDao类:
public class UserInfoDao{
    private static final Logger Log = LoggerFactory.getLogger(DefaultUserProvider.class);
    private static final String GET_USERNAME_BY_PROVINCE = "SELECT username FROM ofUser WHERE province=?";
    private static final String INSERT_USER =
        "INSERT INTO ofUser (username,plainPassword,encryptedPassword,name,email,creationDate,modificationDate,province) " +
        "VALUES (?,?,?,?,?,?,?,?)";
    
   /*查询特定省份的用户名列表*/
    public List<String> getUsernameByProvince(String province){
    Connection con = null;
         PreparedStatement pstmt = null;
         ResultSet rs = null;
         List<String> list = new ArrayList<String>();
         try {
             con = DbConnectionManager.getConnection();
             pstmt = con.prepareStatement(GET_USERNAME_BY_PROVINCE);
             pstmt.setString(1, province);
             rs = pstmt.executeQuery();
             if (rs.wasNull()) {
                 throw new UserNotFoundException();
             }
             while(rs.next()){
          String username = rs.getString(1);
  list.add(username);
             }
         }catch (Exception e) {
             e.printStackTrace();
         }
         finally {
             DbConnectionManager.closeConnection(rs, pstmt, con);
         }
  return list;
    }


    /*
创建带有省份的用户当然要先在数据库ofuser表中添加一个province字段*/
    public void createUser(String username, String password, String name, String email, String province)
{
   // Determine if the password should be stored as plain text or encrypted.
   boolean usePlainPassword = JiveGlobals.getBooleanProperty("user.usePlainPassword");
   String encryptedPassword = null;
   if (!usePlainPassword) {
       try {
           encryptedPassword = AuthFactory.encryptPassword(password);
           // Set password to null so that it's inserted that way.
           password = null;
       }
       catch (UnsupportedOperationException uoe) {
           // Encrypting the password may have failed if in setup mode. Therefore,
           // use the plain password.
       }
   }

   Date now = new Date();
   Connection con = null;
   PreparedStatement pstmt = null;
   try {
       con = DbConnectionManager.getConnection();
       pstmt = con.prepareStatement(INSERT_USER);
       pstmt.setString(1, username);
       if (password == null) {
           pstmt.setNull(2, Types.VARCHAR);
       }
       else {
           pstmt.setString(2, password);
       }
       if (encryptedPassword == null) {
           pstmt.setNull(3, Types.VARCHAR);
       }
       else {
           pstmt.setString(3, encryptedPassword);
       }
       if (name == null || name.matches("\\s*")) {
           pstmt.setNull(4, Types.VARCHAR);
       }
       else {
           pstmt.setString(4, name);
       }
       if (email == null || email.matches("\\s*")) {
           pstmt.setNull(5, Types.VARCHAR);
       }
       else {
           pstmt.setString(5, email);
       }
       pstmt.setString(6, StringUtils.dateToMillis(now));
       pstmt.setString(7, StringUtils.dateToMillis(now));
       if (province == null) {
           pstmt.setNull(8, Types.VARCHAR);
       }
       else {
           pstmt.setString(8, province);
       }
       pstmt.execute();
   }
   catch (Exception e) {
       Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
   }
   finally {
       DbConnectionManager.closeConnection(pstmt, con);
   }
return;
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值