一、简单认识Aviator:

Aviator是一个高性能、轻量级的 java 语言实现的表达式求值引擎,它动态地将表达式编译成字节码并运行,主要用于各种表达式的动态求值。

Aviator的优点:

Aviator的设计目标是轻量级和高性能,相比于Groovy、JRuby的笨重,Aviator非常小。当然,Aviator的语法是受限的,它不是一门完整的语言,而只是语言的一小部分集合。

Aviator的实现思路与其他轻量级的求值器很不相同,其他求值器一般都是通过解释的方式运行,而Aviator则是直接将表达式编译成 JVM 字节码,交给 JVM 去执行。简单来说,Aviator的定位是介于 Groovy 这样的重量级脚本语言和 IKExpression 这样的轻量级表达式引擎之间。

Aviator的特性:

1.支持绝大多数运算操作符,包括算术操作符、关系运算符、逻辑操作符、位运算符、正则匹配操作符(=~)、三元表达式(?: )。

2.支持操作符优先级和括号强制设定优先级。

3.逻辑运算符支持短路运算。

4.支持丰富类型,例如nil、整数和浮点数、字符串、正则表达式、日期、变量等,支持自动类型转换。

5.内置一套强大的常用函数库。

6.可自定义函数,易于扩展。

7.可重载操作符。

8.支持大数运算(BigInteger)和高精度运算(BigDecimal)。

9.性能优秀。

二、Aviator的使用:

包依赖:

com.googlecode.aviatorgroupId>

aviatorartifactId>

3.3.0version>

dependency>

具体使用代码:

Aviator的使用都是集中通过com.googlecode.aviator.AviatorEvaluator这个入口类来处理。

1.常用方法:

// 输出的是6.8

System.out.println(AviatorEvaluator.execute("1 + 2.8 + 3"));

String name = "鹿骁俸";

Map env = Maps.newHashMap();

env.put("name", name);

// 输出的是你的名字是:鹿骁俸

System.out.println(AviatorEvaluator.execute("'你的名字是:' + name", env));

// Aviator 2.2 开始新增加一个exec方法, 可以更方便地传入变量并执行, 而不需要构造env这个map了

System.out.println(AviatorEvaluator.exec("'你的名字是:' + name", name));

env.put("a", 5);

env.put("b", 4);

// 输出的是6.333333333333333

System.out.println(AviatorEvaluator.execute("a + b / 3.0", env));

// 推荐的使用方式

System.out.println(AviatorEvaluator.compile("a + b / 3.0").execute(env));

2.字符串与转义符:

// 输出的是a"b

System.out.println(AviatorEvaluator.execute("'a\"b'"));

// 输出的是a'b

System.out.println(AviatorEvaluator.execute("\"a\'b\""));

// 输出的是hello 8

System.out.println(AviatorEvaluator.execute("'hello ' + 8"));

// 输出的是hello null

System.out.println(AviatorEvaluator.execute("'hello ' + unknow"));

3.函数调用及自定义函数:

@Test

public void test() {

// 输出的是5

System.out.println(AviatorEvaluator.execute("string.length('hello')"));

// 输出的是true

System.out.println(AviatorEvaluator.execute("string.contains(\"test\", string.substring('sword', 0, 1))"));

// 注册函数使用addFunction,移除函数使用removeFunction

AviatorEvaluator.addFunction(new AddFunction());

// 输出的是3.0

System.out.println(AviatorEvaluator.execute("add(1, 2)"));

// 输出的是103.0

System.out.println(AviatorEvaluator.execute("add(add(1, 2), 100)"));

}

class AddFunction extends AbstractFunction {

@Override

public AviatorObject call(Map env, AviatorObject arg1, AviatorObject arg2) {

Number left = FunctionUtils.getNumberValue(arg1, env);

Number right = FunctionUtils.getNumberValue(arg2, env);

return new AviatorDouble(left.doubleValue() + right.doubleValue());

}

public String getName() {

return "add";

}

}

4.编译表达式:

上面的例子大都是 Aviator 背后做了编译并执行的工作。其实可以先编译表达式,返回一个编译的结果,再传入不同的env来复用编译结果,提高性能,这是更推荐的使用方式。

String expression = "a - (b - c) > 100";

// 编译表达式

Expression compiledExp = AviatorEvaluator.compile(expression);

Map env = Maps.newHashMap();

env.put("a", 100.3);

env.put("b", 45);

