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文件中进行设置

 <build>
        <resources>
            <resource>
                <filtering>true</filtering>
                <directory>src/main/resources</directory>
                <excludes>
                    <exclude>**/*.woff</exclude>
                    <exclude>**/*.ttf</exclude>
                    <exclude>**/*.ico</exclude>
                </excludes>
            </resource>
            <resource>
                <filtering>false</filtering>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.woff</include>
                    <include>**/*.ttf</include>
                    <include>**/*.ico</include>
                </includes>
            </resource>
        </resources>
 </build>

自定义欢迎页面

在对静态内目录设置自定义访问路径替换原有的/**后,无法找到目录下的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 = request.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('<link rel="shortcut icon" href= ' + iconurl + '    ></link>');

项目访问框架静态资源

框架静态资源文件获取

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

扫描jar包

 public static void copyFrameStaticFile() {
        String packageName = "com.haopan.frame";
        // 获取包的名字 并进行替换
        String packageDirName = packageName.replace('.', '/');
        // 定义一个枚举的集合 并进行循环来处理这个目录下的things
        Enumeration<URL> dirs;
        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
            // 循环迭代下去
            while (dirs.hasMoreElements()) {
                // 获取下一个元素
                URL url = dirs.nextElement();
                // 得到协议的名称
                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<JarEntry> 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包两种打包方式

到此这篇关于SpringBoot静态资源访问控制和封装集成方案的文章就介绍到这了,更多相关SpringBoot静态资源访问控制内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 基于Springboot2.3访问本地路径下静态资源的方法(解决报错:Not allowed to load local resource)

    最近在做的一个项目中有一个比较奇葩的需求: 要在springboot中,上传本地的图片进行展示 我的第一反应是,直接在数据库字段加一个存储本地路径的字段,然后用thymeleaf的th:src渲染到前端就好了嘛! 理想很丰满,但现实却很骨感~ 前端报了这样的错误Not allowed to load local resource 于是我想到了可以使用IO将图片先上传到static/images目录下,这样就不会出现禁止访问本地路径的问题了 但是这样实现,问题又来了:上传后的图片必须重启sprin

  • springboot项目访问静态资源的配置代码实例

    这篇文章主要介绍了springboot项目访问静态资源的配置代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 这里只是简单记录当上传图片不是放在tomcat其他服务器中时,只是放在磁盘中便可以这样配置,在项目启动后可以访问到磁盘中的资源. @Configuration public class SystemConfigurer implements WebMvcConfigurer { @Value("${jeewx.path.uploa

  • 在SpringBoot中静态资源访问方法

    一.概述 springboot 默认静态资源访问的路径为:/static 或 /public 或 /resources 或 /META-INF/resources 这样的地址都必须定义在src/main/resources目录文件中,这样可以达到在项目启动时候可以自动加载为项目静态地址目录到classpath下 ,静态访问地址其实是使用 ResourceHttpRequestHandler 核心处理器加载到WebMvcConfigurerAdapter进行对addResourceHandlers

  • SpringBoot封装自己的Starter的实现方法

    一.说明 我们在使用SpringBoot的时候常常要引入一些Starter,例如spring-boot-starter-web,官方为我们提供了几乎所有的默认配置,很好的降低了使用框架时的复杂度,所以在用xxx-starter的时候,可以不用费心去写一些繁琐的配置文件,即使必要的配置在application.properties或application.yml中配置就可以了,当你实现了一个Starter,可以在不同的项目中复用,非常方便,今天我们来编写自己的Starter以之前的短信业务为例.

  • SpringBoot静态资源目录访问

    静态资源配置 创建一个StaticConfig 继承 WebMvcConfigurerAdapter package com.huifer.blog.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframewo

  • 详解SpringBoot之访问静态资源(webapp...)

    springboot访问静态资源,默认有两个默认目录, 一个是  classpath/static 目录 (src/mian/resource) 一个是 ServletContext 根目录下( src/main/webapp ) 这在里可能有小伙伴对 classpath 不怎么了解,这里简要的介绍下,classpath 即WEB-INF下面的classes目录 ,在springboot项目中可能就是,src/main/resource 目录. 1,classpath 目录下-访问默认文件夹名为

  • SpringBoot学习系列之MyBatis Plus整合封装的实例详解

    前言 MyBatis-Plus是一款MyBatis的增强工具(简称MP),为简化开发.提高效率,但我们并没有直接使用MP的CRUD接口,而是在原来的基础上封装一层通用代码,单表继承我们的通用代码,实现了单表的基础get.save(插入/更新).list.page.delete接口,使用Vo去接收.传输数据,实体负责与数据库表映射. 这样做的目的是与我们之前的那套jpa保持编码风格上的一致,当我们的通用接口不能满足要求时,应当先考虑使用MP的Service层CRUD接口,然后是Mapper的接口,

  • springboot封装JsonUtil,CookieUtil工具类代码实例

    这篇文章主要介绍了springboot封装JsonUtil,CookieUtil工具类过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 JsonUtil public class JsonUtil { private static ObjectMapper objectMapper = new ObjectMapper(); public static String objectToString(Object object) throws

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

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

  • Springboot如何设置静态资源缓存一年

    这篇文章主要介绍了Springboot如何设置静态资源缓存一年,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 由于本人所在项目组,所用的项目是前后端分离的,前端是React 的SPA,每次打包都会新版本的静态文件. 然而,在有些时候,这些静态资源是不变的,故可以将资源缓存至用户本地,提升性能. 写法如下,需要继承WebMvcConfigurerAdapter类,并重写addResourceHandlers方法.就可以告诉浏览器强制缓存 pack

  • SpringBoot+Thymeleaf静态资源的映射规则说明

    目录 Spring Boot中静态资源的映射规则 Thymeleaf模板引擎的映射规则 SpringBoot对静态资源的映射规则源码学习笔记 Spring Boot中静态资源的映射规则 Spring Boot中静态资源主要包括两部分:1.webjars资源,2.自定义的其他html.css.js资源,下面分别介绍两种资源的映射规则. 1).webjars资源 WebJars是将web前端资源(js,css等)打成jar包文件,然后借助Maven工具,以jar包形式对web前端资源进行统一依赖管理

  • SpringBoot静态资源css,js,img配置方案

    一.概述 springboot 默认静态资源访问的路径为:/static 或 /public 或 /resources 或 /META-INF/resources 这样的地址都必须定义在src/main/resources目录文件中,这样可以达到在项目启动时候可以自动加载为项目静态地址目录到classpath下 ,静态访问地址其实是使用 ResourceHttpRequestHandler 核心处理器加载到WebMvcConfigurerAdapter进行对addResourceHandlers

  • IDEA配置静态资源热加载操作(Springboot修改静态资源不重启)

    第一步: 修改file->settings->compiler->build project automatically 第二步: 按ctrl+shift+a,搜索Registry双击进去,点击面板搜索running,勾选下面的值: 代码的热加载可以使用spring-boot-devtools,百度下就有很多,个人感觉不好用,修改代码需要重启项目,很烦,非常鸡肋,所以我不用,哈哈哈- 补充知识:idea实现修改html等springboot下static目录静态资源重新加载 对于前后端不

  • 使用springboot对外部静态资源文件的处理操作

    目录 springboot对外部静态资源文件的处理 1.存方面倒还简单,这里贴上一个获取微信临时素材并保存的方法 2.取,由于对springboot不熟悉,所以在这上面踩了坑 主要使用到这2个配置 之后,访问文件一直404 SpringBoot2.x静态资源访问 问题 代码 原理 springboot对外部静态资源文件的处理 springboot对外部资源文件的处理主要分为2部分,存和取,通过查看官方文件和看博客踩了坑之后终于搞定了,特此记录. 1.存方面倒还简单,这里贴上一个获取微信临时素材并

  • springboot访问静态资源遇到的坑及解决

    目录 访问静态资源遇到的坑及解决 直接访问静态资源的问题 SpringBoot 默认静态资源访问配置 引入shiro 或 security后的拦截过滤 访问静态资源遇到的坑及解决 开始是以这种结构进行的,结果页面上一篇红,访问的页面是这样的 最终找出来问题,虽然每次调整路径都不对,最终查看多种方法可以看到了: 增加: package com.example.demo.config; import org.springframework.stereotype.Component; import o

  • SpringBoot web静态资源映射实现步骤详解

    目录 静态资源映射规则 自定义静态资源映射规则 静态资源映射规则 “/**” 访问当前项目任何资源,全部找静态资源的文件夹进行映射 静态资源的文件夹包括: "classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/", "classpath:/public/" 静态资源路径下的文件,可以通过地址栏直接访问. 例如:我们在在static

  • SpringBoot访问静态资源的配置及顺序说明

    目录 访问静态资源的配置及顺序 1. SpringBoot的默认配置 2. 测试 3.配置 静态资源的配置心得 举例 访问静态资源的配置及顺序 今天在玩SpringBoot的demo的时候,放了张图片在resources目录下,启动区访问的时候,突然好奇是识别哪些文件夹来展示静态资源的, 为什么有时候放的文件夹不能显示,有的却可以. 1. SpringBoot的默认配置 首先我们打开WebMvcAutoConfiguration类, 因为是静态资源的位置, 所以搜索location,找到这一行代

随机推荐