openfire插件开发(plugin sevlet)入门

openfire插件开发(plugin sevlet)入门

原创  2014年05月13日 21:50:38

近来几天为了写一个openfire的小插件可谓脑袋都大了。。。自己又是初学小菜鸟一个,学习过程算是非常的磕磕绊绊。这里记录下来仅供后来的同学参考,也少走些弯路。勤能补拙,期望大家多多支持,共同学习,共同进步。


1.plugin插件开发

网上关于openfire插件开发的有很多,其中jooho大大的《跟我一步一步开发自己的openfire插件》很是受欢迎,我这里也是参考他的。不过相对于他的《 跟我一步一步开发自己的Openfire插件》相对于我这样的小白还是有点费解的,所以这里我就更简单通俗的再讲解一遍,在助人为乐的同时也能加深学习。

本人用的是myeclipse,其他开发工具类同。

1.1简单插件入门(简单plugin结构)

在结构方面我最初也是很头疼,给那么多图反而更容易把人搞混淆。我们还是用文字加配图说明吧。

新建一个 java project ,这里命名为 test_plugin。(new -> java project -> finish)然后把src删除或重命名为 src/plugins/test/src/java (即与openfire原生插件保持一致)。若是删除src的话,就新建 Source Folder命名为 src/plugins/test/src/java (new ->  Source Folder )。然后项目目录下就会自动生成对应的 src文件夹及层级结构。

   

同样,在工程项目中新建文件夹(new ->folder)命名 build ,lib .其中build下边新建 build.properties 和 build.xml文件,用以ant编译生成插件。llib文件存放openfire等jar库。这里将openfir.jar + sevlet.jar拷贝至lib目录并add to buid path.

(servlet其实可以不用,仅导入openfire.jar即可)

1.2 build文件

build文件用于编译和打包,很多像我这样的小白基本不会用代码打包编译。网上有推荐利用源码包里边的build来编译打包,这也是一种方法,这里我使用的是jooho大大写好的build文件。我稍微做了些修改。贴上两个文件源码

uild.properties

[html]  view plain  copy
  1. tomcat.home=D:/Program Files/tomcat-5.0.28  
  2. # If you want to build a plugin, please set the value to the plugin name.  
  3. # Note:The plugin name must is the same as the plugins folder.  
  4. plugin.name=test  
(tomcat_home是你自己的tomcat安装/解压路径,plugin name是插件名)

build.xml

