Win下用installanywhere2009把jee工程打包成安装包
tag:installanywhere2009 安装包 工程打包
全部文档请
http://windfeng.iteye.com/blog/660762
1. 概要
利用打包工具installanywhere,把jee项目制作成可以自己指定步骤的安装文件,有如下步骤:
a 选择安装语言环境
b 检测操作系统平台,主要是Windows平台
c 检测系统版本及JVM版本
d 检测客户机oracle环境、版本及oracle数据库的连接(通过管理员帐号连接,需要创建默认帐户和授权)
e 安装程序
f 通过java调用imp命令导入dmp文件(未实现远程导入dmp,因为imp命令为oracle提供,如果客户机有oracle环境,则直接安装客户机)
g 通过用户输入连接的数据库信息改变系统数据库连接配置文件
h 通过执行批处理改变系统环境变量,java_home、catalina_home
k 自动启动tomcat服务
l 自动打开浏览器,通过url地址访问系统
m 最后,手工输入登录用户名和密码,查看系统
2. 工具介绍
2.1 版本
InstallAnywhere 2009 Enterprise build 3657
2.2 下载
官方网站 http://www.zerog.com ,注册后可下载,2009-5-30下载的版本见上
2.3 破解
我已经将破解补丁上传,免费下载 installanywhere2009破解方法及补丁
2.4 工具界面介绍
这里主要介绍project部分。
2.4.1 打开软件,能见到破解时输入的注册码
图一 启动画面
2.4.2 创建一个新的工程
图二 创建新工程1
选择“Create New Project”,选择“Basic Project Template”模版,选择“Save as”按钮,弹出保存新建工程的目录以及名称,名称的后缀为.iap_xml。
也可以通过“Open Existing Project”,打开已经存在的文件。这里新建一个项目
图三 创建新工程2
2.4.3 点击“Advanced Designer”按钮,进入高级模式info设置
图四 高级模式
从该界面中可以看到,有很多项设置,一级导航包括:Project、Installer UI、Organization、Files、Pre-Install、Post-Install、Pre-Uninstall、Post-Uninstall、Build。这里主要介绍Project。
2.4.4 进入Description设置
图五 Description设置
Description界面中设置安装包的产品可能写入注册表中的一些信息,包括:产品名称、ID、版本、以及支持、提供商等信息,可以详细的填写相关的信息,包括产品介绍等
2.4.5 File Settings
图六 File Settings界面
该界面中主要设置安装过程中,被安装的文件的时间如何处理,你可以选择保留文件本身的时间,也可以设置为安装时的时间,还可以设置成指定的时间。该界面中还可以设置当文件已经存在时,如何提示或操作。一般,使用缺省设置即可。
2.4.6 Platforms
图七 Platforms界面
我用的InstallAnywhere,支持四种操作系统平台:Mac OS X、Windows、UNIX和System i。因此,Platforms设置界面中,你可以分别对这四种操作平台的缺省安装路径和缺省快捷方式进行设置。一般使用缺省设置即可,我主要是Windows平台。
2.4.7 Locales
图八 Locales安装语言界面选择
Locales项设置安装包所支持的安装界面的语言。缺省是英文安装语言。只有选择了除英文之外的至少一种其他语言,安装包才会在安装开始时显示选择安装语言的界面。一般选择支持简体中文即可
2.4.8 Rules
图九 Rules设置
Rules项中可以配置多种安装规则,如安装前检查安装路径属性、安装平台或者其他自定义的规则。一般,我们会用到检查安装平台,如是否是指定的操作系统。
2.4.9 Config
图十 Config配置
“Config”界面“installer debug output”中有俩个文本框,大家可以在里面填上“console”,这样大家在安装文件生成后,调试安装时可以通过控制台来查看相关的提示信息。正是发布的话,清空即可。其他几项都可以使用缺省设置即可。
2.4.10 Java
图十一 Java配置
如果需要安装VM的话,就需要注意VM的安装路径
3 安装包制作过程
资料补充:
利用该工具提供的各种预安装界面和客户自定义界面来定制安装包安装流程,其中预安装界面是installanywhere提供的模板界面,而客户自定义界面是通过继承实现类
com.zerog.ia.api.pub.CustomCodePanel |
该类要实现的方法是
@Override public boolean setupUI(CustomCodePanelProxy customCodePanelProxy) { return true; } |
如果有点击事件的话还要实现ActionListener接口
@Override public void actionPerformed(ActionEvent e) { } |
界面点击下一步时触发的方法
//点击下一步按钮时触发的事件,返回true时可以进入下一步,返回false时停留在本页面 public boolean okToContinue() { return true; } |
界面点击上一步时触发的方法
//点击上一步按钮时触发的事件,返回true时可以进入下一步,返回false时停留在本页面 public boolean okToGoPrevious() { customCodePanelProxy.setVariable("$DB$", db); customCodePanelProxy.setVariable("$ENV$", env); return true; } |
传参数和取参数
//表示传参数 customCodePanelProxy.setVariable("$DB$", db); //取参数 Object dbInfo = customCodePanelProxy.getVariable("$DB$"); |
面板标题设置
//此面板显示在右上角的标题 public String getTitle() { return "获取数据库连接信息"; } |
因为自定义面板是执行的java代码,所以,应先建立一个项目,编写相关的代码。
3.1 选择安装语言环境
见2.4.7
3.2 检测操作系统平台,主要是Windows平台
见2.4.8
3.3 检测系统版本及JVM版本
3.3.1 新建类CommonEnvironmentPanel,继承CustomCodePanel
CustomCodePanel类路径为com.zerog.ia.api.pub.CustomCodePanel,在IAClasses.zip包中,该包在installanywhere的安装根目录下,拷贝到相应的地方即可。
3.3.2 编写检测系统方法及Java版本
主要通过System.getProperty("aaa")方法提取installanywhere能读取的系统环境。
常用的有java.home、java.version、os.name、os.arch、os.version等,这些可以在调试状态下通过调试窗口的启动画面看到
这里注意取默认安装路径和实际安装路径的过程,下面有批示
/** * 检测系统常用环境 * 如: * 操作系统名称、架构、版本 * JVM安装路径、版本号 * @return CommonEnvironment 常用系统参数对象 */ public CommonEnvironment getEnvDir() { env = new CommonEnvironment(); //取参数值--安装路径 InstallDirMF programDir = (InstallDirMF) customCodePanelProxy.getVariable("$USER_INSTALL_DIR$"); //得到安装产品的目录,如c:/program files MagicFolder mf = programDir.getMagicFolder(); String installRoot = mf.getPath(); //取得产品名 String pdName = (String) customCodePanelProxy.getVariable("$PRODUCT_NAME$"); //默认安装路径 String installPath = installRoot + "//" + pdName; //实际安装路径 InstallDirMF installMF = mf.getInstaller().getInstallDir(); String realPath = installMF.getPath();
//取参数值--安装路径 DoNotInstallMF donotMF = (DoNotInstallMF) customCodePanelProxy.getVariable("$DO_NOT_INSTALL$");
//测试取得java环境 //java home的路径 String javahomeDir = System.getProperty("java.home"); //java version String javaversion = System.getProperty("java.version"); //os name String osname = System.getProperty("os.name"); //os arch String osarch = System.getProperty("os.arch"); //os version String osversion = System.getProperty("os.version"); // JavaHomeMF javahome = new JavaHomeMF(); // System.out.println("/r/n..... java home dir is " + javahome.getPath());
env.setJavahome(javahomeDir); env.setJavaversion(javaversion); env.setDefaultInstallDir(installPath); env.setRealInstallDir(realPath); env.setOsname(osname); env.setOsarch(osarch); env.setOsversion(osversion); return env; } |
其中,CommonEnvironment 常用系统参数对象为
/** * 常用系统参数对象<br> * 如:<br> * 操作系统名称、架构、版本<br> * JVM安装路径、版本号<br> * * @author Gcitec.Feng * @date 2010-04-15 */ public class CommonEnvironment {
//Fields private String osname; //操作系统名称 如Windows 2003 private String osarch; //操作系统架构 如x86 private String osversion; //操作系统版本 如5.2 private String javahome; //JVM安装路径 private String javaversion; //JVM版本号 private String defaultInstallDir; //产品默认安装路径 private String realInstallDir; //产品实际安装路径
public CommonEnvironment() { }
//getter and setter method … } |
3.3.3 在setupUI方法中调用检测环境方法
@Override public boolean setupUI(CustomCodePanelProxy customCodePanelProxy) { env = getEnvDir(); //将参数输出到页面 p = new Panel(); p.setLayout(gb); //指定当组件显示区域大于组件所需区域时,决定是否以及怎样重新定义组件大小 gc.fill = GridBagConstraints.HORIZONTAL; gc.gridwidth = GridBagConstraints.REMAINDER; //一行结束
//显示操作系统名称 initLabel("操作系统:", gb, gc, 1); initLabel(env.getOsname(), gb, gc, 2); gc.gridwidth = GridBagConstraints.REMAINDER; //一行结束 gc.gridwidth = GridBagConstraints.REMAINDER; //一行结束 //显示操作系统架构、版本 initLabel("系统版本:", gb, gc, 1); initLabel(env.getOsversion() + " / " + env.getOsarch(), gb, gc, 2); gc.gridwidth = GridBagConstraints.REMAINDER; //一行结束 //显示JVM版本 initLabel("JVM版本:", gb, gc, 1); initLabel(env.getJavaversion(), gb, gc, 2); gc.gridwidth = GridBagConstraints.REMAINDER; //一行结束 //显示JVM安装路径 initLabel("JVM安装路径:", gb, gc, 1); initLabel(env.getJavahome()!=null?env.getJavahome():"", gb, gc, 2); gc.gridwidth = GridBagConstraints.REMAINDER; //一行结束
p.setSize(384, 294); add(p); return true; } |
其中env、p、gb、gc是CommonEnvironmentPanel的属性
private CommonEnvironment env = null; private DatabaseInfo db = null; private Panel p = null; //布局 GridBagLayout gb = new GridBagLayout(); GridBagConstraints gc = new GridBagConstraints(); |
initLabel方法为
/** * 初始化SWING组件JLabel * @param name 组件名称 * @param gridbag 组件布局 * @param c 组件容器 * @param anchor 文本摆放位置 */ public void initLabel(String name, GridBagLayout gridbag, GridBagConstraints c, int anchor) { //指定当组件显示区域小于组件所需区域时,决定在区域的什么位置放置该组件 if(anchor==1) c.anchor = GridBagConstraints.WEST; else if(anchor==2) c.anchor = GridBagConstraints.EAST; else c.anchor = GridBagConstraints.CENTER; c.weighty = 3; JLabel label = new JLabel(name); gridbag.setConstraints(label, c); p.add(label); } |
另外,还有
/** * 点击下一步按钮时触发的事件,返回true时可以进入下一步,返回false时停留在本页面 */ public boolean okToContinue() { customCodePanelProxy.setVariable("$DB$", db); customCodePanelProxy.setVariable("$ENV$", env); return true; }
/** * 点击上一步按钮时触发的事件,返回true时可以进入下一步,返回false时停留在本页面 */ public boolean okToGoPrevious() { customCodePanelProxy.setVariable("$DB$", db); customCodePanelProxy.setVariable("$ENV$", env); return true; }
/** * 此面板显示在右上角的标题 */ public String getTitle() { return "获取系统及JVM信息"; } |
db数据库信息类
/** * 数据库信息类 <br> * 实例ORACLE 9.2.0.1 * @author Gcitec.Feng * @date 2010-4-12 */ public class DatabaseInfo { //属性 public String host; //数据库连接主机地址 public String port; //端口号 public String sid; //Oracle数据库的SID public String version; //数据库版本号 public String username; //登录用户名 public String password; //登录密码 public String dboptkey; //数据库默认连接用户名
public DatabaseInfo() { this.host = "localhost"; this.port = "1521"; this.sid = ""; this.version = ""; this.username = "system"; this.password = "system"; this.dboptkey = "MPMSBYGCITECOPT"; }
//getter and setter method … } |
3.3.4 将自定义面板添加到安装向导中
这一步是在安装之前就应进行的操作,所以是属于预安装步骤
在installanywhere高级界面>>Pre-Install
图十二 预安装步骤添加自定义面板—总
如图,点击“Add Action”按钮,弹出一个框,选择Panels>>Custom Code Panel,见下图
图十三 添加自定义面板到预安装步骤
并在图十二所示的画面中,添加path(导入执行java类所在的包)、class(自定义面板所在的类全路径)
Dependencies那里添加类文件所依赖的jar包(也支持.zip格式的包)。
3.3.5 添加安装包包含的文件
图十四 添加文件界面
点击“Add Files”按钮,出现
图十五 添加文件到安装包
选中文件,点击“Add”按钮,最后点击“Done”按钮
3.3.6 制作安装包并查看自定义面板效果
图十六 打包
选择安装包的平台和是否安装包内带JVM(客户机没有java环境则需要带JVM的),然后点击“Build Project”按钮,开始打包,提示完成后,点击“Try Installer”,开始执行安装包。
图十七 安装效果1
上面黑色的是调试窗口,蓝色的为安装程序,从调试窗口中可以看到java.version、os.arch等熟悉的信息,检测操作系统版本等信息就是通过这些关键字来提取的。
图十八 操作系统环境检测
调试窗口还能打印调试信息(System.out.println("Version: " + db.getVersion());)
蓝色窗口显示的是当前系统版本和JVM版本及安装路径
3.4 检测客户机oracle环境、版本及oracle数据库的连接
Windows系统如果装有oracle,则会在注册表“HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE”这个位置有相关信息。在注册表路径(“HKEY_LOCAL_MACHINE/SOFTWARE/ORACLE/HOME0”)下面查找关键字(oracle的SID关键字“Oracle_sid”),如果不为空则返回oracle版本,否则返回null,客户机无oracle。
Installanywhere的IAClasses.zip包中可以支持访问注册表,该类为
com.zerog.ia.api.pub.SimpleRegistryManager |
具体用法见下
//检测oracle的sid和版本 Object sidHKEY = null; Object versionHKEY = null;
//Installanywhere自带的注册表管理类进行注册表访问,得到Oracle相关信息 SimpleRegistryManager regManager = (SimpleRegistryManager) customCodePanelProxy.getService(SimpleRegistryManager.class); //通过判断ORACLE的SID来确定系统中是否装有ORACLE服务(会抛出空指针异常) try { sidHKEY = regManager.getRegistryKeyValue(sidDir, sidStr); } catch(NullPointerException e) { sidHKEY = null; } |
sidHKEY应该是String类型的字符串,强转即可(String) sidHKEY
这里主要是在setupUI方法中实现检测oracle环境,然后用Swing创建用户输入面板,用户提供oracle连接信息,注意,用户提供的帐户必须是具有创建oracle用户权限,因为安装程序接下来会根据这个输入的用户创建帐号和授权。
用户输入的信息有
图十九 oracle环境检测及连接自定义面板
点击测试连接按钮,则程序调用jdbc进行oracle连接,下面空格处会有提示信息是否连接上。
3.5 安装程序
点击“安装”按钮进行安装
3.6 通过java调用imp命令导入dmp文件
这里未实现远程导入dmp,因为imp命令为oracle提供,如果客户机有oracle环境,则直接安装客户机。
3.6.1 创建系统指定的oracle用户并授权
/** * 创建Oracle用户并授权(如果存在要添加的用户,则先删除,一般只有重复安装的时候才会出现用户名相同) * @return boolean 创建用户并授权成功返回true / 否则返回false */ public boolean createDBUserandGrant() { boolean rlt = false; Connection conn; PreparedStatement userPrepStmt; PreparedStatement grantPrepStmt; PreparedStatement dropStmt; ResultSet rltset; //查询oracle所有用户SQL String userexistSQL = "select username from all_users"; //创建用户SQL String userSQL = "create user " + DBOPT_KEY + " identified by " + DBOPT_KEY; //授权SQL String grantSQL = "grant dba,resource,connect to " + DBOPT_KEY; //删除用户SQL String dropSQL = "drop user " + DBOPT_KEY + " cascade"; try { conn = new DatabaseConn().getConn(db); //检测需要创建的用户是否存在 userPrepStmt = conn.prepareStatement(userexistSQL); rltset = userPrepStmt.executeQuery(); if(rltset!=null) { String username; while(rltset.next()) { username = rltset.getString("username"); if(DBOPT_KEY.equals(username)) { dropStmt = conn.prepareStatement(dropSQL); rltset = dropStmt.executeQuery(); System.out.println(",,,,,,,,,,,,,,, 删除用户 : " + DBOPT_KEY); break; } } } //创建用户 userPrepStmt = conn.prepareStatement(userSQL); rltset = userPrepStmt.executeQuery(); //授权 grantPrepStmt = conn.prepareStatement(grantSQL); rltset = grantPrepStmt.executeQuery();
rlt = true;
} catch (ClassNotFoundException e) { // e.printStackTrace(); } catch (SQLException e) { // e.printStackTrace(); } return rlt; } |
DBOPT_KEY参数为String类型,是具体某个用户名,这里默认用户名和密码一致。
3.6.2 导入oracle备份文件
Java调用imp命令是用
Process proc = Runtime.getRuntime().exec(dmpstr); |
String类型dmpstr参数就是一个经过拼装后的imp命令,imp命令具体用法这里不描述。
注:
l 数据库备份文件(***.dmp)一般是安装过程中解压缩到安装目录下面
l Imp命令中各个参数是用空格区分的,如果安装路径中间有空格的话,则需要将dmp文件拷贝到其他路径下面去,如“C:/”,再执行导入命令,否则会提示找不到路径
l 导入oracle时,一般不会在调试窗口中显示导入信息,需要查看相关信息,则要另外一个类才达到效果,导入oracle方法代码见下
/** * 导入dmp文件 * @param db DatabaseInfo数据库信息 * @return boolean 成功返回true / 否则返回false */ public boolean importDMP(DatabaseInfo db) { boolean rlt = false; String dbfilename = "mpms.dmp"; String dbfilePath = env.getRealInstallDir(); String[] files = dbfilePath.split(" "); //StringUtils.isWhitespace(dbfilePath) //项目安装路径中间 有 空格 if(files.length>1) { System.out.println("项目安装路径中间 有 空格 "); //复制文件到系统盘根目录下,方便导入数据 imp命令文件路径中间不能带空格 File sourceFile = new File(dbfilePath + "/" + dbfilename); Date d = new Date(); dbfilePath = "C:"; dbfilename = "mpms" + d.getYear() + d.getMonth() + d.getDay() + d.getHours() + d.getMinutes() + d.getSeconds() + ".dmp"; File targetFile = new File(dbfilePath + "/" + dbfilename); try { InstallUtil.copyFile(sourceFile, targetFile);
} catch (IOException e) { // e.printStackTrace(); } }
//远程导入数据库@host String dmpstr = "imp " + db.getUsername() + "/" + db.getPassword() + " file=" + dbfilePath + "/" + dbfilename + " commit=y buffer=65536 fromuser=mpmsother touser=" + DBOPT_KEY + " ignore = y"; System.out.println("导入语句为:" + dmpstr); try { Process proc = Runtime.getRuntime().exec(dmpstr);
// any error message? StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERR");
// any output? StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUT");
// kick them off errorGobbler.start(); outputGobbler.start();
// any error??? int exitVal = proc.waitFor(); System.out.println("ExitValue: " + exitVal);
rlt = true;
} catch (IOException e) { e.printStackTrace(); } catch (Throwable t) { t.printStackTrace(); } finally { InstallUtil.deleteFile(dbfilePath+"/"+dbfilename); if(files.length>1) InstallUtil.deleteFile(env.getRealInstallDir()+"/mpms.dmp"); }
return rlt; } |
env.getRealInstallDir() 是获取项目的实际安装路径,文档上面有提到这个类及获取实际安装路径的方法实现。
InstallUtil.copyFile(sourceFile, targetFile) 该方法是将一个文件复制到另一个指定路径,两个文件名都必须是路径+文件名(如果需要可以自己实现)
InstallUtil.deleteFile(dbfilePath+"/"+dbfilename) 同上,删除文件
StreamGobbler 类文件,代码如下
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader;
public class StreamGobbler extends Thread {
InputStream is; String type;
public StreamGobbler(InputStream is, String type) { this.is = is; this.type = type; }
public void run() { try { InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) System.out.println(type + ">" + line); } catch (IOException ioe) { ioe.printStackTrace(); } }
} |
3.7 通过用户输入连接的数据库信息改变系统数据库连接配置文件
因为数据库连接信息的改变而导致系统数据库连接环境的变化,这里主要是通过dom4j来解析spring配置文件,并进行修改。
/** * 根据dom4j来解析Spring配置文件,并修改Spring XML配置文件<br> * 直接修改后覆盖 * @param fileName Spring配置文件名 * @param db DatabaseInfo 数据库信息 * @return boolean 修改无错误返回true / 否则返回false */ public boolean updSpringXmlFile(String fileName, DatabaseInfo db) { boolean rtn = false;
SAXReader reader = new SAXReader(); try { Document document = reader.read(new File(fileName)); //提取所有bean List list = document.selectNodes("/beans/bean"); Iterator itr = list.iterator(); while(itr.hasNext()) { Element beanElement = (Element)itr.next(); //查找id为dataSource的bean,遍历bean的property属性,逐一改变其值 if("dataSource".equals(beanElement.attributeValue("id"))) { Iterator itr1 = beanElement.elementIterator(); while(itr1.hasNext()) { Element propertyElement = (Element)itr1.next(); Iterator aa = propertyElement.elementIterator(); while(aa.hasNext()) { Element ab = (Element) aa.next(); String tmpname = propertyElement.attributeValue("name"); String tmpstr = ab.getText(); if("url".equals(tmpname)) { String oracleurl = ""; oracleurl = "jdbc:oracle:thin:@" + db.getHost() + ":" + db.getPort() + ":" + db.getSid(); ab.setText(oracleurl);
} //默认用户名和密码 if("username".equals(tmpname)) { ab.setText(db.getDboptkey()); } if("password".equals(tmpname)) { ab.setText(db.getDboptkey()); } System.out.println("... " + propertyElement.attributeValue("name") + "=" + ab.getText()); } } } }
XMLWriter output; OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("utf-8"); try { //防止出现Invalid byte 1 of 1-byte UTF-8 sequence错误, //不用FileWriter(默认GBK或者GB2312),改用FileOutputStream output = new XMLWriter(new FileOutputStream(fileName), format); output.write(document); output.close(); rtn = true; } catch (IOException e) { e.printStackTrace(); }
} catch (DocumentException e) { e.printStackTrace(); }
return rtn;
} |
3.8 通过执行批处理改变系统环境变量
图二十 设置操作系统环境变量
菜单Install>按钮Add Action...>Set System Environment Variable>Add>,设置JAVA_HOME和CATALINA_HOME两个系统环境变量。其中$USER_INSTALL_DIR$表示用户选择的安装路径,见图二十
3.9 自动启动tomcat服务
注册tomcat批处理install.bat
set JAVA_HOME=%1%/jdk1.6.0_10 set CATALINA_HOME=%1%/apache-tomcat-6.0.13 call %1%/apache-tomcat-6.0.13/bin/service install Tomcat net start Tomcat |
%1% 是需要传入的参数,在后面有描述
图二十一 执行批处理
菜单Post-Install>按钮Add Action...>Execute Command>Add
在安装完成后执行install.bat,注册Tomcat服务。
其中Command Line: cmd /c $USER_INSTALL_DIR$/install.bat $USER_INSTALL_DIR$。
l cmd /c表示执行指定的命令并中断。
l $USER_INSTALL_DIR$是传递给install.bat中%1%的参数。
l 选中Options中的3个选项。
将该Execute Command移动到Panel: Install Complete前面
3.10 自动打开浏览器,通过url地址访问系统
菜单Post-Install>,按钮Add Action...>Launch Default Browser>Add,在Other URL: 填入项目地址 http://localhost:端口号/项目名,将该Launch Default Browser移动到Panel: Install Complete后面
4 后记
在制作安装包的工程中,从网络上找了很多的资料,进行参考,下面有一些网址
http://hi.baidu.com/daniel_tu/blog/item/68781723e4b362459358077a.html
…(有些没有保存,遗憾)