env.put("c", 27.68);

// 执行表达式

Boolean result = (Boolean) compiledExp.execute(env);

// 输出的是false

System.out.println(result);

编译后的结果可以自己缓存,也可以交给 Aviator 做缓存。AviatorEvaluator内部有一个全局的缓存池,如果你决定缓存编译结果,可以通过:

public static Expression compile(final String expression, final boolean cached)

将cached设置为true即可。下次编译同一个表达式的时候将直接返回上一次编译的结果。

使缓存失效通过:

public static void invalidateCache(String expression)

5.数组和集合:

可以通过中括号去访问数组和java.util.List对象,可以通过map.key访问java.util.Map中key对应的value。

List list = Lists.newArrayList();

list.add("hello");

list.add(" world");

Map env = Maps.newHashMap();

env.put("list", list);

// hello world

System.out.println(AviatorEvaluator.execute("list[0] + list[1]", env));

int[] array = new int[3];

array[0] = 0;

array[1] = 1;

array[2] = 3;

env.put("array", array);

// array[0] + array[1] + array[2] = 4

System.out.println(AviatorEvaluator.execute("'array[0] + array[1] + array[2] = ' + (array[0] + array[1] + array[2])", env));

Map map = Maps.newHashMap();

map.put("date", new Date());

env.put("map", map);

// today is Sat Dec 22 12:59:15 CST 2018

System.out.println(AviatorEvaluator.execute("'today is ' + map.date", env));

ArrayList numList = Lists.newArrayList();

numList.add(3);

numList.add(20);

numList.add(10);

numList.add(1);

env.put("numList", numList);

// 4

System.out.println(AviatorEvaluator.execute("count(numList)", env));

// 34

System.out.println(AviatorEvaluator.execute("reduce(numList, + ,0)", env));

// [20, 10]

System.out.println(AviatorEvaluator.execute("filter(numList,seq.gt(9))", env));

// [10]

System.out.println(AviatorEvaluator.execute("filter(numList, seq.and(seq.ge(5), seq.lt(15)))", env));

// true

System.out.println(AviatorEvaluator.execute("include(numList,10)", env));

// [1, 3, 10, 20]

System.out.println(AviatorEvaluator.execute("sort(numList)", env));

// 遍历输出

AviatorEvaluator.execute("map(numList,println)", env);

●求长度:count(list)

●求和:reduce(list,+,0),reduce函数接收三个参数,第一个是seq,第二个是聚合的函数,如+等,第三个是聚合的初始值。

●过滤:filter(list,seq.gt(9)),过滤出list中所有大于9的元素并返回集合。seq.gt函数用于生成一个谓词,表示大于某个值。

●判断元素在不在集合里:include(list,10)

●排序:sort(list)

●遍历整个集合:map(list,println),map接受的第二个函数将作用于集合中的每个元素,这里简单地调用println打印每个元素。

6.三目运算符与正则表达式:

Aviator 不提供if else语句,但是提供了三目运算符?:用于条件判断。

// 输出的是yes

System.out.println(AviatorEvaluator.exec("a > 0 ? 'yes':'no'", 1));

Map env = Maps.newHashMap();

env.put("email", "killme2008@gmail.com");

String username = (String) AviatorEvaluator.execute("email=~/([\\w0-8]+)@\\w+[\\.\\w+]+/ ? $1 : 'unknow' ", env);

// 输出的是killme2008

System.out.println(username);

Aviator 的正则表达式规则跟 Java 完全一样,因为内部其实就是使用java.util.regex.Pattern做编译的。

7.nil 对象:

nil是 Aviator 内置的常量,类似 java 中的null,表示空的值。

nil跟null不同的在于,在 java 中null只能使用==、!=比较运算符,而nil还可以使用>、>=、     Aviator 规定,任何对象都比nil大除了nil本身。用户传入的变量如果为null,将自动以nil替代。

// 输出的是true

System.out.println(AviatorEvaluator.execute("nil == nil"));

// 输出的是true

System.out.println(AviatorEvaluator.execute("3 > nil"));

// 输出的是true

System.out.println(AviatorEvaluator.execute("true != nil"));

// 输出的是true

System.out.println(AviatorEvaluator.execute("'' > nil"));

// 输出的是true

System.out.println(AviatorEvaluator.execute("a == nil"));

8.日期比较:

