概述
动态发布接口
HTTP接口分为REST和SOAP2种方式,文中都涉及到,包含从动态生成文件到编译class再到装载到spring容器和ws.Endpoint中。
REST风格
方案:
1.提供java文件模板
2.读取文件内容
3.查库修改生成java文件
4.通过JDK中的javax.tools.JavaCompiler动态编译成class
5.通过继承java.net.URLClassLoader动态加载class文件到内存
6.通过获取spring的ApplicationContext手动把mapping注册到RequestMappingHandlerMapping中完成动态发布
过程:
1.模板文件根据业务自行配置(涉及公司机密,忽略)
2.读取文件内容,生成java文件,编译class,加载class,发布接口
-
//动态创建接口
-
@Override
-
public Boolean createGenerate(String serviceName,Long interfaceId,String structrue) {
-
try {
-
//首字母大写
-
serviceName = StringUtils.firstCharUpper(serviceName);
-
//目录路径
-
Path directoryPath = Paths.get(outDirectory);
-
// 如果目录不存在
-
if (!Files.exists(directoryPath)) {
-
//创建目录
-
Files.createDirectories(directoryPath);
-
}
-
String controllerJava = serviceName + "Controller.java";
-
String autoJavaFile = outDirectory + controllerJava;
-
//文件路径
-
Path filePath = Paths.get(autoJavaFile);
-
if (!Files.exists(filePath)) {
-
//创建文件
-
Files.createFile(filePath);
-
} else {
-
logger.error("动态创建接口错误,文件已存在:"+autoJavaFile);
-
return false;
-
}
-
// 读取模板文件流
-
String javaFile = directory + "RestTemplateController.java";
-
String content = FileUtils.readFile(javaFile);
-
//替换文件
-
content = replaceJava(content, serviceName, interfaceId,structrue);
-
//写入文件
-
Files.write(filePath, content.getBytes(charsetName));
-
String fullName = packageName + serviceName + "Controller";
-
//动态编译class
-
JavaStringCompiler compiler = new JavaStringCompiler();
-
Map<String, byte[]> results = compiler.compile(controllerJava, content);
-
//加载class
-
Class<?> clzMul = compiler.loadClass(fullName, results);
-
//获取spring的applicationContext
-
ApplicationContext applicationContext = SpringContextHelper.getApplicationContext();
-
//注册接口到注册中心
-
MappingRegulator.controlCenter(clzMul, applicationContext, create);
-
} catch (Exception e) {
-
logger.error("动态创建接口错误",e);
-
return false;
-
}
-
return true;
-
}
-
/**
-
* controlCenter(运行时RequestMappingHandlerMapping中添加、删除、修改Mapping接口)
-
* @param Class 希望加载的类Class
-
* @param ApplicationContext spring上下文
-
* @param type 1新增 2修改 3删除
-
* @throws Exception
-
* @throws IllegalAccessException
-
* @Exception 异常对象
-
* @since CodingExample Ver(编码范例查看) 1.1
-
* @author jiaxiaoxian
-
*/
-
public static void controlCenter(Class<?> controllerClass,ApplicationContext Context,Integer type) throws IllegalAccessException, Exception{
-
//获取RequestMappingHandlerMapping
-
RequestMappingHandlerMapping requestMappingHandlerMapping=(RequestMappingHandlerMapping) Context.getBean("requestMappingHandlerMapping");
-
Method getMappingForMethod =ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod",Method.class,Class.class);
-
//设置私有属性为可见
-
getMappingForMethod.setAccessible(true);
-
//获取类中的方法
-
Method[] method_arr = controllerClass.getMethods();
-
for (Method method : method_arr) {
-
//判断方法上是否有注解RequestMapping
-
if (method.getAnnotation(RequestMapping.class) != null) {
-
//获取到类的RequestMappingInfo
-
RequestMappingInfo mappingInfo = (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, method,controllerClass);
-
if(type == 1){
-
//注册
-
registerMapping(requestMappingHandlerMapping, mappingInfo, controllerClass, method);
-
}else if(type == 2){
-
//取消注册
-
unRegisterMapping(requestMappingHandlerMapping, mappingInfo);
-
registerMapping(requestMappingHandlerMapping, mappingInfo, controllerClass, method);
-
}else if(type == 3){
-
unRegisterMapping(requestMappingHandlerMapping, mappingInfo);
-
}
-
}
-
}
-
}
-
/**
-
*
-
* registerMapping(注册mapping到spring容器中)
-
* @param requestMappingHandlerMapping
-
* @Exception 异常对象
-
* @since CodingExample Ver(编码范例查看) 1.1
-
* @author jiaxiaoxian
-
*/
-
public static void registerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping,RequestMappingInfo mappingInfo, Class<?> controllerClass, Method method) throws Exception, IllegalAccessException{
-
requestMappingHandlerMapping.registerMapping(mappingInfo, controllerClass.newInstance(),method);
-
}
-
/**
-
*
-
* unRegisterMapping(spring容器中删除mapping)
-
* @param requestMappingHandlerMapping
-
* @Exception 异常对象
-
* @since CodingExample Ver(编码范例查看) 1.1
-
* @author jiaxiaoxian
-
*/
-
public static void unRegisterMapping(RequestMappingHandlerMapping requestMappingHandlerMapping,RequestMappingInfo mappingInfo) throws Exception, IllegalAccessException{
-
requestMappingHandlerMapping.unregisterMapping(mappingInfo);
-
}
结果:
可以正常发布spring接口,动态生成文件注入mapping到spring接口中。
SOAP风格
方案:
1.提供java文件模板
2.读取文件内容
3.查库修改生成java文件
4.通过JDK中的javax.tools.JavaCompiler动态编译成class
5.通过继承java.net.URLClassLoader动态加载class文件到内存
6.通过javax.xml.ws.Endpoint的publish动态发布接口
过程:
1.模板文件根据业务自行配置(涉及公司机密,忽略)
2.读取文件内容,生成java文件,编译class,加载class,通过Endpoint发布接口
-
@Override
-
public Boolean createGenerate(String serviceName, Long interfaceId, String structrue) {
-
try {
-
serviceName = StringUtils.firstCharUpper(serviceName);
-
Path directoryPath = Paths.get(outDirectory);
-
// 如果文件不存在
-
if (!Files.exists(directoryPath)) {
-
Files.createDirectories(directoryPath);
-
}
-
String controllerJava = serviceName + "Controller.java";
-
String autoJavaFile = outDirectory + controllerJava;
-
Path filePath = Paths.get(autoJavaFile);
-
if (!Files.exists(filePath)) {
-
Files.createFile(filePath);
-
} else {
-
logger.error("动态创建接口错误ws,文件已存在:" + autoJavaFile);
-
return false;
-
}
-
String wsJavaFile = directory + "JwsTemplateController.java";
-
String content = FileUtils.readFile(wsJavaFile);
-
content = replaceJava(content, serviceName, interfaceId, structrue);
-
Files.write(filePath, content.getBytes(charsetName));
-
String fullName = packageName + serviceName + "Controller";
-
JavaStringCompiler compiler = new JavaStringCompiler();
-
Map<String, byte[]> results = compiler.compile(controllerJava, content);
-
Class<?> clzMul = compiler.loadClass(fullName, results);
-
publish(clzMul, serviceName);
-
} catch (Exception e) {
-
logger.error("动态创建接口错误ws", e);
-
return false;
-
}
-
return true;
-
}
-
//动态发布接口
-
private void publish(Class<?> clzMul, String serviceName) throws Exception {
-
serviceName = firstCharLower(serviceName);
-
Endpoint endpoint = Endpoint.create(clzMul.newInstance());
-
endpoint.publish(wsDomain + serviceName);
-
//redisUtil.set(serviceName, endpoint);
-
endpointMap.put(serviceName, endpoint);
-
}
结果:
可以正常发布SOAP接口,动态生成文件发布SOAP接口。
后面附件会上传动态生成需要的工具类,需要的小伙伴可以下载,记得好评!
author:贾小仙
time:2018/9/5
转载于:https://www.cnblogs.com/hackerxian/p/10871649.html
最后
以上就是背后项链为你收集整理的动态发布接口的全部内容,希望文章能够帮你解决动态发布接口所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复