[html]  view plain  copy
  1. <project name="Webapp Precompilation" default="openfire-plugins" basedir=".">  
  2.       
  3.     <!-- 全局变量设置 -->  
  4.     <property file="build.properties" />  
  5.       
  6.     <!-- 插件源码位置 -->  
  7.     <property name="plugin.path" value="../src/plugins/${plugin.name}/src" />  
  8.       
  9.     <!-- web应用输出目录 -->  
  10.     <property name="webapp.output.path" value="../src/plugins/${plugin.name}/bin" />  
  11.       
  12.     <!-- java servlet相关文件编译jar存放位置 -->  
  13.     <property name="java.jar.dir" value="${webapp.output.path}/java-dist"/>  
  14.       
  15.     <!-- jsp servlet编译后jar存放位置 -->  
  16.     <property name="jsp.jar.dir" value="${webapp.output.path}/jsp-dist/lib"/>  
  17.   
  18.     <!-- 定义java servlet编译打包的Jar包名称 -->  
  19.     <property name="java.jar" value="${java.jar.dir}/plugin-${plugin.name}.jar"/>  
  20.       
  21.     <!-- 定义jsp servlet编译打包的Jar包名称 -->  
  22.     <property name="jsp.jar" value="${jsp.jar.dir}/plugin-${plugin.name}-jsp.jar"/>  
  23.   
  24.     <!-- jsp servlet配置到web.xml中 -->  
  25.     <property name="plugin.web.xml" value="${webapp.output.path}/jsp-dist/web.xml"/>  
  26.   
  27.     <!-- 编译jsp 并生成相关jar、xml文件 -->  
  28.     <target name="jspc">  
  29.   
  30.         <taskdef classname="org.apache.jasper.JspC" name="jasper2">  
  31.             <classpath id="jspc.classpath">  
  32.                 <pathelement location="${java.home}/../lib/tools.jar" />  
  33.                 <fileset dir="${tomcat.home}/bin">  
  34.                     <include name="*.jar" />  
  35.                 </fileset>  
  36.                 <fileset dir="${tomcat.home}/server/lib">  
  37.                     <include name="*.jar" />  
  38.                 </fileset>  
  39.                 <fileset dir="${tomcat.home}/common/lib">  
  40.                     <include name="*.jar" />  
  41.                 </fileset>  
  42.                 <!--  
  43.                 <fileset dir="D:/Workspace/openfire/build/lib">  
  44.                     <include name="**/*.jar" />  
  45.                 </fileset-->  
  46.             </classpath>  
  47.         </taskdef>  
  48.   
  49.         <!-- 编译jsp -> servlet class -->  
  50.         <jasper2 javaEncoding="UTF-8" validateXml="false"  
  51.             uriroot="${plugin.path}/web"  
  52.             outputDir="${webapp.output.path}/jsp-dist/src"  
  53.             package="com.qiao.univer.blog.plugin.${plugin.name}" />  
  54.   
  55.         <!-- 编译后的servlet class 配置到web.xml文件中 -->  
  56.         <jasper2  
  57.             validateXml="false"  
  58.             uriroot="${plugin.path}/web"  
  59.             outputDir="${webapp.output.path}/jsp-dist/src"  
  60.             package="com.qiao.univer.blog.plugin.${plugin.name}"  
  61.             webXml="${plugin.web.xml}"/>  
  62.     </target>  
  63.   
  64.     <!-- 编译jsp 并将其打jar包 -->  
  65.     <target name="compile">  
  66.   
  67.         <mkdir dir="${webapp.output.path}/jsp-dist/classes" />  
  68.         <mkdir dir="${webapp.output.path}/jsp-dist/lib" />  
  69.         <mkdir dir="${webapp.output.path}/jsp-dist/src" />  
  70.   
  71.         <javac destdir="${webapp.output.path}/jsp-dist/classes" optimize="off"  
  72.             encoding="UTF-8" debug="on" failonerror="false"  
  73.             srcdir="${webapp.output.path}/jsp-dist/src" excludes="**/*.smap">  
  74.             <classpath>  
  75.                 <pathelement location="${webapp.output.path}/jsp-dist/classes" />  
  76.                 <fileset dir="${webapp.output.path}/jsp-dist/lib">  
  77.                     <include name="*.jar" />  
  78.                 </fileset>  
  79.                 <pathelement location="${tomcat.home}/common/classes" />  
  80.                 <fileset dir="${tomcat.home}/common/lib">  
  81.                     <include name="*.jar" />  
  82.                 </fileset>  
  83.                 <pathelement location="${tomcat.home}/shared/classes" />  
  84.                 <fileset dir="${tomcat.home}/shared/lib">  
  85.                     <include name="*.jar" />  
  86.                 </fileset>  
  87.                 <fileset dir="${tomcat.home}/bin">  
  88.                     <include name="*.jar" />  
  89.                 </fileset>  
  90.             </classpath>  
  91.             <include name="**" />  
  92.             <exclude name="tags/**" />  
  93.         </javac>  
  94.   
  95.         <jar jarfile="${jsp.jar}" basedir="${webapp.output.path}/jsp-dist/classes" />  
  96.     </target>  
  97.   
  98.     <!-- 将java servlet打包成jar -->  
  99.     <target name="java-jar">  
  100.         <mkdir dir="${java.jar.dir}"/>  
  101.         <jar jarfile="${java.jar}">  
  102.             <fileset dir="../bin" includes="**/*.class"/>  
  103.         </jar>  
  104.     </target>  
  105.   
  106.     <!-- 生成可部署的插件包 -->  
  107.     <target name="plug-jar">  
  108.         <!-- 插件插件包相关lib、 web目录 -->  
  109.         <mkdir dir="${webapp.output.path}/${plugin.name}/lib"/>  
  110.         <mkdir dir="${webapp.output.path}/${plugin.name}/web/WEB-INF"/>  
  111.   
  112.         <!-- 复制jsp servlet的jar和java servlet的相关jar包到插件包的lib目录下 -->  
  113.         <copy file="${java.jar}" todir="${webapp.output.path}/${plugin.name}/lib"/>  
  114.         <copy file="${jsp.jar}" todir="${webapp.output.path}/${plugin.name}/lib"/>  
  115.   
  116.         <!-- 将相关的图片、帮助文档、修改日志等文件复制到插件目录下 -->  
  117.         <copy todir="${webapp.output.path}/${plugin.name}">  
  118.             <fileset dir="${plugin.path}" includes="*.*"/>  
  119.         </copy>  
  120.         <copy todir="${webapp.output.path}/${plugin.name}/web">  
  121.             <fileset dir="${plugin.path}/web">  
  122.                 <include name="*"/>  
  123.                 <include name="**/*.*"/>  
  124.                 <exclude name="**/*.xml"/>  
  125.                 <exclude name="**/*.jsp"/>  
  126.             </fileset>  
  127.         </copy>  
  128.         <!-- jsp servlet的web复制到插件目录下 -->  
  129.         <copy file="${plugin.web.xml}" todir="${webapp.output.path}/${plugin.name}/web/WEB-INF"/>  
  130.         <copy todir="${webapp.output.path}/${plugin.name}/web">  
  131.             <fileset dir="${plugin.path}/web" includes="**/*.xml"/>  
  132.         </copy>  
  133.         <!-- 将国际化相关资源文件复制到插件目录下   
  134.         <copy file="${webapp.output.path}/bin/i18n" todir="${webapp.output.path}/${plugin.name}"/>  
  135.         -->  
  136.         <!-- 产生可部署插件包 -->  
  137.         <jar jarfile="${webapp.output.path}/${plugin.name}.jar">  
  138.             <fileset dir="${webapp.output.path}/${plugin.name}" includes="**/**"/>  
  139.         </jar>  
  140.     </target>  
  141.   
  142.     <!-- 生成没有Web资源的可部署插件包 -->  
  143.     <target name="java-plug-jar">  
  144.         <!-- 插件插件包相关lib、 web目录 -->  
  145.         <mkdir dir="${webapp.output.path}/${plugin.name}/lib"/>  
  146.   
  147.         <!-- 复制java servlet的相关jar包到插件包的lib目录下 -->  
  148.         <copy file="${java.jar}" todir="${webapp.output.path}/${plugin.name}/lib"/>  
  149.   
  150.         <!-- 将相关的图片、帮助文档、修改日志等文件复制到插件目录下 -->  
  151.         <copy todir="${webapp.output.path}/${plugin.name}">  
  152.             <fileset dir="${plugin.path}" includes="*.*"/>  
  153.         </copy>  
  154.   
  155.         <!-- 产生可部署插件包 -->  
  156.         <jar jarfile="${webapp.output.path}/${plugin.name}.jar">  
  157.             <fileset dir="${webapp.output.path}/${plugin.name}" includes="**/**"/>  
  158.         </jar>  
  159.     </target>  
  160.   
  161.     <!-- 清理生成的文件 -->  
  162.     <target name="clean">  
  163.         <delete file="${webapp.output.path}/${plugin.name}.jar"/>  
  164.         <delete dir="${webapp.output.path}/${plugin.name}"/>  
  165.         <delete dir="${webapp.output.path}/jsp-dist"/>  
  166.         <delete dir="${webapp.output.path}/java-dist"/>  
  167.     </target>  
  168.   
  169.     <target name="all" depends="clean,jspc,compile"/>  
  170.   
  171.     <target name="openfire-plugin" depends="jspc,java-jar"/>  
  172.   
  173.     <target name="openfire-plugins" depends="all,java-jar,plug-jar"/>  
  174.   
  175.     <target name="openfire-plugin-java" depends="clean,java-jar,java-plug-jar"/>  
  176. </project>  
