HTTP Path 匹配和参数提取

0 条评论

给定一个 REST 的 Path 规则是: /orgs/<orgName>/apis/<apiName>/assets,其中尖括号包含的部分表示是一个可变的参数,参数一般情况下允许包含字母、数字、下划线。然后要求可以匹配符合规则的 HTTP URI Path 部分,并可以根据参数名称提取出参数的值来。

参考 bottle 项目的实现方案,将整个规则转换成一个正则表达式,然后利用 named group 特性,给定正则表达式捕获的分组名称来获取参数的值。

1. 把 /orgs/<orgName>/apis/<apiName>/assets 转换成 /orgs/(?:<orgName>[^/]+)/apis/(?:<apiName>[^/]+)/assets ,注意在 Java 7 后才支持这个正则表达式的写法,其中 (?:<orgName>[^/]+) 表示当前分组捕获结果可以用 orgName 来进行命名。为啥使用 named group 而不是直接按捕获分组顺序来查找,是因为情况再复杂一点的时候,正则表达式里的分组可能就很多很乱了,数也数不清顺序了。

2. 第一步转换成正则表达式的时候,同时把参数名称提取出来。

3. 正则表达式匹配,并根据参数名直接从正则表达式结果里获取参数

Java 代码样例:

  1. public static void main(String[] args) {
  2.     String rule = "/orgs/<orgName>/apis/<apiName>/assets";
  3.     String path = "/orgs/dev/apis/dts/assets";
  4.     Map params = match(rule, path);
  5.     System.out.println(params); // {apiName=dts, orgName=dev}
  6. }
  7. private static Map match(String rule, String path) {
  8.     StringBuilder pathRule = new StringBuilder();
  9.     List params = new ArrayList<>();
  10.     Pattern ruleSyntax = Pattern.compile("<(\\w*)>");
  11.     Matcher ruleMatcher = ruleSyntax.matcher(rule);
  12.     int offset = 0;
  13.     while (ruleMatcher.find()) {
  14.         int groupOffset = ruleMatcher.start();
  15.         pathRule.append(rule.substring(offset, groupOffset));
  16.         String groupName = ruleMatcher.group(1);
  17.         params.add(groupName);
  18.         // 拼接成 (?<name>[^/]+) 的正则表达式
  19.         pathRule.append("(?<").append(groupName).append(">[^/]+)");
  20.         offset = ruleMatcher.end();
  21.     }
  22.     if (offset < rule.length()) {
  23.         pathRule.append(rule.substring(offset, rule.length()));
  24.     }
  25.     Pattern pathPattern = Pattern.compile("^" + pathRule.toString() + "$");
  26.     Matcher pathMatcher = pathPattern.matcher(path);
  27.     Map result = new HashMap<>();
  28.     if (pathMatcher.matches()) {
  29.         for (String param : params) {
  30.             result.put(param, pathMatcher.group(param));
  31.         }
  32.     }
  33.     return result;
  34. }

Java 里 long 可以计数多久

0 条评论

long 作为 JVM 的 primitive 类型之一,是 64bit 长的有符号数字,它的大小范围是 -9223372036854775808 到 9223372036854775807 (-263 to 263- 1),而我们经常使 long (比如 AtomicLong 对象)用来计数,那么现在可以算算,在我们的使用场景下,long 可以使用多久就会达到最大值呢?

假如我们的使用场景中,每一秒使用计数器计数 10w 次,并且不间断保持计数,那么一天会计数 10w*60*60*24=8,640,000,000, 也就是约 86 亿次, 这个数字看起来很大了,我们用 long 的最大值来除以试试

9223372036854775807/8640000000=1067519911.6730064591435185185185

也就是大概可以不间断地计数 10.6 亿天,换算成年呢?

1067519911.6730064591435185185185/365=2924712.086775360162037037037037

也就是大概 292w 年,所以,如果计数器要求每天计数 86 亿次的情况下,long 可以支持我们的程序跑上几百万年,完全不用担心溢出的问题。

The Clay Matthews Retro Alternate Jersey Further My Love Among The Nfl

None

