取代 Ant:使用 Maven 管理 Wowza 插件开发

        Wowza 官方提供的 Eclipse 插件使用的是 Ant 作为项目管理工具(参考《 Eclipse 安装/更新 Wowza IDE 插件的步骤》),如下图所示:
wowza ide原有插件项目
        build.xml 的源代码如下:
<?xml version="1.0"?>
<project name="defonds-live-module" default="jar" basedir="..">
	
	<property name="wowza.lib.dir" value="d:/tools/Wowza Media Systems/Wowza Streaming Engine 4.0.1/lib"/>
	<property name="jar.filename" value="defonds-live-module.jar"/>
	<property name="core.build.dir" value="bin"/>


	<target name="jar">
		<jar jarfile="${wowza.lib.dir}/${jar.filename}">
			<fileset dir="${core.build.dir}"/>
		</jar>
	</target>
	
</project>

        它所做的事情只有一件,就是每次我们修改 Wowza Media Server Project 的源码时,它把 Eclipse 编译好的 class 文件打包到 Wowza 安装目录下的 lib 文件夹中。
        Wowza ide 对于 Wowza 插件的开发不支持 maven,开发调试起来虽然没啥问题,但随着各种功能的不断添加,第三方包会越来越多,各种 jar 包管理起来相当混乱,给开发和维护升级带来很多不便。事实上 Maven 也可以集成进 Wowza 的开发进来,完全可以替代掉 Wowza 官方 IDE 提供的 ant。本文介绍如何使用 Maven 开发一个 Wowza 插件的过程。实践证明,Maven 开发 Wowza 插件,具有 ant 所具备的所有优点(比如对开发中的插件进行断点调试、项目自动部署),不仅把第三方包管理的井井有条,而且还能把 wms 包也有版本区分地管理起来,效果更加完美。
        本文所用 Wowza Streaming Engine 版本是 4.0.1,本文要求读者事先已安装好了 Wowza。
        1. 新建 Maven 项目
        最新版本的 Eclipse 已经把 Maven 集成进来了。Eclipse 3.6 (Helios) 之前的 Eclipse 需要我们自己把 Maven 插件集成进来,关于这个集成参考《 集成 Maven 2 插件到 Eclipse 的过程》。
        Eclipse 支持 Maven 之后,Eclipse 的 Package Explorer 视图下右击 -> New -> Maven -> Maven Project -> Next -> Select project name and location 对话框直接点 Next -> Select an Archetype 对话框,Catalog 选择 "All Catalogs",Filter 选择 Group Id 为 "org.apache.maven.archetypes"、Artifact Id 为 "maven-archetype-quickstart"、Version 为 "1.1" 的那个,点 Next -> Enter an artifact id 对话框,Group Id 输入项目组 "WowzaWithMavenIntegration",Artifact Id 输入 "defonds-server-module"(最好是你的项目名),Version 输入版本号 "1.0.0",Package 输入主干包名 "com.defonds.wms.module",点击 Finish,新的 Maven 项目 defonds-server-module 生成。如下图所示:
新建Maven项目
        2. 编辑 pom.xml
        根据项目的需要,引入所依赖的包。作者的 pom.xml 示例如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
	<groupId>WowzaWithMavenIntegration</groupId>
	<artifactId>defonds-server-module</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>
	<name>defonds-server-module</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<wms.version>4.0.1</wms.version>
		<libFolderName>dep-libs</libFolderName>
		<spring.version>3.1.2.RELEASE</spring.version>
		<httpcomponents.version>4.2.1</httpcomponents.version>
		<javamail.version>1.4.5</javamail.version>
		<commons.email.version>1.1</commons.email.version>
		<commons.exec.version>1.1</commons.exec.version>
		<commons.beanutils.version>1.8.3</commons.beanutils.version>
		<commons.codec.version>1.6</commons.codec.version>
		<commons.collections.version>3.2.1</commons.collections.version>
		<commons.lang.version>2.6</commons.lang.version>
		<commons.io.version>2.4</commons.io.version>
		<commons.pool.version>1.6</commons.pool.version>
		<commons.dbcp.version>1.4</commons.dbcp.version>
		<log4j.version>1.2.16</log4j.version>
		<slf4j.version>1.6.6</slf4j.version>
		<jackson.version>1.9.2</jackson.version>
	</properties>