(这里有两点请注意修改
这两个地方请修改为你新建的包名。例如我的 com.qiao.univer.blogplugin)
此处不修改对 1.1简单plugin并没有影响,但对于复杂插件开发如servlet等功能添加将导致打包失败。

1.3 其他文件结构

在source folder下新建包(例 com.qiao.test.plugin),此包即为上边要修改的地方。

新建TestPlugin 类并实现Plugin接口 中的 init 和 destroy方法:

TestPlugin .java

[java]  view plain  copy
  1. import java.io.File;  
  2.   
  3. import org.jivesoftware.openfire.XMPPServer;  
  4. import org.jivesoftware.openfire.container.Plugin;  
  5. import org.jivesoftware.openfire.container.PluginManager;  
  6.   
  7. public class TestPlugin implements Plugin {  
  8.   
  9.     private XMPPServer server;  
  10.   
  11.     @Override  
  12.     public void initializePlugin(PluginManager manager, File pluginDirectory) {  
  13.         server = XMPPServer.getInstance();  
  14.         System.out.println("qiao init Plugin!");  
  15.         System.out.println(server.getServerInfo());  
  16.     }  
  17.   
  18.     @Override  
  19.     public void destroyPlugin() {  
  20.         System.out.println("qiao destroy Plugin!");  
  21.     }  
  22. }  

