近來幾天爲了寫一個openfire的小插件可謂腦袋都大了。。。自己又是初學小菜鳥一個,學習過程算是非常的磕磕絆絆。這裏記錄下來僅供後來的同學參考,也少走些彎路。勤能補拙,期望大家多多支持,共同學習,共同進步。
1.plugin插件開發
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>
(這裏有兩點請注意修改
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!");
}
}
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-plugin-java
等待打包完成
打包完成後刷新工程項目,會看到多出來個bin文件夾
打包成功的test.jar部署到openfire服務器,部署有兩種方法:
1.直接拷貝至openfire安裝目錄下的plugins的文件夾內,自啓動後它會自動解壓
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都會出現跳轉到登錄界面的情況。
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開發及配置
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
<?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,發佈插件
3.Servlet拓展問題及解決
3.1.servlet登錄驗證問題
那怎麼單獨對自己插件的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
- <filter>
- <filter-name>AuthCheck</filter-name>
- <filter-class>org.jivesoftware.admin.AuthCheckFilter</filter-class>
- <init-param>
- <param-name>excludes</param-name>
- <param-value>
- popplugin/*,login.jsp,index.jsp?logout=true,setup/index.jsp,setup/setup-*,.gif,.png,error-serverdown.jsp,setup/clearspace-integration-prelogin.jsp
- </param-value>
- </init-param>
- </filter>
url的匹配規則比較複雜,有興趣的同學可以去看AuthCheckFilter類源碼,如果要測試自己的pattern對不對,可以使用org.jivesoftware.admin.AuthCheckFilterTest類執行JUnitTest試試,如自己加上一段:
- assertTrue(AuthCheckFilter.testURLPassesExclude("popplugin/sendmessage", "popplugin*"));
- assertTrue(AuthCheckFilter.testURLPassesExclude("popplugin/sendmessage", "popplugin/sendmessage"));
2)使用AuthCheckFilter.addExclude方法
調用該方法和配置web.xml的效果是完全一樣的,個人建議用此方法,因爲本方法綠色安全、無污染,不修改和破壞原生openfire代碼。
這個方法可以在servlet的init方法或plugin的initializePlugin方法中調用。
個人建議在servlet的init方法中調用,因爲servlet的init方法比plugin的initializePlugin方法更早初始化,這個問題在“插件初始化順序”會講到。
使用完後記得removeExclude一下,有始有終嘛。
- @Override
- public void init() throws ServletException
- {
- System.out.println("UserMgrServlet init....");
- AuthCheckFilter.addExclude("popplugin/usermgr*");
- AuthCheckFilter.addExclude("popplugin/usermgr/*");
- }
- @Override
- public void destroy()
- {
- System.out.println("UserMgrServlet destroy....");
- // Release the excluded URL
- AuthCheckFilter.removeExclude("popplugin/usermgr*");
- AuthCheckFilter.removeExclude("popplugin/usermgr/*");
- }
注意:這種方式僅限於servlet的訪問,如果訪問插件的jsp/html頁面,頁面會報NullPointException異常,解決辦法見下面的說明
3.2.servlet仍然需要登錄驗證或者報NullPointException空指針異常
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)
插件的頁面不使用openfire控制檯的頁面框架
安裝版的openfire的話,修改/openfire/plugins/admin/webapp/WEB-INF/decorators.xml文件
源代碼版的,要修改/openfire_src/src/web/WEB-INF/decorators.xml文件
示例:
- <excludes>
- <pattern>/plugins/test/*</pattern>
- <pattern>/setup/setup-completed.jsp*</pattern>
- <pattern>/setup/setup-ldap-server_test.jsp*</pattern>
- <pattern>/setup/setup-ldap-user_test.jsp*</pattern>
- <pattern>/setup/setup-ldap-group_test.jsp*</pattern>
- <pattern>/setup/setup-clearspace-integration_test.jsp*</pattern>
- <pattern>/setup/setup-admin-settings_test.jsp*</pattern>
- <pattern>/login.jsp*</pattern>
- <pattern>/plugin-icon.jsp*</pattern>
- <pattern>/js/jscalendar/i18n.jsp*</pattern>
- </excludes>
這樣,插件popplugin目錄下的所有路徑的jsp頁面及js,css等,都能被自由的訪問了。
至此,海闊天空任鳥飛了。。