前言
我们知道 FastRequest 中有一块前置、后置脚本,允许在 api 执行前后处理一些逻辑。前后置脚本是通过 Groovy 脚本实现的,Groovy是一门跟 Java 非常相像的语言。接下来我们希望利用Groovy来实现加载某个 jar 包下面或者项目下的某个类,并且调用类里面的方法实现一些逻辑
本地Jar 加载
this.class.classLoader.addURL(new URL("file:/path/to/jar"))
def StringUtils = Class.forName("org.apache.commons.lang3.StringUtils").getDeclaredConstructor().newInstance()
if(StringUtils.isNotBlank("")){
//some logic
}
首先我们需要通过 classLoader
的 addURL
方法将 Jar 加载进来,例如 commons.lang
包有一些非常多的工具方法。接下来就可以通过Class.forName实例化类,并且再后面直接进行调用。
本地 Class加载
本地 Class 调用需要通过 ClassLoader
将本地的 class 加载进来再处理
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class FrLocalClassLoader extends ClassLoader {
private final String classpath;
/**
* @param classpath 类路径,例如/Users/username/xx_project/target/classes
*/
public FrLocalClassLoader(String classpath) {
this.classpath = classpath;
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
String filePath = classpath + File.separator + name.replace(".", File.separator) + ".class";
File file = new File(filePath);
if (!file.exists()) {
throw new ClassNotFoundException("Class not found: " + name);
}
try (InputStream inputStream = new FileInputStream(file)) {
byte[] classData = new byte[(int) file.length()];
inputStream.read(classData);
return defineClass(name, classData, 0, classData.length);
} catch (IOException e) {
throw new ClassNotFoundException("Could not load class: " + name, e);
}
}
}
我们需要先定义一个本地加载 Class 的类,并且构造器里面传入classpath,classpath即 class 文件夹所在的目录。例如我们SpringBoot 项目编译后,会在项目模块目录下生产一个 target>classes
层级目录,那么我们需要将 classes
这个目录的绝对路径定义为 classPath。接下来调用findClass找到对应的类即可。
可以这么调用,即可获取XxxUtil
,接下来就可以直接调用
def XxxUtil = new FrLocalClassLoader("path/to/classes").loadClass("some.package.XxxUtil")
那么如果需要加载一个有构造器的类呢?也很简单,只要获取到类以后,再调用getConstructor,传入对应的参数类型即可
Constructor<?> constructor = new FrLocalClassLoader("path/to/classes").loadClass("some.package.User").getConstructor(String.class, int.class);
User instance = constructor.newInstance("Alice", 30);
远程 Jar 加载的形式
@Grab("org.apache.commons:commons-lang3:3.12.0")
import org.apache.commons.lang3.StringUtils
if(StringUtils.isNotBlank("")){
//some logic
}
通过 @Grab("groupId:artifactId:version")
注解非常简单的将 jar 包的加载进来,并且 import 相对应的类,后面再直接调用。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。