Aviator 并不支持日期类型。如果要比较日期,需要将日期写字符串的形式,并且要求是形如“yyyy-MM-dd HH:mm:ss:SS”的字符串,否则都将报错。字符串跟java.util.Date比较的时候将自动转换为Date对象进行比较。

Map env = Maps.newHashMap();

final Date date = new Date();

String dateStr = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS").format(date);

env.put("date", date);

env.put("dateStr", dateStr);

// 输出的是true

System.out.println(AviatorEvaluator.execute("date == dateStr", env));

// 输出的是true

System.out.println(AviatorEvaluator.execute("date > '2010-01-01 00:00:00:00'", env));

// 输出的是false

System.out.println(AviatorEvaluator.execute("date > '2020-01-01 00:00:00:00'", env));

// 输出的是true

System.out.println(AviatorEvaluator.execute("date == date", env));

也就是说String除了能跟String比较之外,还能跟nil和java.util.Date对象比较。

9.大数计算:

从 2.3.0 版本开始,aviator 开始支持大数字计算和特定精度的计算,本质上就是支持java.math.BigInteger和java.math.BigDecimal两种类型,这两种类型在 aviator 中简称为big int和decimal类型。

对于字面量表示,big int和decimal的表示与其他数字不同,有以下三条规则:

●以大写字母N为后缀的整数都被认为是big int,如1N,2N,9999999999999999999999N等,都是big int类型。

●以大写字母M为后缀的数字都被认为是decimal,如1M,2.222M,100000.9999M等,都是decimal类型。

●超过long范围的整数字面量都将自动转换为big int类型。

// 输出的是199999999999999999999999999999998

System.out.println(AviatorEvaluator.exec("99999999999999999999999999999999 + 99999999999999999999999999999999"));

Object rt = AviatorEvaluator.exec("9223372036854775807100.356M * 2");

// 输出的是18446744073709551614200.712 class java.math.BigDecimal

System.out.println(rt + " " + rt.getClass());

rt = AviatorEvaluator.exec("92233720368547758074 + 1000");

// 输出的是92233720368547759074 class java.math.BigInteger

System.out.println(rt + " " + rt.getClass());

BigInteger a = new BigInteger(String.valueOf(Long.MAX_VALUE) + String.valueOf(Long.MAX_VALUE));

BigDecimal b = new BigDecimal("3.2");

BigDecimal c = new BigDecimal("9999.99999");

rt = AviatorEvaluator.exec("a + 10000000000000000000", a);

// 输出的是92233720368547758089223372036854775807 class java.math.BigInteger

System.out.println(rt + " " + rt.getClass());

rt = AviatorEvaluator.exec("b + c * 2", b, c);

// 输出的是20003.19998 class java.math.BigDecimal

System.out.println(rt + " " + rt.getClass());

rt = AviatorEvaluator.exec("a * b / c", a, b, c);

// 输出的是2.951479054745007313280155218459508E+34 class java.math.BigDecimal

System.out.println(rt + " " + rt.getClass());

类型转换和提升:

当big int或者decimal和其他类型的数字做运算的时候,按照long < big int < decimal < double的规则做提升,也就是说运算的数字如果类型不一致,结果的类型为两者之间更“高”的类型。例如:

●1 + 3N,结果为big int的4N

●1 + 3.1M,结果为decimal的4.1M

●1N + 3.1M,结果为decimal的 4.1M

●1.0 + 3N,结果为double的4.0

●1.0 + 3.1M,结果为double的4.1

decimal 的计算精度:

Java 的java.math.BigDecimal通过java.math.MathContext支持特定精度的计算,任何涉及到金额的计算都应该使用decimal类型。

默认 Aviator 的计算精度为MathContext.DECIMAL128,你可以自定义精度,通过:

AviatorEvaluator.setMathContext(MathContext.DECIMAL64);

即可设置,更多关于decimal的精度问题请看java.math.BigDecimal的 javadoc 文档。

10.变量的语法糖:

Aviator 有个方便用户使用变量的语法糖,当你要访问变量a中的某个属性b,那么你可以通过a.b访问到,更进一步,可以通过a.b.c访问变量a的b属性中的c属性值,推广开来也就是说 Aviator 可以将变量声明为嵌套访问的形式。

AviatorTest 类符合JavaBean规范,并且是 public 的,就可以使用语法糖:

@Data

