openfire插件開發(plugin sevlet)入門

近來幾天爲了寫一個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

tomcat.home=D:/Program Files/tomcat-5.0.28
# If you want to build a plugin, please set the value to the plugin name.
# Note:The plugin name must is the same as the plugins folder.
plugin.name=test
(tomcat_home是你自己的tomcat安裝/解壓路徑,plugin name是插件名)

build.xml

<project name="Webapp Precompilation" default="openfire-plugins" basedir=".">
	
	<!-- 全局變量設置 -->
	<property file="build.properties" />
	
	<!-- 插件源碼位置 -->
	<property name="plugin.path" value="../src/plugins/${plugin.name}/src" />
	
	<!-- web應用輸出目錄 -->
	<property name="webapp.output.path" value="../src/plugins/${plugin.name}/bin" />
	
	<!-- java servlet相關文件編譯jar存放位置 -->
	<property name="java.jar.dir" value="${webapp.output.path}/java-dist"/>
	
	<!-- jsp servlet編譯後jar存放位置 -->
	<property name="jsp.jar.dir" value="${webapp.output.path}/jsp-dist/lib"/>

	<!-- 定義java servlet編譯打包的Jar包名稱 -->
	<property name="java.jar" value="${java.jar.dir}/plugin-${plugin.name}.jar"/>
	
	<!-- 定義jsp servlet編譯打包的Jar包名稱 -->
	<property name="jsp.jar" value="${jsp.jar.dir}/plugin-${plugin.name}-jsp.jar"/>

	<!-- jsp servlet配置到web.xml中 -->
	<property name="plugin.web.xml" value="${webapp.output.path}/jsp-dist/web.xml"/>

	<!-- 編譯jsp 並生成相關jar、xml文件 -->
	<target name="jspc">

		<taskdef classname="org.apache.jasper.JspC" name="jasper2">
			<classpath id="jspc.classpath">
				<pathelement location="${java.home}/../lib/tools.jar" />
				<fileset dir="${tomcat.home}/bin">
					<include name="*.jar" />
				</fileset>
				<fileset dir="${tomcat.home}/server/lib">
					<include name="*.jar" />
				</fileset>
				<fileset dir="${tomcat.home}/common/lib">
					<include name="*.jar" />
				</fileset>
				<!--
                <fileset dir="D:/Workspace/openfire/build/lib">
                    <include name="**/*.jar" />
                </fileset-->
			</classpath>
		</taskdef>

		<!-- 編譯jsp -> servlet class -->
		<jasper2 javaEncoding="UTF-8" validateXml="false"
            uriroot="${plugin.path}/web"
            outputDir="${webapp.output.path}/jsp-dist/src"
            package="com.qiao.univer.blog.plugin.${plugin.name}" />

		<!-- 編譯後的servlet class 配置到web.xml文件中 -->
		<jasper2
            validateXml="false"
            uriroot="${plugin.path}/web"
            outputDir="${webapp.output.path}/jsp-dist/src"
            package="com.qiao.univer.blog.plugin.${plugin.name}"
            webXml="${plugin.web.xml}"/>
	</target>

	<!-- 編譯jsp 並將其打jar包 -->
	<target name="compile">

		<mkdir dir="${webapp.output.path}/jsp-dist/classes" />
		<mkdir dir="${webapp.output.path}/jsp-dist/lib" />
		<mkdir dir="${webapp.output.path}/jsp-dist/src" />

		<javac destdir="${webapp.output.path}/jsp-dist/classes" optimize="off"
            encoding="UTF-8" debug="on" failοnerrοr="false"
            srcdir="${webapp.output.path}/jsp-dist/src" excludes="**/*.smap">
			<classpath>
				<pathelement location="${webapp.output.path}/jsp-dist/classes" />
				<fileset dir="${webapp.output.path}/jsp-dist/lib">
					<include name="*.jar" />
				</fileset>
				<pathelement location="${tomcat.home}/common/classes" />
				<fileset dir="${tomcat.home}/common/lib">
					<include name="*.jar" />
				</fileset>
				<pathelement location="${tomcat.home}/shared/classes" />
				<fileset dir="${tomcat.home}/shared/lib">
					<include name="*.jar" />
				</fileset>
				<fileset dir="${tomcat.home}/bin">
					<include name="*.jar" />
				</fileset>
			</classpath>
			<include name="**" />
			<exclude name="tags/**" />
		</javac>

		<jar jarfile="${jsp.jar}" basedir="${webapp.output.path}/jsp-dist/classes" />
	</target>

	<!-- 將java servlet打包成jar -->
	<target name="java-jar">
		<mkdir dir="${java.jar.dir}"/>
		<jar jarfile="${java.jar}">
			<fileset dir="../bin" includes="**/*.class"/>
		</jar>
	</target>

	<!-- 生成可部署的插件包 -->
	<target name="plug-jar">
		<!-- 插件插件包相關lib、 web目錄 -->
		<mkdir dir="${webapp.output.path}/${plugin.name}/lib"/>
		<mkdir dir="${webapp.output.path}/${plugin.name}/web/WEB-INF"/>

		<!-- 複製jsp servlet的jar和java servlet的相關jar包到插件包的lib目錄下 -->
		<copy file="${java.jar}" todir="${webapp.output.path}/${plugin.name}/lib"/>
		<copy file="${jsp.jar}" todir="${webapp.output.path}/${plugin.name}/lib"/>

		<!-- 將相關的圖片、幫助文檔、修改日誌等文件複製到插件目錄下 -->
		<copy todir="${webapp.output.path}/${plugin.name}">
			<fileset dir="${plugin.path}" includes="*.*"/>
		</copy>
		<copy todir="${webapp.output.path}/${plugin.name}/web">
			<fileset dir="${plugin.path}/web">
				<include name="*"/>
				<include name="**/*.*"/>
				<exclude name="**/*.xml"/>
				<exclude name="**/*.jsp"/>
			</fileset>
		</copy>
		<!-- jsp servlet的web複製到插件目錄下 -->
		<copy file="${plugin.web.xml}" todir="${webapp.output.path}/${plugin.name}/web/WEB-INF"/>
		<copy todir="${webapp.output.path}/${plugin.name}/web">
			<fileset dir="${plugin.path}/web" includes="**/*.xml"/>
		</copy>
		<!-- 將國際化相關資源文件複製到插件目錄下 
        <copy file="${webapp.output.path}/bin/i18n" todir="${webapp.output.path}/${plugin.name}"/>
        -->
		<!-- 產生可部署插件包 -->
		<jar jarfile="${webapp.output.path}/${plugin.name}.jar">
			<fileset dir="${webapp.output.path}/${plugin.name}" includes="**/**"/>
		</jar>
	</target>

	<!-- 生成沒有Web資源的可部署插件包 -->
	<target name="java-plug-jar">
		<!-- 插件插件包相關lib、 web目錄 -->
		<mkdir dir="${webapp.output.path}/${plugin.name}/lib"/>

		<!-- 複製java servlet的相關jar包到插件包的lib目錄下 -->
		<copy file="${java.jar}" todir="${webapp.output.path}/${plugin.name}/lib"/>

		<!-- 將相關的圖片、幫助文檔、修改日誌等文件複製到插件目錄下 -->
		<copy todir="${webapp.output.path}/${plugin.name}">
			<fileset dir="${plugin.path}" includes="*.*"/>
		</copy>

		<!-- 產生可部署插件包 -->
		<jar jarfile="${webapp.output.path}/${plugin.name}.jar">
			<fileset dir="${webapp.output.path}/${plugin.name}" includes="**/**"/>
		</jar>
	</target>

	<!-- 清理生成的文件 -->
	<target name="clean">
		<delete file="${webapp.output.path}/${plugin.name}.jar"/>
		<delete dir="${webapp.output.path}/${plugin.name}"/>
		<delete dir="${webapp.output.path}/jsp-dist"/>
		<delete dir="${webapp.output.path}/java-dist"/>
	</target>

	<target name="all" depends="clean,jspc,compile"/>

	<target name="openfire-plugin" depends="jspc,java-jar"/>

	<target name="openfire-plugins" depends="all,java-jar,plug-jar"/>

	<target name="openfire-plugin-java" depends="clean,java-jar,java-plug-jar"/>
