Sunday, December 30, 2018

Java目录


Java 8
Stream API, Optional API, 跟CompletableFuture

lang3
EqualsBuilder
ToStringBuilder

Google Guava (Google Collections Library)
ImmutableSet.of
ImmutableMap.of

Java的Null pointer exception
Java中的ThreadLocal和弱引用

ORM:
lombok

Database ORM:
MyBatis

JSON:
fasterxml

Build tool:
Gradle简介

Saturday, December 15, 2018

NTLK

NTLK主要用于比较两文档的相似度

https://my.oschina.net/Samyan/blog/1796944

Tuesday, November 6, 2018

Cucumber简介

Cucumber是平实语言版的unit test,可用于包层次的测试。优势在于它允许非程序员参与,需求更加明确。

测试方法:
https://www.cnblogs.com/TankXiao/archive/2012/02/20/2347016.html

BDD/Functional test framwork: Cucumber
TDD:

https://cucumber.io/



Gherkin
plain text语音来描述unit test中的arrange(mock), act, assert。

例子
Scenario: Breaker guesses a word
  Given the Maker has chosen a word
  When the Breaker makes a guess
  Then the Maker is asked to score

Friday, October 26, 2018

Gradle简介

Gradle与Maven比较:
1. Gradle利用cache使得build过程更快
2. Gradle利用分块build(incremental),也就是指对修改的文件重新build,如修改了test,只build该test

https://gradle.org/maven-vs-gradle/
https://www.jianshu.com/p/00d5469e25e7

Thursday, October 18, 2018

Java的Null pointer exception

Boolean a;
boolean b = false || a;
会出现NPE因为a可能为null。

switch(a){
    case true:
        return "";
}
会出现NPE因为a可能为null。

Friday, September 21, 2018

Java中的ThreadLocal和弱引用

ThreadLocal就是线程的私有变量和对象

static ThreadLocal<Metric> metric = new ThreadLocal<>();
这里用static因为相当于线程的私有全局变量,避免数据的重复copy(不同实例)。但可能导致内存泄漏(因为static不会被回收)。如果有线程池,线程会被复用就减低内存泄漏的可能。
https://www.zhihu.com/question/35250439

Strong ref是Map m = new HashMap();
Soft Ref内存不足才会回收,适用于缓存
Week Reference是回收器自动回收弱引用对象(HashMap中)
Phantom Ref是在析构finalize中不会复活下回收弱引用


https://droidyue.com/blog/2016/03/13/learning-threadlocal-in-java/
https://droidyue.com/blog/2014/10/12/understanding-weakreference-in-java/

我的书目:

Effective Java中文版(第2版)


Java并发编程实战


深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)



重构:改善既有代码的设计 

系统思维:复杂商业系统的设计之道(原书第3版)

Sunday, September 9, 2018

JS代码缺陷自动分析工具 - eslint

eslint
gulp: js build tool
node.js
webpack: web browser library
unit test: Mocha

http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html

Thursday, August 16, 2018

whistle简介

如何安装
http://wproxy.org/whistle/install.html

https设置
http://wproxy.org/whistle/webui/https.html

windows commands

netstat -ano | findstr :8899
taskkill /PID typeyourPIDhere /F

https://stackoverflow.com/questions/39632667/how-to-kill-a-currently-using-port-on-localhost-in-windows

Thursday, June 28, 2018

AWS CloudFront

CDN service

比如Alexa use case,可以用于给一个skill播放音乐,用CloudFront根据user location来读取相应地区的audio。CloudFront自动配对到S3.

Monday, June 25, 2018

AWS EMR简介

AWS EMR是基于Hadoop来做数据计算的平台。比如Log analysis,用log来抽取结构化数据,上传到S3, Redshift可以从S3读取文件,EMR作用相当于ETL运算机器。

Monday, April 16, 2018

JavaScript Plugin Design pattern

Summary
https://stackoverflow.com/questions/10763006/plugin-architecture-in-web-apps-examples-or-code-snippets


Command
http://www.dofactory.com/javascript/command-design-pattern

var calculator = new Calculator();
// issue commands
calculator.execute(new AddCommand(100));
calculator.execute(new SubCommand(24));
calculator.execute(new MulCommand(6));
calculator.execute(new DivCommand(2));


Callback
https://www.w3schools.com/jquery/jquery_callback.asp

slow之后callback函数:
$("button").click(function(){
    $("p").hide("slow", function(){
        alert("The paragraph is now hidden");
    });
});

Dependency Injection
https://github.com/nikku/didi

有点似Factory pattern,根据不同的输入(car)来决定load哪个object。
var Car = function(engine) {
  this.start = function() {
    engine.start();
  };
};

var createPetrolEngine = function(power) {
  return {
    start: function() {
      console.log('Starting engine with ' + power + 'hp');
    }
  };
};