public class AviatorTest {

int i;

float f;

Date date;

String aa = "jack";

@Test

public void test() {

AviatorTest foo = new AviatorTest();

foo.setI(100);

foo.setF(3.14f);

foo.setDate(new Date());

Map env = Maps.newHashMap();

env.put("foo", foo);

// foo.i = 100

System.out.println(AviatorEvaluator.execute("'foo.i = ' + foo.i", env));

// foo.f = 3.14

System.out.println(AviatorEvaluator.execute("'foo.f = ' + foo.f", env));

// foo.date.year = 2108

System.out.println(AviatorEvaluator.execute("'foo.date.year = ' + (foo.date.year + 1990)", env));

env.put("test", new AviatorTest());

// test.aa = jack

System.out.println(AviatorEvaluator.execute("'test.aa = ' + test.aa", env));

}

}

11.其他设置:

两种运行模式:

默认 AviatorEvaluator 以执行速度优先:

AviatorEvaluator.setOptimize(AviatorEvaluator.EVAL);

可以修改为编译速度优先,这样不会做编译优化:

AviatorEvaluator.setOptimize(AviatorEvaluator.COMPILE);

调试信息:

从 2.1.1.版本开始,Aviator允许设置输出每个表达式生成的字节码,只要设置trace为true即可:

AviatorEvaluator.setTrace(true);

方便用户做跟踪和调试。默认是输出到标准输出,也可以改变输出指向:

AviatorEvaluator.setTraceOutputStream(new FileOutputStream(new File("aviator.log")));

三、详细语法:

语法手册:

1.数据类型:

①Number类型:

数字类型,支持四种类型,分别是long,double,java.math.BigInteger(简称 big int)和java.math.BigDecimal(简称 decimal),规则如下:

◆任何以大写字母 N 结尾的整数都被认为是 big int

◆任何以大写字母 M 结尾的数字都被认为是 decimal

◆其他的任何整数都将被转换为 Long

◆其他任何浮点数都将被转换为 Double

◆超过 long 范围的整数字面量都将自动转换为 big int 类型

其中 big int 和 decimal 是 2.3.0 版本开始引入的。数字还支持十六进制(以0x或者0X开头的数字),以及科学计数法,如1e-3等。 不支持其他进制。

②String类型:

字符串类型,单引号或者双引号括起来的文本串,如’hello world’,变量如果传入的是String或者Character也将转为String类型。

③Bool类型:

常量true和false,表示真值和假值,与 java 的Boolean.TRUE和Boolean.False对应。

④Pattern类型:

正则表达式,以//括起来的字符串,如/\d+/,内部实现为java.util.Pattern。

⑤变量类型:

与 Java 的变量命名规则相同,变量的值由用户传入。

⑥nil类型:

常量nil,类似 java 中的null,但是nil比较特殊,nil不仅可以参与==、!=的比较,也可以参与>、>=、

2.操作符:

①算术运算符:

Aviator 支持常见的算术运算符,包括+,-,*,/,%五个二元运算符,和一元运算符-(负)。其中-,*,/,%和一元的-仅能作用于Number类型。

+不仅能用于Number类型,还可以用于String的相加,或者字符串与其他对象的相加。

Aviator 规定,任何类型与String相加,结果为String。

②逻辑运算符:

Avaitor 的支持的逻辑运算符包括,一元否定运算符!,以及逻辑与的&&,逻辑或的||。逻辑运算符的操作数只能为Boolean。

&&和||都执行短路规则。

③关系运算符:

Aviator 支持的关系运算符包括,>=以及==和!= 。

关系运算符可以作用于Number之间、String之间、Pattern之间、Boolean之间、变量之间以及其他类型与nil之间的关系比较,不同类型除了nil之外不能相互比较。

④位运算符:

Aviator 支持所有的 Java 位运算符,包括&,|,^,~,>>,<>>。

⑤匹配运算符:

匹配运算符=~用于String和Pattern的匹配,它的左操作数必须为String,右操作数必须为Pattern。匹配成功后,Pattern的分组将存于变量$num,num为分组索引。

⑥三目运算符:

Aviator 没有提供if else语句,但是提供了三元运算符?:,形式为bool ? exp1: exp2。其中bool必须为Boolean类型的表达式,而exp1和exp2可以为任何合法的 Aviator 表达式,并且不要求exp1和exp2返回的结果类型一致。

内置函数:

函数名称

说明

sysdate()

返回当前日期对象 java.util.Date

rand()

返回一个介于 0-1 的随机数,double 类型

rand(n)

返回一个介于 0- n 的随机数,long 类型

