首页 文章 精选 留言 我的

精选列表

搜索[持续测试],共10000篇文章
优秀的个人博客,低调大师

D语言 / DLang 2.089.0 发布,持续改进健壮性

D 语言 2.089.0 版本进行了 11 核心改进以及 66 问题修复, 非常感谢 44 位贡献者,他们使 2.089.0 成为可能。 本次版本主要是一个大的改进修正版,提供了经过修正的 extern(C) mixin 模板中的 mangling,改进运行时模块 core.atomic 中的 atomicFetchAdd、atomicFetchSub 方法, 支持链接驱动参数, 在包管理器 dub 中改进对 LDC 编译器的支持, 以及更多细节问题修复和语言层面的改进。 核心编译器功能主要改进 Deprecate allowing shadowing in foreach loops IsExpressions now correctly match combinations of const, inout, and shared. extern(C) declarations in template mixins now mangle as C symbols when mixed in at global scope The default linker for the Digital Mars tool chain is now optlink.exe New -Xcc compiler flag to address issue 6952 Runtime 运行时主要改进 Added core.atomic.atomicFetchAdd and core.atomic.atomicFetchSub. Make wstatus predicates pure and @safe 标准库主要改进 Added std.traits.Unconst Dub 包管理器改进 Improved support for LDC, incl. cross-compilation Lint command added Added SemVer compatibility operator "^" 完整的更新资料请查看本次版本的 Changelogs。

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

借助URLOS快速安装jenkins-持续集成工具

环境需求 最低硬件配置:1核CPU,1G内存(1+1)提示:如果你的应用较多,而主机节点的硬件配置较低,建议在部署节点时开通虚拟虚拟内存; 生产环境建议使用2G或以上内存; 推荐安装系统:Ubuntu-16.04、Ubuntu-18.04、CentOS7.X、Debian9X的64位的纯净的操作系统; URLOS安装 curl -LO www.urlos.com/iu && sh iu Jenkins安装流程 1.在应用市场中搜索“jenkins”并安装,如下图: 2.填写服务名称、选择运行节点、服务端口、选择智能部署 然后点击“提交”按钮,等待部署完成; 3. jenkins初始化向导 访问http://IP:8080(其中的IP是你的服务器的IP) 这里需要填写初始密码,创建服务完成后,可在当前服务的文件管理中找到密码文件,路径为jenkins_home/secrets/initialAdminPassword 找到密码,将密码填入后继续步骤: 选择安装社区流行的插件还是自定义安装插件 我们选择自定义安装插件: 可以看到已经默认选择了一些插件,我们可以选择自己需要的来安装。 选择“install”进行下一步: 创建管理员账户: 登录后: jenkins的详细使用方法请查考官方文档: https://jenkins.io/zh/doc/

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

移动APP持续交付系列之云构建价值分析

现状企业A:小APP,Android、iOS研发各三人;大APP,Android、iOS研发各10人。CICD通过部署一台jenkins服务器 + 一台Android 构建机器来完成Android的APP构建,iOS构建完全依赖开发本地环境。企业B:3个APP5个研发同学,5台服务器年成本一万左右 ,代码规范比较差导致质量不好企业C:十几个研发,五六台服务器。 寻求一站式交付平台可以看出:在企业内部为了支持APP构建需求一般会部署一台jenkins用作构建任务管理,一台以上的linux服务器用于Android APP构建,视实际使用情况量级较小的iOS APP一般在本地完成构建,量级较大的APP会有单独的构建机器。成本中小企业在APP构建部分的成本主要包括三个部分: 机器成本用途 数量配置价格(元/年)jenkins服务器 14

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

Mybatis3.x 遇到的问题整合[持续更新]

在映射文件中写了这样的一条sql <select id="selectUserById" parameter="int" resultType="User"> select * from user <if test="id != 0"> id = #{id} </if> </select> 这条sql运行后会抛出一个There is no getter for property named "id" in "class java.lang.Integer"这样的错误 原因: mybatis默认使用ongl解析参数,在这里就变成了使用 "java.lang.Integer.id"进行取值,而这里的id是User类所以就抛出了异常 解决方案: 1.将#{id}替换为#{_paramter} <select id="selectUserById" parameter="int" resultType="User"> select * from user <if test="id != 0"> id = #{_parameter} </if> </select> 在方法中提前声明 public void methodName(@Param(value ="id") int id,@Param(value="username") String username); 将parameterType="int"转为parameterType="User" 将id的取值顺序重新转到User.id中即可

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

【Spark】Spark SQL, DataFrames and Datasets Guide(翻译文,持续更新)