// a module is just a plain JavaScript object
// it is a recipe for the injector, how to instantiate stuff
var module = {
  // if an object asks for 'car', the injector will call new Car(...) to produce it
  'car': ['type', Car],
  // if an object asks for 'engine', the injector will call createPetrolEngine(...) to produce it
  'engine': ['factory', createPetrolEngine],
  // if an object asks for 'power', the injector will give it number 1184
  'power': ['value', 1184] // probably Bugatti Veyron
};


var di = require('di');
var injector = new di.Injector([module]);

injector.invoke(function(car) {
  car.start();
});

Abstract Factory
http://www.dofactory.com/javascript/abstract-factory-design-pattern

var persons = [];
var employeeFactory = new EmployeeFactory();
var vendorFactory = new VendorFactory();

persons.push(employeeFactory.create("Joan DiSilva"));
persons.push(employeeFactory.create("Tim O'Neill"));

Builder
http://www.dofactory.com/javascript/builder-design-pattern

var shop = new Shop();
var carBuilder = new CarBuilder();
var truckBuilder = new TruckBuilder();
var car = shop.construct(carBuilder);
var truck = shop.construct(truckBuilder);

Others
https://seesparkbox.com/foundry/api_patterns_for_your_open_source_javascript_plugin

Ref
Youtube player APIs: https://developers.google.com/youtube/iframe_api_reference
Android lifecycle: https://developer.android.com/guide/components/activities/activity-lifecycle
Android MediaPlayer State Diagram: https://developer.android.com/reference/android/media/MediaPlayer

Alexa
AVS: 怎么用Alexa来做事,如audio player天气预报,交通情况。这是比较generic的,无skill
Smart Home API: 怎么创建一个SH的skill,比较有针对性,AVS不包括的。
Video API: 同上




Wednesday, April 11, 2018

Token简介

Token是什么?
Token是访问某些资源的凭证。打个比喻,我想进入某个公司的办公室,token就是badge,办公室就是我想访问的资源。

为什么需要token?
Token是一个加密字符串,是被访问资源发给客户端的凭证。用户第一次登录给出用户名和密码,之后获得token,以后每次访问均只需要给出token即可,而不需要再登录。资源服务器只要验证token即可。这机制避免了每访问一次都要发密码的需要,从而大大降低密码被截获的可能性。Token实质上是密码的一个替代,但不带任何用户信息。这叫opaque string(不透明),表示一般人不理解,但它对应着用户id。

Refresh token和access token的区别
Refresh token就是上述描述的token,由资源服务器发出,同时资源服务器也会将其保留在DB中。客户登录即获得此token保存在本地存储比如Android的sqlite。当每次需要访问资源就会发出带此token的request,服务器会进行验证。Refresh token不会过期(比如手机上的微信,永远不用重新登录),这会导致一个问题,就是资源服务器没办法revoke或修改这个权限。为了支持动态更改访问权限,引入access token。access token才是真正访问资源的token,它具有较短的有效期(大多数一小时),保证权限大多数情况下最新且更为安全。

Refresh token和access token的关系
htt分用户登录时候,就会即时获得refresh token和access token,每次访问资源用到access token,当access token过期时候,客户端会用refresh token去获得新的access token,同时也会获得新的refresh token。资源服务器也会更新DB中refresh token。access token含有client id的信息,若access token被盗取(compromised)(比如user id和access token不一致,因为黑客试图随意产生access token来骗资源服务器),客户服务器会删除DB中的refresh token,这样access token过期后便不能访问资源,客户端需要重新登录。资源服务器通过access token授权给单一客户端a single authenticated client。例如,用另一个手机登录微信,原手机就会被迫退出并提示安全风险。

资源服务器架构
一般而言,资源服务器含有Auth server和resource server,分别用于验证和提供资源。刚才提到的所有理论都是来自于Auth server。










登录的request
$ curl -X POST -H 'Authorization: Basic dGVzdGNsaWVudDpzZWNyZXQ=' -d 'grant_type=password&username=test&password=test' localhost:3000/oauth/token

{
    "token_type":"bearer",
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI1NDMsImV4cCI6MTQ0NDI2MjU2M30.MldruS1PvZaRZIJR4legQaauQ3_DYKxxP2rFnD37Ip4",
    "expires_in":20,
    "refresh_token":"fdb8fdbecf1d03ce5e6125c067733c0d51de209c"
}


更新access token的request
curl -X POST -H 'Authorization: Basic dGVzdGNsaWVudDpzZWNyZXQ=' -d 'refresh_token=fdb8fdbecf1d03ce5e6125c067733c0d51de209c&grant_type=refresh_token' localhost:3000/oauth/token

{
    "token_type":"bearer",
    "access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s",
    "expires_in":20,
    "refresh_token":"7fd15938c823cf58e78019bea2af142f9449696a"
}


Token是访问资源的凭证。比如Hulu想发events给A公司,Amazon公司就需要给Hulu一个token。这里的token叫LWA token (Login with Amazon)。又如,vtasters提供FB login,FB就给vtasters一个access token取访问FB的资源,当然第一次用FB login时候,会出现一个页面告知用户哪些FB信息(例如生日)会被vtasters访问。这叫scope,是能访问资源的范围,这种给予第三方的token权限一般比第一方的权限低。