在自动生成的src文件夹层级结构最底层src目录下添加 

changelog.htmllogo_small.giflogo_large.gif readme.html 和plugin.xml文件,其中前面是个可以从openfire源码中拷贝

changelog.html是修改日志;logo_small.gif是插件图标;plugin.xml是我们配置插件的文件,这个很重要。

配置 plugin.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <plugin>  
  3.     <!-- Main plugin class  这里是最重要滴,就是你的插件的全路径-->  
  4.     <class>com.qiao.test.plugin.TestPlugin</class>  
  5.    
  6.     <!-- Plugin meta-data -->  
  7.     <name>TestPlugin</name>  
  8.     <description>This is testplugin.</description>  
  9.     <author>qiao</author>  
  10.    
  11.     <version>1.0</version>  
  12.     <date>10/05/20134</date>  
  13.     <url>http://localhost:9090/openfire/plugins.jsp</url>  
  14.     <minServerVersion>3.4.1</minServerVersion>  
  15.     <licenseType>gpl</licenseType>  
  16.    
  17.     <adminconsole>     
  18.     </adminconsole>  
  19. </plugin>  
注意上面的class的配置,那个配置是最为重要的,配置的是插件的全路径;name是插件的名称,安装后的插件名称;author是插件作者;lincenseType是协议;adminconsole是配置插件关联的页面的,这里用不上

至此,整个框架大概就是这样:



 编写ant命令,打可部署jar包。如果你不懂ant命令也没关系,你总知道java的基本常用的dos命令。只不过ant就是将dos转换成一个可重复多次调用的命令行。我们这里就是用上边的build.xml利用ant来编译和打包。

以下是jooho大大的话,小白可以略过。

注意:这里我没有编写编译java代码到class的步骤,我是直接使用MyEclipse自动编译的bin/class的。如果你没有用MyEclipse或Eclipse,那么你需要将src中的Java代码编译class。

这里需要配置tomcat的目录,我这里是5.0.28的版本。我用tomcat6有些问题,这里主要是用tomcat中的lib库,帮助我们编译jsp。还需要配置你当前工程的所在目录,也就是工程在Eclipse中的目录位置。最后你需要配置插件的名称和插件在工程中的所在目录,这个是在打包的时候,需要将其他的html、image、xml等资源导入的jar内。

因为这里的插件是不带jsp的,所以我们执行clean、java-jar、java-plugin-jar。也就是openfire-plugin-java这个命令即可。执行命令后,你可以看到工作空间的工程目录下多了目录和文件。

1.4 插件打包部署


我们右键点击build.xml选择 run as -> ant build..


一个openfire的完美开发实例


选择openfire-plugin-java


一个openfire的完美开发实例


等待打包完成

一个openfire的完美开发实例

打包完成后刷新工程项目,会看到多出来个bin文件夹


打包成功的test.jar部署到openfire服务器,部署有两种方法:

1.直接拷贝至openfire安装目录下的plugins的文件夹内,自启动后它会自动解压

一个openfire的完美开发实例  

2.登录openfire管理界面,选择插件,上传

在openfire启动的情况下,访问http://localhost:9090/plugin-admin.jsp页面,点击页面下方的upload plugin完成插件上传操作。

插件按照成功后,访问http://localhost:9090/plugin-admin.jsp页面你就可以看到安装好的插件了。



测试插件。启动openfire,就可以看到插件的运行结果如下:



2.含有servlet和JSP的插件开发

2.1 serlet开发及配置

 新建一个TestServlet.java 继承HttpServlet

