在另一个jar包中运行jar文件

3

为了更清晰地表达我的意思,我需要重写这个问题:

我想为一个已经以(可执行)jar格式存在的程序制作一个引导加载器。在其运行时,该引导程序将有三个简单的目标:

  1. 比较本地xml文件和服务器上托管的目标程序的文件,以确保它们是相同版本的。

  2. 如果它们的版本不同且在线版本更新,则下载更新的版本。

  3. 重新编写xml文件以反映此更改。

  4. 执行第二个jar文件(启动它,就好像你启动了可执行文件)。

我遇到的问题是第4步。尽管查看了UrlClassLoader和其他库,但我仍然无法找到一种可靠的方法来从引导程序中启动jar。

由于某些外部问题,JNLP / Web-start对这种情况不可行。

简而言之:我需要找到一种方法,在引导程序运行时从一个jar中下载/启动另一个jar,以便更新程序。

谢谢!


可能是重复的问题:https://dev59.com/mmjWa4cB1Zd3GeqPs6_3 - dan
实际上非常接近,那里的顶部答案的实现甚至可能适合我的需求,感谢您指出 @dan。 - A_Elric
4个回答

0

我讨厌不得不回答自己的问题,但在这种情况下,我觉得必须这样做...

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import org.w3c.dom.Document;


public class updater {
public static void main(String[] args) throws IOException {
    try{
        DefaultHttpClient httpclient = ClientMaker();
        HttpGet get = new HttpGet("http://encorpops04:8080/Updater-test/Version.xml");
        HttpResponse response = httpclient.execute(get);
        InputStream in = response.getEntity().getContent();

        DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = domFactory.newDocumentBuilder();
        Document doc = builder.parse(in);

        //Parse the Xml.
        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        XPathExpression expr = xpath.compile("//version/number/text()");
        String result = (String) expr.evaluate(doc, XPathConstants.STRING);
        System.out.println(result);

        File f = new File(System.getProperty("user.dir")+ "\\Version.xml");
        in = new FileInputStream(f) ;
        doc = builder.parse(in);
        expr=xpath.compile("//version/number/text()");
        String result2 = (String) expr.evaluate(doc, XPathConstants.STRING);
        System.out.println(result2);


        if(Double.parseDouble(result2) < Double.parseDouble(result)){
            HttpGet get2 = new HttpGet("http://encorpops04:8080/Updater-test/MyOutput.jar"); 
            HttpResponse response2 = httpclient.execute(get2);
            InputStream in2 = response2.getEntity().getContent();
            File f2 = new File("MyOutput.jar");
            OutputStream fos = new FileOutputStream(f2);
            byte buf[] = new byte[1024];
            int len;
            while ((len = in2.read(buf)) > 0) {
                fos.write(buf, 0, len);
            }
            fos.close();
            in.close();
        }
        System.out.println("cmd.exe /C  javaw -jar"  +System.getProperty("user.dir") + "\\MyOutput.jar");
        Process p = Runtime.getRuntime().exec("cmd.exe /C  javaw -jar "  +System.getProperty("user.dir") + "\\MyOutput.jar");
        p.waitFor();
        p.destroy();
    }catch(Exception e){ e.printStackTrace(); }


}

public static DefaultHttpClient ClientMaker() {
    int connectiontimeout = 30000; // 1 second int sockettimeout = 1000;
    HttpParams httpparameters = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(httpparameters,
            connectiontimeout);
    HttpConnectionParams.setSoTimeout(httpparameters, connectiontimeout);
    DefaultHttpClient httpclient = new DefaultHttpClient(httpparameters);
    return httpclient;
}

}

Version.xml 的外观如下:

<?xml version="1.0" encoding="ISO-8859-1"?>
<version>
    <number>1.0</number>
</version>

顺便提一下- 我没有让version.xml自动更新,你可以编辑其中的数字以匹配,或者只需拉取您检查的版本来替换它。


0

0

当你说“执行新的jar”时,你是指启动一个独立的应用程序吗? 一种可能的方法是从Updater.jar引导逻辑中简单地执行一个新的Java进程,然后退出自身。


第二个jar文件本身是一个独立的应用程序(它是一个可运行的jar文件,只需要一个更新器,这也是更新器.jar的唯一目的)。我没有问题运行第二个jar文件并退出引导程序,但是我该如何做呢?我知道System.exit(0);会关闭应用程序本身,但我不确定如何先运行另一个jar文件? - A_Elric
看看Jim的回答。问题是,当退出引导过程时,您将丢失原始的stdin和stdout通道。我曾经用一个应用程序做过类似的事情,但我保持了两个进程的活动状态。但是,在启动应用程序进程后,引导进程除了读取其stdout并回显到自己的stdout外什么都不做。 - Udo Klimaschewski

0

换句话说,您想要实现自更新应用程序。这是可能的,甚至不那么困难。

您的程序应该被设计为具有两个部分。加载器(和更新程序)和业务逻辑。加载器应该使用单独的类加载器启动业务逻辑。您可以使用UrlClassLoader。加载器将访问在线服务并检查版本。如果需要,它将创建URLConnection,下载新的jar并将其存储在文件系统中的某个位置(例如用户主目录)。然后,它将使用已经提到的类加载器运行业务逻辑,该类加载器从刚刚下载的jar文件中加载类。

这实际上模仿了JNLP的行为。


你有没有一个实现这个功能的例子?我很感兴趣看看它是否能提供我需要让项目工作所需的功能。 - A_Elric

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接