背景
一个应用了多年的自己编写的java的启动方式,觉得甚是方便,大致与SpringBoot启动jar的方式类似,于是就想把它共享出来,共勉之。
启动时序:
核心类图:
代码共享
java核心源码:
package com.what21; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; public class BootstrapClassLoader extends URLClassLoader { static final String JAR = ".jar"; static final String ZIP = ".zip"; public BootstrapClassLoader(URL[] urls) { super(urls); } public static class Build { /** * @param parentPath * @return */ public static BootstrapClassLoader build(String parentPath) { URL[] urls = toURL(parentPath); // System.out.println(Arrays.toString(urls)); return new BootstrapClassLoader(urls); } /** * @param parentPath * @return */ public static URL[] toURL(String parentPath) { if (parentPath == null) { return null; } File file = new File(parentPath); if (!file.exists()) { return null; } List<String> pathList = new ArrayList<String>(); listFile(parentPath, pathList); URL[] urlArray = new URL[pathList.size()]; for (int i = 0; i < pathList.size(); i++) { try { urlArray[i] = new URL("file:///" + pathList.get(i)); } catch (MalformedURLException e) { e.printStackTrace(); } } return urlArray; } /** * @param filePath * @param pathList */ static void listFile(String filePath, List<String> pathList) { File file = new File(filePath); File[] files = file.listFiles(); for (File subFile : files) { recursionFile(subFile.getAbsolutePath(), pathList); } } /** * @param filePath * @param pathList */ static void recursionFile(String filePath, List<String> pathList) { File file = new File(filePath); if (file.isDirectory()) { for (File subFile : file.listFiles()) { listFile(subFile.getAbsolutePath(), pathList); } } else { String absolutePath = file.getAbsolutePath().toLowerCase(); if (absolutePath.endsWith(".jar") || absolutePath.endsWith(".zip")) { pathList.add(file.getAbsolutePath()); } } } } }
package com.what21; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.reflect.Method; import java.net.URLDecoder; import java.util.ArrayList; import java.util.List; public final class Bootstrap { private static final String BIN = "bin"; private static final String LIB = "lib"; private static final String APPS = "apps"; private static final String launchClass = "com.what21.apps.ApplicationBootstrap"; private static final String launchMethod = "launch"; private static BootstrapClassLoader bootstrapClassLoader; /** * @return */ private static String applicationHome() { // 获取当前系统编码 String encoding = System.getProperty("sun.jnu.encoding"); if (encoding == null || "".equals(encoding)) { encoding = "UTF-8"; } // 获取URL,进行解码 String runPath = Bootstrap.class.getProtectionDomain().getCodeSource().getLocation().getPath(); String decodeRunPath = null; try { decodeRunPath = URLDecoder.decode(runPath, encoding); } catch (Exception e) { } File runFile = new File(decodeRunPath); if (!runFile.exists()) { try { decodeRunPath = URLDecoder.decode(runPath, "UTF-8"); } catch (Exception e) { } runFile = new File(decodeRunPath); } File runHomeFile = runFile.getParentFile(); String homePath = ""; if (BIN.equalsIgnoreCase(runHomeFile.getName())) { homePath = runHomeFile.getParent(); } else { homePath = runHomeFile.getAbsolutePath(); } return homePath; } /** * @param obj */ private static void logger(Object obj) { System.out.println(obj); } /** * @param pidPath * @param pid */ private static void writeProcessPid(String pidPath, String pid) { FileOutputStream fos = null; try { fos = new FileOutputStream(new File(pidPath)); fos.write(pid.getBytes()); fos.flush(); } catch (Exception e) { System.err.println(e.getMessage()); } finally { if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } fos = null; } } } /** * @param applicationApps * @return */ private static String[] toApplicationArray(String applicationApps) { List<String> appList = new ArrayList<String>(); File appsFile = new File(applicationApps); if (appsFile != null) { File[] appFileArray = appsFile.listFiles(); for (File appFile : appFileArray) { if (appFile.isDirectory()) { appList.add(appFile.getAbsolutePath()); } } } return appList.toArray(new String[] {}); } /** * @param args */ public static void main(String[] args) { long startTime = System.currentTimeMillis(); logger("/////////////////////////////////////////////////////////////////////////////////////////////"); logger("/////////////////////////////////////////////////////////////////////////////////////////////"); // logger("// sun.jnu.encoding: " + System.getProperty("sun.jnu.encoding")); logger("// file.encoding: " + System.getProperty("file.encoding")); // home String applicationHome = applicationHome(); System.setProperty("application.home", applicationHome); logger("// application.home: " + applicationHome); // lib String applicationLib = applicationHome + "/" + LIB + "/"; System.setProperty("application.lib", applicationLib); logger("// application.lib: " + applicationLib); // apps String applicationApps = applicationHome + "/" + APPS + "/"; System.setProperty("application.apps", applicationApps); logger("// application.apps: " + applicationApps); bootstrapClassLoader = BootstrapClassLoader.Build.build(applicationLib); logger("// application.classloader: " + bootstrapClassLoader); logger("/////////////////////////////////////////////////////////////////////////////////////////////"); String[] applicationPathArray = toApplicationArray(applicationApps); // invoke try { Class<? extends Object> clazz = bootstrapClassLoader.loadClass(launchClass); Object object = clazz.newInstance(); Method method = clazz.getDeclaredMethod(launchMethod, new Class[] { String[].class }); method.setAccessible(true); method.invoke(object, new Object[] { applicationPathArray }); } catch (Exception e) { e.printStackTrace(); } logger("/////////////////////////////////////////////////////////////////////////////////////////////"); String runName = ManagementFactory.getRuntimeMXBean().getName(); logger("// application.name: " + runName); if (runName != null) { String pid = runName.split("@")[0]; writeProcessPid(applicationHome + "/" + BIN + "/process.pid", pid); } long endTime = System.currentTimeMillis(); logger("// Application startup in " + (endTime - startTime) + " ms"); logger("/////////////////////////////////////////////////////////////////////////////////////////////"); logger("/////////////////////////////////////////////////////////////////////////////////////////////"); } }
Linux启动脚本:
#!/bin/bash #========================================================================================== # export JAVA_HOME=/opt/java/jdk1.8.0_221 export PATH=$JAVA_HOME/bin:$PATH export JAVA_OPTS="-Xmx1024M -Xms512M -XX:MaxPermSize=256m" export JAVA_JAR="startup-single-2.0.jar" export JAVA_MAIN="com.what21.startup.SingleStartUp" export LAUNCH_CLASS="com.what21.simba.netserv.launch.NetServDaemon.launch" export LAUNCH_ARGS="" export WORK_HOME=$(dirname "$PWD") #========================================================================================== export CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$CLASSPATH #========================================================================================== echo "Java Home <=====> $JAVA_HOME" echo "JVM Parameters <=====> $JAVA_OPTS" echo "Start Jar <=====> $JAVA_JAR" echo "Start Class <=====> $JAVA_MAIN" echo "Launch Class <=====> $LAUNCH_CLASS" echo "Start Parameters <=====> $LAUNCH_ARGS" echo "Execute Command <=====> $CMD" #========================================================================================== nohup $JAVA_HOME/bin/java -DWorkHome=$WORK_HOME $JAVA_OPTS -classpath "$CLASSPATH:./$JAVA_JAR" "$JAVA_MAIN" "$LAUNCH_CLASS" "$LAUNCH_ARGS" "$CMD" >/dev/null 2>&1 & #==========================================================================================
Windows启动脚本:
@echo off rem ======================================================================== rem set JAVA_HOME=D:MyAppsJavajdk1.8.0_131 set JAVA_OPTS="-Xmx1024M -Xms512M -XX:MaxPermSize=256m" set JAVA_JAR="startup-single-2.0.jar" set JAVA_MAIN="com.what21.startup.SingleStartUp" set LAUNCH_CLASS="com.what21.simba.netserv.launch.NetServDaemon.launch" set LAUNCH_ARGS= rem ======================================================================== set CLASSPATH=.;%JAVA_HOME%libdt.jar;%JAVA_HOME%libtools.jar set WORK_HOME=%cd% rem ======================================================================== rem 接收传入参数 rem ======================================================================== if "%1"=="" goto doStart if "%1"=="start" goto doStart if "%1"=="stop" goto doShutdown rem ======================================================================== :doStart set CMD=start goto doExe rem ======================================================================== :doShutdown set CMD=stop goto doExe rem ======================================================================== :doExe echo "================================================================================================================" echo "Execute Directory <=====> %WORK_HOME%" echo "Java Home <=====> %JAVA_HOME%" echo "JVM Parameters <=====> %JAVA_OPTS%" echo "Start Jar <=====> %JAVA_JAR%" echo "Start Class <=====> %JAVA_MAIN%" echo "Launch Class <=====> %LAUNCH_CLASS%" echo "Start Parameters <=====> %LAUNCH_ARGS%" echo "Execute Command <=====> %CMD%" echo "================================================================================================================" echo. %JAVA_HOME%binjava -DWorkHome=$WORK_HOME "%JAVA_OPTS%" -classpath "%CLASSPATH%;%JAVA_JAR%" "%JAVA_MAIN%" "%LAUNCH_CLASS%" "%LAUNCH_ARGS%" "%CMD%" & pause goto end rem ======================================================================== :notParam echo not params rem ======================================================================== :end
还没有评论,来说两句吧...