TestServlet.java

[java]  view plain  copy
  1. import java.io.IOException;  
  2. import java.io.PrintWriter;  
  3. import javax.servlet.ServletException;  
  4. import javax.servlet.http.HttpServlet;  
  5. import javax.servlet.http.HttpServletRequest;  
  6. import javax.servlet.http.HttpServletResponse;  
  7.   
  8. import org.jivesoftware.admin.AuthCheckFilter;  
  9.   
  10. public class TestServlet extends HttpServlet {  
  11.   
  12.     private static final long serialVersionUID = 1L;  
  13.     private static final String SERVICE_NAME = "test/*";  
  14.   
  15.     @Override  
  16.     public void init() throws ServletException {  
  17.         super.init();  
  18.         AuthCheckFilter.addExclude(SERVICE_NAME);  
  19.     }  
  20.   
  21.     @Override  
  22.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  23.           
  24.         response.setContentType("text/plain");  
  25.         PrintWriter out = response.getWriter();  
  26.         System.out.println("请求TestServlet GET Method");  
  27.         out.print("请求TestServlet GET Method");  
  28.         out.flush();  
  29.     }  
  30.    
  31.     @Override  
  32.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  33.           
  34.         response.setContentType("text/plain");  
  35.         PrintWriter out = response.getWriter();  
  36.         System.out.println("请求TestServlet GET Method");  
  37.         out.print("请求TestServlet POST Method");  
  38.         out.flush();  
  39.     }  
  40.   
  41.     @Override  
  42.     public void destroy() {  
  43.         super.destroy();  
  44.         AuthCheckFilter.removeExclude(SERVICE_NAME);  
  45.     }  
  46. }  

其中 AuthCheckFilter.addExclude(SERVICE_NAME); 是为了避免登录验证,如果没有这一段代码。每次访问TestServelt都会出现跳转到登录界面的情况。

在项目目录src层次结构最底层的src添加web目录,在目录下建立WEB-INF目录,添加web-custom.xml文件(文件名应该是固定的)。在里面配置我们的servlet。

web-custom.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="ISO-8859-1"?>  
  2. <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">  
  3. <web-app>  
  4.       
  5.     <servlet>  
  6.         <servlet-class>com.qiao.test.plugin.servlet.TestServlet</servlet-class>  
  7.         <servlet-name>TestServlet</servlet-name>  
  8.     </servlet>  
  9.       
  10.     <servlet-mapping>  
  11.         <servlet-name>TestServlet</servlet-name>  
  12.         <url-pattern>/servlet</url-pattern>  
  13.     </servlet-mapping>  
  14. </web-app>  


2.2 Jsp开发及配置

在web目录下添加jsp文件。例 test-demo.jsp

test-demo.jsp

[html]  view plain  copy
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
  3. <html>  
  4.   <head>  
  5.     <title>test service: 你好openfire</title>  
  6.     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7.     <meta name="pageID" content="test-service"/>  
  8.   </head>  
  9.     
  10.   <body>  
  11.     <h3>test server jsp!! <a href="/plugins/test/servlet">TestServlet</a></h3>  
  12.     <div class="jive-contentBoxHeader">jive-contentBoxHeader</div>  
  13.     <div class="jive-contentBox">jive-contentBox</div>  
  14.       
  15.     <div class="jive-table">  
  16.         <table cellpadding="0" cellspacing="0" border="0" width="100%">  
  17.             <thead>  
  18.                 <tr>  
  19.                     <th> sss</th>  
  20.                     <th nowrap>a</th>  
  21.                     <th nowrap>b</th>  
  22.                 </tr>  
  23.             </thead>  
  24.             <tbody>  
  25.                 <tr>  
  26.                     <td align="center">asdf</td>  
  27.                     <td align="center">asdf</td>  
  28.                     <td align="center">asdf</td>  
  29.                 </tr>  
  30.                 <tr class="jive-even">  
  31.                        <td align="center">asdf</td>  
  32.                     <td align="center">asdf</td>  
  33.                     <td align="center">asdf</td>  
  34.                 </tr>  
  35.                 <tr class="jive-odd">  
  36.                        <td align="center">asdf</td>  
  37.                     <td align="center">asdf</td>  
  38.                     <td align="center">asdf</td>  
  39.                 </tr>  
  40.              </tbody>  
  41.         </table>  
  42.     </div>  
  43.   </body>  
  44. </html>  

