软件编程
位置:首页>> 软件编程>> java编程>> SpringBoot设置静态资源访问控制和封装集成方案

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

作者:code2roc  发布时间:2021-08-23 19:08:44 

标签:SpringBoot,静态资源,封装

背景

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

结构设计

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

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

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

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

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设置静态资源访问控制和封装集成方案

来源:https://www.cnblogs.com/yanpeng19940119/p/15084899.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com