All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.shepherdviolet.glacimon.java.protocol.url.ResInJarURLStreamHandlerFactory Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2022-2022 S.Violet
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Project GitHub: https://github.com/shepherdviolet/glacimon
 * Email: [email protected]
 */

package com.github.shepherdviolet.glacimon.java.protocol.url;

import com.github.shepherdviolet.glacimon.java.protocol.url.installer.URLStreamHandlerFactoryWrapper;
import com.github.shepherdviolet.glacimon.java.protocol.url.installer.URLStreamHandlerFactoryInstaller;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;

/**
 * 

URL协议: 访问jar包中的资源(jar包中的jar包等)

* *

resinjar:META-INF/libs/name.jar --> 访问classpath下的META-INF/libs/name.jar

* *

============================================================================================================

*

示例: Classloader加载jar包中的jar包

*

* *

Q: 为什么不直接从jar包加载类呢?

*

A: 如果jar包是独立的文件, 确实可以直接加载. 但如果想要加载jar包中的jar包, 就只能用这个办法了, 因为ClassLoader不支持加载jar包中的jar包. * (直接用getClassLoader().getResource(path)获取的URL, 交给ClassLoader加载会报错)

*

* *

安装URL协议

* *
 *      static {
 *          // 安装URL协议: resinjar
 *          ResInJarURLStreamHandlerFactory.install();
 *      }
 * 
* *

使用URL协议

* *
 *      List jarUrls = new ArrayList<>();
 *
 *      // 加载classpath下的Jar包: META-INF/libs/name.jar
 *      jarUrls.add(new URL("resinjar:META-INF/libs/name.jar"));
 *
 *      URL[] jarUrlArray = new URL[jarUrls.size()];
 *      jarUrls.toArray(jarUrlArray);
 *
 *      // 创建普通ClassLoader
 *      ClassLoader classLoader = new URLClassLoader(jarUrlArray, getClass().getClassLoader());
 *
 *      // 创建特殊的ClassLoader (过滤部分类加载不走双亲委派模型)
 *      ClassLoader classLoader = new FilteringDelegateClassLoader(jarUrlArray, getClass().getClassLoader()) {
 *          protected boolean isClassDelegatedByParent(String name) {
 *              return false;
 *          }
 *      };
 * 
* * @author shepherdviolet */ public class ResInJarURLStreamHandlerFactory implements URLStreamHandlerFactory { // 协议名称 public static final String PROTOCOL = "resinjar"; /** * 安装URL协议: resinjar */ public static void install() { if (!URLStreamHandlerFactoryInstaller.isProtocolInstalled(PROTOCOL)) { URLStreamHandlerFactoryInstaller.setURLStreamHandlerFactory(new URLStreamHandlerFactoryWrapper(new ResInJarURLStreamHandlerFactory())); } } private ResInJarURLStreamHandlerFactory() { } @Override public URLStreamHandler createURLStreamHandler(String protocol) { if (PROTOCOL.equals(protocol)) { return new ResInJarURLStreamHandler(); } return null; } public static class ResInJarURLStreamHandler extends URLStreamHandler { @Override protected URLConnection openConnection(URL url) throws IOException { return new ResInJarURLConnection(url); } private static class ResInJarURLConnection extends URLConnection { // 目标URL private URL targetUrl; public ResInJarURLConnection(URL url) { super(url); } /** * 连接的时候从classpath下找资源, 不存在就报错 */ public void connect() throws IOException { if (!this.connected) { try { targetUrl = getClassLoader().getResource(getURL().getPath()); } catch (Throwable t){ throw new ResourceNotFoundException("ResInJarURLStreamHandlerFactory | Resource '" + getURL() + "' not found in classpath, classloader: " + getClassLoader(), t); } if (targetUrl == null) { throw new ResourceNotFoundException("ResInJarURLStreamHandlerFactory | Resource '" + getURL() + "' not found in classpath, classloader: " + getClassLoader()); } this.connected = true; } } /** * 目标资源的InputStream转交给resinjar协议 */ @Override public InputStream getInputStream() throws IOException { this.connect(); return targetUrl.openStream(); } /** * 不支持输出 */ @Override public OutputStream getOutputStream() throws IOException { throw new UnknownServiceException("ResInJarURLStreamHandlerFactory | protocol doesn't support output"); } /** * 重要!!! * * 在TOMCAT等WEB容器中, 一个JVM内含多个WEB应用, 这些WEB应用会共享URL.class, 所以本协议实际上是给所有WEB应用安装了. * 因此, 在获取资源的时候, 要用contextClassLoader, 这样才能正确加载到WEB应用自己的类和资源. */ private ClassLoader getClassLoader() { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = ClassLoader.getSystemClassLoader(); } return classLoader; } } } /** * 在classpath下找不到指定的资源 */ public static class ResourceNotFoundException extends IOException { private static final long serialVersionUID = 7084349948577031022L; public ResourceNotFoundException(String message) { super(message); } public ResourceNotFoundException(String message, Throwable cause) { super(message, cause); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy