一、缘由:网关项目,项目源代码有groovy文件夹(内有多个.groovy文件),此文件夹和src目录平级。要求此文件夹和jar启动目录平级,GroovyFilter才能初始化。发布使用已有环境,所以不考虑改发布脚本。
二、问题:发布流程只会打jar包,不会将外部的其他文件打进去。
三、思路:在打包时,将外部指定文件打包到jar指定位置;在启动时,初始化GroovyFilter前,将内部文件复制到外部指定目录地址。
四、第一步:在打包时,将外部指定文件打包到jar指定位置
使用maven插件,在打包时,将groovy文件夹下所有内容,打包到jar包的/BOOT-INF/classes目录下。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<encoding>UTF-8</encoding>
<!--打成jar包后复制到的路径-->
<outputDirectory>
${project.build.directory}/BOOT-INF/classes
</outputDirectory>
<resources>
<resource>
<!--项目中的路径-->
<directory>groovy/</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
五、第二步:在启动时,初始化GroovyFilter前,将内部文件复制到外部指定目录地址。
此处拷贝一个文件做demo。/groovy/文件夹会自动创建。
GroovyFilterConfig.java
package com.xx.application.api.gateway.config;
import com.netflix.zuul.FilterFileManager;
import com.netflix.zuul.FilterLoader;
import com.netflix.zuul.groovy.GroovyCompiler;
import com.netflix.zuul.groovy.GroovyFileFilter;
import com.xx.application.api.gateway.utils.FileCopyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GroovyFilterConfig {
private static final Logger LOG = LoggerFactory.getLogger(GroovyFilterConfig.class);
@Value("${zuul.groovy.filter.interval}")
private int interval;
@Bean
public FilterLoader filterLoader(){
try{
//初始化前,拷贝所需配置
FileCopyUtils.copy("ErrorFilter.groovy","/groovy/");
} catch (Exception e) {
e.printStackTrace();
}
FilterLoader filterLoader = FilterLoader.getInstance();
filterLoader.setCompiler(new GroovyCompiler());
try {
FilterFileManager.setFilenameFilter(new GroovyFileFilter());
FilterFileManager.init(interval,
"groovy/filters/pre",
"groovy/filters/route",
"groovy/filters/post",
"groovy");
}catch (Exception e){
LOG.error("FilterLoader for groovy failed!!!", e);
throw new RuntimeException(e);
}
return filterLoader;
}
}
FileCopyUtils.java
package com.xx.application.api.gateway.utils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
public class FileCopyUtils {
private static InputStream getResource(String location) throws IOException {
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
InputStream in = resolver.getResource(location).getInputStream();
byte[] byteArray = IOUtils.toByteArray(in);
in.close();
return new ByteArrayInputStream(byteArray);
}
/**
* 获取项目所在文件夹的绝对路径
* @return
*/
private static String getCurrentDirPath() {
URL url = FileCopyUtils.class.getProtectionDomain().getCodeSource().getLocation();
String path = url.getPath();
if(path.startsWith("file:")) {
path = path.replace("file:", "");
}
if(path.contains(".jar!/")) {
path = path.substring(0, path.indexOf(".jar!/")+4);
}
File file = new File(path);
path = file.getParentFile().getAbsolutePath();
return path;
}
private static Path getDistFile(String path,String outPath) throws IOException {
String currentRealPath = getCurrentDirPath();
Path dist = Paths.get(currentRealPath + File.separator + outPath +path);
Path parent = dist.getParent();
if(parent != null) {
Files.createDirectories(parent);
}
Files.deleteIfExists(dist);
return dist;
}
/**
* 复制classpath下的文件到jar包的同级目录下
* @param location 相对路径文件
* @return
* @throws IOException
*/
public static String copy(String location,String outPath) throws IOException {
InputStream in = getResource("classpath:"+location);
Path dist = getDistFile(location, outPath);
Files.copy(in, dist);
in.close();
return dist.toAbsolutePath().toString();
}
}
六、执行结果模拟
执行启动前,没有文件夹/groovy/
执行启动后,创建了文件夹/groovy/,内部拷贝文件也存在