<dependencies>
	
		<!-- wms dependence jar -->

		<dependency>
			<groupId>com.wms</groupId>
			<artifactId>wms-server</artifactId>
			<version>${wms.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.wms</groupId>
			<artifactId>wms-stream-publish</artifactId>
			<version>${wms.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.wms</groupId>
			<artifactId>wms-httpstreamer-smoothstreaming</artifactId>
			<version>${wms.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.wms</groupId>
			<artifactId>wms-httpstreamer-cupertinostreaming</artifactId>
			<version>${wms.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.wms</groupId>
			<artifactId>wms-httpstreamer-directstreaming</artifactId>
			<version>${wms.version}</version>
			<scope>provided</scope>
		</dependency>





		<!-- not wms dependence jar -->

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${spring.version}</version>
		</dependency>
		
		<dependency>    
		    <groupId>net.sf.json-lib</groupId>   
		    <artifactId>json-lib</artifactId>    
		    <version>2.4</version>  
		    <classifier>jdk15</classifier>  
		</dependency>
		
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>${commons.lang.version}</version>
		</dependency>
		
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>${commons.beanutils.version}</version>
		</dependency>
		
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>${commons.codec.version}</version>
		</dependency>
		
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>${commons.collections.version}</version>
		</dependency>
		
		<dependency>
			<groupId>commons-pool</groupId>
			<artifactId>commons-pool</artifactId>
			<version>${commons.pool.version}</version>
		</dependency>

		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>${commons.dbcp.version}</version>
		</dependency>
		
		<dependency>
			<groupId>commons-httpclient</groupId>
			<artifactId>commons-httpclient</artifactId>
			<version>3.1</version>
		</dependency>
		
		<dependency>
			<groupId>org.apache.ibatis</groupId>
			<artifactId>ibatis-sqlmap</artifactId>
			<version>2.3.4.726</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.19</version>
		</dependency>
		
		<!-- logs -->
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>${log4j.version}</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${slf4j.version}</version>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${slf4j.version}</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<!-- lets force java 1.6 version for this project -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<version>2.2</version>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>prepare-package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<includeScope>runtime</includeScope>
							<outputDirectory>${project.build.directory}/${libFolderName}</outputDirectory>
							<overWriteReleases>false</overWriteReleases>
							<overWriteSnapshots>false</overWriteSnapshots>
							<overWriteIfNewer>true</overWriteIfNewer>
						</configuration>
					</execution>
				</executions>
			</plugin>


			<!-- build jar and add main class delaration to metafile -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-jar-plugin</artifactId>
				<version>2.3.1</version>
				<configuration>
					<finalName>${project.artifactId}</finalName>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
							<classpathPrefix>${libFolderName}/</classpathPrefix>
						</manifest>
						<manifestEntries>
						</manifestEntries>
						<addMavenDescriptor>false</addMavenDescriptor>
					</archive>
				</configuration>
			</plugin>

			<plugin>
				<artifactId>maven-antrun-plugin</artifactId>
				<executions>
					<execution>
						<phase>package</phase>
						<configuration>
							<tasks>
								<copy file="${project.build.directory}/${project.artifactId}.jar"
									tofile="${env.WMSINSTALL_HOME}/lib/${project.artifactId}.jar"
									overwrite="true" />

								<copy todir="${env.WMSINSTALL_HOME}/lib/${libFolderName}"
									overwrite="true">
									<fileset dir="${project.build.directory}/${libFolderName}"
										includes="**" />
								</copy>

							</tasks>
						</configuration>
						<goals>
							<goal>run</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

			<!-- lets execute our project exec:java goal -->
			<plugin>
				<groupId>org.codehaus.mojo</groupId>
				<artifactId>exec-maven-plugin</artifactId>
				<version>1.2</version>
				<configuration>
				</configuration>
			</plugin>


			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-install-plugin</artifactId>
				<version>2.3.1</version>
				<executions>
					<execution>
						<id>Install Wmsserver</id>
						<phase>validate</phase>
						<goals>
							<goal>install-file</goal>
						</goals>
						<configuration>
							<packaging>jar</packaging>
							<groupId>com.wms</groupId>
							<artifactId>wms-server</artifactId>
							<version>${wms.version}</version>
							<file>${basedir}/lib/wms-server.jar</file>
						</configuration>
					</execution>
					<execution>
						<id>Install Wmsserver stream-publish library</id>
						<phase>validate</phase>
						<goals>
							<goal>install-file</goal>
						</goals>
						<configuration>
							<packaging>jar</packaging>
							<groupId>com.wms</groupId>
							<artifactId>wms-stream-publish</artifactId>
							<version>${wms.version}</version>
							<file>${basedir}/lib/wms-stream-publish.jar</file>
						</configuration>
					</execution>
					<execution>
						<id>Install Wmsserver wms-httpstreamer-smoothstreaming library</id>
						<phase>validate</phase>
						<goals>
							<goal>install-file</goal>
						</goals>
						<configuration>
							<packaging>jar</packaging>
							<groupId>com.wms</groupId>
							<artifactId>wms-httpstreamer-smoothstreaming</artifactId>
							<version>${wms.version}</version>
							<file>${basedir}/lib/wms-httpstreamer-smoothstreaming.jar</file>
						</configuration>
					</execution>
					<execution>
						<id>Install Wmsserver wms-httpstreamer-cupertinostreaming library</id>
						<phase>validate</phase>
						<goals>
							<goal>install-file</goal>
						</goals>
						<configuration>
							<packaging>jar</packaging>
							<groupId>com.wms</groupId>
							<artifactId>wms-httpstreamer-cupertinostreaming</artifactId>
							<version>${wms.version}</version>
							<file>${basedir}/lib/wms-httpstreamer-cupertinostreaming.jar</file>
						</configuration>
					</execution>
					<execution>
						<id>Install Wmsserver wms-httpstreamer-directstreaming library</id>
						<phase>validate</phase>
						<goals>
							<goal>install-file</goal>
						</goals>
						<configuration>
							<packaging>jar</packaging>
							<groupId>com.wms</groupId>
							<artifactId>wms-httpstreamer-directstreaming</artifactId>
							<version>${wms.version}</version>
							<file>${basedir}/lib/wms-httpstreamer-directstreaming.jar</file>
						</configuration>
					</execution>
				</executions>
			</plugin>

		</plugins>
	</build>


</project>

        注意 1
        项目依赖到的 Wowza 包(即 wms 包,比如 wms-server.jar 等等,这些包在 %wowza%/lib 目录下)也要依赖进来,而且这些包的 scope 设置成 provided,这样打包部署的时候,就不会把这些包也给打进来了。这些包最好和其他第三方包分开管理,以免造成混乱。
        注意 2
        每一个 wms 包,在 pom.xml 中有两处需要配置,dependencies 标签下的 dependency 一个,maven-install-plugin 插件的 executions 标签下 execution 一个。
        3. Wowza 依赖包的安装
        这时会发现,defonds-server-module 项目有错误:
项目错误警告
        错误详情如下:
错误详情
        就是本地 Maven 库里找不着 pom.xml 定义的 wms-server-4.0.1.jar、wms-httpstreamer-directstreaming-4.0.1.jar 等 wms 包。
        defonds-server-module 项目根目录下新建 lib 文件夹,把项目依赖到的 Wowza jar 包拷贝到 lib 中。
        然后命令行切换到 defonds-server-module 项目所在目录,执行 mvn install。
        刷新 Maven 本地库(比如作者的是 D:/javaprojects/mlib),发现 wms-server-4.0.1.jar 已经被存放在本地库中:
wms包已在本地库
        查看 defonds-server-module 项目目录下的 target 目录,发现已经多了一个 dep-libs 文件夹,打开发现所有依赖的第三方包(pom.xml 中定义了的,或者定义的包所依赖到的)都已经被拷贝到了这个目录中:
所有第三方包都在dep-libs
        这些包暂时集中缓存这个目录中,将在项目部署时被用到,接下来的步骤中会有提到。
        这时发现 defonds-server-module 依然有找不着 wms-server-4.0.1.jar 等 wms 包的错误,可是这些包明明已经在 mlib 中了呀。
        Package Explorer 视图下右击 defonds-server-module 项目名,选择 Maven 菜单里的 Disable Dependency Management。然后,仍右击该项目名,选择 Maven 菜单里的 Enable Dependency Management,发现该错误已消失:
wms包找不着异常已不见
        需要注意的是 Wowza 依赖包的安装,这里引入 Wowza 包的依赖主要是编译期的需要。
        其他第三方依赖包的安装跟其他 Maven 项目一般无二,这里不再赘述。
        注意:
        以后每次新加 wms 相关依赖包,都要重复以上步骤一遍,简而言之就是:拷贝 wms 包到 lib,添加 dependency,添加 execution,执行 mvn install。
        4. 编写 Wowza 插件
        这时我们就可以开发 Wowza 插件了。仍以上一篇博客中的 DefondsWowzaServerListener 为例,编写插件后的项目如下:
编写插件后的项目
        5. 插件打包
        开发 Wowza 插件,Maven 和 ant 的不同点在于,在每次修改完源码后,ant 自动把插件打包到 Wowza 的 lib 目录中去,而 Maven 需要我们手工去打。
        命令行切换到 defonds-server-module 项目所在目录,执行 mvn package,BUILD SUCCESSFUL 之后发现 defonds-server-module.jar 已被打到 %wowza%/lib 目录下:
defonds-server-module.jar打包
        同时 %wowza%/lib 目录下多出一个 dep-libs 文件夹,打开后发现第三步所缓存的第三方包都已被放在这个目录中了:
第三方包都已被放在这个目录中
        我们打开 defonds-server-module.jar 包下 META-INF 中的 MANIFEST.MF 文件,其内容如下:
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: Defonds
Build-Jdk: 1.6.0_39
Class-Path: dep-libs/spring-core-3.1.2.RELEASE.jar dep-libs/spring-asm
 -3.1.2.RELEASE.jar dep-libs/commons-logging-1.1.1.jar dep-libs/spring
 -orm-3.1.2.RELEASE.jar dep-libs/spring-beans-3.1.2.RELEASE.jar dep-li
 bs/spring-jdbc-3.1.2.RELEASE.jar dep-libs/spring-tx-3.1.2.RELEASE.jar
  dep-libs/aopalliance-1.0.jar dep-libs/spring-aop-3.1.2.RELEASE.jar d
 ep-libs/spring-context-3.1.2.RELEASE.jar dep-libs/spring-expression-3
 .1.2.RELEASE.jar dep-libs/spring-context-support-3.1.2.RELEASE.jar de
 p-libs/json-lib-2.4-jdk15.jar dep-libs/commons-beanutils-1.8.3.jar de
 p-libs/commons-collections-3.2.1.jar dep-libs/commons-lang-2.6.jar de
 p-libs/ezmorph-1.0.6.jar dep-libs/commons-codec-1.6.jar dep-libs/comm
 ons-pool-1.6.jar dep-libs/commons-dbcp-1.4.jar dep-libs/commons-httpc
 lient-3.1.jar dep-libs/ibatis-sqlmap-2.3.4.726.jar dep-libs/mysql-con
 nector-java-5.1.19.jar dep-libs/log4j-1.2.16.jar dep-libs/slf4j-api-1
 .6.6.jar dep-libs/slf4j-log4j12-1.6.6.jar

        也就是说,defonds-server-module.jar 依赖到的其他非 Wowza 的第三方包都被放在了这个目录中。这样做的好处是不言而喻的,避免了我们把所有依赖的第三方包都放在 %wowza%/lib 下,而造成 Wowza 原生态包的混乱。
        6. 插件注入 Wowza
        在调试之前,先别忘了在 %wowza%/conf 下的 Server.xml 把我们的 DefondsWowzaServerListener 进行注入哦(详细参考《 使用 spring 集成 dbcp 数据库连接池到 Wowza 插件》):
			<ServerListener> 
				<BaseClass>com.defonds.wms.module.server.DefondsWowzaServerListener</BaseClass> 
			</ServerListener>

        7. 新建 Debug 远程调试
        Wowza IDE 开发 Wowza 插件最令人振奋的用户体验之一就是能够在 Eclipse 中进行断点跟踪调试(参考《 使用 Wowza IDE 开发第一个 Wowza 服务器扩展应用 -- 监控直播频道》)。我们使用 Maven 取代其原生态 ant (原生态 Wowza IDE 插件开发仅支持 ant)对 Wowza 插件开发进行依赖管理之后,当然不希望这么优秀的用户体验也随 ant 而去。
        Eclipse 工具栏中点开 Debug 图标的下拉菜单 -> Debug Configurations... -> Name 输入 defonds-server-module,Classpath 页项下点击 User Entries -> Add External JARS... -> 选中你的 Wowza 安装目录下的 bin 目录中的 wms-bootstrap.jar,然后将其他 User Entries 移除(不然会 class load 其他依赖包失败);Source 页项下 Add... -> Java Project -> OK -> 选中 defonds-server-module 项目 -> OK;Main 页项下,Project 选择 defonds-server-module,Main class 输入 com.wowza.wms.bootstrap.Bootstrap;Arguments 页项下,Program arguments 输入 start,VM arguments 输入以下内容:
-Xmx768M
-Dcom.wowza.wms.AppHome="d:/tools/Wowza Media Systems/Wowza Streaming Engine 4.0.1"
-Dcom.wowza.wms.ConfigHome="d:/tools/Wowza Media Systems/Wowza Streaming Engine 4.0.1"
-Dcom.sun.management.jmxremote=true
-Dcom.wowza.wms.native.base="win"

        如下图所示:
断点调试前的配置
        注意 d:/tools/Wowza Media Systems/Wowza Streaming Engine 4.0.1 是作者的 Wowza 的安装目录,读者需要换成自己的。然后点击 Apply,远程调试设置保存成功,最后点击 Debug 我们就在 Eclipse 启动 Wowza 对我们的插件进行断点跟踪调试了。
        8. Eclipse 断点调试

        在 TestServiceImpl 中加个断点,然后 debug 启动上一步建好的 defonds-server-module,断点效果图如下:

断点调试效果图

        看上去是不是很 perfect?就此开始你的 Wowza 插件开发之旅吧,Maven supported 哦!

        写在最后的话
        感谢 WMSPanel 项目组的开源精神,没有他们公布在 github 上的开源项目 wowza-maven-template 拿下来做 demo,我可能至今还在像无头苍蝇似的对 Wowza 插件开发和 Maven 的集成根本无从下手!该项目在 github 上的地址是 https://github.com/WMSPanel/wowza-maven-template,笔者上传了一份到 csdn 资源,如果读者觉得 github 打开慢想从国内服务器下载该项目可以直接去 csdn 资源下载,地址是: http://download.csdn.net/detail/defonds/7136969
        本文示例项目 defonds-server-module 也已完整打包到 csdn 资源,有需要的朋友可以去下载: http://download.csdn.net/detail/defonds/7136979
        参考资料
posted @ 2014-04-02 17:47  Defonds  阅读(43)  评论(0编辑  收藏  举报