首页 文章 精选 留言 我的

精选列表

搜索[绑定复杂度],共10004篇文章
优秀的个人博客,低调大师

为什么说开源是物联网开发消除厂商绑定的关键?

物联网(IoT)项目的开发可能是一个艰巨的任务。从原型的设计和代码的构建,到产品的最终发布和全球部署,如何确保您的IoT项目顺利实现和上市? 鉴于未来数年将有数十亿设备投放市场,封闭的专属系统会使不同设备间的互操作变得更困难。ProgrammableWeb主编David Berlind将持续演化的封闭IoT生态系统看作一种“连环事故”。让按照设计本无法配合使用的不同系统组件和元素协同工作,可能需要花费大量的时间和精力,延长部署所需时间并导致总成本飙升。开源技术是解决这种问题让不同设备相互通信的方法之一。 不同应用领域的IoT解决方案有很多共通之处:需要无线连接的能力,需要在设备和后端系统之间具备通信能力,需要收集和解析获得的数据,大量共通之处不一而足。但是随之而来的大量专有系统通常是“各自为政”的,这使得解决方案的开发和构建工作变得更为复杂,需要额外投入更多时间。专有系统还会让不同系统之间的开放式通信变得更复杂,并有可能妨碍到未来的创新和更广泛的运用。 面对这个快速演进,碎片化程度日趋严重的行业,这些挑战也变得越来越棘手,不过只要愿意配合使用,市面上依然有几个可用的解决方案。之所以说开源技术是IoT开发的关键,主要有下列几个原因: 用开放式协作和标准铺平道路 行业标准的建立和实施可以帮助我们实现更强的互操作性。通过合作制定的完善标准可提供更丰富的选择和更大灵活性:开发者可以针对具体需求,使用不同供应商的设备构建解决方案,进而在构建解决方案的过程中实现更大的创新,获得更大成本效益。 除了标准化开发,另一种互补的方法是将行业生态系统制定的设计和规范开放给开源社区,借此形成由所有人遵守的开源硬件和接口标准。这种方法日益受到欢迎,随着主要业内人士通过合作提供支持,开放的硬件参考设计和接口标准逐渐变得唾手可得。 例如越来越多的开发者开始通过Arduino、Raspberry Pi以及BeagleBone快速创建原型。但此类开放式硬件有一个问题,尽管可用于快速创建原型,但如果想将产品投放市场,还需要重新再来一遍,这可能是因为此类硬件产品的许可不允许用于最终产品,或者组件过于廉价不适合用于商用级别的产品。开放式硬件平台也在进化,其中一些已经可以同时用于原型和商用产品中。 开发者需要寻找对业务更为友好的开源许可,要找到以开源方式提供的工业级组件以及一系列工具,随后才能更快速地将有关IoT的创意从最初的原型变为可量产的大规模部署。实际上这一过程需要进行的大量集成、测试,以及验证工作已经预先完成了,就算需要扩展为全球化规模,开发者也不需要付出太多成本。 通过开放式硬件加速IoT开发 上述开放式平台可以让开发者借助有限的硬件、无线网络,或低层软件开发经验,在数天而非数月内完成应用程序的开发。若能妥善运用,开源平台和硬件之间的相互通信能力可确保各种连接器和传感器无需额外编写代码便可自动配合使用,这样便可以大幅缩短从构思和原型,再到最终量产过程所要付出的时间和精力。借助工业级的规范,此类下一代平台不仅可用于快速创建原型,而且可以快速实现IoT应用程序的工业化生产,因为原型可直接进入量产阶段。 配合使用多个供应商和多个平台,这样的能力为第三方合作关系和IoT初创企业提供了大量新机遇。这样的做法为新一代互联应用程序奠定了基础,使得开发者可以无需考虑所用设备直接开发IoT应用程序。 更完善的生态系统支持 开源解决方让项目在投资和周期方面更经得起考验,项目完成后多年时间内均可通过各种资源和工具不断对项目进行完善。这样的特性不仅可以保护解决方案开发阶段所付出的时间和投资,也可以通过简化的过程缩短从创新到最终上市所需的时间。 软件方面,如果使用能得到广泛支持的开源软件应用程序框架和开发环境,例如Linux,将能为开发工作提供极大的帮助。如果使用专有解决方案,只能从原始供应商处获得有关开发框架的支持,而这些供应商的规划可能无法与您的需求保持一致。开源解决方案可以通过更广泛的开发社区为您提供帮助,确保哪怕在多年后您依然能找到各种实用的开发资源。您在解决方案开发过程中投入的时间和成本也能获得更妥善的保护。 使用开源软件还能获得另一个优势。例如,为数众多的开发者确保软件代码可以经历更严格的审查,这样您的解决方案也能更安全。此外IoT应用程序开发者还可以根据具体安全需求对代码进行修改。 没人可以预见IoT技术适用的每个应用场景,但基于标准和开源技术的战略有助于促进IoT创新,让开发者能够以更快,更简单的方式将更长生命周期的应用程序投放到市场。标准保障了技术的互操作性,开源项目保障了软硬件组件在产品和服务平台演进之后依然可以实现复用。如果不这样做,IoT领域的创新将依然面临各种阻碍。 文章转载自 开源中国社区[http://www.oschina.net]

优秀的个人博客,低调大师

JFinal 表自动绑定插件实现,实现零配置,支持多数据源

以mysql数据库实现为例,其它的db也可基于这种方式自己实现 大概的思路是这样的,为了简少配置,所以不使用注解的方式 首先需要一个工具类来拿到所有的Model类大体的实现方式如下 package com.nmtx.utils; import java.io.File; import java.util.ArrayList; import java.util.List; import com.jfinal.kit.PathKit; import com.jfinal.kit.StrKit; public class ClassUtils { public static String classRootPath = null; public static List<Class<?>> scanPackage(String packageName) throws ClassNotFoundException { List<Class<?>> classList = new ArrayList<Class<?>>(); String path = getClassRootPath() + "/" + packageName.replace(".", "/"); List<String> fileNameList = getAllFileName(path); for (String fileName : fileNameList) { classList.add(Class.forName(fileName)); } return classList; } public static List<String> getAllFileName(String path) { List<String> fileNameList = new ArrayList<String>(); File rootFile = new File(path); if (rootFile.isFile()) { String fileName = rootFile.getPath().replace(PathKit.getRootClassPath(), "").replace(File.separator, ".") .replaceFirst(".", ""); String prefix = fileName.substring(fileName.lastIndexOf(".") + 1); if (prefix.equals("class")) { fileNameList.add(fileName.substring(0, fileName.lastIndexOf("."))); } } else { File[] files = rootFile.listFiles(); if (files != null) { for (File file : files) { fileNameList.addAll(getAllFileName(file.getPath())); } } } return fileNameList; } public static String getClassRootPath() { if (StrKit.isBlank(classRootPath)) classRootPath = PathKit.getRootClassPath(); return classRootPath; } public static void setClassRootPath(String classRootPath) { ClassUtils.classRootPath = classRootPath; } } 有了工具类,就去处理自动扫描插件,大概实现是这样的 package com.nmtx.plugins.db; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.jfinal.kit.StrKit; import com.jfinal.plugin.IPlugin; import com.jfinal.plugin.activerecord.ActiveRecordPlugin; import com.jfinal.plugin.activerecord.Model; import com.jfinal.plugin.c3p0.C3p0Plugin; import com.nmtx.plugins.db.impl.TableToModelByUnderline; import com.nmtx.utils.ClassUtils; public class AutoTabelPlugin implements IPlugin { private String db; private ActiveRecordPlugin arp; private String pacekageName; private String idKey; private ITableToModelFormat tableToModelFormate; private C3p0Plugin c3p0Plugin; public AutoTabelPlugin(C3p0Plugin erpC3p0, ActiveRecordPlugin arp, String db, String packageName, String idKey, ITableToModelFormat tableToModelFormate) { this.db = db; this.arp = arp; this.idKey = idKey; this.tableToModelFormate = tableToModelFormate; this.c3p0Plugin = erpC3p0; } public AutoTabelPlugin(C3p0Plugin erpC3p0, ActiveRecordPlugin arp, String db, String packageName, String idKey) { this.db = db; this.arp = arp; this.idKey = idKey; this.pacekageName = packageName; this.tableToModelFormate = new TableToModelByUnderline(); this.c3p0Plugin = erpC3p0; } @SuppressWarnings({ "unchecked" }) public List<Class<? extends Model<?>>> getModelClass() throws ClassNotFoundException { List<Class<?>> classes = ClassUtils.scanPackage(pacekageName); List<Class<? extends Model<?>>> modelClasses = new ArrayList<Class<? extends Model<?>>>(); for (Class<?> classer : classes) { modelClasses.add((Class<? extends Model<?>>) classer); } return modelClasses; } public boolean start() { try { HashMap<String, String> tableMap = getTableMap(); List<Class<? extends Model<?>>> modelClasses = getModelClass(); for (Class<? extends Model<?>> modelClass : modelClasses) { String tableName = tableMap.get(modelClass.getSimpleName()); if (tableName != null) { if (StrKit.notBlank(idKey)) { arp.addMapping(tableName, idKey, modelClass); } else { arp.addMapping(tableName, modelClass); } } } } catch (ClassNotFoundException e) { throw new RuntimeException("auto table mappming is exception" + e); } return true; } /** * 获取Model和表名的映射 * * @return */ private HashMap<String, String> getTableMap() { HashMap<String, String> map = new HashMap<String, String>(); Connection connection = null; PreparedStatement preStatement = null; ResultSet resultSet = null; try { c3p0Plugin.start(); connection = c3p0Plugin.getDataSource().getConnection(); preStatement = connection.prepareStatement( "select table_name as tableName from information_schema.tables where table_schema='" + db + "' and table_type='base table'"); resultSet = preStatement.executeQuery(); while (resultSet.next()) { String tableName = resultSet.getString(1); map.put(tableToModelFormate.getTableByModel(tableName), tableName); } } catch (Exception e) { closeConnection(connection, preStatement, resultSet); throw new RuntimeException("auto table mappming is exception" + e); } finally { closeConnection(connection, preStatement, resultSet); } return map; } private void closeConnection(Connection connection, PreparedStatement preStatement, ResultSet resultSet) { try { if (resultSet != null) { resultSet.close(); } if (preStatement != null) { preStatement.close(); } if (connection != null) { connection.close(); } } catch (SQLException e) { throw new RuntimeException("auto close db connection is exception" + e); } } public boolean stop() { return true; } } 因为java里的属性一般都是驼峰规则,代码看起来舒服一点,这里以数据库中以大写字母为例,表名为T_USER,对应Model名为User实现如下 接口定义 package com.nmtx.plugins.db; public interface ITableToModelFormat { public String generateTableNameToModelName(String tableName); } 实现如下 package com.nmtx.plugins.db.impl; import com.nmtx.plugins.db.ITableToModelFormat; public class TableToModelByUnderline implements ITableToModelFormat{ public String generateTableNameToModelName(String tableName) { StringBuilder modelName = new StringBuilder(); tableName = tableName.substring(2).toLowerCase(); String tableNames[] = tableName.split("_"); for(String tableNameTemp:tableNames){ modelName.append(fisrtStringToUpper(tableNameTemp)); } return modelName.toString(); } private String fisrtStringToUpper(String string){ return string.replaceFirst(string.substring(0, 1),string.substring(0, 1).toUpperCase()); } } 如果不同的格式可以实现不同的方法,根据自己的需求,这样就完成了自动扫描插件,使用起来也方便如下 C3p0Plugin spuC3p0= new C3p0Plugin(getProperty("jdbc.mysql.url"), getProperty("jdbc.mysql.username").trim(), getProperty("jdbc.mysql.password").trim(), getProperty("jdbc.mysql.driverClass")); spuC3p0.setMaxPoolSize(Integer.parseInt(getProperty("jdbc.mysql.maxPool"))); spuC3p0.setMinPoolSize(Integer.parseInt(getProperty("jdbc.mysql.minPool"))); spuC3p0.setInitialPoolSize(Integer.parseInt(getProperty("jdbc.mysql.initialPoolSize"))); ActiveRecordPlugin spuArp = new ActiveRecordPlugin(DbConfigName.SPU, spuC3p0); AutoTabelPlugin spuAutoTabelPlugin = new AutoTabelPlugin(spuC3p0, spuArp, getProperty("jdbc.mysql.spu.db"), "com.nmtx.manager.model", "ID"); me.add(spuAutoTabelPlugin); me.add(spuArp); 如果有多个就可以配置多个插件,而无需在管映射了,新增Model直接新增即可,不要再管映射

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册