OAuth token
refresh token(never expire) refresh tokens have a very long duration (month to unlimited) and are stored at the client in a persistent storage (e.g. database or filesystem)
bearer token=access token(an hour): user's permission scope
correlation token: A token that identifies the message exchange. map to 用户id
LWA token: amazon第三方token
MAP token: amazon第一坊token
auth token key

怎么防止篡改token
要求token的时候,加入一个client secret加密的字符串即可,验证此request是否来自于官方的app。这个client secret只有client app和server知道。所以通过这个方法就可以验证token request是否被篡改,如client assertion和用户名密码一起发送获取access token。client assertion又叫JWT(json web token)就是用client key对一些字段进行加密发到server端,它有一套工业标准。

headers = json.dumps({
    "typ" : "JWT",
    "alg" : "HS256"
})
claims = json.dumps({
    "iss": "mozillazg.com",
    "exp": 1435055117,
    "user_id": 1,
    "foo": "bar"
})
content = base64url_encode(headers) + '.' + base64url_encode(claims)
secret_key = 'your secret key'
signature = hmac.new(secret_key, content, hashlib.sha256).digest()

token = content + '.' + base64url_encode(signature)

curl -X POST -H 'Authorization: B

Token的历史
API keys
Google maps用的就是API key,只要从Google获取,每次request加入key即可访问。
用户场景:公司内部应用,不需访问与用户相关的数据。

OAuth Token
第三方Facebook Login. 用户需同意第三方可访问FB的scope获refresh/access token。对比与API keys,好处是限定访问资源范围,会过期减少资源不法访问的可能,access token可以revoke(删除其在数据库的记录)。

Json web token
OAuth token的进化版,客户端对字符串进行加密,server端进行验证。可避免数据库查找access token。
用户场景:减少数据库访问,且不需要立即revoke token。

Page token:
Page token与start index。page token是该search搜索结果的该页的最后一个item的hash,这样获取下一页的时候就可以知道从哪开始。好处是即使有新收据加入,获取下一页的时候也有可能得到。坏处是只能按顺序获取,也就是不能从一页跳到第10页,所以用于Infinite scrolling.

Ref:
https://stackoverflow.com/questions/25838183/what-is-the-oauth-2-0-bearer-token-exactly
https://auth0.com/learn/refresh-tokens/
https://jwt.io/
https://mozillazg.com/2015/06/hello-jwt.html
https://zapier.com/engineering/apikey-oauth-jwt/
Page token作用

Friday, March 23, 2018

HTML5 video player

<!DOCTYPE html>
<html>
<body>

<button onclick="playVid()" type="button">Play</button>
<button onclick="pauseVid()" type="button">Pause</button>
<button onclick="seekVid()" type="button">Seek</button>
<button onclick="ccVid()" type="button">CC</button><br>
<video id="myVideo" width="600" height="400" autoplay="autoplay" controls='false'>
  <source src="./big.mp4" type="video/mp4">
  <track label="pt" kind="subtitles" srclang="pt" src="./small.vtt" default />
  Your browser does not support the video tag.
</video>
<script>

var vid = document.getElementById("myVideo");
var aaaa = 'showing';
function myFunction() {
    document.getElementById("myVideo").controls = true;
}

function playVid() {
    vid.play();
}

function pauseVid() {
    vid.pause();
}

function seekVid() {
    var cTime = vid.currentTime;
    vid.currentTime += 3;
}

function ccVid() {
   if (aaaa==='showing')
      aaaa = 'hidden';
   else
      aaaa = 'showing';
   for (var i = 0; i < vid.textTracks.length; i++)
      vid.textTracks[i].mode = aaaa;
}

</script>
</body>
</html>

Monday, March 12, 2018

Android之webview



1. webview的基本代码

https://developer.android.com/guide/webapps/webview.html

webview.xml:
<?xml version="1.0" encoding="utf-8"?>
<WebView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webView1"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
/>

MainActivity.java:
public class MainActivity extends Activity {
 
    private WebView webView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.webview);
        webView = (WebView) findViewById(R.id.webView1);
        webView.setJavaScriptEnabled(true);
        webView.loadUrl("http://www.vtasters.com/unittest");
       //webView.loadUrl("file:///android_asset/abc.html");//in app/assets/abc.html

AndroidManifest.xml:
<manifest ... >
    <uses-permission android:name="android.permission.INTERNET" />
    ...
</manifest>


2. JS和webview交互

http://mthli.github.io/Android-WebView-JavaScript
需要准备一个网站如vtasters,webview可以通过loadUrl来执行对应功能。

public class MyWebView extends WebView {
    public MyWebView(Context context) {
        ...
        getSettings().setJavaScriptEnabled(true);
        addJavascriptInterface(this, "MyName");
        ...
    }

    @JavascriptInterface
    public void example() {
        ...
    }
}

Sunday, February 25, 2018

Protobuf协议

http://blog.csdn.net/antgan/article/details/52103966

解码:
http://yura415.github.io/js-protobuf-encode-decode/