本文主要是翻译Spark官网SparkSQL programming guide 。只能保证大概意思,尽量保证细节。英文水平有限,如果有错误的地方请指正,轻喷。目录导航在右上角 Spark SQL、DataFrames 和 Datasets 指南 概述 Spark SQL 是一个结构化数据处理的 Spark 模块 。 与基础的 Spark RDD API 不同的是, Spark SQL 所提供的接口为 Spark 提供了 更多关于数据结构和正在执行的计算结构的信息。 Spark 在其内部利用这些额外的信息去做更多的优化。有几种用于和 Sparrk SQL交互的方法,包括 SQL 和 Dataset API。 当你计算一个结果, 会使用同一个执行引擎, 这独立于你所用来描述这个算法的API和语言。这种一致性意味着开发者可以轻易地在不同的 API 中来回切换, 因为它为表达给定的转换提供了最自然的方式。 本页所有示例使用了 Spark 提供的样例数据并且可以在 spark-shell 、pyspark shell 或者 sparkR shell 中运行。 SQL Spark SQL 的一个用处是执行 SQL 查询。 Spark SQL 同样可以用来从 现有的 HIVE 中读取数据。 更多有关配置这个特性的信息,请查阅 HIVE Tables 部分。当你使用其他语言执行SQL时,将会返回一个 Dataset 或者 DataFrame 作为结果。你同样可以使用命令行或者 JDBC/ODBC 与 SQL 接口进行交互。 Dataset 和 Dataframe Dataset 是一种分布式数据集,是 Spark1.6 新增的接口。它提供了RDD(强类型,可以使用强大的 lambda 表达式)的优点,并受益于Spark SQL 的优化执行引擎。Dataset 可以通过 JVM 构建,然后使用转换方法(map, flatMap, filter等等)进行操作。 Dataset API在 Java 和 Scala 中可用。 Python 并不支持Dataset API。但是由于Python的动态特性, Dataset API 的很多优势都是可用的(比如你可以自然地使用名称 row.columnName 来访问 row 的域 )。 R 语言的情况类似。 DataFrame 是一种按列命名组织的 Dataset, 它在概念上等价于关系型数据库的一个表或者 R/Python 的一个数据帧, 但是它(DataFrame)的底层做了更多的优化。DataFrame 可以通过大量的数据源构建,例如:结构化的数据文件, HIVE 的表, 数据库,或现有的RDD。Java、Python、Scala、R语言都支持 DataFrame API。 在 Scala 和 Java, DataFrame 由Dataset的 rowS 表示。 在 Scala API 中,DataFrame 可以简单地认为是 Dataset[Row] 的别名。 然而,在 Java API 中, 用户需要使用 Dataset<Row> 来表示 DataFrame。 在整个文档中, 我们通常把 Scala/Java Dataset 的 RowS 称为 DataFrames。 准备开始 起点: SparkSession Spark 所有功能的入口是 SparkSession 类。创建最基本的 SaprkSession, 只需要调用 SparkSession.builder(): scala版 import org.apache.spark.sql.SparkSession val spark = SparkSession .builder() .appName("Spark SQL basic example") .config("spark.some.config.option", "some-value") .getOrCreate() // For implicit conversions like converting RDDs to DataFrames import spark.implicits. 在 Spark 仓库 “examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala” 中可以找到完整的示例代码。 java版 import org.apache.spark.sql.SparkSession; SparkSession spark = SparkSession .builder() .appName("Java Spark SQL basic example") .config("spark.some.config.option", "some-value") .getOrCreate(); 在 Spark 仓库 “examples/src/main/java/org/apache/spark/examples/sql/JavaSparkSQLExample.java” 中可以找到完整的示例代码。 Python版 from pyspark.sql import SparkSession spark = SparkSession \ .builder \ .appName("Python Spark SQL basic example") \ .config("spark.some.config.option", "some-value") \ .getOrCreate() 在 Spark 仓库 “examples/src/main/python/sql/basic.py” 中可以找到完整的示例代码。 R语言 sparkR.session(appName = "R Spark SQL basic example", sparkConfig = list(spark.some.config.option = "some-value")) 在 Spark 仓库 “examples/src/main/r/RSparkSQLExample.R” 中可以找到完整的示例代码 请注意,sparkR.session() 第一次被调用时,它会初始化一个全局的 SparkSession 单例对象,并且之后继续调用这个方法都将返回这个实例。 通过这种方式,用户只需要对 SparkSession 做一次初始化,然后 SparkR 的其他方法比如 read.df 将会隐式地访问这个全局地单例对象, 并且用户不需要传递 SparkSession 的实例。 Spark2.0 的 SparkSession 提供了对 HIVE 特性的内置支持, 包括使用 HiveQL 编写查询语句的能力,访问 Hive UDFs 和 从 Hive Table 中读取数据的能力。为了使用这些特性,您需要安装一个 HIVE。 创建 DataFrame 有了SparkSession, 应用程序可以通过本地的 R data.frame、Hive Table、 或者 Spark 数据源 来创建DataFrame。 作为示例,以下代码使用一个 JSON 文件的内容 创建一个 DataFrame Scala版 val df = spark.read.json("examples/src/main/resources/people.json") // Displays the content of the DataFrame to stdout df.show() // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala” 中可以找到完整的示例代码。 Java版 import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; Dataset<Row> df = spark.read().json("examples/src/main/resources/people.json"); // Displays the content of the DataFrame to stdout df.show(); // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/java/org/apache/spark/examples/sql/JavaSparkSQLExample.java” 中可以找到完整的示例代码。 Python版 # spark is an existing SparkSession df = spark.read.json("examples/src/main/resources/people.json") # Displays the content of the DataFrame to stdout df.show() # +----+-------+ # | age| name| # +----+-------+ # |null|Michael| # | 30| Andy| # | 19| Justin| # +----+-------+ 在 Spark 仓库 “examples/src/main/python/sql/basic.py” 中可以找到完整的示例代码。 R语言 df <- read.json("examples/src/main/resources/people.json") # Displays the content of the DataFrame head(df) ## age name ## 1 NA Michael ## 2 30 Andy ## 3 19 Justin # Another method to print the first few rows and optionally truncate the printing of long values showDF(df) ## +----+-------+ ## | age| name| ## +----+-------+ ## |null|Michael| ## | 30| Andy| ## | 19| Justin| ## +----+-------+ 在 Spark 仓库 “examples/src/main/r/RSparkSQLExample.R” 中可以找到完整的示例代码 弱类型的 Dataset 操作(aka DataFrame 操作) DataFrame 为 Scala、Java、Python、R语言提供了一种特定的结构化数据操作。 上面提到过,在 Spark2.0 中,DataFrame 对于 Scala 和 Java API 仅仅是 Dataset 的 RowS。这些操作也被称为 “弱类型转换”,这与 强类型的Scala/Java 中的 “强类型转换” 形成了鲜明的对比。 这里我们囊括了使用 Datasets 做结构化数据处理的基本示例: Scala版 // This import is needed to use the $-notation import spark.implicits._ // Print the schema in a tree format df.printSchema() // root // |-- age: long (nullable = true) // |-- name: string (nullable = true) // Select only the "name" column df.select("name").show() // +-------+ // | name| // +-------+ // |Michael| // | Andy| // | Justin| // +-------+ // Select everybody, but increment the age by 1 df.select($"name", $"age" + 1).show() // +-------+---------+ // | name|(age + 1)| // +-------+---------+ // |Michael| null| // | Andy| 31| // | Justin| 20| // +-------+---------+ // Select people older than 21 df.filter($"age" > 21).show() // +---+----+ // |age|name| // +---+----+ // | 30|Andy| // +---+----+ // Count people by age df.groupBy("age").count().show() // +----+-----+ // | age|count| // +----+-----+ // | 19| 1| // |null| 1| // | 30| 1| // +----+-----+ 在 Spark 仓库 “examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala” 中可以找到完整的示例代码。 java版 // col("...") is preferable to df.col("...") import static org.apache.spark.sql.functions.col; // Print the schema in a tree format df.printSchema(); // root // |-- age: long (nullable = true) // |-- name: string (nullable = true) // Select only the "name" column df.select("name").show(); // +-------+ // | name| // +-------+ // |Michael| // | Andy| // | Justin| // +-------+ // Select everybody, but increment the age by 1 df.select(col("name"), col("age").plus(1)).show(); // +-------+---------+ // | name|(age + 1)| // +-------+---------+ // |Michael| null| // | Andy| 31| // | Justin| 20| // +-------+---------+ // Select people older than 21 df.filter(col("age").gt(21)).show(); // +---+----+ // |age|name| // +---+----+ // | 30|Andy| // +---+----+ // Count people by age df.groupBy("age").count().show(); // +----+-----+ // | age|count| // +----+-----+ // | 19| 1| // |null| 1| // | 30| 1| // +----+-----+ 在 Spark 仓库 “examples/src/main/java/org/apache/spark/examples/sql/JavaSparkSQLExample.java” 中可以找到完整的示例代码。 Python版 对于Python来说,我们可以通过属性(df.age)或者通过索引(df['age']) 来访问 DataFrame 的列。 虽然前者用于交互式数据探索非常方便, 但使用者强烈建议使用后者,因为它具有前瞻性,并且不会因为 DataFrame 的列命和属性名重复产生冲突。 # spark, df are from the previous example # Print the schema in a tree format df.printSchema() # root # |-- age: long (nullable = true) # |-- name: string (nullable = true) # Select only the "name" column df.select("name").show() # +-------+ # | name| # +-------+ # |Michael| # | Andy| # | Justin| # +-------+ # Select everybody, but increment the age by 1 df.select(df['name'], df['age'] + 1).show() # +-------+---------+ # | name|(age + 1)| # +-------+---------+ # |Michael| null| # | Andy| 31| # | Justin| 20| # +-------+---------+ # Select people older than 21 df.filter(df['age'] > 21).show() # +---+----+ # |age|name| # +---+----+ # | 30|Andy| # +---+----+ # Count people by age df.groupBy("age").count().show() # +----+-----+ # | age|count| # +----+-----+ # | 19| 1| # |null| 1| # | 30| 1| # +----+-----+ 在 Spark 仓库 “examples/src/main/python/sql/basic.py” 中可以找到完整的示例代码。 R语言 # Create the DataFrame df <- read.json("examples/src/main/resources/people.json") # Show the content of the DataFrame head(df) ## age name ## 1 NA Michael ## 2 30 Andy ## 3 19 Justin # Print the schema in a tree format printSchema(df) ## root ## |-- age: long (nullable = true) ## |-- name: string (nullable = true) # Select only the "name" column head(select(df, "name")) ## name ## 1 Michael ## 2 Andy ## 3 Justin # Select everybody, but increment the age by 1 head(select(df, df$name, df$age + 1)) ## name (age + 1.0) ## 1 Michael NA ## 2 Andy 31 ## 3 Justin 20 # Select people older than 21 head(where(df, df$age > 21)) ## age name ## 1 30 Andy # Count people by age head(count(groupBy(df, "age"))) ## age count ## 1 19 1 ## 2 NA 1 ## 3 30 1 在 Spark 仓库 “examples/src/main/r/RSparkSQLExample.R” 中可以找到完整的示例代码 关于 DataFrame 可执行的操作的完整列表,请移步API Documentation。 除了简单的列引用和表示之外,DataFrame 同样有一个丰富的函数库,包括字符串操作、日期算法、常用数学操作 等等。 完整的列表可以在DataFrame Function Reference.中找到。 以编程方式执行 SQL 查询 Scala版 SparkSession 的 sql 功能使应用可以以编程的方式执行 SQL 查询并且返回一个 DataFrame // Register the DataFrame as a SQL temporary view df.createOrReplaceTempView("people") val sqlDF = spark.sql("SELECT * FROM people") sqlDF.show() // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala” 中可以找到完整的示例代码。 java版 SparkSession 的 sql 功能使应用可以以编程的方式执行 SQL 查询并且返回一个 DataSet<Row> import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; // Register the DataFrame as a SQL temporary view df.createOrReplaceTempView("people"); Dataset<Row> sqlDF = spark.sql("SELECT * FROM people"); sqlDF.show(); // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/java/org/apache/spark/examples/sql/JavaSparkSQLExample.java” 中可以找到完整的示例代码。 Python版 SparkSession 的 sql 功能使应用可以以编程的方式执行 SQL 查询并且返回一个 DataFrame # Register the DataFrame as a SQL temporary view df.createOrReplaceTempView("people") sqlDF = spark.sql("SELECT * FROM people") sqlDF.show() # +----+-------+ # | age| name| # +----+-------+ # |null|Michael| # | 30| Andy| # | 19| Justin| # +----+-------+ 在 Spark 仓库 “examples/src/main/python/sql/basic.py” 中可以找到完整的示例代码。 R语言 SparkSession 的 sql 功能使应用可以以编程的方式执行 SQL 查询并且返回一个SparkDataFrame df <- sql("SELECT * FROM table") 在 Spark 仓库 “examples/src/main/r/RSparkSQLExample.R” 中可以找到完整的示例代码 全局临时视图 Spark SQL 临时视图的作用域是 session 并且如果创建它(临时视图)的 session 终止,视图就会消失。如果你想使一个临时视图在 Spark 应用终止之前可以在所有 session 中共享, 那么你可以创建一个全局临时视图。全局临时视图是和系统保存的数据库global_temp 联系在一起的, 我们必须使用限定的名称来指代它,比如:SELECT * FROM global_temp.view1 Scala版 // Register the DataFrame as a global temporary view df.createGlobalTempView("people") // Global temporary view is tied to a system preserved database `global_temp` spark.sql("SELECT * FROM global_temp.people").show() // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ // Global temporary view is cross-session spark.newSession().sql("SELECT * FROM global_temp.people").show() // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala” 中可以找到完整的示例代码。 java版 // Register the DataFrame as a global temporary view df.createGlobalTempView("people"); // Global temporary view is tied to a system preserved database `global_temp` spark.sql("SELECT * FROM global_temp.people").show(); // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ // Global temporary view is cross-session spark.newSession().sql("SELECT * FROM global_temp.people").show(); // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/java/org/apache/spark/examples/sql/JavaSparkSQLExample.java” 中可以找到完整的示例代码。 Python版 # Register the DataFrame as a global temporary view df.createGlobalTempView("people") # Global temporary view is tied to a system preserved database `global_temp` spark.sql("SELECT * FROM global_temp.people").show() # +----+-------+ # | age| name| # +----+-------+ # |null|Michael| # | 30| Andy| # | 19| Justin| # +----+-------+ # Global temporary view is cross-session spark.newSession().sql("SELECT * FROM global_temp.people").show() # +----+-------+ # | age| name| # +----+-------+ # |null|Michael| # | 30| Andy| # | 19| Justin| # +----+-------+ 在 Spark 仓库 “examples/src/main/python/sql/basic.py” 中可以找到完整的示例代码。 SQL CREATE GLOBAL TEMPORARY VIEW temp_view AS SELECT a + 1, b * 2 FROM tbl SELECT * FROM global_temp.temp_view 创建 Dataset Dataset 与 RDD 很像, 当然,它们使用专门的编码器, 而不是 java 序列化或 Kryo, 来序列化一个对象以便在网络上进行处理或者传输。 Scala版 case class Person(name: String, age: Long) // Encoders are created for case classes val caseClassDS = Seq(Person("Andy", 32)).toDS() caseClassDS.show() // +----+---+ // |name|age| // +----+---+ // |Andy| 32| // +----+---+ // Encoders for most common types are automatically provided by importing spark.implicits._ val primitiveDS = Seq(1, 2, 3).toDS() primitiveDS.map(_ + 1).collect() // Returns: Array(2, 3, 4) // DataFrames can be converted to a Dataset by providing a class. Mapping will be done by name val path = "examples/src/main/resources/people.json" val peopleDS = spark.read.json(path).as[Person] peopleDS.show() // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/scala/org/apache/spark/examples/sql/SparkSQLExample.scala” 中可以找到完整的示例代码。 java版 import java.util.Arrays; import java.util.Collections; import java.io.Serializable; import org.apache.spark.api.java.function.MapFunction; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.Encoder; import org.apache.spark.sql.Encoders; public static class Person implements Serializable { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // Create an instance of a Bean class Person person = new Person(); person.setName("Andy"); person.setAge(32); // Encoders are created for Java beans Encoder<Person> personEncoder = Encoders.bean(Person.class); Dataset<Person> javaBeanDS = spark.createDataset( Collections.singletonList(person), personEncoder ); javaBeanDS.show(); // +---+----+ // |age|name| // +---+----+ // | 32|Andy| // +---+----+ // Encoders for most common types are provided in class Encoders Encoder<Integer> integerEncoder = Encoders.INT(); Dataset<Integer> primitiveDS = spark.createDataset(Arrays.asList(1, 2, 3), integerEncoder); Dataset<Integer> transformedDS = primitiveDS.map( (MapFunction<Integer, Integer>) value -> value + 1, integerEncoder); transformedDS.collect(); // Returns [2, 3, 4] // DataFrames can be converted to a Dataset by providing a class. Mapping based on name String path = "examples/src/main/resources/people.json"; Dataset<Person> peopleDS = spark.read().json(path).as(personEncoder); peopleDS.show(); // +----+-------+ // | age| name| // +----+-------+ // |null|Michael| // | 30| Andy| // | 19| Justin| // +----+-------+ 在 Spark 仓库 “examples/src/main/java/org/apache/spark/examples/sql/JavaSparkSQLExample.java” 中可以找到完整的示例代码。 (2018-10-08)

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

比原链社区项目一览(持续更新)

钱包 后端服务节点:https://github.com/Bytom-Community/Bytom-Server Android前端:https://github.com/Bytom-Community/Bytom-Mobile-Wallet-Android iOS前端:https://github.com/Bytom-Community/Bytom-Mobile-Wallet-iOS 钱包前端SDK:https://github.com/Bytom-Community/Bytom-Mobile-Wallet-SDK SDK PHP SDK:https://github.com/lxlxw/bytom-php-sdk Java SDK:https://github.com/chainworld/java-bytom Java SDK:https://github.com/successli/Bytom-Java-SDK Python SDK:https://github.com/Bytom-Community/python-bytom Node SDK:https://github.com/Bytom/node-sdk 其他 UTXO合并工具:https://github.com/wincss/bytom-utils API工具:https://github.com/myeth/bytom-api-doc-util 文档类 Derek读比原:http://shanhuhai5739.github.io/ 剥开比原看源码系列:https://github.com/freewind/unwrap-bytom 比原UTXO管理:https://github.com/oysheng/bytom.doc 挖矿相关文档:https://github.com/bigbigbigfish/howtowriteaminerforbytom 各类文档:https://github.com/Bytom/wiki 浏览器 http://blockmeta.com/ http://www.btmscan.com/ https://tokenview.com/cn/analysis/btm 矿池 鱼池:https://labs.f2pool.com/labs 双U矿池:https://uupool.cn/btm/ BTCC矿池:https://btccpool.com/?lang=zh Pool矿池:https://pool.ren/ 蚂蚁矿池:https://antpool.com/ 蜘蛛矿池:https://pool.zhizhu.top/ 蜜蜂矿池:https://beepool.org/ viabtc矿池:https://pool.viabtc.com/ Mat矿池:http://matpool.io/ 第三方主网钱包 比特派:https://bitpie.com/ 币派:https://bepal.pro/ hyperpay:https://hyperpay.me/

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

《WCF技术剖析》博文系列汇总[持续更新中]

近半年以来,一直忙于我的第一本WCF专著《WCF技术剖析(卷1)》的写作,一直无暇管理自己的Blog。在《WCF技术剖析(卷1)》写作期间,对WCF又有了新的感悟,为此以书名开始本人的第三个WCF系列。本系列的目的在于对《WCF技术剖析》的补充,会对书中的一些内容进行展开讲述,同时会囊括很多由于篇幅的原因忍痛割弃的内容。 [第1篇] 通过一个ASP.NET程序模拟WCF基础架构 本系列的第一篇,我将会对WCF的基本架构作一个大致的讲解。不过,一改传统对WCF的工作流程进行平铺直叙,我将另辟蹊径,借助于我们熟悉的ASP.NET作为请求处理平台,通过一个简单的托管程序模拟整个WCF客户端和服务端的架构。源代码从这里下载。 [第2篇] 再谈IIS与ASP.NET管道 在2007年9月份,我曾经写了三篇详细介绍IIS架构和ASP.NET运行时管道的文章,深入介绍了IIS 5.x与IIS 6.0HTTP请求的监听与分发机制,以及ASP.NET运行时管道对HTTP请求的处理流程:《IIS和ASP.NET ISAPI》、《ASP.NET运行时管道[上篇][下篇]》很多人留言为何没有IIS 7的介绍。在写作《WCF技术剖析(卷1)》中,为了剖析基于IIS的WCF服务寄宿(Hosting),再次对相关内容进行了研究,在这里一并与大家分享。 [第3篇] 如何进行基于非HTTP的IIS服务寄宿 在介绍IIS7.0的时候,我们谈到,HTTP.SYS+W3SVC实现了基于HTTP的请求监听,在此基础上引入了以下三组网络监听器(Listener)和监听适配器(Adapter),实现了基于TCP、Named Pipes和MSMQ的网络监听。TCPListener|TCP Listener Adapter、NamedPipes Listener|Named Pipes Listener Adapter、MSMQ Listener|MSMQ Listener Adapter。由于IIS 7提供了基于非HTTP网络协议的监听支持,那么就意味着当我们当我们通过IIS进行WCF服务寄宿(Hosting)的时候,可以采用非HTTP的通信方式。在本篇文章中,我们将通过一个简单实例介绍进行非HTTP的IIS服务寄宿,源代码从这里下载。 [第4篇] 基于IIS的WCF服务寄宿(Hosting)实现揭秘 通过《再谈IIS与ASP.NET管道》的介绍,相信读者已经对IIS和ASP.NET的请求处理管道有了一个大致的了解,在此基础上去理解基于IIS服务寄宿的实现机制就显得相对容易了。概括地说,基于IIS的服务寄宿依赖于两个重要的对象:System.ServiceModel.Activation.HttpModule和System. ServiceModel.Activation.HttpHandler。 [第5篇] 利用ASP.NET兼容模式创建支持会话(Session)的WCF服务 在《基于IIS的WCF服务寄宿(Hosting)实现揭秘》中,我们谈到在采用基于IIS(或者说基于ASP.NET)的WCF服务寄宿中,具有两种截然不同的运行模式:ASP.NET并行(Side by Side)模式和ASP.NET兼容模式。对于前者,WCF通过HttpModule实现了服务的寄宿,而对于后者,WCF的服务寄宿通过一个 HttpHandler实现。只有在ASP.NET兼容模式下,我们熟悉的一些ASP.NET机制才能被我们使用,比如通过HttpContext的请求下下文;基于文件或者Url的授权;HttpModule扩展;身份模拟(Impersonation)等。 由于在ASP.NET兼容模式下,ASP.NET采用与.aspx Page完全一样的方式处理基于.svc的请求,换言之,我们就可以借助当前HttpContext的SessionState维护会话状态,进而创建一个支持会话的WCF Service。接下来,我们就通过一个简单的例子,一步步地创建这样的会话服务。 [第6篇] 为什么在基于ASP.NET应用寄宿(Hosting)下配置的BaseAddress无效 本篇文章来源于几天前一个朋友向我咨询的问题。问题是这样的,他说他采用ASP.NET应用程序的方式对定义的WCF服务进行寄宿(Hosting),并使用配置的方式对服务的BaseAddress进行了设置,但是在创建ServiceHost的时候却抛出 InvalidOperationException,并提示相应Address Scheme的BaseAddress找不到。我意识到这可能和WCF中用于判断服务寄宿方式的逻辑有关,于是我让这位朋友将相同的服务寄宿代码和配置迁移到GUI程序或者Console应用中,看看是否正常。结果如我所想,一切正常,个人觉得这应该是WCF的一个Bug。今天撰文与大家讨论,看看大家对这个问题有何见解。 [第7篇] 如何实现WCF与EnterLib PIAB、Unity之间的集成 在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅《MS Enterprise Library Policy Injection Application Block 深入解析[总结篇]》),也写过WCF与PIAB的集成(参阅:《WCF后续之旅(8):通过WCF Extension 实现与MS Enterprise Library Policy Injection Application Block 的集成》)、WCF与Unity的集成(参阅《WCF后续之旅(7):通过WCF Extension实现和Enterprise Library Unity Container的集成》)以及Unity与PIAB的集成(参阅《Enterprise Library深入解析与灵活应用(1):通过Unity Extension实现和Policy Injection Application Block的集成》、《Enterprise Library深入解析与灵活应用(7):再谈PIAB与Unity之间的集成》)。由于部分实现时基于EnterLib、Unity前一个版本,在新的版本中(EnterLib V4.1与Unity 1.2)中,MS通过Unity对PIAB进行了重新设计与实现,所以我们很有必要重拾着这个话题,谈谈对于新的EnterLib和Unity,如何将 PIAB和Unity集成到WCF之中。(Source Code从这里下载) [第8篇] ClientBase<T>中对ChannelFactory<T>的缓存机制 和传统的分布式远程调用一样,WCF的服务调用借助于服务代理(Service Proxy)。而ChannelFactory<T>则是服务代理的创建者。WCF采用基于终结点(Endpoint)服务消费方式:WCF 服务通过一个或者多个终结点暴露给潜在的服务消费者,服务的消费中通过与之匹配的终结点与之交互。在客户端,我们具有两种典型的服务代理创建方式,其一是通过诸如SvcUtil.exe这样的工具导入服务的元数据生成相应的服务代理(一个继承自ClientBase<T>的类型)代码和相关配置;其二是直接通过相应的终结点信息(通过代码指定或者配置)创建ChannelFactory<T>对象,并借助该对象直接进行服务代理的创建。 实际上,即使通过ClientBase<T>对象进行服务调用,其内部也是调用 ChannelFactory<T>创建的服务代理。整个ChannelFactory<T>的创建是一项相对复杂并且费时的工作,会涉及很多诸如反射、配置文件的读取等操作。为了提高服务调用的性能,在.NET 3.5中,WCF在ClientBase<T>中引入了ChannelFactory<T>的缓存机制。 [第9篇] 服务代理不能得到及时关闭会有什么后果? 我们想对WCF具有一定了解的人都会知道:在客户端通过服务调用进行服务调用过程中,服务代理应该及时关闭。但是如果服务的代理不等得到及时的关闭,到底具有怎样的后果?什么要关闭服务代理?在任何时候都需要关闭服务代理吗?是否有一些例外呢?本篇文章将会围绕着这些问题展开。 [第10篇] 调用WCF服务的客户端应该如何进行异常处理 在前面一片文章(服务代理不能得到及时关闭会有什么后果?)中,我们谈到及时关闭服务代理(Service Proxy)在一个高并发环境下的重要意义,并阐明了其根本原因。但是,是否直接调用ICommunicationObject的Close方法将服务代理关闭就万事大吉了呢?事情远不会这么简单,这其中还会涉及关于异常处理的一些操作,这就是本篇文章需要讨论的话题。 [第11篇] 异步操作在WCF中的应用[上篇][下篇] 按照操作执行所需的资源类型,我们可以将操作分为CPU绑定型(CPU Bound)操作和I/O绑定型(I/O Bound)操作。对于前者,操作的执行主要利用CPU进行密集的计算,而对于后者,大部分的操作处理时间花在I/O操作处理,比如访问数据库、文件系统、网络资源等。对于I/O绑定型操作,我们可以充分利用多线程的机制,让多个操作在自己的线程并发执行,从而提高系统性能和响应能力。服务调用就是典型的I/O绑定型操作,所以多线程在服务调用中具有广泛的应用。在本篇文章中,我们专门来讨论多线程或者是异步操作在WCF中的具体应用。 [第12篇] 数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) 大部分的系统都是以数据为中心的(Data Central),功能的实现表现在对相关数据的正确处理。而数据本身,是有效信息的载体,在不同的环境具有不同的表示。一个分布式的互联系统关注于数据的交换,而数据正常交换的根本前提是参与数据交换的双方对于数据结构的一致性理解。这就为数据的表现提出了要求,为了保证处于不同平台、不同厂商的应用能够正常地进行数据交换,交换的数据必须采用一种大家都能够理解的展现方式。在这方面,XML无疑是最好的选择。所以WCF下的序列化(Serialization)解决的就是如何将数据从对象的表现形式转变成XML表现形式,以确保数据的正常交换。 [第13篇] 序列化过程中的已知类型(Known Type) DataContractSerializer承载着所有数据契约对象的序列化和反序列化操作。在上面一篇文章(《数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)》)中,我们谈到DataContractSerializer基本的序列化规则;如何控制DataContractSerializer序列化或者反序列化对象的数量;以及如何在序列化后的XML中保存被序列化对象的对象引用结构。在这篇文章中,我们会详细讨论WCF序列化中一个重要的话题:已知类型(Known Type)。 WCF下的序列化与反序列化解决的是数据在两种状态之间的相互转化:托管类型对象和XML。由于类型定义了对象的数据结构,所以无论对于序列化还是反序列化,都必须事先确定对象的类型。如果被序列化对象或者被反序列化生成的对象包含不可知的类型,序列化或者反序列化将会失败。为了确保DataContractSerializer的正常序列化和反序列化,我们需要将“未知”类型加入 DataContractSerializer“已知”类型列表中。 [第14篇] 泛型数据契约和集合数据契约[上篇][下篇] 在.NET Framework 2.0中,泛型第一次被引入。我们可以定义泛型接口、泛型类型、泛型委托和泛型方法。序列化依赖于真实具体的类型,而泛型则刻意模糊了具体类型概念。而集合代表一组对象的组合,集合具有可迭代(Enumerable)的特性,可以通过某个迭代规则遍历集合中的每一个元素。由于范型类型和集合类型在序列化和反序列化上具有一些特殊的行为和规则,在这篇文章中,我将会对此进行详细介绍。 [第15篇] 数据契约代理(DataContractSurrogate)在序列化中的作用 如果一个类型,不一定是数据契约,和给定的数据契约具有很大的差异,而我们要将该类型的对象序列化成基于数据契约对应的XML。反之,对于一段给定的基于数据契约的XML,要通过反序列化生成该类型的对象,我们该如何实现这样的场景? [第16篇] 数据契约的等效性和版本控制 数据契约是对用于交换的数据结构的描述,是数据序列化和反序列化的依据。在一个WCF应用中,客户端和服务端必须通过等效的数据契约方能进行有效的数据交换。随着时间的推移,不可避免地,我们会面临着数据契约版本的变化,比如数据成员的添加和删除、成员名称或者命名空间的修正等,如何避免数据契约这种版本的变化对客户端现有程序造成影响,就是本节着重要讨论的问题。 [第17篇] 消息(Message)详解[上篇][中篇][下篇] 消息交换是WCF进行通信的唯一手段,通过方法调用(Method Call)形式体现的服务访问需要转化成具体的消息,并通过相应的编码(Encoding)才能通过传输通道发送到服务端;服务操作执行的结果也只能以消息的形式才能被正常地返回到客户端。所以,消息在整个WCF体系结构中处于一个核心的地位,WCF可以看成是一个消息处理的管道。 尽管消息在整个WCF体系中具有如此重要的意义,可是一般的WCF编程人员,却意识不到消息的存在。原因很简单,WCF设计的目标就是实现消息通信的所有细节,为最终的编程人员提供一个完全面向对象的编程模型。所以对于一般的编程人员来说,他们面对的是接口,却不知道服务契约对于服务的描述;面对的是数据类型,却不知道数据契约对序列化的作用;面对的是方法调用和返回值的获取,却不了解底层消息交换的过程。 鼓励大家深入了解WCF关于消息处理的流程具有两个目的:第一,只有在对整个消息处理流程具有清晰认识的基础上才能写出高质量的WCF程序。第二,WCF是一个极具可扩展性的通信框架,可以灵活地创建一些自定义WCF扩展(WCF Extension)以实现你所需要的功能。如同WCF的插件一样,这些自定义的WCF扩展以即插即用的方式参与到WCF整个消息处理流程之中。了解 WCF整个消息处理流程是灵活进行WCF扩展的前提。 [第18篇] 消息契约(Message Contract)和基于消息契约的序列化 在本篇文章中,我们将讨论WCF四大契约(服务契约、数据契约、消息契约和错误契约)之一的消息契约(Message Contract)。服务契约关注于对服务操作的描述,数据契约关注于对于数据结构和格式的描述,而消息契约关注的是类型成员与消息元素的匹配关系。 我们知道只有可序列化的对象才能通过服务调用在客户端和服务端之间进行传递。到目前为止,我们知道的可序列化类型有两种:一种是应用了System.SerializableAttribute特性或者实现了System.Runtime.Serialization.ISerializable接口的类型;另一种是数据契约对象。对于基于这两种类型的服务操作,客户端通过System.ServiceModel.Dispatcher.IClientMessageFormatter将输入参数格式化成请求消息,输入参数全部内容作为有效负载置于消息的主体中;同样地,服务操作的执行结果被System.ServiceModel.Dispatcher.IDispatchMessageFormatter序列化后作为回复消息的主体。 在一些情况下,具有这样的要求:当序列化一个对象并生成消息的时候,希望将部分数据成员作为SOAP的报头,部分作为消息的主体。比如说,我们有一个服务操作采用流的方式进行文件的上载,除了以流的方式传输以二进制表示的文件内容外,还需要传输一个额外的基于文件属性的信息,比如文件格式、文件大小等。一般的做法是将传输文件内容的流作为SOAP的主体,将其属性内容作为SOAP的报头进行传递。这样的功能,可以通过定义消息契约来实现。 [第19篇] 深度剖析消息编码(Encoding)实现[上篇][下篇] 消息作为WCF进行通信的唯一媒介,最终需要通过写入传输层进行传递。而对消息进行传输的一个前提或者是一项必不可少的工作是对消息进行相应的编码。WCF 提供了一系列可供选择的编码方式,它们分别在互操作和性能各具优势。在本篇文章我们将对各种编码方式进行消息的讨论。 从互操作性的角度来看,编码方法很大程度上决定了跨平台支持的能力。有的编码方式是平台无关的,有的则仅限于某种特定的平台。WCF提供了3种典型的编码方式:Binary、Text和MTOM。Binrary以二进制的方式进行消息的编码,但是仅限于.NET平台之间的通信;Text则提供平台无关的基于文本的编码方式。MTOM编码基于WS-MTOM规范,对于改善大规模二进制数据在SOAP消息的传输性能具有重大的意义,既然该编码方式遵循相应的规范,无疑这也是一种跨平台的编码方式。 [第20篇] 服务在WCF体系中是如何被描述的? 任何一个程序都需要运行于一个确定的进程中,进程是一个容器,其中包含程序实例运行所需的资源。同理,一个WCF服务的监听与执行同样需要通过一个进程来承载。我们将为WCF服务创建或指定一个进程的方式称为服务寄宿(Service Hosting)。服务寄宿的本质通过某种方式,创建或者指定一个进程用以监听服务的请求和执行服务操作,为服务提供一个运行环境。 服务寄宿的方式大体分两种:一种是为一组WCF服务创建一个托管的应用程序,通过手工启动程序的方式对服务进行寄宿,所有的托管的应用程序均可作为WCF服务的宿主,比如Console应用、Windows Forms应用和ASP.NET应用等,我们把这种方式的服务寄宿方式称为自我寄宿(Self Hosting)。另一种则是通过操作系统现有的进程激活方式为WCF服务提过宿主,Windows下的进程激活手段包括IIS、Windows Service或者WAS(Windows Process Activation Service)等。 服务寄宿的手段是为一个 WCF服务类型创建一个ServiceHost对象(或者任何继承于ServiceHostBase的对象)。无论采用哪种寄宿方式,在为某个服务创建 ServiceHost的过程中,WCF框架内部会执行一系列的操作,其中最重要的步骤就是为服务创建服务描述(Service Description)。在本篇文章中,我们将对服务描述进行全面的介绍。 [第21篇] WCF基本的异常处理模式[上篇][中篇][下篇] 由于WCF采用.NET托管语言(C#和NET)作为其主要的编程语言,注定以了基于WCF的编程方式不可能很复杂。同时,WCF设计的一个目的就是提供基于非业务逻辑的通信实现,为编程人员提供一套简单易用的应用编程接口(API)。WCF编程模式的简单性同样体现在异常处理上面,本篇文章的主要目的就是对WCF基于异常处理的编程模式做一个简单的介绍。 [第22篇] 深入剖析WCF底层异常处理框架实现原理[上篇][中篇][下篇] 对于上一篇文章 (WCF基本异常处理模式:[上篇]、[中篇]、[下篇]),主要是站在最终开发者的角度对WCF关于异常处理编程模式进行了介绍,接下来,我们需要将我们的目光转移到WCF框架内部,深入剖析整个WCF异常处理流程。 [第23篇] 服务实例(Service Instance)生命周期如何控制[上篇][中篇][下篇] 服务调用的目的体现在对某项服务功能的消费上,而功能的实现又定义在相应的服务类型中。不论WCF服务端框架处理服务调用请求的流程有多么复杂,最终都落实在服务实例的激活和操作方法的执行上面。WCF中的实例管理(Instance Management)旨在解决服务实例的激活和服务实例生命周期的控制。 会话(Session)的目的在于保持来自相同客户端(服务代理)多次服务调用之间的状态。从消息交换的角度来讲,会话通过消息识别机制判断调用某个服务的消息来源,从而将来自相同客户端的所有消息关联在一起。所以,会话实现了消息关联(Message Correlation)。 实例与会话是WCF非常重要的两个特性,它们既相对独立,又互相制约。实例模式与对会话支持程度的不同组合,会让最终的服务表现出截然不同的行为。对实例管理和会话的合理利用,对于改善和提高WCF服务应用的可扩展性(Scalability)、性能(Performance)、吞吐量(Throughput)等具有决定性作用。 [第24篇] ServiceDebugBehavior服务行为是如何实现异常的传播的? 服务端只有抛出FaultException异常才能被正常地序列化成Fault消息,并实现向客户端传播。对于一般的异常(比如执行Divide操作抛出的DivideByZeroException),在默认的情况下,异常信息无法实现向客户端传递。但是,倘若为某个服务应用了ServiceDebugBehavior这么一个服务行为,并开启了IncludeExceptionDetailInFaults开关,异常信息将会原封不动地传播到客户端。WCF内部是如何处理抛出的非FaultException异常的呢? [第25篇] 元数据(Metadata)架构体系全景展现[WS标准篇][数据描述篇] 在《WCF技术剖析(卷1)》中,我多次向读者强调WCF进行通信的本质:终结点是客户端和服务端进行通信的手段。服务的提供者通过一个或者多个终结点将服务发布出来;服务的消费者则通过创建于之匹配的终结点进行服务的调用。站在服务消费者的角度,这样一个“匹配”的终结点该如何创建呢?或者说客户端基于何种信息创建能够有效调用目标服务的终结点呢?这就是元数据需要解决的问题。 [第26篇] 如何导出WCF服务的元数据(Metadata)[实现篇][扩展篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框架体系中,元数据的导出工作由 MetadataExporter实现。MetadataExporter是一个抽象类型,定义了导出元数据的基本行为。WCF定义一个具体的 MetadataExporter:WsdlExporter,将基于某个终结点的元数据导出生成基于WSDL的MetadataSet。我们先来认识 MetadataExporter和MetadataSet。 WSDL的Binding元素来源于终结点的绑定对象,那么这些基于Binding的元数据以及相应的策略断言是如何被写入WSDL的呢?WSDL导出扩展(WSDL Export Extension)和策略导出扩展(Policy Export Extension)就是为此设计的。 [第27篇] 如何将一个服务发布成WSDL[编程篇][基于WS-MEX的实现][基于HTTP-GET的实现] 对于WCF服务端元数据架构体系来说,通过MetadataExporter将服务的终结点导出成MetadataSet,仅仅是完成了一半的工作。被成功导出的以MetadataSet对象表示的元数据需要最终作为可被访问的网络资源发布出来,才能被服务消费者获取,进而有效地帮助他们进行服务调用。元数据的发布最终是通过ServiceMetadataBehavior这样一个服务行为实现的。 可以通过编程或者配置的方式将ServiceMetadataBehavior这样一个服务形式应用到相应的服务上面,从而实现基于HTTP-GET或者WS-MEX的元数据发布机制。那么在WCF内部具体的实现原理又是怎样的呢?相信很多人对此都心存好奇,本篇文章为为你揭示其本质。 [第28篇] 自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过ServiceMetadataBehavior实现了基于WS-MEX和 HTTP-GET的元数据发布,针对这两种不同的协议,元数据获取的实现方式也是不同的,本片文章中通过自己的方式进行元数据获取,可以看成是对WCF客户端元数据框架的模拟。 [第29篇] 换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置;通过ChannelFactory创建服务代理对象。在这篇文章中,我们采用一种独特的方式进行服务的调用。 [第30篇] 一个很有用的WCF调用编程技巧[上篇][下篇] 在进行基于会话信道的WCF服务调用中,由于受到并发信道数量的限制,我们需要及时的关闭信道;当遇到某些异常,我们需要强行中止(Abort)信道。在真正的企业级开发中,正如我们一般不会让开发人员手工控制数据库连接的开启和关闭一样,我们一般也不会让开发人员手工去创建、开启、中止和关闭信道,这些工作是框架应该完成的操作。这篇文章,我们就来介绍如果通过一些编程技巧,让开发者能够无视“信道”的存在,像调用一个普通对象一样进行服务调用。 作者:蒋金楠 微信公众账号:大内老A 微博: www.weibo.com/artech 如果你想及时得到个人撰写文章以及著作的消息推送,或者想看看个人推荐的技术资料,可以扫描左边二维码(或者长按识别二维码)关注个人公众号(原来公众帐号 蒋金楠的自媒体将会停用)。 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 原文链接

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

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

WebStorm

WebStorm

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

用户登录
用户注册