千家信息网

动态发布接口

发表于:2025-02-06 作者:千家信息网编辑
千家信息网最后更新 2025年02月06日,动态发布接口HTTP接口分为REST和SOAP2种方式,文中都涉及到,包含从动态生成文件到编译class再到装载到spring容器和ws.Endpoint中。REST风格方案:1.提供java文件模板
千家信息网最后更新 2025年02月06日动态发布接口

动态发布接口

HTTP接口分为RESTSOAP2种方式,文中都涉及到,包含从动态生成文件到编译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 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 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


0