其中最重要的一点就是:<meta name="pageID" content="sample-service"/>这个pageID。这里的是固定的,后面的content对应我们plugin.xml的内容(等下看看plguin.xml的配置)。然后可以适当的看下里面table的 属性和样式,因为很多时候会在jsp中显示内容,且用table布局的。
改下之前的plugin.xml的配置,配置组件在openfire 管理员控制台的哪个地方显示,以及显示的页面。

plugin.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <plugin>  
  3.     <!-- Main plugin class  这里是最重要滴,就是你的插件的全路径-->  
  4.     <class>com.qiao.test.plugin.TestPlugin</class>  
  5.    
  6.     <!-- Plugin meta-data -->  
  7.     <name>TestPlugin</name>  
  8.     <description>This is testplugin.</description>  
  9.     <author>qiao</author>  
  10.    
  11.     <version>1.0</version>  
  12.     <date>10/05/20134</date>  
  13.     <url>http://localhost:9090/openfire/plugins.jsp</url>  
  14.     <minServerVersion>3.4.1</minServerVersion>  
  15.     <licenseType>gpl</licenseType>  
  16.    
  17.     <adminconsole>     
  18.         <tab id="tab-server">  
  19.             <sidebar id="sidebar-server-settings">  
  20.                 <item id="test-service" name="Test Service" url="test-demo.jsp"  
  21.                      description="Click is trigger blog plugin" />  
  22.             </sidebar>  
  23.         </tab>  
  24.     </adminconsole>  
  25. </plugin>  

注意,这里是jsp里边的 pageID


2.3 运行ant,发布插件

这里选中openfire-plugins(default)命令打包,然后发布test.jar
注意:若最初没有修改build.xml中的包名(com.***略),这里会报错。打包失败



将test.jar发布之后,启动openfire,在openfire管理员控制台页面的服务器->服务器设置中就可以看到Test Service插件了。

点击Sample Servlet就可以看到openfire控制台打印请求的文字信息。

3.Servlet拓展问题及解决

3.1.servlet登录验证问题

在没有特殊要求的情况下,我们希望直接调用sevlet却常常会跳转到另外一个界面,即管理控制台登录界面。

那怎么单独对自己插件的url进行排除呢?接着往下看!

有两种方法:修改openfire的web.xml或使用AuthCheckFilter.addExclude方法其中一种即可

1)修改openfire的web.xml

这个web.xml出现在openfire的源码很多地方,了解正确的配置方法很重要。下面展示不同路径下的web.xml修改说明,取其一即可。

a. 修改/openfire_src/src/web/WEB-INF/web.xml,修改完后,记得还要用ant编译一次并重启才能生效。

b. 修改/openfire_src/target/openfire/plugins/admin/webapp/WEB-INF/web.xml

修改完后,直接重启即可生效,本方法同样适用于安装版的openfire

