import com.alibaba.fastjson.JSON;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.annotation.PostConstruct;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Slf4j
@Component
public class OpenApiHelper {
private static final String OPENAPI_PACKAGE = "com.umgsai.open.api";
@SofaReference
private OpenApiService openApiService;
private Map<String, String> uriMethodMap = Maps.newHashMap();
@PostConstruct
public void initOpenApi() {
Reflections methodReflections = new Reflections(new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage(OPENAPI_PACKAGE))
.setScanners(new MethodAnnotationsScanner()));
Set<Method> methods = methodReflections.getMethodsAnnotatedWith(RequestMapping.class);
List<OpenApi> openApiListInCode = Lists.newArrayList();
for (Method method : methods) {
//log.info(method.getName());
//log.info(method.getClass().getCanonicalName());
//log.info(method.getClass().getName());
//method所在的类
Class<?> controllerClass = method.getDeclaringClass();
//log.info(controllerClass.getName());
//参数类型
Type[] parameterTypes = method.getParameterTypes();
List<String> parameterTypeNameList = Lists.newArrayList();
for (Type parameterType : parameterTypes) {
parameterTypeNameList.add(parameterType.getTypeName());
}
Type returnType = method.getReturnType();
//对应Modifier中定义的public private 。。。
int modifiers = method.getModifiers();
List<String> parameterNameList = Lists.newArrayList();
//获取方法的参数名称
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] parameterNames = u.getParameterNames(method);
for (int i = 0; i < parameterNames.length; i++) {
parameterNameList.add(parameterNames[i]);
}
int parameterCount = method.getParameterCount();
List<String> parameterList = Lists.newArrayList();
for (int i = 0; i < parameterCount; i++) {
parameterList.add(String.format("%s %s", parameterTypeNameList.get(i), parameterNameList.get(i)));
}
//public java.lang.Object com.umgsai.open.api.controller.ContainerApiController.deleteContainer(long id)
String methodName = String.format("%s %s %s.%s(%s)", Modifier.toString(modifiers), ((Class) returnType).getName(),
controllerClass.getName(), method.getName(), Joiner.on(",").join(parameterList));
RequestMapping controllerRequestMappingAnnotation = controllerClass.getAnnotation(RequestMapping.class);
String[] controllerRequestMapping = controllerRequestMappingAnnotation.value();
if (controllerRequestMapping.length > 1) {
throw new RuntimeException(String.format("Controller上不允许配置多个RequestMapping注解!方法名:%s", controllerClass.getName()));
}
RequestMapping methodRequestMappingAnnotation = method.getAnnotation(RequestMapping.class);
String[] methodRequestMapping = methodRequestMappingAnnotation.value();
if (methodRequestMapping.length > 1) {
throw new RuntimeException(String.format("方法上不允许配置多个RequestMapping注解!方法名:%s", methodName));
}
StringBuilder uriBuilder = new StringBuilder();
if (controllerRequestMapping.length == 1) {
uriBuilder.append("/");
String[] controllerUris = StringUtils.split(controllerRequestMapping[0], "/");
uriBuilder.append(Joiner.on("/").join(Arrays.asList(controllerUris)));
}
if (methodRequestMapping.length == 1) {
uriBuilder.append("/");
String[] methodUris = StringUtils.split(methodRequestMapping[0], "/");
uriBuilder.append(Joiner.on("/").join(Arrays.asList(methodUris)));
}
String uri = uriBuilder.toString();
//log.info(methodName);
//log.info(uri);
uriMethodMap.put(uri, methodName);
MethodComment methodComment = method.getAnnotation(MethodComment.class);
String methodCommentValue = "";
if (methodComment != null) {
methodCommentValue = methodComment.value();
}
String[] strs = StringUtils.split(controllerClass.getName(), ".");
String apiControllerName = strs[strs.length - 1];
openApiListInCode.add(new OpenApi(uri, methodName, methodCommentValue, apiControllerName, method.getName()));
}
openApiService.updateOpenApi(openApiListInCode);
log.info(JSON.toJSONString(uriMethodMap));
}
}
//使用注解配置方法的注释信息
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodComment {
String value() default "";
}
对应的controller中的方法
@ResponseBody
@MethodComment("分页查询容器列表")
@RequestMapping(value = "/queryContainerList.json", method = RequestMethod.GET)
public Object queryContainerList(@RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) {
DataResult<PageInfo<Container>> dataResult = containerService.queryByPage(pageNum, pageSize);
return dataResult;
}
@Slf4j
@Component
@SofaService
public class OpenApiServiceImpl implements OpenApiService {
@AutoWired
private OpenApiDao openApiDao;
@Override
public DataResult updateOpenApi(List<OpenApi> openApiListInCode) {
if (CollectionUtils.isEmpty(openApiListInCode)) {
return DataResult.successResult("openApiListInCode为空");
}
Map<String, OpenApi> map = Maps.newHashMap();
for (OpenApi openApi : openApiListInCode) {
map.put(openApi.getApiUri(), openApi);
}
List<OpenApi> openApiListInDb = openApiDao.queryAll();
Set<String> uriSetInDb = Sets.newHashSet();
for (OpenApi openApiInDb : openApiListInDb) {
uriSetInDb.add(openApiInDb.getApiUri());
OpenApi openApiInCode = map.get(openApiInDb.getApiUri());
if (openApiInCode == null) {
//需要删除DB里的记录
openApiDao.delete(openApiInDb.getId());
continue;
}
if (openApiInCode.equals(openApiInDb)) {
//DB里的记录和代码中的数据一致,不需要操作
continue;
}
//DB里的记录和代码中的数据不一致,需要更新,以代码中的数据为准
openApiInDb.setApiUri(openApiInCode.getApiUri());
openApiInDb.setApiMethod(openApiInCode.getApiMethod());
openApiInDb.setApiComment(openApiInCode.getApiComment());
openApiDao.update(openApiInDb);
}
for (OpenApi openApiInCode : openApiListInCode) {
//如果代码中存在 但是DB中不存在,则需要添加到DB中
if (!uriSetInDb.contains(openApiInCode.getApiUri())) {
openApiDao.insert(new OpenApi(openApiInCode.getApiUri(), openApiInCode.getApiMethod(), openApiInCode.getApiComment(),
openApiInCode.getApiControllerName(), openApiInCode.getApiMethodName()));
}
}
return DataResult.successResult();
}
}
需要依赖的jar包
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>