</project>
(這裏有兩點請注意修改
這兩個地方請修改爲你新建的包名。例如我的 com.qiao.univer.blogplugin)
此處不修改對 1.1簡單plugin並沒有影響,但對於複雜插件開發如servlet等功能添加將導致打包失敗。

1.3 其他文件結構

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

新建TestPlugin 類並實現Plugin接口 中的 init 和 destroy方法:

TestPlugin .java

import java.io.File;

import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.container.Plugin;
import org.jivesoftware.openfire.container.PluginManager;

public class TestPlugin implements Plugin {

	private XMPPServer server;

	@Override
	public void initializePlugin(PluginManager manager, File pluginDirectory) {
		server = XMPPServer.getInstance();
		System.out.println("qiao init Plugin!");
		System.out.println(server.getServerInfo());
	}

	@Override
	public void destroyPlugin() {
		System.out.println("qiao destroy Plugin!");
	}
}

在自動生成的src文件夾層級結構最底層src目錄下添加 

changelog.htmllogo_small.giflogo_large.gif readme.html 和plugin.xml文件,其中前面是個可以從openfire源碼中拷貝

changelog.html是修改日誌;logo_small.gif是插件圖標;plugin.xml是我們配置插件的文件,這個很重要。

配置 plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
	<!-- Main plugin class  這裏是最重要滴,就是你的插件的全路徑-->
	<class>com.qiao.test.plugin.TestPlugin</class>
 
	<!-- Plugin meta-data -->
	<name>TestPlugin</name>
	<description>This is testplugin.</description>
	<author>qiao</author>
 
	<version>1.0</version>
	<date>10/05/20134</date>
	<url>http://localhost:9090/openfire/plugins.jsp</url>
	<minServerVersion>3.4.1</minServerVersion>
	<licenseType>gpl</licenseType>
 
	<adminconsole>   
    </adminconsole>
