SpringBoot设置静态资源访问控制和封装集成方案

网友投稿 337 2022-10-08


SpringBoot设置静态资源访问控制和封装集成方案

背景

最近在着手公司框架优化及项目实际应用,原先方案是springboot+html前后端分离单独部署,后端人员兼职前端开发,后续产品线业务进行优化,面向企业使用部分由移动网站人员负责设计开发,内部配置后台管理还是由后端负责,随着框架不停迭代与使用的项目越来越多,项目升级框架变得十分麻烦,后端部分可以通过maven私服进行版本迭代,后台管理页面升级则需要进行各个项目拷贝,所以决定对框架进行整合,将后台管理页面与框架后端代码进行整合发布。

结构设计

框架打包后台管理相关标准资源及页面(框架public文件夹)

项目使用框架,开发具体业务配置管理页面(项目static文件夹)

项目需要个性化框架页面时,在项目static文件夹建立与框架同目录同名称资源文件进行覆盖,访问时优先级高于框架目录

SpringBoot静态资源访问

自定义访问路径

自定义WebConfig实现WebMvcConfigurer,重写addResourceHandlers方法

@Configuration

public class WebConfig implements WebMvcConfigurer {

@Value("${system.projectName}")

private String projectName;

/**

* 添加静态资源文件,外部可以直接访问地址

*

* @param registry

*/

@Override

public void addResourceHandlers(ResourceHandlerRegistry registry) {

//第一个方法设置访问路径前缀,第二个方法设置资源路径

registry.addResourceHandler("/" + projectName + "/**").addResourceLocations("classpath:/static/","classpath:/public/","file:static/");

}

}

图标与字体文件夹访问失败问题

将静态文件拷贝到static/public/resource文件夹下访问时,图标与字体文件会进行过滤导致损坏,需要在pom文件中进行设置

true

src/main/resources

**/*.woff

**/*.ttf

**/*.ico

false

src/main/resources

**/*.woff

**/*.ttf

**/*.ico

自定义欢迎页面

在对静态内目录设置自定义访问路径替换原有的/**后,无法找到目录下的index页面,需要建立拦截器手动进行判断,效果为访问http://localhost:port/projectName 会自动跳转到 http://localhost:port/projectName/index.html

@Component

public class PageRedirectInterceptor implements HandlerInterceptor {

@Value("${system.projectName}")

private String projectName;

@Override

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

String requestURL = request.getRequestURL().toString();

String scheme = rehttp://quest.getScheme();

String servaerName = request.getServerName();

int port = request.getServerPort();

String rootPageURL = scheme + ":" + "//" + servaerName + ":" + port + "/" + projectName;

if (requestURL.equals(rootPageURL)) {

response.sendRedirect(request.getContextPath() + "/"+projectName + "/index.html");

return false;

}

return true;

}

}

自定义页面图标

在对静态内目录设置自定义访问路径替换原有的/**后,无法找到目录下的favcion.ico图标,需要在页面引用统一js统一设置,同时需要在配置文件中关闭默认图标,替换spring的小叶子

spring:

mvc:

favicon:

enabled: false

function GetRootPath() {

var loc = window.location,

host = loc.hostname,

protocol = loc.protocol,

port = loc.port ? (':' + loc.port) : '';

var path = location.pathname;

if (path.indexOf('/') === 0) {

path = path.substring(1);

}

var mypath = '/' + path.split('/')[0];

path = (mypath != undefined ? mypath : ('/' + loc.pathname.split('/')[1])) + '/';

var rootPath = protocol + '//' + host + port + path;

return rootPath;

}

var iconurl = GetRootPath()+"favicon.ico"

document.write('');

项目访问框架静态资源

框架静态资源文件获取

项目启动时,因为是引用框架的jar包,我们需要先找到指定jar包,再将jar包进行解压,找到对应目录将资源拷贝到我们需要的地方便于访问

扫描jar包

public static void copyFrameStaticFile() {

String packahttp://geName = "com.haopan.frame";

// 获取包的名字 并进行替换

String packageDirName = packageName.replace('.', '/');

// 定义一个枚举的集合 并进行循环来处理这个目录下的things

Enumeration dirs;

try {

dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);

// 循环迭代下去

while (dirs.hasMoreElements()) {

// 获取下一个元素

URL url = dirs.nextElement();

// 得到协议的名称

jxVCOhd String protocol = url.getProtocol();

if ("jar".equals(protocol)) {

// 如果是jar包文件

// 定义一个JarFile

JarFile jar;

try {

// 获取jar

jar = ((JarURLConnection) url.openConnection()).getJarFile();

String templateDecompressPath = "tempfiles/decompress/" + CommonUtil.getNewGuid() + "/";

File targetFile = new File(templateDecompressPath);

if (!targetFile.exists()) {

targetFile.mkdirs();

}

decompressJarFile(jar, templateDecompressPath);

String frameStaticPath = templateDecompressPath + "public/";

File frameStaticFile = new File(frameStaticPath);

if (frameStaticFile.exists()) {

String copyTargetPath = "static/";

File copyTargetFolder = new File(copyTargetPath);

if (copyTargetFolder.exists()) {

FileUtil.deleteDirectory(copyTargetPath);

}

copyTargetFolder.mkdirs();

FileUtil.copyFileFolder(frameStaticPath, copyTargetPath);

}

FileUtil.deleteDirectory(templateDecompressPath);

System.out.println("框架静态文件复制完毕!");

} catch (IOException e) {

e.printStackTrace();

}

}

}

} catch (IOException e) {

e.printStackTrace();

}

}

解压jar包

对JarFile中的JarEntry对象进行遍历,判断是文件还是目录分类处理

public static synchronized void decompressJarFile(JarFile jf,String outputPath){

if (!outputPath.endsWith(File.separator)) {

outputPath += File.separator;

}

File dir = new File(outputPath);

if (!dir.exists()) {

dir.mkdirs();

}

try{

for (Enumeration e = jf.entries(); e.hasMoreElements();) {

JarEntry je = (JarEntry) e.nextElement();

String outFileName = outputPath + je.getName();

File f = new File(outFileName);

if(je.isDirectory()){

if(!f.exists()){

f.mkdirs();

}

}else{

File pf = f.getParentFile();

if(!pf.exists()){

pf.mkdirs();

}

InputStream in = jf.getInputStream(je);

OutputStream out = new BufferedOutputStream(

new FileOutputStream(f));

byte[] buffer = new byte[2048];

int nBytes = 0;

while ((nBytes = in.read(buffer)) > 0) {

out.write(buffer, 0, nBytes);

}

out.flush();

out.close();

in.close();

}

}

}catch(Exception e){

System.out.println("解压"+jf.getName()+"出错---"+e.getMessage());

}finally{

if(jf!=null){

try {

jf.close();

File jar = new File(jf.getName());

if(jar.exists()){

jar.delete();

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

拷贝目录到指定位置

public class FileUtil {

private static void copy(String f1, String f2) throws IOException {

File file1=new File(f1);

/* File file2=new File(f2);*/