You can send your as Brown Trent jersey well colorado avalanche jersey authentic as family family showing some love graphics, thank Davis Mike jersey them for the comments, appreciate your sharing the add, tell them hello or goodnight. Doggie clothes are fun and make wonderful conversational pieces. Soccer jerseys are often noticed from a distance.

I hope you realize the awesome Havenstein Rob jersey responsibility you in order to be your players in cheap baseball jerseys. New stadium opens: Bidding farewell to Memorial Stadium, the Ravens entered brand-new age by opening beautiful PSINet Stadium on September 6th, 1996. Even though the Eagles in order to pass, the RB's and FB nonetheless vital towards the Eagles excellent. The 1992 Orange Bowl, on the opposite hand, was simply pathetic.

He is wilson kyle game jersey remembered ultimately field for his amazing ability to coat a large area and the fantastic great hit robbing wall climbs. After his 285 yards rushing against Fresno State, Gartrell is now in the nfl Carl Soderberg jersey Draft conversation. Usually, this clothing is ideal if its 2 sizes bigger than yours. Play thinking games- Have games already on personally? Many youth baseball coaches take their responsibilities and position lightly, also.

Probably detroit lions jersey authentic the most in mlb history. He also needs to play more assertively and get more of a leader. Andy Pettitte is tipping his hat and saying goodbye. And if you new orleans saints jersey wholesale like coffee-flavored milkshakes (some call them mochas), almost do that, too, though the regular coffee is alright.

Crabbe san francisco 49ers jersey currently plays with the Pensacola Blue Wahoos among the Double-A Southern League. Prior to Opening los angeles rams jersey Day I predicted that Philadelphia Phillies C bell vonn elite jersey Carlos Ruiz would have a breakout fall. semyon varlamov jersey wholesale Cycling socks are designed with aren't reasons specified. Oswalt hasn't thrown greater than six innings all season long, is very unlikely that he's going to pitch any deeper than that tonight, which suggests that a much maligned bullpen is probably going to be called bell joique jersey cheap upon for several innings do the job.

Touchdown Football Party
Who Is Your New Nfl Team

Best Time Purchase Football Shirts
De inhoud van de Koran begrijpelijk maken
Nfl Dog Clothes Tiny Dogs

并发编程 Promise, Future 和 Callback

1 条评论

在并发编程中,我们通常会用到一组非阻塞的模型:Promise,Future 和 Callback。其中的 Future 表示一个可能还没有实际完成的异步任务的结果,针对这个结果可以添加 Callback 以便在任务执行成功或失败后做出对应的操作,而 Promise 交由任务执行者,任务执行者通过 Promise 可以标记任务完成或者失败。 可以说这一套模型是很多异步非阻塞架构的基础。

这一套经典的模型在 Scala、C# 中得到了原生的支持,但 JDK 中暂时还只有无 Callback 的 Future 出现,当然也并非在 JAVA 界就没有发展了,比如 Guava 就提供了ListenableFuture 接口,而 Netty 4+ 更是提供了完整的 Promise、Future 和 Listener 机制,在 Netty 的官方文档 Using as a generic library 中也介绍了将 Netty 作为一个 lib 包依赖,并且使用 Listenable futures 的示例。在实际的项目使用中,发现 Netty 的 EventLoop 机制不一定适用其他场景,因此想去除对 EventLoop 的依赖,实现一个简化版本。

参考 Scala 和 Netty 的代码重新定义了接口和实现,先介绍下和 Netty 版本的区别:

  1. 去除了对 EventLoop 的依赖,Callback 的执行策略不同:任务未完成时添加的 Callback,会在结束任务的线程执行;任务完成后添加的 Callback 会在添加 Callback 线程立即执行
  2. 一个 Callback 执行后会立即被清理
  3. Callback 可以根据任务结果添加,支持添加以下三种 Callback: onComplete, onSuccess, onFailure, 不需要和 Netty 的 FutureListener 一样大部分场景下都需要检查 future.isSuccess 等
  4. 支持 Callback 的组合,Callback 包含一些函数式的方法,比如 compose 和 andThen 可以用来组合
  5. 使用 CountdownLatch 替换掉了 Netty 的 wait/notify 实现
  6. 去掉 Netty Future 一些不常使用的方法,同时补充一些模型间关联的方法,比如 Promise.getFuture