print([out],obj)

打印对象,如果指定 out,向 out 打印,否则输出到控制台

println([out],obj)

与 print 类似,但是在输出后换行

now()

返回 System.currentTimeMillis

long(v)

将值的类型转为 long

double(v)

将值的类型转为 double

boolean(v)

将值的类型转为 boolean,除了 nil 和 false,其他都值都将转为布尔值 true

str(v)

将值的类型转为 string

date_to_string(date,format)

将 Date 对象转化化特定格式的字符串,2.1.1 新增

string_to_date(source,format)

将特定格式的字符串转化为 Date 对象,2.1.1 新增

string.contains(s1,s2)

判断 s1 是否包含 s2,返回 Boolean

string.length(s)

求字符串长度,返回 Long

string.startsWith(s1,s2)

s1 是否以 s2 开始,返回 Boolean

string.endsWith(s1,s2)

s1 是否以 s2 结尾,返回 Boolean

string.substring(s,begin[,end])

截取字符串 s,从 begin 到 end,如果忽略 end 的话,将从 begin 到结尾,与 java.util.String.substring 一样

string.indexOf(s1,s2)

java 中的 s1.indexOf(s2),求 s2 在 s1 中 的起始索引位置,如果不存在为-1

string.split(target,regex,[limit])

Java 里的 String.split 方法一致,2.1.1 新增函数

string.join(seq,seperator)

将集合 seq 里的元素以 seperator 为间隔连接起来形成字符串,2.1.1 新增函数

string.replace_first(s,regex,replacement)

Java 里的 String.replaceFirst 方法,2.1.1 新增

string.replace_all(s,regex,replacement)

Java 里的 String.replaceAll 方法,2.1.1 新增

math.abs(d)

求 d 的绝对值

math.sqrt(d)

求 d 的平方根

math.pow(d1,d2)

求 d1 的 d2 次方

math.log(d)

求 d 的自然对数

math.log10(d)

求 d 以 10 为底的对数

math.sin(d)

正弦函数

math.cos(d)

余弦函数

math.tan(d)

正切函数

map(seq,fun)

将函数 fun 作用到集合 seq 每个元素上,返回新元素组成的集合

filter(seq,predicate)

将谓词 predicate 作用在集合的每个元素上,返回谓词为 true 的元素组成的集合

count(seq)

返回集合大小

include(seq,element)

判断 element 是否在集合 seq 中,返回 boolean 值

sort(seq)

排序集合,仅对数组和 List 有效,返回排序后的新集合

reduce(seq,fun,init)

fun 接收两个参数,第一个是集合元素,第二个是累积的函数,本函数用于将 fun 作用在集合每个元素和初始值上面,返回最终的 init 值

seq.every(seq, fun)

fun 接收集合的每个元素作为唯一参数,返回 true 或 false。当集合里的每个元素调用 fun 后都返回 true 的时候,整个调用结果为 true,否则为 false

seq.not_any(seq, fun)

fun 接收集合的每个元素作为唯一参数,返回 true 或 false。当集合里的每个元素调用 fun 后都返回 false 的时候,整个调用结果为 true,否则为 false

seq.some(seq, fun)

fun 接收集合的每个元素作为唯一参数,返回 true 或 false。当集合里的只要有一个元素调用 fun 后返回 true 的时候,整个调用结果立即为 true,否则为 false

seq.eq(value)

返回一个谓词,用来判断传入的参数是否跟 value 相等,用于 filter 函数,如filter(seq,seq.eq(3)) 过滤返回等于3 的元素组成的集合

seq.neq(value)

与 seq.eq 类似,返回判断不等于的谓词

seq.gt(value)

返回判断大于 value 的谓词

seq.ge(value)

返回判断大于等于 value 的谓词

seq.lt(value)

返回判断小于 value 的谓词

seq.le(value)

返回判断小于等于 value 的谓词

seq.nil()

返回判断是否为 nil 的谓词

seq.exists()

返回判断不为 nil 的谓词

seq.and(p1, p2, p3, …)

组合多个谓词函数,返回一个新的谓词函数,当今仅当 p1、p2、p3 …等所有函数都返回 true 的时候,新函数返回 true

seq.or(p1, p2, p3, …)

组合多个谓词函数,返回一个新的谓词函数,当 p1, p2, p3… 其中一个返回 true 的时候,新函数立即返回 true,否则返回 false

四、官方资料:

操作手册

API文档

