我是靠谱客的博主 背后项链,最近开发中收集的这篇文章主要介绍动态发布接口,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

动态发布接口

    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,发布接口

 
  1.         //动态创建接口

  2.         @Override

  3. public Boolean createGenerate(String serviceName,Long interfaceId,String structrue) {

  4. try {

  5.         //首字母大写

  6. serviceName = StringUtils.firstCharUpper(serviceName);

  7. //目录路径

  8. Path directoryPath = Paths.get(outDirectory);

  9. // 如果目录不存在

  10. if (!Files.exists(directoryPath)) {

  11.     //创建目录

  12.     Files.createDirectories(directoryPath);

  13. }

  14. String controllerJava = serviceName + "Controller.java";

  15. String autoJavaFile = outDirectory + controllerJava;

  16. //文件路径

  17. Path filePath = Paths.get(autoJavaFile);

  18. if (!Files.exists(filePath)) {

  19.     //创建文件

  20.     Files.createFile(filePath);

  21. } else {

  22. logger.error("动态创建接口错误,文件已存在:"+autoJavaFile);

  23. return false;

  24. }

  25. // 读取模板文件流

  26. String javaFile = directory + "RestTemplateController.java";

  27. String content = FileUtils.readFile(javaFile);

  28. //替换文件

  29. content = replaceJava(content, serviceName, interfaceId,structrue);

  30. //写入文件

  31. Files.write(filePath, content.getBytes(charsetName));

  32. String fullName = packageName + serviceName + "Controller";

  33. //动态编译class

  34. JavaStringCompiler compiler = new JavaStringCompiler();

  35. Map<String, byte[]> results = compiler.compile(controllerJava, content);

  36. //加载class

  37. Class<?> clzMul = compiler.loadClass(fullName, results);

  38. //获取spring的applicationContext

  39. ApplicationContext applicationContext = SpringContextHelper.getApplicationContext();

  40. //注册接口到注册中心

  41. MappingRegulator.controlCenter(clzMul, applicationContext, create);

  42. } catch (Exception e) {

  43. logger.error("动态创建接口错误",e);

  44. return false;

  45. }

  46. return true;

  47. }

  48.  
  49. /**

  50. * controlCenter(运行时RequestMappingHandlerMapping中添加、删除、修改Mapping接口)    

  51. * @param   Class 希望加载的类Class    

  52. * @param  ApplicationContext spring上下文 

  53. * @param  type 1新增 2修改 3删除

  54.  * @throws Exception 

  55.  * @throws IllegalAccessException 

  56. * @Exception 异常对象    

  57. * @since  CodingExample Ver(编码范例查看) 1.1

  58. * @author jiaxiaoxian

  59.  */

  60. public static void controlCenter(Class<?> controllerClass,ApplicationContext  Context,Integer type) throws IllegalAccessException, Exception{

  61. //获取RequestMappingHandlerMapping 

  62. RequestMappingHandlerMapping requestMappingHandlerMapping=(RequestMappingHandlerMapping) Context.getBean("requestMappingHandlerMapping");

  63. Method getMappingForMethod =ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod",Method.class,Class.class);

  64. //设置私有属性为可见

  65. getMappingForMethod.setAccessible(true);

  66. //获取类中的方法

  67. Method[] method_arr = controllerClass.getMethods();

  68. for (Method method : method_arr) {

  69.         //判断方法上是否有注解RequestMapping

  70. if (method.getAnnotation(RequestMapping.class) != null) {

  71.         //获取到类的RequestMappingInfo 

  72. RequestMappingInfo mappingInfo = (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, method,controllerClass);

  73. if(type == 1){

  74.         //注册

  75. registerMapping(requestMappingHandlerMapping, mappingInfo, controllerClass, method);

  76. }else if(type == 2){

  77.         //取消注册

  78. unRegisterMapping(requestMappingHandlerMapping, mappingInfo);

  79. registerMapping(requestMappingHandlerMapping, mappingInfo, controllerClass, method);

  80. }else if(type == 3){

  81. unRegisterMapping(requestMappingHandlerMapping, mappingInfo);

  82. }

  83.  
  84. }

  85. }

  86. }

  87.  
  88. /**

  89.  * 

  90. * registerMapping(注册mapping到spring容器中)    

  91. * @param   requestMappingHandlerMapping    

  92. * @Exception 异常对象    

  93. * @since  CodingExample Ver(编码范例查看) 1.1

  94. * @author jiaxiaoxian

  95.  */

  96. public static void registerMapping(RequestMappingHandlerMapping requestMappingHandlerMapping,RequestMappingInfo mappingInfo, Class<?> controllerClass, Method method) throws Exception, IllegalAccessException{

  97. requestMappingHandlerMapping.registerMapping(mappingInfo, controllerClass.newInstance(),method);

  98. }

  99.  
  100. /**

  101.  * 

  102. * unRegisterMapping(spring容器中删除mapping)    

  103. * @param   requestMappingHandlerMapping    

  104. * @Exception 异常对象    

  105. * @since  CodingExample Ver(编码范例查看) 1.1

  106. * @author jiaxiaoxian

  107.  */

  108. public static void unRegisterMapping(RequestMappingHandlerMapping requestMappingHandlerMapping,RequestMappingInfo mappingInfo) throws Exception, IllegalAccessException{

  109. requestMappingHandlerMapping.unregisterMapping(mappingInfo);

  110. }

         

        结果:

            可以正常发布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发布接口

 
  1.         @Override

  2. public Boolean createGenerate(String serviceName, Long interfaceId, String structrue) {

  3.  
  4. try {

  5. serviceName = StringUtils.firstCharUpper(serviceName);

  6. Path directoryPath = Paths.get(outDirectory);

  7. // 如果文件不存在

  8. if (!Files.exists(directoryPath)) {

  9. Files.createDirectories(directoryPath);

  10. }

  11. String controllerJava = serviceName + "Controller.java";

  12. String autoJavaFile = outDirectory + controllerJava;

  13. Path filePath = Paths.get(autoJavaFile);

  14. if (!Files.exists(filePath)) {

  15. Files.createFile(filePath);

  16. } else {

  17. logger.error("动态创建接口错误ws,文件已存在:" + autoJavaFile);

  18. return false;

  19. }

  20.  
  21. String wsJavaFile = directory + "JwsTemplateController.java";

  22. String content = FileUtils.readFile(wsJavaFile);

  23. content = replaceJava(content, serviceName, interfaceId, structrue);

  24. Files.write(filePath, content.getBytes(charsetName));

  25. String fullName = packageName + serviceName + "Controller";

  26. JavaStringCompiler compiler = new JavaStringCompiler();

  27. Map<String, byte[]> results = compiler.compile(controllerJava, content);

  28. Class<?> clzMul = compiler.loadClass(fullName, results);

  29. publish(clzMul, serviceName);

  30. } catch (Exception e) {

  31. logger.error("动态创建接口错误ws", e);

  32. return false;

  33. }

  34. return true;

  35. }

  36. //动态发布接口

  37. private void publish(Class<?> clzMul, String serviceName) throws Exception {

  38. serviceName = firstCharLower(serviceName);

  39. Endpoint endpoint = Endpoint.create(clzMul.newInstance());

  40. endpoint.publish(wsDomain + serviceName);

  41. //redisUtil.set(serviceName, endpoint);

  42. endpointMap.put(serviceName, endpoint);

  43. }

        结果:

            可以正常发布SOAP接口,动态生成文件发布SOAP接口。

        后面附件会上传动态生成需要的工具类,需要的小伙伴可以下载,记得好评!

                                                 author:贾小仙

                                                 time:2018/9/5 

 

 

转载于:https://www.cnblogs.com/hackerxian/p/10871649.html

最后

以上就是背后项链为你收集整理的动态发布接口的全部内容,希望文章能够帮你解决动态发布接口所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部