Ai
2 Star 3 Fork 1

汪少棠/java-se

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
ClassLoaderController.java 16.63 KB
一键复制 编辑 原始数据 按行查看 历史
package org.example.controller;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import org.example.uitls.ResultData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.Assert;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 类加载器读取:读取类路径下任意位置中的任意资源.
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
*
* @author wangMaoXiong
* @version 1.0
* @date 2021/4/2 19:29
*/
@RestController
public class ClassLoaderController {
private static final Logger log = LoggerFactory.getLogger(ClassLoaderController.class);
/**
* http://localhost:8080/classLoader/URL2File
* 1、ClassLoader.getResource 方法内部使用 utf-8 对路径信息进行了编码,当路径中存在中文或空格等字符时,就会对它们进行转换,
* 这样获取路径信息时就会出现 utf-8 编码后的字符,如 '85%ac%e5%bc%80%e9%85%8d%e7%bd',看起以来就像乱码一样。
* 2、解决乱码的办法是使用 URLDecoder.decoder 方法对地址进行解码,以得到原始路径。
*
* @throws UnsupportedEncodingException
*/
@GetMapping("classLoader/URL2File")
public ResultData URL2File() throws Exception {
List<String> list = new ArrayList<>(8);
// String classPath = "static/测试单位-001001_多表头.xlsx";
String classPath = "static/index.html";
URL url = ClassLoaderController.class.getClassLoader().getResource(classPath);
String path = url.getPath();
// "/D:/project/IDEA_project/java-se/target/classes/static/%e6%b5%8b%e8%af%95%e5%8d%95%e4%bd%8d-001001_%e5%a4%9a%e8%a1%a8%e5%a4%b4.xlsx,false",
list.add(path + "," + new File(path).exists());
// "file:/D:/project/IDEA_project/java-se/target/classes/static/%e6%b5%8b%e8%af%95%e5%8d%95%e4%bd%8d-001001_%e5%a4%9a%e8%a1%a8%e5%a4%b4.xlsx,false",
list.add(url.toString() + "," + new File(url.toString()).exists());
// "/D:/project/IDEA_project/java-se/target/classes/static/%e6%b5%8b%e8%af%95%e5%8d%95%e4%bd%8d-001001_%e5%a4%9a%e8%a1%a8%e5%a4%b4.xlsx,false",
list.add(url.getFile() + "," + new File(url.getFile()).exists());
// "/D:/project/IDEA_project/java-se/target/classes/static/测试单位-001001_多表头.xlsx",
list.add(URLDecoder.decode(path, "utf-8"));
// "D:\\project\\IDEA_project\\java-se\\target\\classes\\static\\测试单位-001001_多表头.xlsx,true"
list.add(new File(URLDecoder.decode(path, "utf-8")).getAbsolutePath() + "," + new File(URLDecoder.decode(path, "utf-8")).exists());
return ResultData.success(list);
}
/**
* http://localhost:8080/classLoader/read1
* <p>
* URL getResource(String name) : 查找类路径下指定名称的资源
* 1、name :只要是编译后位于 classed 目录下的任意文件都行,多级时用左斜杠即可,如 config/root/data.xml
* 2、通常用于读取 resources 资源目录下的资源,然而其实 src/java 源码目录的文件同样可以,只要编译后能到 classes 目录下
* 3、注意只能是类路径下的,不能是其它位置,也不能是绝对路径,不存在时 getResource 返回 null。
*/
@GetMapping("classLoader/read1")
public ResultData classLoader1() {
Map<String, Object> dataMap = new HashMap<>(8);
// String classPath = "config/config2.properties";
String classPath = "config/配置说明.setting";
URL url = ClassLoaderController.class.getClassLoader().getResource(classPath);
Assert.notNull(url, "资源文件不存在!");
String path1 = url.getPath();
dataMap.put("path", path1);
List<String> list = FileUtil.readUtf8Lines(url);
dataMap.put("content", list);
return ResultData.success(dataMap);
}
/**
* http://localhost:8080/classLoader/read2
* <p>
* InputStream getResourceAsStream(String name) :读取类路径下知道名称的资源,并返回字节输入流
* 其实底层就是在 getResource 的基础上,加了一个 url.openStream(),所以资源不存在时,返回 null。
* 注意只能是类路径下的,不能是其它位置,也不能是绝对路径。
* <p>
* 使用流的好处是可以读取任何文件的内容,比如图片、音视频等等。
* 如果是文本文件则推荐使用其它更加简易快捷的方式。cn.hutool.core.io.resource.ResourceUtil
* <p>
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
*/
@GetMapping("classLoader/read2")
public ResultData classLoader2() throws IOException {
List<String> dataList = new ArrayList<>();
// String classPath = "config/config2.properties";
String classPath = "config/配置说明.setting";
try (InputStream inputStream = ClassLoaderController.class.getClassLoader().getResourceAsStream(classPath)) {
dataList = IoUtil.readUtf8Lines(inputStream, dataList);
return ResultData.success(dataList);
}
}
/**
* http://localhost:8080/resource/read1
* <p>
* org.springframework.core.io.ClassPathResource(String path):类路径资源文件,读取类路径下下的任意资源文件,如果路径有前缀 / 也会自动被去掉,
* <pre>
* org.springframework.core.io.Resource 有以下常用的方法:
* boolean exists = resource.exists();
* InputStream inputStream1 = resource.getInputStream();
* File file = resource.getFile();
* String filename = resource.getFilename();
* URI uri = resource.getURI();
* URL url = resource.getURL();
* long l = resource.contentLength();
* boolean file1 = resource.isFile();
* long l1 = resource.lastModified();
* </pre>
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
*
* @return
*/
@GetMapping("resource/read1")
public ResultData resource1() throws IOException {
Resource resource = new ClassPathResource("application.yml");
try (InputStream inputStream = resource.getInputStream()) {
String readUtf8 = IoUtil.readUtf8(inputStream);
return ResultData.success(readUtf8);
}
}
/**
* http://localhost:8080/resourceUtils/read1
* <p>
* org.springframework.util.ResourceUtils:用于将资源位置解析为文件系统中的文件的实用程序方法。主要用于框架内部使用。
* 不推荐使用!!!
* 不推荐使用!!!
* 不推荐使用!!!
* JAR 包内部的文件无法获取,必须是一个独立的文件,即项目打包后,无法再获取包中的文件。
* <p>
* File getFile(String resourceLocation):将给定的资源位置解析为文件系统中的文件。不检查文件是否实际存在;只需返回给定位置对应的文件。
* * resourceLocation:要解析的资源位置:"classpath:" 伪URL,类路径资源;"file:" URL或纯文件路径
* File getFile(URI resourceUri):将给定的资源URI解析为文件系统中的文件。
* File getFile(URL resourceUrl):将给定的资源URL解析为文件系统中的文件。
* URL extractJarFileURL(URL jarUrl):从给定的URL中提取实际jar文件的URL(可能指向jar文件中的资源或jar文件本身)。
*
* @return
*/
@GetMapping("resourceUtils/read1")
public ResultData resourceUtils1() throws FileNotFoundException {
File file = ResourceUtils.getFile("classpath:application.yml");
List<String> list = FileUtil.readUtf8Lines(file);
return ResultData.success(list);
}
/**
* Spring 框架提供了 Resource 接口和 ResourceLoader 接口来方便地访问资源文件
* http://localhost:8080/resourceLoader/read1
* <p>
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
*/
@javax.annotation.Resource
private ResourceLoader resourceLoader;
@GetMapping("resourceLoader/read1")
public ResultData resourceLoader() throws Exception {
String classPath = "classpath:config/配置说明.setting";
Resource resource = resourceLoader.getResource(classPath);
try (InputStream inputStream = resource.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
List<String> readLines = new ArrayList<>();
readLines = IoUtil.readLines(bufferedReader, readLines);
return ResultData.success(readLines);
}
}
/**
* 可以直接使用 getClass().getResourceAsStream() 方法,它 会返回一个 InputStream 对象。
* 如果此对象是由引导类加载器加载的,则该方法将委托给{@link ClassLoader#getSystemResourceAsStream}。
* http://localhost:8080/class/getResourceAsStream
* <p>
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
*
* @return
* @throws Exception
*/
@GetMapping("class/getResourceAsStream")
public ResultData getResourceAsStream() throws Exception {
List<String> readLines = new ArrayList<>();
// 类路径下的文件时必须以"/"开头.
String classPath = "/config/配置说明.setting";
InputStream inputStream = getClass().getResourceAsStream(classPath);
if (inputStream != null) {
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
readLines = IoUtil.readLines(bufferedReader, readLines);
}
} else {
return ResultData.error("读取类路径下文件失败:" + classPath);
}
return ResultData.success(readLines);
}
/**
* Spring 框架的 StreamUtils 类提供了一个便捷的方法来直接读取资源内容到字符串
* http://localhost:8080/streamUtils/copyToString
* <p>
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
*
* @return
* @throws Exception
*/
@GetMapping("streamUtils/copyToString")
public ResultData streamUtils() throws Exception {
String classPath = "config/配置说明.setting";
Resource resource = new ClassPathResource(classPath);
String copyToString = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
return ResultData.success(copyToString);
}
/**
* Spring 的 ApplicationContext 提供了一种访问资源的方式,它允许你按名称查找资源。
* http://localhost:8080/applicationContext/getResource
* <p>
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
* <p>
* 直接从容器中获取 ApplicationContext 实例即可,默认已经有了。
*/
@javax.annotation.Resource
private ApplicationContext applicationContext;
@GetMapping("applicationContext/getResource")
public ResultData applicationContext() throws Exception {
List<String> readLines = new ArrayList<>();
String classPath = "classpath:config/配置说明.setting";
Resource resource = applicationContext.getResource(classPath);
try (InputStream inputStream = resource.getInputStream()) {
readLines = IoUtil.readLines(inputStream, Charset.forName("UTF-8"), readLines);
}
return ResultData.success(readLines);
}
/**
* http://localhost:8080/classLoader/listFiles2
* PathMatchingResourcePatternResolver-资源模式解析器 批量读取类路径文件资源
* 使用场景1:读取服务包中指定目录下的所有文件信息,比如想读取整个服务中的所有 .html 文件信息。
* <p>
* 即便是打包成 .jar、.war 包部署到生产环境,照样读取正常。
*
* @return
* @throws Exception
*/
@GetMapping("classLoader/listFiles2")
public ResultData listFiles2() throws Exception {
List<Map<String, Object>> fileInfos = new ArrayList<>();
// 创建 资源模式解析器 对象,ClassLoader 访问将通过线程上下文类加载器进行
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// 将给定的位置模式解析为 Resource 资源对象(包括目录与文件)。
// /*:表示直接子级(不包括孙级)、/**:表示递归下面的所有子孙级资源
// 示例1:static/**:表示类路径下static目录下面的全部文件,包括子孙文件
// 示例2:static/**/*.html:表示类路径下static目录下面所有的html文件,包括子孙文件
// 示例3:**/cors/**/*.html:表示类路径下,路径包含cors的html文件
// 示例4:**/*.html:表示类路径下全部的html文件
// 示例5:*.*:表示类路径根目录下的全部文件,不包括子目录下的文件
// 示例6:**/*.*:表示类路径下的全部文件,包括子孙文件
Resource[] resources = resolver.getResources("static/**");
for (Resource resource : resources) {
Map<String, Object> fileInfo = new HashMap<>(16);
// 确定此资源的文件名,即通常是路径的最后一部分:例如“myfile.txt";如果此类资源没有文件名,则返回 null;
fileInfo.put("fileName", resource.getFilename());
// 返回此资源的描述;
fileInfo.put("description", resource.getDescription());
// 获取资源的绝对路径,并防止中文乱码
fileInfo.put("absolutePath", URLDecoder.decode(resource.getURL().getPath(), "utf-8"));
if (StrUtil.endWithIgnoreCase(resource.getFilename(), "html")) {
// 如果是 html 文件,则读取它的 title 值
String readUtf8 = IoUtil.readUtf8(resource.getInputStream());
String title = readUtf8.substring(readUtf8.indexOf("<title>") + 7, readUtf8.indexOf("</title>"));
// title=CSRF 跨站请求
// title=蚩尤后裔
System.out.println("title=" + title);
}
fileInfos.add(fileInfo);
}
// 下面是 IDEA 直接访问的效果
// {
// "fileName": "cors",
// "description": "file [D:\\project\\IDEA_project\\java-se\\target\\classes\\static\\cors]",
// "absolutePath": "/D:/project/IDEA_project/java-se/target/classes/static/cors/"
// },
// {
// "fileName": "cors_filter.html",
// "description": "file [D:\\project\\IDEA_project\\java-se\\target\\classes\\static\\cors\\cors_filter.html]",
// "absolutePath": "/D:/project/IDEA_project/java-se/target/classes/static/cors/cors_filter.html"
// }
// 下面是打成 jar 后访问的效果
// {
// "fileName": "",
// "description": "class path resource [static/]",
// "absolutePath": "file:/D:/project/IDEA_project/java-se/target/java-se-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/static/"
// },
// {
// "fileName": "",
// "description": "class path resource [static/cors/]",
// "absolutePath": "file:/D:/project/IDEA_project/java-se/target/java-se-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/static/cors/"
// },
// {
// "fileName": "cors_filter.html",
// "description": "class path resource [static/cors/cors_filter.html]",
// "absolutePath": "file:/D:/project/IDEA_project/java-se/target/java-se-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/static/cors/cors_filter.html"
//
return ResultData.success(fileInfos);
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Java
1
https://gitee.com/wangmx1993/java-se.git
git@gitee.com:wangmx1993/java-se.git
wangmx1993
java-se
java-se
master

搜索帮助