File[] flist=file1.listFiles();

for (File f : flist) {

if(f.isFile()){

copyFile(f.getPath(),f2+"/"+f.getName()); //调用复制文件的方法

//System.out.println("原路径["+f.getPath()+"] 被复制路径["+f2+"/"+f.getName()+"]");

}else if(f.isDirectory()){

copyFileFolder(f.getPath(),f2+"/"+f.getName()); //调用复制文件夹的方法

//System.out.println("原路径["+f.getPath()+"] 被复制路径["+f2+"/"+f.getName()+"]");

}

}

}

/**

* 复制文件夹

* @throws IOException

*/

public static void copyFileFolder(String sourceFolderPath,String targetFolderPath) throws IOException {

//创建文件夹

File file=new File(targetFolderPath);

if(!file.exists()){

file.mkdirs();

}

copy(sourceFolderPath,targetFolderPath);

}

/**

* 复制文件

* @throws IOException

*/

public static void copyFile(String sourceFilePath, String tagretFilePath) throws IOException {

try {

InputStream in = new FileInputStream(sourceFilePath);

OutputStream out = new FileOutputStream(tagretFilePath);

byte[] buffer = new byte[2048];

int nBytes = 0;

while ((nBytes = in.read(buffer)) > 0) {

out.write(buffer, 0, nBytes);

}

out.flush();

out.close();

in.close();

} catch (FileNotFoundException e) {

e.printStackTrace();

}

}

public static boolean delete(String fileName) {

File file =new File(fileName);

if (!file.exists()) {

//System.out.println("删除文件失败:" + fileName +"不存在!");

return false;

}else {

if (file.isFile())

return deleteFile(fileName);

else

return deleteDirectory(fileName);

}

}

/**

* 删除单个文件

*

* @param fileName:要删除的文件的文件名

* @return 单个文件删除成功返回true,否则返回false

*/

public static boolean deleteFile(String fileName) {

File file =new File(fileName);

// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除

if (file.exists() && file.isFile()) {

if (file.delete()) {

//System.out.println("删除单个文件" + fileName +"成功!");

return true;

}else {

//System.out.println("删除单个文件" + fileName +"失败!");

return false;

}

}else {

//System.out.println("删除单个文件失败:" + fileName +"不存在!");

return false;

}

}

/**

* 删除目录及目录下的文件

*

* @param dir:要删除的目录的文件路径

* @return 目录删除成功返回true,否则返回false

*/

public static boolean deleteDirectory(String dir) {

// 如果dir不以文件分隔符结尾,自动添加文件分隔符

if (!dir.endsWith(File.separator))

dir = dir + File.separator;

File dirFile =new File(dir);

// 如果dir对应的文件不存在,或者不是一个目录,则退出

if ((!dirFile.exists()) || (!dirFile.isDirectory())) {

System.out.println("删除目录失败:" + dir +"不存在!");

return false;

}

boolean flag =true;

// 删除文件夹中的所有文件包括子目录

File[] files = dirFile.listFiles();

for (int i =0; i < files.length; i++) {

// 删除子文件

if (files[i].isFile()) {

flag = deleteFile(files[i].getAbsolutePath());

if (!flag)

break;

}

// 删除子目录

else if (files[i].isDirectory()) {

flag = deleteDirectory(files[i].getAbsolutePath());

if (!flag)

break;

}

}

if (!flag) {

//System.out.println("删除目录失败!");

return false;

}

// 删除当前目录

if (dirFile.delete()) {

//System.out.println("删除目录" + dir +"成功!");

return true;

}else {

return false;

}

}

}

外部静态资源访问与优先级设置

设置yml文件中的static-locations配置项,多个使用,隔开,同时指定顺序为访问的优先级

spring:

resources:

static-locations: classpath:static/,classpath:public/,file:static/

最终目录结构图如下,框架部分完全是项目启动时自动解压拷贝的,项目部分则是由具体项目进行开发,项目部分也可以很方便的进行框架部分功能重构,例如登录页,主页面修改等,本方式支持jar包和war包两种打包方式


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:从源码分析:Linux共享库安全风险剖析 之 运行时加载顺序风险(linux 共享库原理)
下一篇:一文揭秘安芯网盾内存安全(安芯网盾公司有前景吗)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~