</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

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jivesoftware.admin.AuthCheckFilter;

public class TestServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private static final String SERVICE_NAME = "test/*";

	@Override
	public void init() throws ServletException {
		super.init();
		AuthCheckFilter.addExclude(SERVICE_NAME);
	}

	@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();
        System.out.println("請求TestServlet GET Method");
        out.print("請求TestServlet GET Method");
        out.flush();
    }
 
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        response.setContentType("text/plain");
        PrintWriter out = response.getWriter();
        System.out.println("請求TestServlet GET Method");
        out.print("請求TestServlet POST Method");
        out.flush();
    }

	@Override
	public void destroy() {
		super.destroy();
		AuthCheckFilter.removeExclude(SERVICE_NAME);
	}
}

其中 AuthCheckFilter.addExclude(SERVICE_NAME); 是爲了避免登錄驗證,如果沒有這一段代碼。每次訪問TestServelt都會出現跳轉到登錄界面的情況。

在項目目錄src層次結構最底層的src添加web目錄,在目錄下建立WEB-INF目錄,添加web-custom.xml文件(文件名應該是固定的)。在裏面配置我們的servlet。

web-custom.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    
    <servlet>
        <servlet-class>com.qiao.test.plugin.servlet.TestServlet</servlet-class>
        <servlet-name>TestServlet</servlet-name>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>TestServlet</servlet-name>
        <url-pattern>/servlet</url-pattern>
    </servlet-mapping>
</web-app>


2.2 Jsp開發及配置

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

test-demo.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>test service: 你好openfire</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="pageID" content="test-service"/>
  </head>
  
  <body>
    <h3>test server jsp!! <a href="/plugins/test/servlet">TestServlet</a></h3>
    <div class="jive-contentBoxHeader">jive-contentBoxHeader</div>
    <div class="jive-contentBox">jive-contentBox</div>
    
    <div class="jive-table">
        <table cellpadding="0" cellspacing="0" border="0" width="100%">
            <thead>
                <tr>
                    <th> sss</th>
                    <th nowrap>a</th>
                    <th nowrap>b</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td align="center">asdf</td>
                    <td align="center">asdf</td>
                    <td align="center">asdf</td>
                </tr>
                <tr class="jive-even">
                       <td align="center">asdf</td>
                    <td align="center">asdf</td>
                    <td align="center">asdf</td>
                </tr>
                <tr class="jive-odd">
                       <td align="center">asdf</td>
                    <td align="center">asdf</td>
                    <td align="center">asdf</td>
                </tr>
             </tbody>
        </table>
    </div>
  </body>
</html>

其中最重要的一點就是:<meta name="pageID" content="sample-service"/>這個pageID。這裏的是固定的,後面的content對應我們plugin.xml的內容(等下看看plguin.xml的配置)。然後可以適當的看下里面table的 屬性和樣式,因爲很多時候會在jsp中顯示內容,且用table佈局的。
改下之前的plugin.xml的配置,配置組件在openfire 管理員控制檯的哪個地方顯示,以及顯示的頁面。

plugin.xml

<?xml version="1.0" encoding="UTF-8"?>
<plugin>
	<!-- Main plugin class  這裏是最重要滴,就是你的插件的全路徑-->
	<class>com.qiao.test.plugin.TestPlugin</class>
 
	<!-- Plugin meta-data -->
	<name>TestPlugin</name>
	<description>This is testplugin.</description>
	<author>qiao</author>
 
	<version>1.0</version>
	<date>10/05/20134</date>
	<url>http://localhost:9090/openfire/plugins.jsp</url>
	<minServerVersion>3.4.1</minServerVersion>
	<licenseType>gpl</licenseType>
 
	<adminconsole>   
	 	<tab id="tab-server">
            <sidebar id="sidebar-server-settings">
                <item id="test-service" name="Test Service" url="test-demo.jsp"
                     description="Click is trigger blog plugin" />
            </sidebar>
        </tab>
    </adminconsole>
</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 plaincopy
  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 plaincopy
  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 plaincopy
  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 plaincopy
  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插件的全過程。文中參考借鑑和挪用了不少大大的文字說明及圖片,就不一一感謝了。希望看了這篇文章有收穫的童鞋能給支持下。
最後附上今天開發的插件示例源碼:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章