通过web访问项目中(resources文件夹下)的静态资源!
问题1-禁用默认规则
问题描述
配置了全局异常处理,禁用了默认的静态资源规则,将无法通过web访问项目中的静态资源。
#当没有对应处理器时,允许抛出异常(让自定义的异常处理类捕获404)
spring.mvc.throw-exception-if-no-handler-found=true
#禁用默认静态资源规则(不为工程中的资源文件建立映射)
spring.web.resources.add-mappings=false
#上述配置:所有访问不到的路径,均会抛出404异常,捕获之后返回自定义的DataVo实例-json对象。
#将不能访问static下的静态资源(若部署前端项目将不能访问),得前后端分开部署。
解决方法
要(通过web)访问项目中的静态资源(部署网站、图片等资源),**解决方法:**在自定义配置类中添加相关的ResourceHandler。
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author: 轻率的保罗
* @since: 2023-01-16
* @Description: 静态资源规则配置。配置 全局异常处理-404异常捕获 之后(所有访问不到的路径,均会抛出404异常,捕获之后返回自定义的DataVo实例-json对象),导致静态资源无法正常访问,添加如下配置。
* 注意:若访问路径(静态资源),从以下addResourceHandler配置的目录中找不到,则会返回“Whitelabel Error Page”页面,而不是经过全局异常处理捕获后返回的404错误信息(DataVo对象)
*/
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//静态资源:
// 前端网站,访问 路径/web/** ,会在 项目resources/static/web/ 目录下查找
// 文件,访问 路径/public/file/** ,会在 项目resources/static/public/file/ 目录下查找
// 放图片,访问 路径/public/** 下的静态资源,会在 项目resources/static/public/image/ 目录下查找
registry.addResourceHandler("/web/**").addResourceLocations("classpath:/static/web/");
registry.addResourceHandler("/public/file/**").addResourceLocations("classpath:/static/public/file/");
registry.addResourceHandler("/public/image/**").addResourceLocations("classpath:/static/public/image/");
//swaggerUI:
// swagger第三方UI - Knife4j,访问地址为:http://localhost:8181/malldemo/doc.html
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");//以jar包方式访问js、css、html等静态资源(Knife4j的相关依赖已打包成jar包)
}
}
需要注意的是文件放在resource文件夹下,会与项目一起打包成jar包。不想打包成jar包,见下边问题2。
问题2-jar包
问题描述
文件放在resources文件夹下,会与项目一起打包成jar包。若部署了前端项目,要更新只能重新打包jar包,略显麻烦。若有文件上传功能,也不方便对上传的文件进行管理。
解决方法
解决方案:项目初始化时用到的静态资源放在resources文件夹下;后期提交/更新的静态资源(文件上传等),通过 自定义路径+配置静态资源规则 实现web访问功能。
配置文件
在springboot配置文件中添加几个自定义配置项。
-
1、文件默认的保存位置为项目部署地址下的data文件夹(项目名_data),若要自定义文件保存位置,在springboot配置文件中添加自定义配置
path.custom.enable、path.filepath.xxx
设置文件保存位置。 -
2、是否启用自定义静态资源映射,使用自定义配置
web.resources.add-mappings.enable
设置是否启用,使用自定义配置web.resources.path-pattern
设置web访问匹配路径。
# 文件上传位置:
# 文件默认保存在项目部署地址下的data文件夹中(项目名_data),详情见AppConfig类init()方法。自定义文件保存位置,则同时添加下边三个配置:
#path.custom.enable=true
#path.filepath.linux=/usr/local/java/@artifactId@/
#path.filepath.windows=C:\\javafile\\@artifactId@\\
# 是否启用静态资源映射(上边文件保存地址,是否可以通过 http://xxx/xxx/xxx 访问到。默认不启用,详情见AppConfig类init()方法)
# add-mappings.enable,用于设置是否启用。path-pattern,用于设置web访问匹配路径(默认为/web/**)。映射的服务器路径为文件保存地址。
web.resources.add-mappings.enable=true
#web.resources.path-pattern=/web/**
获取项目部署地址
文件默认保存在项目部署地址下的data文件夹中(项目名_data),就需要先获取项目部署地址。
直接通过java -jar xxx.jar
命令运行springboot项目,获取jar包的位置(即项目部署地址)。
/**
* 获取运行Jar包的目录,即项目部署地址。并检查是否有读写权限。
* MacOs 13.1、Linux-Centos7、Win10环境中可获取到。
* @return 路径
*/
private String getJarFilePathAndCheck() throws Exception {
//方案一:可能Linux-Ubuntu中jarFile为null,无法获取到项目部署地址。无测试环境,未测试。
ApplicationHome home = new ApplicationHome(getClass());
File jarFile = home.getSource();
String path = null;
if(jarFile != null){
path = jarFile.getParentFile().toString();
}else{
//方案二:获取classpath,从中截取(未在win系统中测试该方案。方案一大部分情况可正常获取)
String classpath = ResourceUtils.getURL("classpath:").getPath();
if(classpath.contains("file:")){
//win系统,file:/F:/xxx,所以len为6
int len = SysUtil.isWin()?6:5;
classpath = classpath.substring(len);
log.info("处理1 = "+classpath);
}
if(classpath.contains(".jar!")){
classpath = classpath.substring(0,classpath.indexOf(".jar!"));
}
// 再把最后一个分隔符后边的去掉
classpath = classpath.substring(0,classpath.lastIndexOf(File.separator)+1);
path = classpath;
}
if(path == null || path == ""){
String errMsg = "无法获取项目部署地址!!!";
log.error(errMsg);
throw new Exception(errMsg);
}
//目录最后须带有分隔符
path = File.separator.equals(path.substring(path.length()-1))?path:path+File.separator;
//检查读写权限
SysUtil.checkAndCreatePath(path);
return path;
}
SysUtil.checkAndCreatePath()如下:(类SysUtil,见附件3)
/**
* 检查路径是否存在,不存在则创建,同时检查路径是否是目录、检查是否有读写权限。
* @param path 绝对地址
*/
public static void checkAndCreatePath(String path) throws Exception {
File file = new File(path);
if(file.exists()){
//存在,则:1、检查是否是目录。2、检查是否有读写权限。
if(!file.isDirectory()){
String errMsg = "警告!路径【"+path+"】不是目录!";
log.error(errMsg);
throw new IllegalArgumentException(errMsg);
}
if(!file.canRead() || !file.canWrite()){
String errMsg = "警告!路径【"+path+"】无读写权限!";
log.error(errMsg);
throw new AccessDeniedException(errMsg);
}
}else{
//不存在,则创建目录。
if(!file.mkdirs()){
if(!file.canRead() || !file.canWrite()){
String errMsg = "警告!路径【"+path+"】无读写权限!";
log.error(errMsg);
throw new AccessDeniedException(errMsg);
}else {
String errMsg = "路径【"+path+"】不存在,尝试创建目录,目录创建失败!";
log.error(errMsg);
throw new IOException(errMsg);
}
}
}
}
初始化文件保存地址
定义一个类AppConfig,用于保存和初始化一些配置项,例如:
- 文件保存地址
filepath
(根地址)- 其他文件保存地址(filepath下的子目录)
- 检查目录是否已存在,存在则检查是否有读写权限,不存在则创建。
- 静态资源映射匹配路径
PATH_PATTERN
- 如果配置文件中有配置则更新,否则使用默认配置“/web/**”
在类AppConfig中添加一个init()方法用于初始化这些配置。为了让init()方法在项目启动的时候执行,需要添加注解@PostConstruct。init()方法如下:
/**
* 初始化变量jarFilePath、filepath
* 检查是否有权限访问(读写)filepath,不存在则创建。无访问权限或创建失败会抛出异常,阻止项目启动
*/
@PostConstruct
public void init() throws Exception {
log.info("---- 初始化AppConfig start ----");
//初始化变量jarFilePath
jarFilePath = getJarFilePathAndCheck();
//初始化变量filepath
Boolean isEnable = Boolean.valueOf(env.getProperty("path.custom.enable"));
//是否自定义文件保存位置。默认保存在项目部署地址下(data文件夹)
if(isEnable){
log.info("自定义文件保存位置!");
String filepathLinux = env.getProperty("path.filepath.linux");
String filepathWin = env.getProperty("path.filepath.windows");
if(filepathLinux == null || filepathWin == null){
String errMsg = "自定义文件保存位置,但是未提供【path.filepath.linux】、【path.filepath.windows】!";
log.error(errMsg);
throw new IllegalArgumentException(errMsg);
}
if (SysUtil.isUnix()) {
//Mac、Linux、Unix 系统
filepath = filepathLinux;
}else{
if(SysUtil.isWin()){
//Windows 系统
filepath = filepathWin;
}else{
String errMsg = "未知系统类型【"+SysUtil.getOsName()+"】,无法初始化文件保存位置!!!";
log.error(errMsg);
throw new Exception(errMsg);
}
}
}else{
log.info("文件默认保存在项目部署地址下(data文件夹)!");
//获取项目部署地址
filepath = jarFilePath + env.getProperty("spring.application.name")+"_data" + File.separator;
}
//目录最后须带有分隔符
filepath = File.separator.equals(filepath.substring(filepath.length()-1))?filepath:filepath+File.separator;
//创建相关路径(无权限会抛出异常,阻止程序启动)
String[] paths = {
filepath,filepath+WEB_FOLDER,filepath+FILE_FOLDER,filepath+IMG_FOLDER,filepath+IMG_FOLDER+File.separator+CONTENT_IMG_FOLDER,filepath+IMG_FOLDER+File.separator+TAG_IMG_FOLDER,filepath+IMG_FOLDER+File.separator+AVATAR_IMG_FOLDER,filepath+IMG_FOLDER+File.separator+COMMON_IMG_FOLDER};
for (String path : paths) {
SysUtil.checkAndCreatePath(path);
}
log.info("文件保存根路径为: "+paths[0]);
log.info(" -前端项目部署路径为: "+paths[1]);
log.info(" -文件保存路径为: "+paths[2]);
log.info(" -图片文件保存路径为: "+paths[3]);
log.info(" +图片-动态配图 保存路径为: "+paths[4]);
log.info(" +图片-标签图片 保存路径为: "+paths[5]);
log.info(" +图片-头像图片 保存路径为: "+paths[6]);
log.info(" +图片-其他类型图片 保存路径为: "+paths[7]);
//是否启用静态资源映射
if(isEnabelWebMapping()){
String pathPattern = env.getProperty("web.resources.path-pattern");
if(pathPattern != null){
this.PATH_PATTERN = pathPattern;
}
log.info("是否启用静态资源映射: yes");
log.info(" 文件保存根路径为: "+filepath);
log.info(" web路径为: "+getWebUrl());
log.info(" 前端项目访问url为: "+getWebUrl()+WEB_FOLDER+"/index.html");
log.info(" 静态资源访问示例:️");
log.info(" 访问动态配图,服务器保存路径为【"+paths[4]+"/图片文件名】️");
log.info(" web路径为【"+getWebUrl()+IMG_FOLDER+"/"+CONTENT_IMG_FOLDER+"/图片文件名】");
// 示例: http://localhost:8181/malldemo/web/image/contentimg/assii.jpg
}else{
log.info("是否启用静态资源映射: no");
}
log.info("---- 初始化AppConfig end ----");
}
类AppConfig代码见最后的附件1
设置静态资源映射规则
同问题1-解决方法中类MyWebMvcConfigurer,在重写的addResourceHandlers方法中添加如下内容:
根据springboot配置文件中的配置,判断是否要配置 自定义静态资源映射规则。
//配置 静态资源映射(详情见AppConfig类中的init()方法),同时映射jar包内的resources文件夹下的static文件夹
if(appConfig.isEnabelWebMapping()){
registry.addResourceHandler(appConfig.getPATH_PATTERN()).addResourceLocations("file:" + appConfig.getFilePath(),"classpath:/static/");
}
//url路径 “/web/**” 映射到 服务器地址“filePath”(文件保存地址)和项目的resources/static/文件夹。变量PATH_PATTERN配置在类AppConfig中。
类MyWebMvcConfigurer代码见最后的附件2
测试1
不配置文件保存地址,即默认保存在项目部署地址下的data文件夹中(项目名_data)。
启用静态资源映射。
# 文件上传位置:
# 自定义文件保存位置,则同时添加下边三个配置:
#path.custom.enable=true
#path.filepath.linux=/usr/local/java/@artifactId@/
#path.filepath.windows=C:\\javafile\\@artifactId@\\
# 是否启用静态资源映射
web.resources.add-mappings.enable=true
运行结果:IDEA中启动项目
---- 初始化AppConfig start ----
文件默认保存在项目部署地址下(data文件夹)!
文件保存根路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/
-前端项目部署路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/project
-文件保存路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/file
-图片文件保存路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/image
+图片-动态配图 保存路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/image/contentimg
+图片-标签图片 保存路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/image/tagimg
+图片-头像图片 保存路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/image/avatarimg
+图片-其他类型图片 保存路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/image/common
是否启用静态资源映射: yes
文件保存根路径为: /Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/
web路径为: http://127.0.0.1:8181/malldemo/web/
前端项目访问url为: http://127.0.0.1:8181/malldemo/web/project/index.html
静态资源访问示例:️
访问动态配图,服务器保存路径为【/Users/qsdbl/Documents/workspace/java/mall-demo/target/mall-demo_data/image/contentimg/图片文件名】️
web路径为【http://127.0.0.1:8181/malldemo/web/image/contentimg/图片文件名】
---- 初始化AppConfig end ----
测试2
配置自定义文件保存地址。
启用静态资源映射。
# 文件上传位置:
# 自定义文件保存位置,则同时添加下边三个配置:
path.custom.enable=true
path.filepath.linux=/usr/local/java/@artifactId@/
path.filepath.windows=C:\\javafile\\@artifactId@\\
# 是否启用静态资源映射
web.resources.add-mappings.enable=true
运行结果:IDEA中启动项目
---- 初始化AppConfig start ----
自定义文件保存位置!
文件保存根路径为: /usr/local/java/mall-demo/
-前端项目部署路径为: /usr/local/java/mall-demo/project
-文件保存路径为: /usr/local/java/mall-demo/file
-图片文件保存路径为: /usr/local/java/mall-demo/image
+图片-动态配图 保存路径为: /usr/local/java/mall-demo/image/contentimg
+图片-标签图片 保存路径为: /usr/local/java/mall-demo/image/tagimg
+图片-头像图片 保存路径为: /usr/local/java/mall-demo/image/avatarimg
+图片-其他类型图片 保存路径为: /usr/local/java/mall-demo/image/common
是否启用静态资源映射: yes
文件保存根路径为: /usr/local/java/mall-demo/
web路径为: http://127.0.0.1:8181/malldemo/web/
前端项目访问url为: http://127.0.0.1:8181/malldemo/web/project/index.html
静态资源访问示例:️
访问动态配图,服务器保存路径为【/usr/local/java/mall-demo/image/contentimg/图片文件名】️
web路径为【http://127.0.0.1:8181/malldemo/web/image/contentimg/图片文件名】
---- 初始化AppConfig end ----
将图片assii.jpg放到目录“/usr/local/java/mall-demo/image/contentimg
”下,访问地址“http://localhost:8181/malldemo/web/image/contentimg/assii.jpg
”,结果如下:
附件
附件1
package com.qsdbl.malldemo.configuration;
import com.qsdbl.malldemo.common.utils.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import javax.annotation.PostConstruct;
import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @author: 轻率的保罗
* @since: 2023-01-30
* @Description: 程序配置信息
*/
@Slf4j
@Component(value = "appconfig")
public class AppConfig {
/**
* 静态资源映射 匹配路径(web访问路径前缀)
*/
private String PATH_PATTERN = "/web/**";
/**
* 项目部署地址。
*/
private String jarFilePath;
/**
* 文件保存地址。包含jarFilePath
*/
private String filepath;
/**
* 保存文件 文件夹。filepath下的一级文件夹,即 filepath + FILE_FOLDER
*/
private String FILE_FOLDER = "file";
/**
* 存放前端项目 文件夹。filepath下的一级文件夹。
* 将前端项目部署在 filepath + WEB_FOLDER 下,即可通过 getWebUrl() + WEB_FOLDER 访问前端项目。
*/
private String WEB_FOLDER = "project";
/**
* 图片文件 文件夹。filepath下的一级文件夹。
*/
private String IMG_FOLDER = "image";
/**
* 动态配图 文件夹。
* IMG_FOLDER下的一级文件夹,即 filepath + IMG_FOLDER + CONTENT_IMG_FOLDER。下同。
*/
private String CONTENT_IMG_FOLDER = "contentimg";
/**
* 标签图片 文件夹。
*/
private String TAG_IMG_FOLDER = "tagimg";
/**
* 头像图片 文件夹。
*/
private String AVATAR_IMG_FOLDER = "avatarimg";
/**
* 其他类型图片 文件夹。
*/
private String COMMON_IMG_FOLDER = "common";
/**
* 获取配置文件中的配置信息
*/
@Autowired
private Environment env;
/**
* 初始化变量jarFilePath、filepath
* 检查是否有权限访问(读写)filepath,不存在则创建。无访问权限或创建失败会抛出异常,阻止项目启动
*/
@PostConstruct
public void init() throws Exception {
log.info("---- 初始化AppConfig start ----");
//初始化变量jarFilePath
jarFilePath = getJarFilePathAndCheck();
//初始化变量filepath
Boolean isEnable = Boolean.valueOf(env.getProperty("path.custom.enable"));
//是否自定义文件保存位置。默认保存在项目部署地址下(data文件夹)
if(isEnable){
log.info("自定义文件保存位置!");
String filepathLinux = env.getProperty("path.filepath.linux");
String filepathWin = env.getProperty("path.filepath.windows");
if(filepathLinux == null || filepathWin == null){
String errMsg = "自定义文件保存位置,但是未提供【path.filepath.linux】、【path.filepath.windows】!";
log.error(errMsg);
throw new IllegalArgumentException(errMsg);
}
if (SysUtil.isUnix()) {
//Mac、Linux、Unix 系统
filepath = filepathLinux;
}else{
if(SysUtil.isWin()){
//Windows 系统
filepath = filepathWin;
}else{
String errMsg = "未知系统类型【"+SysUtil.getOsName()+"】,无法初始化文件保存位置!!!";
log.error(errMsg);
throw new Exception(errMsg);
}
}
}else{
log.info("文件默认保存在项目部署地址下(data文件夹)!");
//获取项目部署地址
filepath = jarFilePath + env.getProperty("spring.application.name")+"_data" + File.separator;
}
//目录最后须带有分隔符
filepath = File.separator.equals(filepath.substring(filepath.length()-1))?filepath:filepath+File.separator;
//创建相关路径(无权限会抛出异常,阻止程序启动)
String[] paths = {
filepath,filepath+WEB_FOLDER,filepath+FILE_FOLDER,filepath+IMG_FOLDER,filepath+IMG_FOLDER+File.separator+CONTENT_IMG_FOLDER,filepath+IMG_FOLDER+File.separator+TAG_IMG_FOLDER,filepath+IMG_FOLDER+File.separator+AVATAR_IMG_FOLDER,filepath+IMG_FOLDER+File.separator+COMMON_IMG_FOLDER};
for (String path : paths) {
SysUtil.checkAndCreatePath(path);
}
log.info("文件保存根路径为: "+paths[0]);
log.info(" -前端项目部署路径为: "+paths[1]);
log.info(" -文件保存路径为: "+paths[2]);
log.info(" -图片文件保存路径为: "+paths[3]);
log.info(" +图片-动态配图 保存路径为: "+paths[4]);
log.info(" +图片-标签图片 保存路径为: "+paths[5]);
log.info(" +图片-头像图片 保存路径为: "+paths[6]);
log.info(" +图片-其他类型图片 保存路径为: "+paths[7]);
//是否启用静态资源映射
if(isEnabelWebMapping()){
String pathPattern = env.getProperty("web.resources.path-pattern");
if(pathPattern != null){
this.PATH_PATTERN = pathPattern;
}
log.info("是否启用静态资源映射: yes");
log.info(" 文件保存根路径为: "+filepath);
log.info(" web路径为: "+getWebUrl());
log.info(" 前端项目访问url为: "+getWebUrl()+WEB_FOLDER+"/index.html");
log.info(" 静态资源访问示例:️");
log.info(" 访问动态配图,服务器保存路径为【"+paths[4]+"/图片文件名】️");
log.info(" web路径为【"+getWebUrl()+IMG_FOLDER+"/"+CONTENT_IMG_FOLDER+"/图片文件名】");
// 示例: http://localhost:8181/malldemo/web/image/contentimg/assii.jpg
}else{
log.info("是否启用静态资源映射: no");
}
log.info("---- 初始化AppConfig end ----");
}
/**
* 获取ip地址
*/
public String getIpAddress() throws UnknownHostException {
return InetAddress.getLocalHost().getHostAddress();
}
/**
* 获取web url(即静态资源访问路径,要加上静态资源保存位置相对于filepath的 相对地址 才能访问到具体的资源)。
* 前提是启用静态资源映射,通过isEnabelWebMapping()来判断。
* 最后带有分隔符。
* @return url 或者 空字符串(说明未启用静态资源映射)
*/
public String getWebUrl() throws UnknownHostException {
// /malldemo/ 处理成 /malldemo
String contextPath = env.getProperty("server.servlet.context-path");
if(contextPath != null && contextPath.endsWith("/")){
contextPath = contextPath.substring(0,contextPath.length()-1);
}
String url = "http://"+ getIpAddress()+":"+env.getProperty("server.port")+contextPath+ PATH_PATTERN.substring(0, PATH_PATTERN.lastIndexOf("/**")+1);
return isEnabelWebMapping()?url:"";
}
/**
* 是否启用静态资源映射
*/
public boolean isEnabelWebMapping(){
return Boolean.valueOf(env.getProperty("web.resources.add-mappings.enable"));
}
/**
* 获取项目部署地址(最后有分隔符)
*/
public String getJarFilePath(){
return jarFilePath;
}
/**
* 获取文件保存地址(最后有分隔符)
*/
public String getFilePath(){
return filepath;
}
/**
* 获取运行Jar包的目录,即项目部署地址。并检查是否有读写权限。
* MacOs 13.1、Linux-Centos7、Win10环境中可获取到。
* @return 路径
*/
private String getJarFilePathAndCheck() throws Exception {
//方案一:可能Linux-Ubuntu中jarFile为null,无法获取到项目部署地址。无测试环境,未测试。
ApplicationHome home = new ApplicationHome(getClass());
File jarFile = home.getSource();
String path = null;
if(jarFile != null){
path = jarFile.getParentFile().toString();
}else{
//方案二:获取classpath,从中截取(未在win系统中测试该方案。方案一大部分情况可正常获取)
String classpath = ResourceUtils.getURL("classpath:").getPath();
if(classpath.contains("file:")){
//win系统,file:/F:/xxx,所以len为6
int len = SysUtil.isWin()?6:5;
classpath = classpath.substring(len);
log.info("处理1 = "+classpath);
}
if(classpath.contains(".jar!")){
classpath = classpath.substring(0,classpath.indexOf(".jar!"));
}
// 再把最后一个分隔符后边的去掉
classpath = classpath.substring(0,classpath.lastIndexOf(File.separator)+1);
path = classpath;
}
if(path == null || path == ""){
String errMsg = "无法获取项目部署地址!!!";
log.error(errMsg);
throw new Exception(errMsg);
}
//目录最后须带有分隔符
path = File.separator.equals(path.substring(path.length()-1))?path:path+File.separator;
//检查读写权限
SysUtil.checkAndCreatePath(path);
return path;
}
public String getFILE_FOLDER() {
return FILE_FOLDER;
}
public String getIMG_FOLDER() {
return IMG_FOLDER;
}
public String getCONTENT_IMG_FOLDER() {
return CONTENT_IMG_FOLDER;
}
public String getTAG_IMG_FOLDER() {
return TAG_IMG_FOLDER;
}
public String getAVATAR_IMG_FOLDER() {
return AVATAR_IMG_FOLDER;
}
public String getCOMMON_IMG_FOLDER() {
return COMMON_IMG_FOLDER;
}
/**
* 获取保存 文件 根文件夹 完整路径(服务器绝对路径)
* @return 路径最后带有分隔符
*/
public String getFILE_FOLDER_FULL() {
return filepath+FILE_FOLDER+File.separator;
}
//
// /**
// * 获取保存 图片文件 根文件夹 完整路径(服务器绝对路径)
// * @return 路径最后带有分隔符
// */
// public String getIMG_FOLDER_FULL() {
// return filepath+IMG_FOLDER+File.separator;
// }
/**
* 获取保存 动态配图 文件夹 完整路径(服务器绝对路径)
* @return 路径最后带有分隔符
*/
public String getCONTENT_IMG_FOLDER_FULL() {
return filepath+IMG_FOLDER+File.separator+CONTENT_IMG_FOLDER+File.separator;
}
/**
* 获取保存 标签图片 文件夹 完整路径(服务器绝对路径)
* @return 路径最后带有分隔符
*/
public String getTAG_IMG_FOLDER_FULL() {
return filepath+IMG_FOLDER+File.separator+TAG_IMG_FOLDER+File.separator;
}
/**
* 获取保存 头像图片 文件夹 完整路径(服务器绝对路径)
* @return 路径最后带有分隔符
*/
public String getAVATAR_IMG_FOLDER_FULL() {
return filepath+IMG_FOLDER+File.separator+AVATAR_IMG_FOLDER+File.separator;
}
/**
* 获取保存 其他类型图片 文件夹 完整路径(服务器绝对路径)
* @return 路径最后带有分隔符
*/
public String getCOMMON_IMG_FOLDER_FULL() {
return filepath+IMG_FOLDER+File.separator+COMMON_IMG_FOLDER+File.separator;
}
/**
* 获取静态资源映射路径
*/
public String getPATH_PATTERN() {
return PATH_PATTERN;
}
}
附件2
package com.qsdbl.malldemo.configuration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author: 轻率的保罗
* @since: 2023-01-16
* @Description: 静态资源规则配置。配置 全局异常处理-404异常捕获 之后(所有访问不到的路径,均会抛出404异常,捕获之后返回自定义的DataVo实例-json对象),导致静态资源无法正常访问,添加如下配置。
* 注意:若访问路径(静态资源),从以下addResourceHandler配置的目录中找不到,则会返回“Whitelabel Error Page”页面,而不是经过全局异常处理捕获后返回的404错误信息(DataVo对象)
* 注意:addResourceLocations中地址最后带有分隔符
*/
@Slf4j
@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {
/**
* 获取配置文件中的配置信息
*/
@Autowired
private Environment env;
/**
* 程序配置信息
*/
@Autowired
private AppConfig appConfig;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//配置 静态资源映射(详情见AppConfig类中的init()方法)
if(appConfig.isEnabelWebMapping()){
registry.addResourceHandler(appConfig.getWEBPATH()).addResourceLocations("file:" + appConfig.getFilePath());
}
//swaggerUI:
// swagger第三方UI - Knife4j,访问地址为:http://localhost:8181/malldemo/doc.html
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");//以jar包方式访问js、css、html等静态资源(Knife4j的相关依赖已打包成jar包)
}
}
附件3
package com.qsdbl.malldemo.common.utils;
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.IOException;
import java.nio.file.AccessDeniedException;
/**
* @author: 轻率的保罗
* @since: 2023-01-30
* @Description: 通用工具类
*/
@Slf4j
public class SysUtil {
/**
* 检查路径是否存在,不存在则创建,同时检查路径是否是目录、检查是否有读写权限。
* @param path 绝对地址
*/
public static void checkAndCreatePath(String path) throws Exception {
File file = new File(path);
if(file.exists()){
//存在,则:1、检查是否是目录。2、检查是否有读写权限。
if(!file.isDirectory()){
String errMsg = "警告!路径【"+path+"】不是目录!";
log.error(errMsg);
throw new IllegalArgumentException(errMsg);
}
if(!file.canRead() || !file.canWrite()){
String errMsg = "警告!路径【"+path+"】无读写权限!";
log.error(errMsg);
throw new AccessDeniedException(errMsg);
}
}else{
//不存在,则创建目录。
if(!file.mkdirs()){
if(!file.canRead() || !file.canWrite()){
String errMsg = "警告!路径【"+path+"】无读写权限!";
log.error(errMsg);
throw new AccessDeniedException(errMsg);
}else {
String errMsg = "路径【"+path+"】不存在,尝试创建目录,目录创建失败!";
log.error(errMsg);
throw new IOException(errMsg);
}
}
}
}
/**
* 是否是 Unix 系统,包括Mac、Linux、Unix 系统
* @return true - 是;false - 不是;
*/
public static boolean isUnix(){
String osName = getOsName();
return osName.contains("mac") || osName.contains("linux") || osName.contains("unix");
}
/**
* 是否是 Windows 系统
* @return true - 是;false - 不是;
*/
public static boolean isWin(){
String osName = getOsName();
return osName.contains("win");
}
/**
* 获取系统名称(转换为小写)
* @return 例如:mac os x
*/
public static String getOsName(){
return System.getProperty("os.name").toLowerCase();
}
}
说明
本博客中的案例,使用的maven依赖如下:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<!-- 启用web支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 启用lombok(lombok 与 日志@Slf4j)-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 启用单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>