需要事先将api模块打成jar,这样就可以只读取该jar里面的controller
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.var;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ApiReader {
public static void main(String[] args) {
new ApiReader().read();
}
private void read() {
File api=new File("api");
var target=new File(api,"target");
var jars=target.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".jar");
}
});
Preconditions.checkArgument(jars.length==1);
List<Class> clazzs = new ArrayList<Class>();
JarFile jarFile = null;
try {
jarFile = new JarFile(jars[0]);
} catch (IOException e1) {
e1.printStackTrace();
}
List<JarEntry> jarEntryList = new ArrayList<JarEntry>();
Enumeration<JarEntry> ee = jarFile.entries();
while (ee.hasMoreElements()) {
JarEntry entry = (JarEntry) ee.nextElement();
// 过滤我们出满足我们需求的东西
if ( entry.getName().endsWith(".class")) {
jarEntryList.add(entry);
}
}
for (JarEntry entry : jarEntryList) {
String className = entry.getName().replace('/', '.');
className = className.substring(0, className.length() - 6);
// 也可以采用如下方式把类加载成一个输入流
// InputStream in = jarFile.getInputStream(entry);
try {
clazzs.add(Thread.currentThread().getContextClassLoader()
.loadClass(className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
clazzs.stream().filter(c->c.getName().endsWith("Controller")).forEach(controller->consume(controller));
}
private void consume(Class<?> controller) {
var api=controller.getAnnotation(Api.class);
if(null==api){
System.err.println("can not get Api from "+controller.getName());
return;
}
Page page=new Page();
page.setName(api.tags()[0]);
page.setController(controller);
Stream.of(controller.getDeclaredMethods()).forEach(method -> {
Page.Function i=page.new Function();
page.getFunctions().add(i);
i.setJavaMethod(method);
String methodName = controller.getName() + "." + method.getName();
ApiOperation apiOperation=method.getAnnotation(ApiOperation.class);
if(null==apiOperation){
System.err.println("can not get operation from " + methodName);
}else{
i.setName(apiOperation.value());
}
RequestMapping requestMapping= AnnotationUtils.findAnnotation(method,RequestMapping.class);
if(null==requestMapping){
System.err.println("can not get request mapping from "+methodName);
}else{
var methods=requestMapping.method();
if(methods.length==1){
RequestMethod m = requestMapping.method()[0];
i.setHttpMethod(m);
String[] paths = requestMapping.value();
switch (m){
case GET:
GetMapping getMapping=method.getAnnotation(GetMapping.class);
if(null!=getMapping){
paths=getMapping.value();
}
break;
case POST:
PostMapping postMapping=method.getAnnotation(PostMapping.class);
if(null!=postMapping){
paths=postMapping.value();
}
break;
case PUT:
PutMapping putMapping=method.getAnnotation(PutMapping.class);
if(null!=putMapping){
paths=putMapping.value();
}
break;
case PATCH:
PatchMapping patchMapping=method.getAnnotation(PatchMapping.class);
if(null!=patchMapping){
paths=patchMapping.value();
}
break;
case DELETE:
DeleteMapping deleteMapping=method.getAnnotation(DeleteMapping.class);
if(null!=deleteMapping){
paths=deleteMapping.value();
}
break;
}
if(paths.length==1){
i.setPath(paths[0]);
}else{
System.err.println("can not get path from "+methodName);
}
}else{
System.err.println("can not get HttpMethod from "+methodName);
}
}
});
System.out.println(page);
}
@Data
public static class Page {
private String name;
@Data
class Function {
private String name;
private RequestMethod httpMethod;
private String path;
private Method javaMethod;
@Override
public String toString() {
return "接口:"+name+"\t,来自"+javaMethod.getName()+"\t,请求方式为:"+ httpMethod +" "+path;
}
}
private List<Function> functions = Lists.newArrayList();
private Class<?> controller;
@Override
public String toString() {
return "页面:"+name+"\t,来自"+controller.getName()+"\t,包含以下方法:\n"+ functions.stream().map(i->"\t"+i+"\n").collect(Collectors.joining());
}
}
}