用OSX内置应用练习听力 - 数字篇

不知道大家有没有觉得,英文听数字实在是个坎儿。有句话叫熟能生巧,不过大量练习数字的语料也不是很好找。幸亏OSX内置了TTS引擎和相应的指令可以不厌烦地帮我们练习。

  1. 打开系统设置,选择Accessibility
  2. 从左边选择Speech,在System Voice里面选最下面的Customize...
  3. 安装自己想听的语音,我这里练习英音,因此勾上了英国英语的Daniel和Kate(如果有可选的高清音频建议也钩上,合成感会小很多)
  4. 等下载完之后就用打开Terminal下面的指令来练习听力吧!(注意把VOICES里面的几个声音换成你安装的音源名称)
#练习听价格
VOICES=(Daniel Kate);VOICE=${VOICES[$(($RANDOM % 2))]};NUM=$(($RANDOM % 1000));NUM2=$(($RANDOM % 100)); say -v $VOICE -i "The price is £$NUM.$NUM2"

#练习听长串数字,如卡号
VOICES=(Daniel Kate);VOICE=${VOICES[$(($RANDOM % 2))]};NUM=""; for i in `seq 1 4`; do for i in `seq 1 4`; do NUM="$NUM$(($RANDOM%10)) "; done; NUM="$NUM,"; done; say -v $VOICE -i "My card number is $NUM"

#练习听日期(需要先装nodejs,如[brew install node],另外可能要把操作系统区域和语言设定成英文的)
VOICES=(Daniel Kate);VOICE=${VOICES[$(($RANDOM % 2))]};NUM=`node -e "console.log(new Date(Math.random() * Date.now()).toLocaleDateString())"`; say -v $VOICE -i "My birthday is $NUM"

这才是NB的黑客

原文链接: https://www.jitbit.com/alexblog/249-now-thats-what-i-call-a-hacker/

之前看到的一篇文章,觉得很有意思,就转过来翻译一下w貌似原作者也是从一个前同事的毛子文的博客里面翻译过来的。咱们这就来看看这位运维中的神人吧

xxx: 嗯,我们的运维跳槽去别的公司了。那哥们儿可真是字面意义上的活在终端里的人。你懂的。就是那种爱着Vim,使用Dot来创建图表,使用Markdown来写Wiki页面的那种人……如果有任何事情得花他90秒钟时间,他肯定是会写个脚本来搞定的

xxx: 让我们坐下看看他留下的……嗯……“遗产”

xxx: 你会喜欢的

xxx: 第一个,smack-my-bitch-up.sh(来针鸡血.sh) - 发一条“在加班”的短信给他老婆(疑似),自动从一个字符串数组里面随机取一条作为理由拼到后面。这个脚本作为一个cron任务,当每天晚上9点,服务器上他还连着的时候就会自动触发。

xxx: 然后是这个,kumar-asshole.sh(Kumar个人渣.sh) - 扫描电子邮件收件箱中来自“Kumar”(我们的客户那边的DBA)的邮件。在里面查找诸如“救命”,“麻烦了”,“对不起”等关键字,如果关键字匹配了,这个脚本自动登录到客户的服务器上,回滚部署数据库到上一个备份,之后再回复一封“没事儿伙计,下次注意”。

xxx: 还有这个,hangover.sh(宿醉.sh) - 这又是一个cron任务,自动发送诸如“浑身脑袋疼/在家办公”之类的邮件,并从另外一个定义好的的字符串数组中选一个“理由”。这个任务在几个指定的日期早上8点45分的时候服务器没有他的SSH会话的时候就会自动触发。

xxx: 最后一个(这个绝B能拿奥斯卡) fuckingcoffee.sh(TMD咖啡.sh) - 这脚本开始的时候会先等整整17秒(!),然后用SSH连接我们的咖啡机(我们根本TM不知道这玩意儿还连着网,跑着Linux并且开着SSH服务)并发送一堆鬼话过去(看起来像二进制)。然后这玩意儿就开始自动煮一中杯半咖啡拿铁,然后再等整整24秒(!)后开始让咖啡流出来。总时间正好让那哥们儿从他的办公桌走道咖啡机这边儿。