然后再介绍几个使用这个 commons-future 的示例:

  1. 异步执行任务,获得 Future 后添加 Callback
    1. final TaskPromise promise = new DefaultTaskPromise();
    2. final TaskFuture future = promise.getFuture();
    3. final CountDownLatch latch = new CountDownLatch(1);
    4. future.onComplete(new TaskCallback() { // 添加结束 Callback
    5.     @Override
    6.     public TaskFuture apply(TaskFuture f) {
    7.         latch.countDown();
    8.         return f;
    9.     }
    10. });
    11. new Thread(new Runnable() {
    12.     @Override
    13.     public void run() {
    14.         promise.setSuccess(null);
    15.     }
    16. }).start();
    17. latch.await();
  2. 异步执行任务,获得 Future 后添加成功结束的 Callback
    1. final TaskPromise promise = new DefaultTaskPromise();
    2. final TaskFuture future = promise.getFuture();
    3. final CountDownLatch latch = new CountDownLatch(1);
    4. future.onSuccess(new TaskCallback() { // 添加成功结束 Callback
    5.     @Override
    6.     public TaskFuture apply(TaskFuture f) {
    7.         latch.countDown();
    8.         return f;
    9.     }
    10. });
    11. new Thread(new Runnable() {
    12.     @Override
    13.     public void run() {
    14.         promise.setSuccess(null);
    15.     }
    16. }).start();
    17. latch.await();
  3. 异步执行任务,获得 Future 后,添加失败结束的组合 Callback
    1. final TaskPromise promise = new DefaultTaskPromise();
    2. final TaskFuture future = promise.getFuture();
    3. final CountDownLatch latch = new CountDownLatch(2);
    4. future.onFailure(new TaskCallback() {
    5.     @Override
    6.     public TaskFuture apply(TaskFuture f) {
    7.         latch.countDown();
    8.         return f;
    9.     }
    10. }.andThen(new TaskCallback() {
    11.     @Override
    12.     public TaskFuture apply(TaskFuture f2) {
    13.         latch.countDown();
    14.         return f2;
    15.     }
    16. }));
    17. new Thread(new Runnable() {
    18.     @Override
    19.     public void run() {
    20.         promise.setFailure(new IllegalStateException("cm"));
    21.     }
    22. }).start();
    23. latch.await();
  4. 异步执行任务,获得 Future 后阻塞等待任务完成
    1. final TaskPromise promise = new DefaultTaskPromise();
    2. final TaskFuture future = promise.getFuture();
    3. new Thread(new Runnable() {
    4.     @Override
    5.     public void run() {
    6.         try {
    7.             TimeUnit.SECONDS.sleep(2);
    8.         } catch (InterruptedException e) {
    9.         }
    10.         promise.setFailure(new IllegalStateException("cm"));
    11.     }
    12. }).start();
    13. future.await();

代码仓库: https://bitbucket.org/qiyi/commons-future
参考:

golang 以 dom 方式解析 xml

0 条评论

直到 golang 1.2,标准库的 encoding/xml 包里依然没有出现 xml dom 解析相关的支持,网上搜索了一圈,倒是一早就有开源项目提供了第三方库(code.google.com/p/godom)。godom 项目实现了大部分的 dom 规范常用接口,够一般场景使用的了,可惜下载源码下来尝试 build 居然失败,原来项目已经两年多没有维护,而 golang 在快速演进过程中废弃了一些内置结构的支持,并且部分功能包的位置也发生了变化。

别无他法,官方的指望不上,只能修正 godom 工程的代码,费了些时间,将原本代码里已经被废弃的 vector 替换成 slice,此外修改了几个 xml 包的导入位置,终于 build 成功,开源项目就是好,clone了原作者的工程到 https://bitbucket.org/qiyi/godom/ , 支持 golang 1.2。

使用时先 go get bitbucket.org/qiyi/godom,示例代码,接口使用和 JAVA 类似:

godom-1