最近使用layui作为javafx的表现层,发现layui的字体文件在打包后无法正常加载,在经过仔细排查后,发现是打包后路径发生变化导致的,所以就自定义了URLStreamHandlerFactory来处理无法加载的文件。
static { URL.setURLStreamHandlerFactory(new CustomURLStreamHandlerFactory()); } public static class CustomURLStreamHandlerFactory implements URLStreamHandlerFactory { @Override public URLStreamHandler createURLStreamHandler(String protocol) { if("local".equals(protocol)){ return new LocalStreamHandler(); } if ("jar".equals(protocol)){ return new CustomJarStreamHandler(); } else { return null; } } } public static class LocalStreamHandler extends URLStreamHandler { @Override protected URLConnection openConnection(URL u) throws IOException { return new CustomURLConnection(u); } } public static class CustomJarStreamHandler extends sun.net.www.protocol.jar.Handler { @Override protected URLConnection openConnection(URL url) throws IOException { if(url.toString().contains("local")||url.toString().contains("app.jar!")){ return new CustomURLConnection(url); }else{ return super.openConnection(url); } } }
public static class CustomURLConnection extends HttpURLConnection { private InputStream inputStream; CustomURLConnection(URL url) throws IOException { super(url); } @Override public void disconnect() { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { log.debug(e.getMessage(), e); } } connected = false; } @Override public boolean usingProxy() { return false; } @Override public void connect() throws IOException { if (connected) { return; } inputStream = loadData(CustomURLConnection.class.getClassLoader()); connected = true; } @Override public int getResponseCode() throws IOException { return HttpURLConnection.HTTP_OK; } @Override public InputStream getInputStream() throws IOException { return inputStream; } private InputStream loadData(ClassLoader loader) { String protocol = url.getProtocol(); if (protocol.equals("jar")) { String path = url.getPath(); if (path.contains("local")) { byte[] response = JavaScriptNative.scriptNative.getResponse(url.toExternalForm()); return new ByteArrayInputStream(response); } if (path.contains("jar://file/")) { path = path.substring(path.indexOf("jar://file") + "jar://file".length() + 1); try { path = URLDecoder.decode(path, "UTF-8"); return Files.newInputStream(Paths.get(path)); } catch (IOException e) { log.debug(e.getMessage(), e); } return new ByteArrayInputStream(new byte[0]); } path = path.substring(path.indexOf("app.jar!") + "app.jar!".length() + 1); return loader.getResourceAsStream(path); } byte[] response = JavaScriptNative.scriptNative.getResponse(url.toExternalForm()); return new ByteArrayInputStream(response); } }