java aviator使用类_Aviator学习笔记相关推荐

  1. Java文件压缩工具类ZipUtils学习笔记

    最近工作中用到了文件的压缩,经过在网上查询和自己的摸索总结如下工具了,支持文件压缩,嵌套文件压缩: package utils;import java.io.File; import java.io. ...

  2. Java程序猿的JavaScript学习笔记(10—— jQuery-在“类”层面扩展)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  3. Java程序猿的JavaScript学习笔记(12——jQuery-扩展选择器)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  4. 《Java并发编程实践》学习笔记之一:基础知识

    <Java并发编程实践>学习笔记之一:基础知识 1.程序与进程 1.1 程序与进程的概念 (1)程序:一组有序的静态指令,是一种静态概念:  (2)进程:是一种活动,它是由一个动作序列组成 ...

  5. Java程序猿的JavaScript学习笔记(汇总文件夹)

    最终完结了,历时半个月. 内容包含: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源代码级解析. jQuery EasyUI源代码级解析. Java程序猿的J ...

  6. 拉勾网《32个Java面试必考点》学习笔记之一------Java职业发展路径

    本文为拉勾网<32个Java面试必考点>学习笔记.只是对视频内容进行简单整理,详细内容还请自行观看视频<32个Java面试必考点>.若本文侵犯了相关所有者的权益,请联系:txz ...

  7. Java开发面试高频考点学习笔记(每日更新)

    Java开发面试高频考点学习笔记(每日更新) 1.深拷贝和浅拷贝 2.接口和抽象类的区别 3.java的内存是怎么分配的 4.java中的泛型是什么?类型擦除是什么? 5.Java中的反射是什么 6. ...

  8. 杨晓峰-java核心技术36讲(学习笔记)- 第1讲 | 谈谈你对Java平台的理解?

    杨晓峰-java核心技术36讲(学习笔记) 接下来我会分享杨晓峰-java核心技术36讲的学习笔记,内容较多,补充了其中一些牛人评论,相对详细(仅供个人学习记录整理,希望大家支持正版:https:// ...

  9. Java虚拟机(JVM)学习笔记(不定时更新)

    Java虚拟机(JVM)学习笔记 不少组织都曾开发过Java虚拟机: SUN公司曾经使用过3个虚拟机,Classic.Exact VM.Hotspot.     其中Hotspot虚拟机沿用至今,并已 ...

最新文章

  1. C#语言与面向对象技术(1)
  2. 事务连接中断_HTTP长连接和短连接
  3. 如何自动导出内存映像文件?
  4. java中使用QBC的好处_使用QBC的方式应用多对多关系中的查询
  5. AIR访问操作系统剪贴板粘贴操作延迟呈现解决办法
  6. 品优购-01分布式框架-Dubbox
  7. 网联兴,银联苦:一文看清支付清算市场新局面的矛盾和疑惑
  8. 踩坑:文件路径过长问题(超过260字符)
  9. mysql 部分汉字乱码_一次mysql部分汉字乱码解决过程
  10. VPX-M1 3U VPX 刀片计算机产品
  11. ajax java首字母检索_AJAX的拼音首字母查找对应中文的portlet
  12. SQL Server 使用DATEADD()函数实现秒、分钟、小时、日、周、月份、季度、年份加减
  13. iOS crash报告问题
  14. 中国第一代程序员列传 我的偶像
  15. PPT实例虚化图片突出主题的封面页效果
  16. 水浒二十八回--施恩重霸孟州道 武松醉打蒋门神
  17. 实验室风淋系统洁净风淋室
  18. 阿德勒《被讨厌的勇气》
  19. 浏览器如何解析HTML字符编码
  20. 用Matlab对图像进行ROI的标记与保存

热门文章

  1. 计算机网络 第一章计算机网络体系结构
  2. 故障分析 | show processlist 引起的性能问题
  3. python plot参数,python plot函数参数
  4. 数字通信系统简易信道编码仿真与性能分析
  5. 一个舞台剧的小剧本, 希望能博得大家的一笑
  6. 给hmailserver添加DKIM签名
  7. bfs( L2-016 愿天下有情人都是失散多年的兄妹 (25 分))
  8. 2006河北高考五分一档统计表
  9. php生成zip压缩包、thinkphp压缩和打包下载实例
  10. 驱逐舰:U型艇猎手 – Destroyer: The U-Boat Hunter V0.9.28最新官方中文学习版【6.4G】