- 浏览: 407154 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (325)
- 神经网络 (1)
- javascript (11)
- 数据结构 (2)
- 计算机图形学 (11)
- 模式识别 (1)
- 前端开发 (14)
- 机器学习 (11)
- ios开发 (50)
- Python (9)
- HTML5 (4)
- 计算机视觉 (9)
- 数字图像处理 (7)
- 架构设计 (19)
- 数据库设计 (9)
- 算法设计 (59)
- Java (37)
- 其他 (3)
- 游戏开发 (5)
- c++ (17)
- Linux (3)
- TCP/IP (2)
- Flex (41)
- 健康 (6)
- AI (2)
- 工具 (1)
- 数据挖掘 (1)
- 性能优化 (6)
- 综合 (2)
- 网络通信 (12)
- Android (2)
- UML (3)
- 软件设计 (11)
- 编程经验 (7)
- J2EE (1)
- 多媒体技术 (3)
- 数学 (7)
- php (4)
- 设计 (1)
- CS (2)
- 计算机理论 (1)
- 信息安全 (1)
最新评论
-
ahead_zhan:
good good good
flex3控件_ModuleLoader -
lonerzf:
好样的。非常感谢楼主
OpenCV视频教程整理 -
lonerzf:
好样的。谢谢~
OpenCV视频教程整理 -
coding1688:
博主说的不错,我在实现瀑布流布局时也用的masonry插件,有 ...
Javascript 瀑布流式布局及其动态效果的实现 -
snowolf:
除非玩游戏,不然没啥win的事情,或者用win的银行客户端,通 ...
macbook安装操作系统的机理分析
对于大多数 Java 开发人员来说,JAR 文件及其 “近亲” WAR 和 EAR 都只不过是漫长的 Ant 或 Maven 流程的最终结果。标准步骤是将一个 JAR 复制到服务器(或者,少数情况下是用户机)中的合适位置,然后忘记它。
事实上,JAR 能做的不止是存储源代码,您应该了解 JAR 还能做什么,以及如何进行。在这一期的 5 件事 系列中,将向您展示如何最大限度地利用 Java Archive 文件(有时候也可是 WAR 和 EAR),特别是在部署时。
由于有很多 Java 开发人员使用 Spring(因为 Spring 框架给传统的 JAR 使用带来一些特有的挑战),这里有几个具体技巧用于在 Spring 应用程序中处理 JAR 。
关于本系列
您觉得自己懂 Java 编程?事实是,大多数开发人员都只领会到了 Java 平台的皮毛,所学也只够应付工作。在本 系列 中,Ted Neward 深度挖掘 Java 平台的核心功能,揭示一些鲜为人知的事实,帮助您解决最棘手的编程困难。
我将以一个标准 Java Archive 文件产生过程的简单示例开始,这将作为以下技巧的基础。
通常,在源代码被编译之后,您需要构建一个 JAR 文件,使用 jar
命令行实用工具,或者,更常用的是 Ant jar
任务将 Java 代码(已经被包分离)收集到一个单独的集合中,过程简洁易懂,我不想在这做过多的说明,稍后将继续说明如何构建 JAR。现在,我只需要存档 Hello
,这是一个独立控制台实用工具,对于执行打印消息到控制台这个任务十分有用。如清单 1 所示:
package com.tedneward.jars; public class Hello { public static void main(String[] args) { System.out.println("Howdy!"); } } |
Hello
实用工具内容并不多,但是对于研究 JAR 文件却是一个很有用的 “脚手架”,我们先从执行此代码开始。
.NET 和 C++ 这类语言一直是 OS 友好的,只需要在命令行(helloWorld.exe
)引用其名称,或在 GUI shell 中双击它的图标就可以启动应用程序。然而在 Java 编程中,启动器程序 —java
— 将 JVM 引导入进程中,我们需要传递一个命令行参数(com.tedneward.Hello
)指定想要启动的 main()
方法的类。
这些附加步骤使使用 Java 创建界面友好的应用程序更加困难。不仅终端用户需要在命令行输入所有参数(终端用户宁愿避开),而且极有可能使他或她操作失误以及返回一个难以理解的错误。
这个解决方案使 JAR 文件 “可执行” ,以致 Java 启动程序在执行 JAR 文件时,自动识别哪个类将要启动。我们所要做的是,将一个入口引入 JAR 文件清单文件(MANIFEST.MF
在 JAR 的 META-INF
子目录下),像这样:
Main-Class: com.tedneward.jars.Hello |
这个清单文件只是一个名值对。因为有时候清单文件很难处理回车和空格,然而在构建 JAR 时,使用 Ant 来生成清单文件是很容易的。在清单 3 中,使用 Ant jar
任务的 manifest
元素来指定清单文件:
<target name="jar" depends="build"> <jar destfile="outapp.jar" basedir="classes"> <manifest> <attribute name="Main-Class" value="com.tedneward.jars.Hello" /> </manifest> </jar> </target> |
现在用户在执行 JAR 文件时需要做的就是通过 java -jar outapp.jar
在命令行上指定其文件名。就 GUI shell 来说,双击 JAR 文件即可。
似乎 Hello
实用工具已经展开,改变实现的需求已经出现。Spring 或 Guice 这类依赖项注入(DI)容器可以为我们处理许多细节,但是仍然有点小问题:修改代码使其含有 DI 容器的用法可能导致清单 4 所示的结果,如:
package com.tedneward.jars; import org.springframework.context.*; import org.springframework.context.support.*; public class Hello { public static void main(String[] args) { ApplicationContext appContext = new FileSystemXmlApplicationContext("./app.xml"); ISpeak speaker = (ISpeak) appContext.getBean("speaker"); System.out.println(speaker.sayHello()); } } |
关于 Spring 的更多信息
这个技巧将帮助您熟悉依赖项注入和 Spring 框架。如果您需要温习其他主题,见 参考资料。
由于启动程序的 -jar
选项将覆盖 -classpath
命令行选项中的所有内容,因此运行这些代码时,Spring 必须是在 CLASSPATH
和 环境变量中。幸运的是,JAR 允许在清单文件中出现其他的 JAR 依赖项声明,这使得无需声明就可以隐式创建 CLASSPATH,如清单 5 所示:
<target name="jar" depends="build"> <jar destfile="outapp.jar" basedir="classes"> <manifest> <attribute name="Main-Class" value="com.tedneward.jars.Hello" /> <attribute name="Class-Path" value="./lib/org.springframework.context-3.0.1.RELEASE-A.jar ./lib/org.springframework.core-3.0.1.RELEASE-A.jar ./lib/org.springframework.asm-3.0.1.RELEASE-A.jar ./lib/org.springframework.beans-3.0.1.RELEASE-A.jar ./lib/org.springframework.expression-3.0.1.RELEASE-A.jar ./lib/commons-logging-1.0.4.jar" /> </manifest> </jar> </target> |
注意 Class-Path
属性包含一个与应用程序所依赖的 JAR 文件相关的引用。您可以将它写成一个绝对引用或者完全没有前缀。这种情况下,我们假设 JAR 文件同应用程序 JAR 在同一个目录下。
不幸的是,value
属性和 Ant Class-Path
属性必须出现在同一行,因为 JAR 清单文件不能处理多个 Class-Path
属性。因此,所有这些依赖项在清单文件中必须出现在一行。当然,这很难看,但为了使 java -jar outapp.jar
可用,还是值得的!
如果有几个不同的命令行实用工具(或其他的应用程序)在使用 Spring 框架,可能更容易将 Spring JAR 文件放在公共位置,使所有实用工具能够引用。这样就避免了文件系统中到处都有 JAR 副本。Java 运行时 JAR 的公共位置,众所周知是 “扩展目录” ,默认位于 lib/ext
子目录,在 JRE 的安装位置之下。
JRE 是一个可定制的位置,但是在一个给定的 Java 环境中很少定制,以至于可以完全假设 lib/ext
是存储 JAR 的一个安全地方,以及它们将隐式地用于 Java 环境的 CLASSPATH
上。
为了避免庞大的 CLASSPATH
环境变量(Java 开发人员几年前就应该抛弃的)和/或命令行 -classpath
参数,Java 6 引入了类路径通配符 的概念。与其不得不启动参数中明确列出的每个 JAR 文件,还不如自己指定 lib/*
,让所有 JAR 文件列在该目录下(不递归),在类路径中。
不幸的是,类路径通配符不适用于之前提到的 Class-Path
属性清单入口。但是这使得它更容易启动 Java 应用程序(包括服务器)开发人员任务,例如 code-gen 工具或分析工具。
Spring,就像许多 Java 生态系统一样,依赖于一个描述构建环境的配置文件,前面提到过,Spring 依赖于一个 app.xml 文件,此文件同 JAR 文件位于同一目录 — 但是开发人员在复制 JAR 文件的同时忘记复制配置文件,这太常见了!
一些配置文件可用 sysadmin 进行编辑,但是其中很大一部分(例如 Hibernate 映射)都位于 sysadmin 域之外,这将导致部署漏洞。一个合理的解决方案是将配置文件和代码封装在一起 — 这是可行的,因为 JAR 从根本上来说就是一个 “乔装的” ZIP 文件。 当构建一个 JAR 时,只需要在 Ant 任务或 jar
命令行包括一个配置文件即可。
JAR 也可以包含其他类型的文件,不仅仅是配置文件。例如,如果我的 SpeakEnglish
部件要访问一个属性文件,我可以进行如下设置,如清单 6 所示:
package com.tedneward.jars; import java.util.*; public class SpeakEnglish implements ISpeak { Properties responses = new Properties(); Random random = new Random(); public String sayHello() { // Pick a response at random int which = random.nextInt(5); return responses.getProperty("response." + which); } } |
可以将 responses.properties
放入 JAR 文件,这意味着部署 JAR 文件时至少可以少考虑一个文件。这只需要在 JAR 步骤中包含 responses.properties 文件即可。
当您在 JAR 中存储属性之后,您可能想知道如何将它取回。如果所需要的数据与 JAR 文件在同一位置,正如前面的例子中提到的那样,不需要费心找出 JAR 文件的位置,使用 JarFile
对象就可将其打开。相反,可以使用类的 ClassLoader
找到它,像在 JAR 文件中寻找 “资源” 那样,使用 ClassLoader getResourceAsStream()
方法,如清单 7 所示:
package com.tedneward.jars; import java.util.*; public class SpeakEnglish implements ISpeak { Properties responses = new Properties(); // ... public SpeakEnglish() { try { ClassLoader myCL = SpeakEnglish.class.getClassLoader(); responses.load( myCL.getResourceAsStream( "com/tedneward/jars/responses.properties")); } catch (Exception x) { x.printStackTrace(); } } // ... } |
您可以按照以上步骤寻找任何类型的资源:配置文件、审计文件、图形文件,等等。几乎任何文件类型都能被捆绑进 JAR 中,作为一个 InputStream
获取(通过 ClassLoader
),并通过您喜欢的方式使用。
本文涵盖了关于 JAR 大多数开发人员所不知道的 5 件最重要的事 — 至少基于历史,有据可查。注意,所有的 JAR 相关技巧对于 WAR 同样可用,一些技巧(特别是 Class-Path
和 Main-Class
属性)对于 WAR 来说不是那么出色,因为 servlet 环境需要全部目录,并且要有一个预先确定的入口点,但是,总体上来看这些技巧可以使我们摆脱 “好的,开始在该目录下复制......” 的模式,这也使得他们部署 Java 应用程序更为简单。
本系列的下一个主题是:关于 Java 应用程序性能监视您不知道的 5 件事。
<!-- CMA ID: 501416 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->
发表评论
-
多种加密算法实现(JAVA)
2013-10-24 09:18 1616有短句“Sun Yat-sen University is ... -
断点续传的原理
2013-05-07 19:53 826转自:http://www.ibm.com/develope ... -
《JAVA与模式》之调停者模式
2012-06-21 20:06 630参考:http://www.cnblo ... -
Java 线程池的原理与实现
2011-10-23 15:48 691参考: http://www.blogjava.ne ... -
Java中读取字节流并按指定编码转换成字符串的方法
2011-05-21 11:22 1447参考: http://www.blogjava.net/pen ... -
字节流编码获取原来这么复杂,但也很简单
2011-05-21 11:02 1498参考:http://www.cnblogs ... -
使用Java.util.zip下的zipOutStream和zipInStream对字节流进行压缩和解压缩
2011-05-21 10:08 1714参考:http://www.blogjava.net/ushe ... -
ActionScript与Java类型对应表
2011-05-21 09:46 1029当你使用AMF格式进行RemoteObject 调用时,肯定会 ... -
基于red5的在线视频录制实例和详细注释
2011-05-14 23:03 1575参考:http://www.ccvita.com/130.ht ... -
Java 中几种查找算法
2011-05-12 10:31 1463顺序查找说明:顺序查找适合于存储结构为顺序存储或链接存储的线性 ... -
Converting data from Java to ActionScript
2011-05-07 14:23 976On the client side, the ide ... -
java大整数相加及相乘
2011-05-04 18:34 1483import java.io.BufferedInputStr ... -
.org.hibernate.ObjectNotFoundException: No row with the given identifier exists
2011-04-20 18:09 1130说到底,就是外键关联引起的问题。 问题产生原因:有一个 ... -
java.util.ConcurrentModificationException
2011-04-19 10:07 573一般来说这个异常是容器类在遍历的时候被修改时抛出的。比 ... -
Spring+Hibernate+Flex,update、delete操作无法持久到数据库的解决办法
2011-04-17 21:42 1412这个解决办法就是才有事务机制了。。。 我是spring ... -
hibernate 注解 一对多 唯一索引
2011-04-17 02:00 2824今天被hibernate和mysql整了一下,切身感受到索引的 ... -
精通Hibernate——映射一对多关联关系
2011-04-17 01:38 1010在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据U ... -
junit实现opensessionInView保持session
2011-04-11 10:00 825参考:http://allenwei.iteye.com/bl ... -
Hibernate中cascade与inverse属性详解
2011-04-07 10:57 1047原文: 忘记存了..... ... -
HIbernate注解
2011-04-07 10:37 895Hibernate注解 文章分类:Web前端 @o ...
相关推荐
综合以上信息,我们可以知道这是一个关于如何使用JavaMail、Apache Commons Email和Ant发送测试报告邮件的场景。通过导入这些库,开发者或测试工程师可以编写脚本自动发送包含JMeter测试结果的邮件,提高工作效率。...
Java开发过程中,jar(Java Archive)包是必不可少的资源,它们包含了预编译的类、接口、资源和其他元数据,方便开发者在项目中引用。在给出的标题和描述中,提到了几个常用的Java jar包,分别是:activation.jar、...
在Java编程中,直接调用操作系统底层的动态链接库(DLL)是相对复杂的一件事情,因为Java是一种跨平台的语言,而DLL通常与特定的操作系统紧密关联。为了在Java中实现这一功能,Java Native Access(JNA)应运而生。...
这个jar包集合包含了三个核心的库文件:activation-1.1.jar、commons-email-1.4.jar和mail-1.4.jar,它们各自扮演着不同的角色,共同支持电子邮件的发送功能。 首先,`activation-1.1.jar`是JavaBeans Activation ...
5. **pop3.jar**:POP3(Post Office Protocol version 3)是另一种常用的邮件协议,主要用于从邮件服务器下载邮件。pop3.jar包含了处理POP3协议所需的类和方法。 6. **smtp.jar**:SMTP(Simple Mail Transfer ...
激活框架允许应用程序识别和操作不知道的数据类型,是JavaMail的重要组成部分,因为它帮助识别邮件中的不同内容类型并进行正确处理。 接下来,我们来看看如何在MyEclipse中使用这两个库来发送邮件: 1. **引入依赖...
4. **创建Message对象**:定义邮件的基本信息,包括发件人、收件人、主题和正文。 ```java InternetAddress from = new InternetAddress("your-email@example.com"); InternetAddress to = new InternetAddress(...
JAF 提供了数据类型识别和对象创建的能力,使得 Java 程序能够识别和操作不预先知道的数据格式。当发送或接收包含多种类型数据的邮件时,`activation.jar` 是必不可少的。 使用 JavaMail 进行邮件操作的基本步骤...
它提供了一种机制来解析和操作MIME消息,即使开发者事先并不知道消息的具体内容。通过注册“数据处理者”(DataHandler),Activation可以自动选择合适的类来处理不同类型的附件。 在提供的压缩包中,`mail.jar`...
5. **错误处理和资源释放**:在转换过程中,你可能需要处理各种异常,如网络连接问题、文件不存在或格式不支持等。转换完成后,记得关闭打开的文档和断开与OpenOffice服务的连接,以释放资源。 6. **优化和性能**:...
在Android开发中,有时我们需要集成邮件发送功能,这时就涉及到了“發送郵件工具類”。这个类主要用于帮助应用程序在Android设备上实现电子邮件的发送。通常,为了完成这个任务,开发者会引入特定的库或者依赖,例如...
在了解"alimama LIB包"之前,我们首先需要知道阿里妈妈是什么。阿里妈妈是阿里巴巴集团旗下的一个数字营销平台,它主要提供包括淘宝联盟、广告投放、效果营销等服务,帮助商家推广产品,同时也为网站主和媒体提供...
Selenium RC,全称为Selenium Remote Control,是Selenium测试工具套件中的一个早期组件,主要用于自动化Web应用程序的测试。Selenium RC允许测试者通过编程语言(如Java、Python、Ruby等)编写测试脚本,然后控制...
此外,他们还需要知道如何使用JavaMail API来创建和设置邮件消息,包括添加收件人、主题、正文和附件。对于源码有深入研究的开发者,还可以根据自己的需求对SendMail进行定制和扩展。总之,SendMail是一个方便的工具...
5. 设置邮件的发件人、收件人和主题。 6. 创建`Multipart`对象,用于存储邮件的多个部分,如纯文本和附件。 7. 创建`MimeBodyPart`对象,设置邮件正文内容,然后添加到`Multipart`中。 8. 最后,通过`Transport`类的...
4. **腾讯邮件服务器配置**: 要使用JavaMail连接腾讯的邮件系统,需要知道腾讯SMTP服务器的地址、端口以及认证方式。通常,这包括用户名(通常是邮件地址)和密码。 5. **Java客户端应用**: 这个电子邮件系统不是...
我们做项目的时候,并不是所有文 件都是要提交的,比如构建的build 文件夹,本地配置文件,每个Module 生成的iml 文件,但是我们每次add,commit 都会不小心把它们添加上去,而gitignore 就是解决这种痛点的,如果你...
5. **处理错误和异常**:在实际应用中,你需要处理可能发生的错误,如文件找不到、OpenOffice未运行、转换失败等。添加适当的错误处理机制,确保程序的健壮性。 6. **优化和扩展**:JODConverter还支持批量转换和...
JavaMail的依赖库包括`javax.mail`和`javax.mail-api`,以及SMTP服务器所需的协议库,如`mailapi.jar`和` Activation.jar`。 2. **SMTP服务器设置**:JavaMail需要知道如何连接到SMTP服务器来发送邮件。你需要配置...
4. **邮件消息对象**:在Java中,你可以创建`Message`对象来封装邮件信息,包括发件人、收件人、主题和正文。`MimeMessage`是`Message`的一个子类,用于处理多部分和非ASCII字符的邮件。 5. **Session对象**:`...