[html]  view plain copy
  1. <filter>  
  2.     <filter-name>AuthCheck</filter-name>  
  3.     <filter-class>org.jivesoftware.admin.AuthCheckFilter</filter-class>  
  4.     <init-param>  
  5.         <param-name>excludes</param-name>  
  6.         <param-value>  
  7.             popplugin/*,login.jsp,index.jsp?logout=true,setup/index.jsp,setup/setup-*,.gif,.png,error-serverdown.jsp,setup/clearspace-integration-prelogin.jsp  
  8.         </param-value>  
  9.     </init-param>  
  10. </filter>  


 url的匹配规则比较复杂,有兴趣的同学可以去看AuthCheckFilter类源码,如果要测试自己的pattern对不对,可以使用org.jivesoftware.admin.AuthCheckFilterTest类执行JUnitTest试试,如自己加上一段:

[java]  view plain copy
  1. assertTrue(AuthCheckFilter.testURLPassesExclude("popplugin/sendmessage""popplugin*"));  
  2. assertTrue(AuthCheckFilter.testURLPassesExclude("popplugin/sendmessage""popplugin/sendmessage"));  

 

2)使用AuthCheckFilter.addExclude方法

调用该方法和配置web.xml的效果是完全一样的,个人建议用此方法,因为本方法绿色安全、无污染,不修改和破坏原生openfire代码。

这个方法可以在servlet的init方法或plugin的initializePlugin方法中调用。

个人建议在servlet的init方法中调用,因为servlet的init方法比plugin的initializePlugin方法更早初始化,这个问题在“插件初始化顺序”会讲到。

使用完后记得removeExclude一下,有始有终嘛。

[java]  view plain copy
  1. @Override  
  2. public void init() throws ServletException  
  3. {  
  4.     System.out.println("UserMgrServlet init....");  
  5.     AuthCheckFilter.addExclude("popplugin/usermgr*");  
  6.     AuthCheckFilter.addExclude("popplugin/usermgr/*");  
  7. }  
  8.   
  9. @Override  
  10. public void destroy()  
  11. {  
  12.     System.out.println("UserMgrServlet destroy....");  
  13.     // Release the excluded URL  
  14.     AuthCheckFilter.removeExclude("popplugin/usermgr*");  
  15.     AuthCheckFilter.removeExclude("popplugin/usermgr/*");  
  16. }  


 注意:这种方式仅限于servlet的访问,如果访问插件的jsp/html页面,页面会报NullPointException异常,解决办法见下面的说明

3.2.servlet仍然需要登录验证或者报NullPointException空指针异常

有时候在添加 AuthCheckFilter.addExclude()后虽然没有跳转到登录验证了,但是若果没有登录过(session记录下管理控制台验证),会出现空指针现象:

异常:
java.lang.NullPointerException
	at org.jivesoftware.openfire.admin.decorators.main_jsp._jspService(main_jsp.java:195)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:547)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:480)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:520)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:941)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:409)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:875)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
	at org.eclipse.jetty.server.Dispatcher.include(Dispatcher.java:195)
	at com.opensymphony.module.sitemesh.filter.PageFilter.applyDecorator(PageFilter.java:156)
	at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:59)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1330)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:478)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:119)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:520)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:227)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:941)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:409)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:186)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:875)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
	at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
	at org.eclipse.jetty.server.Server.handle(Server.java:349)
	at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441)
	at org.eclipse.jetty.server.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:919)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:582)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:218)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:51)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:586)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:44)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533)
	at java.lang.Thread.run(Unknown Source)

而如果我们先在管理控制台登录一次就可以正常跳转了,这又怎么解决呢?!


还有一种情况,我们发现在单纯使用servlet作为服务接口提供数据时候,openfire会莫名地加上它原有的布局及样式,而我们仅仅只需要 servlet的 writer 去 out.print()来respons回应数据,这又该如何解决呢?


在多方查阅资料无果后,恨不得自己另写个服务器端的时候,终于找到了解决方案:

插件的页面不使用openfire控制台的页面框架

安装版的openfire的话,修改/openfire/plugins/admin/webapp/WEB-INF/decorators.xml文件

源代码版的,要修改/openfire_src/src/web/WEB-INF/decorators.xml文件

示例:

[html]  view plain copy
  1. <excludes>  
  2.     <pattern>/plugins/test/*</pattern>  
  3.     <pattern>/setup/setup-completed.jsp*</pattern>  
  4.     <pattern>/setup/setup-ldap-server_test.jsp*</pattern>  
  5.     <pattern>/setup/setup-ldap-user_test.jsp*</pattern>  
  6.     <pattern>/setup/setup-ldap-group_test.jsp*</pattern>  
  7.     <pattern>/setup/setup-clearspace-integration_test.jsp*</pattern>  
  8.     <pattern>/setup/setup-admin-settings_test.jsp*</pattern>  
  9.     <pattern>/login.jsp*</pattern>  
  10.     <pattern>/plugin-icon.jsp*</pattern>  
  11.     <pattern>/js/jscalendar/i18n.jsp*</pattern>  
  12. </excludes>  

这样,插件popplugin目录下的所有路径的jsp页面及js,css等,都能被自由的访问了。

至此,海阔天空任鸟飞了。。


感谢各位认真努力的童鞋看完这篇博文,同小白我一起了解学习了openfire插件的全过程。文中参考借鉴和挪用了不少大大的文字说明及图片,就不一一感谢了。希望看了这篇文章有收获的童鞋能给支持下。
最后附上今天开发的插件示例源码:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值