PathKit工具类
package com.itmc.education.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
/**
* @Author: yhf
* @Date: 2026/4/10 11:20
*/
public final class PathKit {
private PathKit() {
// 工具类,私有构造禁止实例化
}
private static final Logger log = LoggerFactory.getLogger(PathKit.class);
// 系统分隔符(Windows \,Linux /,自动适配)
private static final String SEPARATOR = File.separator;
//==================================================================================================================
/**
* @description: 获取【classpath根目录,即classes文件夹】
*
* 开发时(IDEA):src/main/java + src/main/resources
* 编译后(IDEA):项目路径/target/classes/
* 部署后(Tomcat):Tomcat路径/webapps/项目名/WEB-INF/classes/
* 开发时源码java+resources = 编译后的target/classes = 部署后的WEB-INF/classes
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:24
* @author: yhf
**/
public static String getClassPath() {
String path = "";
try {
// 获取类加载器根路径URL
URL resource = ClassUtils.getDefaultClassLoader().getResource("");
if (resource == null) {
// throw new RuntimeException("未获取到类路径资源");
return getProjectPath() + SEPARATOR + "target" + SEPARATOR + "classes";
}
path = resource.getPath();
path = decodePath(path);
// 处理Windows路径(去掉开头/,/D:/xxx → D:/xxx)
if (isWindows() && path.startsWith("/")) {
path = path.substring(1);
}
} catch (Exception e) {
// throw new RuntimeException("获取类路径失败", e);
log.error("获取类路径失败:" + e.getMessage());
path = "";
} finally {
return path;
}
}
/**
* @description: 获取【classpath:/static 静态资源目录】
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 13:57
* @author: yhf
**/
public static String getStaticPath() {
return getClassPath() + "static" + SEPARATOR;
}
/**
* @description: 获取【classpath:/templates 模板目录】
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 13:57
* @author: yhf
**/
public static String getTemplatesPath() {
return getClassPath() + "templates" + SEPARATOR;
}
/**
* @description: 获取【Web应用根目录(webapp),即web访问路径】
*
* 当前Web项目在服务器上的真实物理磁盘路径(绝对路径),也就是项目部署到Tomcat后,对应文件夹在硬盘上的实际位置
* IDEA开发目录的src/main/webapp,编译后=web根目录,即Tomcat路径/webapp/项目名/,编译后WEB-INF也会完整转移到这里面
* Service直接调用getWebRootPath()会报错NPE,因为方法依赖HttpServletRequest,只能在Controller里调用
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:25
* @author: yhf
**/
public static String getWebRootPath() {
HttpServletRequest request = getRequest();
if (request == null) {
throw new RuntimeException("非 Web 环境,无法获取 Web 根路径");
}
String path = request.getServletContext().getRealPath("");
return decodePath(path);
}
/**
* @description: 获取【WEB-INF目录】
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:25
* @author: yhf
**/
public static String getWebInfPath() {
return getWebRootPath() + "WEB-INF" + SEPARATOR;
}
/**
* @description: 获取【系统临时文件目录】
* 操作系统专门用来存临时文件的目录,重启电脑可能会清空
* Windows --> C:\Users\你的用户名\AppData\Local\Temp
* Linux --> /tmp
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 14:01
* @author: yhf
**/
public static String getTempPath() {
return System.getProperty("java.io.tmpdir");
}
/**
* @description: 获取【用户目录】
* 当前电脑用户目录,即登录操作系统的用户文件夹
* Windows --> C:\Users\你的用户名
* Linux --> /home/你的用户名
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 14:02
* @author: yhf
**/
public static String getUserHomePath() {
return System.getProperty("user.home");
}
/**
* @description: 获取【项目根目录】
* 当前项目所在的文件夹路径,就是打开IDEA时最外层的项目文件夹,即src的父级目录
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:25
* @author: yhf
**/
public static String getProjectPath() {
return System.getProperty("user.dir");
}
//==================================================================================================================
/**
* 判断字符串中是否包含中文
*/
private static boolean containsChinese(String str) {
if (str == null || str.isEmpty()) {
return false;
}
// 正则:匹配中文字符范围
return str.matches(".*[\\u4e00-\\u9fa5].*");
}
/**
* 判断路径是否被 URL 编码(含 %xx)
*/
private static boolean hasUrlEncoded(String path) {
if (path == null || path.isEmpty()) {
return false;
}
//有 %20、%E4、%B8 这类 → 返回 true → 必须解码
return path != null && path.matches(".*%[0-9A-Fa-f]{2}.*");
}
/**
* 自动解码中文路径,解码解决"中文乱码"问题
*/
private static String decodePath(String path) {
if (hasUrlEncoded(path)) {
try {
path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
} catch (Exception ignored) {}
}
return path;
}
/**
* 判断当前是否为windows环境
*/
private static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("win");
}
/**
* 获取HttpServletRequest
*/
private static HttpServletRequest getRequest() {
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attributes == null ? null : attributes.getRequest();
} catch (Exception e) {
return null;
}
}
/*
1.在 resources 下放了一个文件:
src/main/resources/application.yml
2.运行时,它的真实路径是:
classpath:/application.yml
3.用工具类获取:
String path = getClassPath() + "application.yml";
src/main/java + resources
编译后 → classes(classpath) 获取用:getClassPath()
src/main/webapp
编译后 → Tomcat/webapps/项目名/ 获取用:getWebRootPath()
src/main/webapp/WEB-INF
编译后 → Tomcat/webapps/项目名/WEB-INF 获取用:getWebInfPath()
在【传统war部署 + Tomcat】环境下,三者完全等价!
getWebRootPath() + "WEB-INF" + File.separator + "classes"
等价于getWebInfPath() + "classes"
等价于getClassPath()
Web根目录 (getWebRootPath())
└── WEB-INF/ (getWebInfPath())
└── classes/ (getClassPath())
在【SpringBoot jar包运行】环境下:前两个会报错/失效,只有getClassPath()永远有效!
*/
}
升级版
package com.itmc.education.common.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.servlet.ServletContext;
import java.io.File;
/**
* @Author: yhf
* @Date: 2026/7/22 9:43
*/
@Component
@Order(1) // 数字越小,越先初始化
public class WebRootPathHolder {
public static String WEB_ROOT_PATH;
// Spring自动注入ServletContext,不用request
@Autowired
private ServletContext servletContext;
// Bean初始化完成后赋值,只执行一次
@PostConstruct
public void init() {
// 拿到 /webapps/项目名 物理路径
WEB_ROOT_PATH = servletContext.getRealPath("");
}
public static File getChildDir(String child) {
File childDir = new File(WEB_ROOT_PATH, child);
if (!childDir.exists()) {
childDir.mkdirs();
}
return childDir;
}
}
package com.itmc.education.common.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
/**
* @Author: yhf
* @Date: 2026/4/10 11:20
*/
public final class PathKit {
private PathKit() {
// 工具类,私有构造禁止实例化
}
private static final Logger log = LoggerFactory.getLogger(PathKit.class);
// 系统分隔符(Windows \,Linux /,自动适配)
private static final String SEPARATOR = File.separator;
//==================================================================================================================
/**
* @description: 获取【classpath根目录,即classes文件夹】
*
* 开发时(IDEA):src/main/java + src/main/resources
* 编译后(IDEA):项目路径/target/classes/
* 部署后(Tomcat):Tomcat路径/webapps/项目名/WEB-INF/classes/
* 开发时源码java+resources = 编译后的target/classes = 部署后的WEB-INF/classes
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:24
* @author: yhf
**/
public static String getClassPath() {
String path = "";
try {
// 获取类加载器根路径URL
URL resource = ClassUtils.getDefaultClassLoader().getResource("");
if (resource == null) {
// throw new RuntimeException("未获取到类路径资源");
return getProjectPath() + SEPARATOR + "target" + SEPARATOR + "classes";
}
path = resource.getPath();
path = decodePath(path);
// 处理Windows路径(去掉开头/,/D:/xxx → D:/xxx)
if (isWindows() && path.startsWith("/")) {
path = path.substring(1);
}
} catch (Exception e) {
// throw new RuntimeException("获取类路径失败", e);
log.error("获取类路径失败:" + e.getMessage());
path = "";
} finally {
return path;
}
}
/**
* @description: 获取【classpath:/static 静态资源目录】
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 13:57
* @author: yhf
**/
public static String getStaticPath() {
return getClassPath() + "static" + SEPARATOR;
}
/**
* @description: 获取【classpath:/templates 模板目录】
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 13:57
* @author: yhf
**/
public static String getTemplatesPath() {
return getClassPath() + "templates" + SEPARATOR;
}
/**
* @description: 获取【Web应用根目录(webapp),即web访问路径】
*
* 当前Web项目在服务器上的真实物理磁盘路径(绝对路径),也就是项目部署到Tomcat后,对应文件夹在硬盘上的实际位置
* IDEA开发目录的src/main/webapp,编译后=web根目录,即Tomcat路径/webapp/项目名/,编译后WEB-INF也会完整转移到这里面
* Service直接调用getWebRootPath()会报错NPE,因为方法依赖HttpServletRequest,只能在Controller里调用
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:25
* @author: yhf
**/
public static String getWebRootPath(HttpServletRequest request) {
if (request == null) {
log.info("非 Web 环境,无法获取 Web 根路径,尝试获取 WEB_ROOT_PATH");
String root = WebRootPathHolder.WEB_ROOT_PATH;
if (root == null) {
throw new RuntimeException("非Web环境,且WEB_ROOT_PATH未初始化");
}
return decodePath(root);
}
String path = request.getServletContext().getRealPath("");
return decodePath(path);
}
public static String getWebRootPath() {
return getWebRootPath(null);
}
/**
* @description: 获取【WEB-INF目录】
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:25
* @author: yhf
**/
public static String getWebInfPath(HttpServletRequest request) {
return getWebRootPath(request) + "WEB-INF" + SEPARATOR;
}
public static String getWebInfPath() {
return getWebRootPath() + "WEB-INF" + SEPARATOR;
}
/**
* @description: 获取【系统临时文件目录】
* 操作系统专门用来存临时文件的目录,重启电脑可能会清空
* Windows --> C:\Users\你的用户名\AppData\Local\Temp
* Linux --> /tmp
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 14:01
* @author: yhf
**/
public static String getTempPath() {
return System.getProperty("java.io.tmpdir");
}
/**
* @description: 获取【用户目录】
* 当前电脑用户目录,即登录操作系统的用户文件夹
* Windows --> C:\Users\你的用户名
* Linux --> /home/你的用户名
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 14:02
* @author: yhf
**/
public static String getUserHomePath() {
return System.getProperty("user.home");
}
/**
* @description: 获取【项目根目录】
* 当前项目所在的文件夹路径,就是打开IDEA时最外层的项目文件夹,即src的父级目录
* @param: []
* @return: java.lang.String
* @date: 2026/4/10 11:25
* @author: yhf
**/
public static String getProjectPath() {
return System.getProperty("user.dir");
}
//==================================================================================================================
/**
* 判断字符串中是否包含中文
*/
private static boolean containsChinese(String str) {
if (str == null || str.isEmpty()) {
return false;
}
// 正则:匹配中文字符范围
return str.matches(".*[\\u4e00-\\u9fa5].*");
}
/**
* 判断路径是否被 URL 编码(含 %xx)
*/
private static boolean hasUrlEncoded(String path) {
if (path == null || path.isEmpty()) {
return false;
}
//有 %20、%E4、%B8 这类 → 返回 true → 必须解码
return path != null && path.matches(".*%[0-9A-Fa-f]{2}.*");
}
/**
* 自动解码中文路径,解码解决"中文乱码"问题
*/
private static String decodePath(String path) {
if (hasUrlEncoded(path)) {
try {
path = URLDecoder.decode(path, StandardCharsets.UTF_8.name());
} catch (Exception ignored) {}
}
return path;
}
/**
* 判断当前是否为windows环境
*/
private static boolean isWindows() {
return System.getProperty("os.name").toLowerCase().contains("win");
}
/**
* 获取HttpServletRequest
*/
public static HttpServletRequest getRequest() {
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attributes == null ? null : attributes.getRequest();
} catch (Exception e) {
return null;
}
}
/*
1.在 resources 下放了一个文件:
src/main/resources/application.yml
2.运行时,它的真实路径是:
classpath:/application.yml
3.用工具类获取:
String path = getClassPath() + "application.yml";
src/main/java + resources
编译后 → classes(classpath) 获取用:getClassPath()
src/main/webapp
编译后 → Tomcat/webapps/项目名/ 获取用:getWebRootPath()
src/main/webapp/WEB-INF
编译后 → Tomcat/webapps/项目名/WEB-INF 获取用:getWebInfPath()
在【传统war部署 + Tomcat】环境下,三者完全等价!
getWebRootPath() + "WEB-INF" + File.separator + "classes"
等价于getWebInfPath() + "classes"
等价于getClassPath()
Web根目录 (getWebRootPath())
└── WEB-INF/ (getWebInfPath())
└── classes/ (getClassPath())
在【SpringBoot jar包运行】环境下:前两个会报错/失效,只有getClassPath()永远有效!
*/
}

浙公网安备 33010602011771号