xxx: 太NB了我可得留着他们

之前断断续续堆了个WebMVC框架结果一直拖延症终于完工

陆陆续续用闲暇时间写的自用 MVC 框架,本来想利用十一期间整理整理代码放出来,结果一直拖延症终于缓慢地完工了(然后这帖又写了两天……)

先放地址:https://github.com/cloudeecn/mocha-mvc 欢迎大家clone下来吐嘈,如果觉得博主写得好的话,欢迎Star/Fork

运行环境要求:

  • Java7
  • Servlet3.0容器

运行Example

clone工程,用eclipse/IDEA/whatever你喜欢的IDE导入maven工程,用支持Servlet3.0的容器启动里面的example子工程就OK啦

在web.xml中有使用SpringGuice作为DI的两套配置,默认打开的是用Guice作DI的,也可以打开Spring来试一下。

Spring的配置在example工程中src/main/resources/works/cirno/mocha/example/spring/applicationContext.xml

Guice的配置在 works.cirno.mocha.example.guice 包下

运行起来后,可以尝试一下 /example/parameter 和 /example/+(随便你起个名字) 两个地址来感受一下Bean绑定上传文件和RESTful地址的支持

快速上手创建自己的工程

  1. git clone Mocha工程,maven clean install安装到本地库中

  2. 创建一个web maven工程,假设命名为mocha-example,加上如下依赖:

<dependency>
  <groupId>works.cirno.mocha</groupId>
  <artifactId>mvc-core</artifactId>
  <version>0.1-SNAPSHOT</version>
</dependency>
  1. 创建MVCConfigurator的子类
package example;

import ...

public class HelloConfigurator extends MVCConfigurator {
  public void configure(){
    serve("/hello/${name}").with(HelloController.class, "hello");
  }
}
  1. 创建Controller类
package example;

import ...

public class HelloController {
  void hello(PrintWriter out, String name){
    out.print("Hello " + name);
  }
}
  1. web.xml中加入如下配置:
<filter>
  <filter-name>dispatcher</filter-name>
  <filter-class>works.cirno.mocha.DispatcherFilter</filter-class>
  <init-param>
    <param-name>configurator</param-name>
    <param-value>example.HelloController</param-value>
  </init-param>
</filter>

完成. 用Servlet容器运行这个工程,访问

http://127.0.0.1:8080/mocha-example/hello/user

输出为

Hello user

更复杂的配置请参考工程中的Example工程和下面的章节:

(GitHub上的详细文档还没写好,请耐心等待orz)

略微详细的配置介绍

用过Guice的同学应该对这种方式很熟悉,创建一个works.cirno.mocha.MVCConfigurator的子类,并在public void configure()方法中进行配置。

配置路由项

serve({路径}[, "GET/POST/PUT..."])

会产生一个路由项,利用方法链的方式可以进一步对匹配这个路径的访问进行配置

配置响应

serve({路径}[, "GET/POST/PUT..."]).with({controller}, {method});

中的with方法给路由项配置响应的Controller和其中的方法method

Controller返回

Controller方法可以支持返回一下几个类型

Integer:直接用response.sendError返回返回码

String:作为view的名字寻找对应的jsp进行渲染

View对象:根据view的名字寻找对应的jsp进行渲染,view对象中有attribute(key, value)方法可以给request的attribute提供值

null或者方法返回类型为void:不做后续处理

配置view返回

可以通过forward方法执行响应view名对应的jsp文件(forward方法返回一个支持to方法的接口,其中的to方法执行JSP的位置)

可以配置多个

serve({路径}[, "GET/POST/PUT..."]).with({controller}, {method})
  .forward("view名").to("JSP位置")
  .forward("view名").to("JSP位置")
  ...
  ;

支持Restful风格的api

serve("/parameter/\\+${userId}").with(ParameterController.class, "user").forward("success").to("/WEB-INF/jsp/parameter-rest.jsp");

serve("/parameter/\\+${userId}", "POST").with(ParameterController.class, "userPost");

serve("/parameter/\\+${userId}.json").with(ParameterController.class, "userJson");

会匹配/parameter/+后面的任何内容,并作为userId参数和候选

目前有两种写法:

JDK7终于支持了的namedGroup:写法如下:(?&lt;name&gt;pattern),会匹配pattern正则并且作为name参数的候选

另外支持一种比较基本的${name}写法,会被翻译成(?&lt;name&gt;.*?),最小匹配接下来的内容作为name参数的候选

参数获取

Controller方法中的参数目前会根据以下的规则获取:

  1. 按类型匹配

    • 类型为HttpServletRequest的参数会给予request对象
    • 类型为HttpServletResponse的参数会给予response对象
    • 类型为ServletOutputStream或OutputStream的参数会给予response.getOutputStream()的结果
    • 类型为PrintWriter或Writer的参数会给予response.getWriter()的结果
  2. 如果是multipart请求,如果参数类型是InputStream或者Reader,根据参数名匹配上传文件的内容

  3. 根据参数的名称,按照url中的变量 - multipart中解析到的表单域 - request.getParameter的顺序获取字符串,并尝试通过系统中的PropertyEditor进行类型转换,如果转换成功将转换结果给予参数

  4. 将这个类型用无参构造函数实例化,如果成功作为JavaBean遍历其中的属性,根据规则1-4获取参数名.属性名的参数值进行填充,如果能获取到至少一个,将这个实例给予参数

  5. 以上都不匹配返回参数的默认值(基本类型给false/0,对象类型给null)

TODO

  • 写文档(README.md居然只写了一半的内容!)
  • 写文档(注释简直是没有)
  • 写文档(Wiki也没有!)
  • 修改路径匹配的规则,现在是用正则匹配的,对带正则元字符的的路径不友好
  • 优化获取参数的性能……从request中填充一个5个属性的Bean居然要16毫秒简直不能忍
  • 重构一下View的结构,现在的View机制是在Renderer之下的,结构很诡异
  • 用一个比较优雅的方式封装参数获取和转换的配置(目前是写死的规则……)
  • 继续把之前的连载填上

随后我会慢慢在GitHub的README.md和Wiki中补充上各种文档,请大家期待;)

从零开始手写WebMVC框架 第1章

终于进入正题了,本章起开始介绍最简单的请求路由机制,也就是将请求路由到开发者自己写的Controller

首先请读者们站在使用Mocha(还记得么,这个WebMVC的名字)的开发者的角度,先想象一下用最基本的方式使用Mocha需要进行怎样的配置,编写怎样的代码呢?

查看完整版...

从零开始手写WebMVC框架 第0.8章

在开始正式的内容之前,我们先来回顾一下大家比较熟悉的处理Web请求的模式。

经过了多年的发展,J2EE处理请求基本上是符合这样的模式的

  1. 接收用户参数
  2. 处理请求(这一步一般会引入Service层)
  3. 决定输出参数(绑定变量到request.attribute或者form bean等等)
  4. 渲染返回结果(直接返回json/通过jsp或者其他模板引擎渲染页面)

为了对比几种常见开发方式的异同,我们首先基于最传统的Servlet,实现一个简单的功能:

当用户访问/hello的时候,浏览器上就会出现Hello World!
而用户访问的时候传入username参数,如/hello?username=User的时候,后台程序会将用户传入的username转成大写,并输出到Hello World的前面。在这个例子中,浏览器上就会出现USER: Hello World!

查看完整版...

切换到新加坡服务器

之前某篇日志提到过,博客的服务器前一段时间搬到腐国了,不过这腐国的服务器是真稳定唉,天天雷打不动的1.5秒延时……开坑以后转发朋友圈(喂)都费劲,于是今天打开DO的控制台,把所有地区都开了一台LEMP的服务器,挨个测试访问速度,终于发现新加坡的服务器还是不错的,那么就把服务器迁移过去把……目前这台服务器上跑着三个服务,这个博客(静态),fantasy2.me(php),邮箱,当然还有配套的mysql等等等等,于是怎么迁移呢……

  1. 服务器关机
  2. 在DO的控制面板上创建镜像
  3. 在DO的控制面板上把镜像迁移到新加坡地区
  4. 在新加坡地区用镜像创建一个新服务器
  5. 修改DNS

…………完成(嗒搭~)。太简单了不是么wwww,现在真是方便啊