{"id":13753554,"url":"https://github.com/jeffreyning/nh-micro","last_synced_at":"2025-10-26T17:31:05.075Z","repository":{"id":15148269,"uuid":"77651357","full_name":"jeffreyning/nh-micro","owner":"jeffreyning","description":"micro service and dynamic script","archived":false,"fork":false,"pushed_at":"2022-12-14T20:36:01.000Z","size":94523,"stargazers_count":55,"open_issues_count":2,"forks_count":25,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-07-04T18:15:51.817Z","etag":null,"topics":["antimvc","development-environment","groovy","java","microservice","user-management","workflow"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jeffreyning.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-30T01:42:19.000Z","updated_at":"2025-04-07T23:19:23.000Z","dependencies_parsed_at":"2023-01-13T20:30:10.294Z","dependency_job_id":null,"html_url":"https://github.com/jeffreyning/nh-micro","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jeffreyning/nh-micro","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyning%2Fnh-micro","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyning%2Fnh-micro/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyning%2Fnh-micro/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyning%2Fnh-micro/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jeffreyning","download_url":"https://codeload.github.com/jeffreyning/nh-micro/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jeffreyning%2Fnh-micro/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":281140933,"owners_count":26450543,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-26T02:00:06.575Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["antimvc","development-environment","groovy","java","microservice","user-management","workflow"],"created_at":"2024-08-03T09:01:24.477Z","updated_at":"2025-10-26T17:31:01.332Z","avatar_url":"https://github.com/jeffreyning.png","language":"Java","funding_links":[],"categories":["java","开发框架"],"sub_categories":["微服务框架"],"readme":"﻿# nh-micro\nmicro service and dynamic script\n\nMVC框架的缺点\n系统按照Controller、Service、Dao层次划分，虽然在建设初期技术结构清晰。但每个业务逻辑代码都分散到不同代码框，业务结构不直观，不利于后期业务重构。\n业务代码与MVC技术栈深度耦合，某层技术框架升级，导致整体服务不可复用。\n由于代码分散，支持版本化成本很高。\n\n\n\n脚本化微服务(NHMicro开源框架)实现MVC反模式\nController层改造\n\n使用微服务交互接口取代Controller，或者仍使用原有Controller技术栈，但调用NHMicro微服务提供的脚本调用Util。\nService层改造\n\nuService层功能代码脚本化，脚本化有利于快速调整调用流程，有利于版本化。\nDao层改造\n\n统一封装Dao（NHMicro开源框架已经提供Dao封装），基于Spring-jdbcTemplate封装统一Dao。\n\n\n\n脚本化微服务(NHMicro开源框架)-实现技术栈中的虚拟机\nNHMicro微服务架构中交互层和dao层不含有业务属性，需求变更时不需要修改微服务交互层代码和微服务Dao层代码。\n\n一个脚本实现一个业务功能，业务框架清晰。\n\n脚本内容修改后，设置新的名称，可以和旧脚本部署在同一个系统中，实现版本化。\n\n脚本可以被复制到另一个不同MVC栈的系统中，实现代码复用。\n\nNHMicro微服务架构是Java技术栈中的虚拟机，一次脚本编写到处复用。\n\n\nnh-micro框架开源代码和demo已经开源地址为\n\nhttps://github.com/jeffreyning/nh-micro\n\n\nmicro-rule-engine项目为脚本化核心引擎\n\n核心引擎基于groovy技术实现，支持groovy脚本热加载。\n\n服务业务逻辑均使用groovy实现脚本化。\n\n\n\nnh-micro-db项目为标准化dao层\n\n标准化dao层基于jdbctemplate封装，同时支持MySQL和Oracle，可以在框架外单独使用。\n\n忽略orm映射功能，内置根据id进行增删改查接口，强化参数类型兼容性。\n\n使开发人员不必关系查询条件参数或查询结果的数据类型。提高开发效率。\n\n\n\nnh-micro-template为nh-micro-db层工具化封装\n\n可以快速构建增删改查应用。目前支持mysql，后续支持oracle。\n\n自动过滤参数中有效字段。如果使用mysql5.7+版本，支持动态字段功能。\n\n可以在insert或update时自动创建不存在的字段。\n\n动态字段功能基于mysql的json字段实现，没有ddl操作，不受运维制约。\n\n封装sql模板功能，可以实现mybatis相同的功能。\n\n\n\nproject-demo项目为使用nh-micro框架的完整演示\n\n同时也是脚本微服务的默认的开发平台和默认运行容器。\n\nnh-micro框架可以与任何使用spring框架的技术栈兼容，\n\n因此project-demo项目并不是必须的运行环境和开发技术栈环境。\n\nproject-demo项目，内置的登录，用户管理，角色管理，部门管理，菜单管理，字典管理等基础功能。\n\n这些功能均使用groovy脚本实现，可以直接使用project-demo项目进行业务开发，也可以将nh-micro技术框架移植到开发人员自有项目中使用，使开发人员有更高的起点更关注业务实现，而不是重复进行基础功能实现。\n\n后续会添加封装好的业务功能groovy脚本，方便快速支撑业务。\n\n\n内置产品中心功能\n基于nhmicro框架封装了产品中心功能：包括产品信息增删改查、阶梯利率设置、本金利息服务费算法实现、还款计划试算。\n相关脚本有：\nMicro_product_center_list.groovy，现实产品列表和产品信息增删改查功能。\nProduct_algo_repayplan.groovy，实现还款计划试算功能。\nProduct_algo_fuwufei_yicixing.groovy,实现服务费（一次性服务费）计算功能。\nProduct_algo_lixi_xxhb.groovy,实现利息(先息后本)计算功能。\n产品中心需要表nh_micro_product_center_list\n\n内置合同模板管理功能\n可以将word模板转为pdf合同\n在合同模板列表中创建记录，上传word（2003版）合同模板文件，点击编译后就可以下载pdf了。\n在编写word文件是可以使用${somekey}作为占位符，下载pdf时输入json对占位符进行替换。\n\n内置贷款进件管理功能\n提交贷款进件、查看修改进件信息、上传附件、提交审批。\n\n内置信审审核管理功能\n\n内置互联网金融p2p理财功能和互联网页面\n\n内置动态热部署数据源配置功能\n内置动态热部署api服务功能\n内置分库分表查询合并分页功能\n内置分布式事务管理功能\n\nnhmicro微服务框架开发技术说明\n框架描述\n封装统一的dao层（micro-db），业务逻辑在groovy中实现。\ngroovy脚本放置在groovy路径下，启动时自动加载。修改时自动热部署提高调试效率。\n通过复用MicroMvcTemplate和MicroServiceTemplate，降低代码量提高开发效率。\n采用NhEsbServiceServlet作为controller的，调用MicroMvcTemplate子类groovy脚本。\n采用springmvc作为controller的，调用MicroServiceTemplate子类groovy脚本。\nJava调用groovy或groovy间调用，使用GroovyExecUtil.execGroovyRetObj(groovy文件名,方法名,…)\n\n1,\nMicroMvcTemplate封装方法有\na,分页查询 getInfoList4Page\nb,插入新记录 createInfo\nc,更新记录updateInfo\nd，删除记录delInfo\ne，根据id查询记录getInfoById\nf,不分页查询记录getInfoListAll\n\n2,\nMicroServiceTemplate封装方法有\na,分页查询getInfoList4PageService\nb,创建记录createInfoService\nc,更新记录updateInfoService\ne,删除记录delInfoService\nf，使用占位符拼装sql sqlTemplateService\n还有其他重载方法可直接根据sql进行增删改查，分页操作。\n\n3,通过MicroMvcTemplate和MicroServiceTemplate与数据库交互，输入输出map中的value都是string类型\n\n4、不使用封装好模板，直接执行查询sql的方法是，\nList infoList=(MicroMetaDao.getInstance()).queryObjJoinByCondition(sql);\n或调用？占位的sql\npublic List\u003cMap\u003cString, Object\u003e\u003e queryObjJoinByCondition(String sql,Object[] paramArray)\n\n直接写sql进行更新操作  int status=(MicroMetaDao.getInstance()).updateObjByCondition(sql)\n或调用？占位的sql\nupdateObjByCondition(sql,paramArray)\n\nMicroMetaDao()底层是jdbctemplate,有特别复杂的操作时可调用getMicroJdbcTemplate() 获取MicroMetaDao底层jdbctemplate\n\n5、根据物理uuid查一条记录的封装\n(microdb2.0以后版本支持表的id字段和bizid字段为数字)\n在service层可使用\npublic Map getInfoByIdService(Map requestParamMap,String tableName)\npublic Map getInfoByIdService(String id,String tableName)\n\n在dao层可使用queryObjJoinById\nMap retMap=(MicroMetaDao.getInstance()).queryObjJoinById(tableName, id);\n\n6、根据业务bizid查一条记录的封装\n在service层可使用\npublic Map getInfoByBizIdService(String bizId,String tableName,String bizCol)\n\n在dao层可以使用\nMap rowMap=(MicroMetaDao.getInstance()).queryObjJoinByBizId(\"cms_template_list\", bizid值,bizid在表中的列名称);\n\n7、使用groovy mvc和service模板时，传入的map参数和返回的结果map的value都是string类型的\n比如requestParamMap.put(\"update_time\",DateTimeUtil.getNowStrTime());\n日期字段，insert或update时，可以用\"now()\"小写的。如requestParamMap.put(\"update_time\",\"now()\");\n\n8、groovy中获取springbean或全局变量\n在groovy中调用获取springbean,  MicroContextHolder.getContext().getBean(\"xxxx springbeanid\");\n在groovy中获取配置的全局变量，MicroContextHolder.getContextMap().get(\"xxxx key\");\nMicroContextHolder需要在xml中配置，map中可以配置其他的全局变量\n\u003cbean class=\"com.minxin.micro.rule.engine.context.MicroContextHolder\" lazy-init=\"false\"\u003e\n\u003cproperty name=\"contextMap\"\u003e\n\u003cmap\u003e\n\n\u003c/map\u003e\n\u003c/property\u003e\n\u003c/bean\u003e \n\n9、关于事务配置\nmicrodb内部使用jdbctemplate，也使用spring事务进行配置\n如果controller层使用springmvc，建议在controller层配置事务\n如果使用NhEsbServiceServlet作为controller层如下配置在WsGroovyCmdHandler中开启事务\n        \u003c!--micro 声明式事物管理，配置事物管理advice--\u003e\n    \u003ctx:advice id=\"txAdviceMicro\" transaction-manager=\"txManager\"\u003e\n        \u003ctx:attributes\u003e\n            \u003ctx:method name=\"execHandler\" propagation=\"REQUIRED\"/\u003e\n        \u003c/tx:attributes\u003e\n    \u003c/tx:advice\u003e\n\n    \u003c!--micro 配置事物管理advice作用范围与作用条件--\u003e\n    \u003caop:config\u003e\n        \u003caop:pointcut id=\"serviceLayerTransactionMicro\" expression=\"execution( * com.project.frame.handler.*..*(..))\"/\u003e\n        \u003caop:advisor pointcut-ref=\"serviceLayerTransactionMicro\" advice-ref=\"txAdviceMicro\"/\u003e\n    \u003c/aop:config\u003e\n\n\n\n或使用MicroServiceTemplateSupport中的execGroovyRetObjByDbTran方法。\n\ngroovy中遇到需要局部使用特殊事务控制时，使用显示编程事务实现。\nTransactionTemplate transactionTemplate = (TransactionTemplate) MicroDbHolder.getDbSource(\"default_transaction\");\ntransactionTemplate.execute(new TransactionCallback() {\n\t@Override\n\tpublic Object doInTransaction(TransactionStatus status) {\n\t\txxxx\n\t}\n\n});\n\n10，支持like查询\n将key从requestParamMap删除，拼装自定义where条件，调用service模板的方法\npublic Map getInfoList4PageService(Map requestParamMap,String tableName,Map pageMap,String cusWhere)\n例如：\nMap requestParamMap=getRequestParamMap(httpRequest);\n\t\tString noticeNameValue=requestParamMap.get(\"dbcol_ext_notice_name\");\n\t\trequestParamMap.remove(\"dbcol_ext_notice_name\");\n\t\tString cusWhere=\"\";\n\t\tif(noticeNameValue!=null \u0026\u0026 !\"\".equals(noticeNameValue)){\n\t\t\tcusWhere=\"meta_content-\u003e\u003e'\\$.dbcol_ext_notice_name' like '%\"+noticeNameValue+\"%'\";\n\t\t}\n\t\tMap pageMap=new HashMap();\n\t\tpageMap.put(\"page\", page);\n\t\tpageMap.put(\"rows\", rows);\n\t\tpageMap.put(\"sort\", sort);\n\t\tpageMap.put(\"order\", order);\n\t\tMap retMap=GroovyExecUtil.execGroovyRetObj(\"MicroServiceTemplate\", \"getInfoList4PageService\",requestParamMap, tableName,pageMap,cusWhere);\n\n\n11、如果使用了NhEsbServiceServlet作为controller层，groovy中返回自定义httpResponse时，\n需要设置httpRequest.setAttribute(\"forwardFlag\", \"true\");否则可能追加多余字段返回。\n\t\tHttpServletResponse httpResponse = gContextParam.getContextMap().get(\"httpResponse\");\n\t\thttpResponse.getOutputStream().write(retStr.getBytes(\"UTF-8\"));\n\t\t\n\t\thttpRequest.setAttribute(\"forwardFlag\", \"true\");\n\n12、增改查时都可以输入部分自定义sql\n查询时（分页，不分页）\ntableName可输入join连接字符串连接多个表\ncusWhere可输入自定义的where条件sql串（可以和原功能叠加）\ncusSelect可输入自定义select字符串\npublic  Map getInfoList4PageService(Map requestParamMap,String tableName,Map pageMap,String cusWhere,String cusSelect) \npublic List getInfoListAllService(Map requestParamMap,String tableName,Map sortMap,String cusWhere,String cusSelect)\n例如getInfoList4PageService(Map requestParamMap,\"t_account a left join t_user u on a.user_code=u.user_code\",Map pageMap,String cusWhere,\"a.*,u.user_name\")\n\n\n插入时\ncusCol可输入自定义的列字符串（可以和原功能叠加）\ncusValue可输入自定义value字符串（可以和原功能叠加）\npublic Integer createInfoService(Map requestParamMap,String tableName,String cusCol,String cusValue) \n例如插入时记录数据库时间createInfoService(requestParamMap, tableName,\"create_time\",\"now()\") \n\n更新时\ncusCondition可输入自定义where条件sql串（可以和原功能叠加）\ncusSetStr可输入自定义set字符串（可以和原功能叠加）\npublic Integer updateInfoService(Map requestParamMap,String tableName,String cusCondition,String cusSetStr)\n例如更新时记录数据库时间updateInfoService(requestParamMap, tableName,cusCondition,\"update_time=now()\") \n\n\n13,MicroServiceTemplate中添加sqlTemplateService方法，用于做sql替换\n替换的语法是velocity\n判断是否为null #if(\\${param.p1})\n判断是否为\"\" #if(\\${param.p1}!='')\n判断不为null且不为\"\" #if(\\$!{param.p1}!='')\n例如以下的代码\n\t\tMap paramMap=new HashMap();\n\t\tparamMap.put(\"p1\", \"1\");\n\t\tparamMap.put(\"p2\", \"2\");\n\t\tparamMap.put(\"p3\", \"3\");\n\t\tparamMap.put(\"p4\", \"4\");\n\t\tparamMap.put(\"p5\", \"5\");\n\t\tString sql=\n\t\t\t\"select * from aaa where 1=1\"+\n\t\t\t\t\"#if(\\${param.p1})\"+\n\t\t\t\t\t\" and c1='\\${param.p2}'   \"+\n\t\t\t\t\"#end\"+\n\t\t\t\t\"#if(\\${param.p2})\"+\n\t\t\t\t\t\" and c2= #sqlreplace(\\${param.p2}) \"+\n\t\t\t\t\"#end\"+\n\t\t\t\t\"#if(\\${param.p3})\"+\n\t\t\t\t\t\" and c3 like '%\\${param.p3}%' \"+\n\t\t\t\t\"#end\"\n\t\t\t\t;\n\n\t\tList placeList=new ArrayList();\n\t\tString retStr=sqlTemplateService(sql,paramMap,placeList);\n\t\tSystem.out.println(retStr);\n\t\tSystem.out.println(placeList);\n\n返回如下的sql替换结果\nselect * from aaa where 1=1 and c1=1  true  and c2=? true and c3 like '%3%' true \n[2]\n\n14，MicroServiceTemplate中生成序列号\npublic Integer getSeqByMysql(String seqKey)\n\n\n15，MicroServiceTemplate中直接根据查询sql分页\n不必拼装count查询sql\npublic Map getInfoList4PageServiceByMySql(String sql,Map pageMap) \n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffreyning%2Fnh-micro","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjeffreyning%2Fnh-micro","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjeffreyning%2Fnh-micro/lists"}