arthinking

ChinSyun Pang's blog


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

Maven插件编译问题

发表于 2016-05-03   |   分类于 Java , Maven

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in:

Maven插件编译问题

1
TestService testService = serviceFactory.getService(ServiceType.testServiceClazz);

maven compile 报如下错误:

1
2
3
4
[ERROR] /xxx.java:[100,20] xxx.java:106: 不兼容的类型
找到: java.lang.Object
需要: TestService
[INFO] 1 error

而以下代码则不会报错:

1
TestService testService = serviceFactory.getService(TestService.class);

其中getService()方法如下:

1
2
3
public<T> T getService(Class<T> class){
...
}

可以发现,报错的代码,传入的Class是动态的,这是导致Maven编译报错的原因。

查看下项目的maven-compiler-plugin插件配置:

1
2
3
4
5
6
7
8
9
10
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<showWarnings>flase</showWarnings>
</configuration>
</plugin>

可以发现我们并没有为maven指定其他的JDT(Java Development Tools),使用的是默认的javac进行编译。而我们在Eclipse里面使用的是自带的JDT,编译没有问题。可见,javac的检查机制更加严格,导致Eclipse可以编译通过的,用Maven编译会报错。在用Maven编译的时候要注意下这点哦。

Reference

maven插件列表

maven编译问题

Compiling Java code

关于Eclipse和Javac编译结果不一致的问题分析与解决

What is the difference between javac and the Eclipse compiler?

MySQL 安装问题

发表于 2016-05-03   |   分类于 Database

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

批量插入:

http://blog.sina.com.cn/s/blog_662e56ec0100jtg5.html

Mac下新安装的MySQL无法登陆root用户解决方法

mac下安装MySQL5.7遇到默认密码的大坑

HighPay Zoom博客系统搭建说明

发表于 2016-05-03   |   分类于 杂谈

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: HighPay Zoom博客系统搭建说明

HighPay Zoom博客托管于Github,基于Hexo制作成静态博客;

Hexo

Hexo是一款基于Node.js的静态博客框架,简单的说,就是可以通过Hexo,把markdown文件直接转换成一个静态的网站输出到一个文件夹,然这个文件夹可以直接上传到服务器或者github,就可以访问啦~

接下来是使用Hexo的使用方法:

Hexo基于Node.js,所以需要先安装NodeJS的环境,怎么安装就不说啦,搜索一下可以找到相应的教程;主要通过NodeJS生成静态站点;

同时你需要安装Git,用于把代码提交到github上面去;

安装Hexo:

sudo npm install-g hexo

初始化项目:

hexo init

生成静态页面:

hexo generate

本地启动访问静态网站:

hexo server

启动之后会提示本地访问的地址,直接输入地址访问就可以啦;

接下来是把静态网站发布到github上面去,怎么使用github创建主页就不多说了,搜一下github搭建博客即可找到答案.

执行完hexo init之后,会在目录下面生成hexo相关的文件,其中_config.yml是hexo的配置文件,用于配置站点信息和发布信息的,我们编辑这个文件,在最后加上:

1
2
3
4
5
6
7
deploy:

type: git

repo:https://github.com/您的github项目仓库地址

branch:master

注意,我们这里的branch需要设置为master,否则,css,js,图片等资源文件加载不到.

好的,为了通过hexo直接把项目直接发布到github仓库的master分支,需要再安装一个模块:

npm install hexo-deployer-git–save

执行如下命令,静态站点就push到github上面去啦:

hexo deploy

这个命令实际上是把我们刚才执行hexo generate所生成的public文件夹里面的所有内容,既是静态站点,push到了github的master分支上面;

每次部署的步骤,可以按照这样来:

1
2
3
4
5
hexo clean

hexo generate

hexo deploy

如果需要给博文添加标签或者分类,可以直接在markdown文件顶部这样设置:

1
2
3
4
5
---
title: HighPay Zoom博客系统搭建说明
categories: [杂谈]
tags: [Hexo]
---

其中title是博文的标题,categories是分类,tags是标签,如果有多个标签或者分类,按照这个格式进行添加:[a,b,c]

Hexo相关的问题

文档中的分隔项不可以使用---,与hexo的文件顶部定义的字符冲突了,报如下错:

1
YAMLException: end of the stream or a document separator is expected at

您应该尝试使用***替代。

以上就是我们搭建过程啦, Bon Voyage!

References

  • Hexo官网
  • HEXO+Github,搭建属于自己的博客
  • Hexo@简书
  • Hexo使用攻略
  • Hexo添加Toc支持,生成文章目录
  • hexo next主题配置

MySQL emoji表情支持

发表于 2016-05-03   |   分类于 Database

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

1、数据库需要5.5.3+的支持

2、修改database、table和column字符集

1
2
3
4
5
ALTER DATABASE guitargg CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; 
ALTER TABLE gt_comment_content CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE gt_comment_content CHANGE content VARCHAR(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

SHOW VARIABLES LIKE '%char%';

3、修改配置文件

etc/mysql/my.cnf

1
2
3
4
5
6
7
8
9
[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci init_connect='SET NAMES utf8mb4'

4、重启MySQL Server

1
/etc/init.d/mysql restart

5、升级JDBC驱动

确保mysql connector版本高于5.1.13

6、检查应用的数据库连接配置:

1
2
3
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=TRUE jdbc.username=root
jdbc.password=password

mysql/Java服务端对emoji的支持

Dubbo Introduction

发表于 2016-04-27   |   分类于 服务治理

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

官网

RMI Hessian暴露和引用远程服务,H5硬件进行负载均衡;

软负载均衡和Failover,降低F5负载均衡的依赖;

1、连通性
2、健壮性
3、伸缩性
对等集群,可动态增加实例
4、升级性

Zookeeper introduction

发表于 2016-04-26   |   分类于 Java , Spring

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

introduction

Zookeeper安装配置

NIO intro

发表于 2016-04-22   |   分类于 Java

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

缓冲区操作

缓冲区操作简图


用户空间:常规进程所在区域,不能直接访问硬件设备。

内核空间:操作系统所在区域,所有I/O都直接或间接通过内核空间。

请求I/O操作过程:系统调用 –> 内核 –> 传送数据到用户空间 –> 如果数据不在内核空间,则进程被挂起,内核着手把数据读进内存。

注意:硬件通常不能直接访问用户空间,内核负责数据的分解,再组合工作,充当着中间人的角色。

发散/汇聚

IDE相关问题

发表于 2016-04-22   |   分类于 IDE

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

IntelliJ IDEA 控制台中文乱码

IntelliJ IDEA项目部署问题

发表于 2016-04-22   |   分类于 IDE

有时候Tomcat运行好好的,停掉之后再次运行就报错了:

Name jdbc is not bound in this Context in Tomcat

这个时候你可以尝试在context.xml文件里面配置ResourceLink:

1
2
3
4
5
<Context>
...
<ResourceLink global="jdbc/MyDS" name="jdbc/MyDS" type="javax.sql.DataSource" />
...
</Context>

以上纯粹是一个巧合,IntelliJ IDEA项目通过maven编译之后,一般会在target目录下面生成一个编译的目录,我们通过 war wxploded进行部署的时候就会读取这里的文件进行部署,所以,查看一下META-INF目录下的context.xml文件数据源配置是否存在。

#References

Name jdbc is not bound in this Context in Tomcat

Git常见问题

发表于 2016-04-20   |   分类于 版本控制

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

pull遇到的问题

团队协作问题

如果相同的模块同事开发不同的需求,而拉取了不同的分支,这样会加大代码冲突的可能性,建议的做法是把这些不同需求同一个模块的修改都分配给同一批人,方便模块代码维护和管理。基于模块的开发,后续的版本兼容以前的版本。

Redis命令

发表于 2016-04-19   |   分类于 Cache

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

  1. SETNX key value (SET if Not eXists):当且仅当 key 不存在,将 key 的值设为 value ,并返回1;若给定的 key 已经存在,则 SETNX 不做任何动作,并返回0。
  2. GETSET key value:将给定 key 的值设为 value ,并返回 key 的旧值 (old value),当 key 存在但不是字符串类型时,返回一个错误,当key不存在时,返回nil。
  3. GET key:返回 key 所关联的字符串值,如果 key 不存在那么返回 nil 。
  4. DEL key [KEY …]:删除给定的一个或多个 key ,不存在的 key 会被忽略,返回实际删除的key的个数(integer)。
  5. HSET key field value:给一个key 设置一个{field=value}的组合值,如果key没有就直接赋值并返回1,如果field已有,那么就更新value的值,并返回0.
  6. HEXISTS key field:当key 中存储着field的时候返回1,如果key或者field至少有一个不存在返回0。
  7. HINCRBY key field increment:将存储在 key 中的哈希(Hash)对象中的指定字段 field 的值加上增量 increment。如果键 key 不存在,一个保存了哈希对象的新建将被创建。如果字段 field 不存在,在进行当前操作前,其将被创建,且对应的值被置为 0。返回值是增量之后的值。
  8. PEXPIRE key milliseconds:设置存活时间,单位是毫秒。expire操作单位是秒。
  9. PUBLISH channel message:向channel post一个message内容的消息,返回接收消息的客户端数。

Redis分布式锁

发表于 2016-04-19   |   分类于 Cache

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

设计要点:

  • 锁的实效,避免被强制解锁,或者单点故障影响其他客户端获取锁;
  • 可重入锁和吞吐量的权衡;
  • 减少redis压力(减少获取锁的操作);
  • 加锁的事务尽量细粒度;
  • 同步锁状态给其他客户端(分布式消息:类似线程的notifyAll);
  • 考虑执行句柄中的异常,状态的正确流转和状态。

设计细节

时间戳的设计有很多问题

通过一些java.util.concurrent的API来处理一些本地队列的同步以及等待信号量的处理

  • Semaphore

  • ConcurrentHashMap

redis中使用java脚本实现分布式锁

解决Mac外接显示器字体模糊的问题

发表于 2016-04-17   |   分类于 Mac

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

解决外接显示器字体模糊的问题:

解决Mac外接显示器字体发虚的终极方法

Mac外接显示器那让人纠结的字体渲染问题,通过修改字体平滑等级能否解决?揭秘!

1080p - MacOS X - Screen / Font rendering very bad

ReactJS开发需要了解的概念

发表于 2016-04-04   |   分类于 web前端 , Javascript

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

html-webpack-plugin

http://www.cnblogs.com/haogj/p/5160821.html

ES6 module default

EJS

lodash

ReactJS的PropTypes defaultProps

http://facebook.github.io/react/docs/reusable-components.html

react-router

https://github.com/reactjs/react-router/tree/master/docs

cnpm

ReactJS和AngularJS相关

发表于 2016-04-04   |   分类于 web前端

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in:

ReactJS和AngularJS相关

React

React JS入门:
一看就懂的ReactJS入门教程(精华版)

React 入门实例教程

ReactJS UI库:
ReactJS UI库

React Native:

React Native文档

如何评价React Native

《React Native入门与实战》

使用React Native,你可以使用标准的平台组件。

AngularJS

AugularJS UI库:

http://blog.ionic.io/built-with-ionic-sworkit/
http://www.ionic.wang/start-index.html

使用Ionic构建的App,本质上基于HTML5创建类似于手机平台原生应用的一个开发框架。Ionic框架的目的是从web的角度开发手机应用,基于PhoneGap的编译平台,可以实现编译成各个平台的应用程序。

Webpack笔记

发表于 2016-04-01   |   分类于 web前端 , Javascript

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

0、introduction

1、webpack compared

2、developing with webpack

2.1、Setting Up the Project

web前端项目搭建说明

发表于 2016-03-30   |   分类于 web前端 , Javascript

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: web前端项目搭建说明
项目地址:app-mis

安装webpack:

1
$ npm install webpack -g

关于npm install

初始化项目:

1
$ npm init

执行完这步会在目录下生成package.json文件

为项目安装webpack:

1
$ npm install webpack --save-dev

或者安装特定的版本:

1
$ npm install webpack@1.2.x --save-dev

webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。

–save-dev 与 –save的区别

–save-dev: Package will appear in your devDependencies.
seeGrunt.js: What does -save-dev mean in npm install grunt –save-dev

安装webpack调试工具:

$ npm install webpack-dev-server –save-dev

启动webpack-dev-server:

1
$ webpack-dev-server --inline --hot

webpack-dev-serverwebpack-dev-server是一个小型的node.js Express服务器,它使用webpack-dev-middleware中间件来为通过webpack打包生成的资源文件提供Web服务。它还有一个通过Socket.IO连接着webpack-dev-server服务器的小型运行时程序。webpack-dev-server发送关于编译状态的消息到客户端,客户端根据消息作出响应。

webpack构建命令:

1
2
$ webpack --display-modules
$ webpack --display-modules --display-chunks

–display-modules 和 –display-chunks的作用

by default Webpack hides modules that are not yours. To see all the modules compiled by Webpack, we can pass the –display-modules flag.

run webpack with the –display-chunks flag to see what modules are in which chunks.

安装需要的模块:

lodash

1
npm install --save lodash

lodash是一个Javascript工具库。

安装babel:

1
$ npm install babel-core babel-loader babel-preset-es2015 babel-preset-react babel-preset-stage-2 --save-dev

然后在文件目录下创建 .babelrc 文件。详细配置参考:babel

  • babel是一个Javascript代码转换器,可以把你写的符合 ECMAScript 6 标准的代码完美地转换为 ECMAScript 5 标准的代码,并且可以确保良好地运行在所有主流 JavaScript 引擎中。

安装eslint:

1
$ npm install eslint eslint-loader babel-eslint eslint-plugin-react --save-dev

在团队协作中,为避免低级 Bug、产出风格统一的代码,会预先制定编码规范。使用 Lint 工具和代码风格检测工具,则可以辅助编码规范执行,有效控制代码质量。在以前的项目中,我们选择 JSHint 和 JSCS 结合使用,使用 React JSX 语法时,却遇到了问题:JSHint 不支持 JSX 语法,以有了 ESLint。
eslint

安装react:

1
npm install react react-dom react-router --save

安装antd

1
npm install antd --save

安装需要的webpack loader:

1
2
3
$ npm install css-loader postcss-loader less-loader style-loader html-loader sass-loader node-sass --save-dev
$ npm install url-loader file-loader --save-dev
$ npm install baggage-loader --save-dev

loader配置说明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require("./loader!./dir/file.txt");
// => uses the file "loader.js" in the current directory to transform
// "file.txt" in the folder "dir".

require("jade!./template.jade");
// => uses the "jade-loader" (that is installed from npm to "node_modules")
// to transform the file "template.jade"
// If configuration has some transforms bound to the file, they will still be applied.

require("!style!css!less!bootstrap/less/bootstrap.less");
// => the file "bootstrap.less" in the folder "less" in the "bootstrap"
// module (that is installed from github to "node_modules") is
// transformed by the "less-loader". The result is transformed by the
// "css-loader" and then by the "style-loader".
// If configuration has some transforms bound to the file, they will not be applied.

安装需要的webpack plugin:

1
2
3
$ npm install clean-webpack-plugin --save-dev
$ npm install extract-text-webpack-plugin --save-dev
$ npm install html-webpack-plugin
  • clean-webpack-plugin: A webpack plugin to remove/clean your build folder(s) before building.
  • extract-text-webpack-plugin: It moves every require(“style.css”) in entry chunks into a separate css output file. So your styles are no longer inlined into the javascript, but separate in a css bundle file (styles.css).
  • html-webpack-plugin: Simplifies creation of HTML files to serve your webpack bundles

参考:

  • webpack 入门指南
  • webpack-dev-server
  • Webpack-dev-server结合后端分缶的热替换配置
  • WEBPACK DEV SERVER
  • webpack your bags
  • lodash
  • babel
  • Babel-现在开始使用 ES6
  • eslint
  • ESLint 使用入门

IntelliJ IDEA热部署

发表于 2016-03-28   |   分类于 IDE

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

Java开发

IntelliJ IDEA Tomcat JSP热部署

Webpack Introduction

发表于 2016-03-27   |   分类于 web前端 , Javascript

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

使用

I also recommend you add node_modules/.bin to your PATH variable to avoid having to type node_modules/.bin/webpack every time.

创建项目并使用webpack

初始化项目

1
2
3
$ npm init
$ npm install jquery --save
$ npm install webpack --save-dev

webpack.config.js 配置

1
2
3
4
5
6
7
module.exports = {
entry: './src',
output: {
path: 'builds',
filename: 'bundle.js',
},
};

页面引入

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
<body>
<h1>My title</h1>
<a>Click me</a>

<script src="builds/bundle.js"></script>
</body>
</html>

by default Webpack hides modules that are not yours. To see all the modules compiled by Webpack, we can pass the –display-modules flag:

1
2
3
4
$ webpack --display-modules
bundle.js 257 kB 0 [emitted] main
[0] ./src/index.js 53 bytes {0} [built]
[1] ./~/jquery/dist/jquery.js 248 kB {0} [built]

设置你的第一个loader

我们的期望是这样的:当我们引入一个按钮组件的时候,我们希望能够自动引入相关的图片,样式资源。

安装loader

To install a loader in Webpack you do two things: npm install {whatever}-loader, and add it to the module.loaders part of your Webpack configuration

1
$ npm install babel-loader --save-dev

我们希望babel处理所有以js作为后缀的文件,但是我不希望babel去处理第三方的类库,如jQuery,所以我们可以设置一些过滤规则。(Loaders can have both an include or an exclude rule. It can be a string, a regex, a callback, whatever you want.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module.exports = {
entry: './src',
output: {
path: 'builds',
filename: 'bundle.js',
},
module: {
loaders: [
{
test: /\.js/,
loader: 'babel',
include: __dirname + '/src',
}
],
}
};

接下来可以使用ES6的语法编写一个Button组件了。我们会使用到Mustache,我们也需要Sass and HTML files的loader:

1
2
$ npm install mustache --save
$ npm install css-loader style-loader html-loader sass-loader node-sass --save-dev

Now in order to tell Webpack to “pipe” things from one loader to another we simply pass a series of loaders, from right to left, separated by a !. Alternatively you can use an array by using the loaders attribute instead of loader:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
test: /\.js/,
loader: 'babel',
include: __dirname + '/src',
},
{
test: /\.scss/,
loader: 'style!css!sass',
// Or
loaders: ['style', 'css', 'sass'],
},
{
test: /\.html/,
loader: 'html',
}

You’ve now learned how to setup loaders and how to define the dependencies of each part of your app. This may look like it doesn’t matter much now, but let’s push our example further.

Code splitting

1
2
3
4
5
6
7
8
9
import $ from 'jquery';

// This is a split point
require.ensure([], () => {
// All the code in here, and everything that is imported
// will be in a separate file
const library = require('some-big-library');
$('foo').click(() => library.doSomething());
});

Everything in the require.ensure callback would be split into a chunk – a separate bundle that Webpack will load only when needed, through an AJAX request.

1
2
3
4
5
6
7
8
if (document.querySelectorAll('a').length) {
require.ensure([], () => {
const Button = require('./Components/Button');
const button = new Button('google.com');

button.render('a');
});
}

会生成 builds/1.bundle.js 文件

add configuration:

1
2
3
path:       'builds',
filename: 'bundle.js',
publicPath: 'builds/',

The output.publicPath option tells Webpack where to find built assets from the point of view of the page (so in our case in /builds/).

重命名bundle:

1
2
3
4
5
6
require.ensure([], () => {
const Button = require('./Components/Button');
const button = new Button('google.com');

button.render('a');
}, 'button');

添加第二个组件之后重复引入jQuery的问题。这个时候需要使用到组件:

Webpack comes will a handful of plugins to perform all various kinds of optimizations. The one that interests us in this case is the CommonChunksPlugin: it analyzes your chunks for recurring dependencies, and extracts them somewhere else. It can be a completely separate file (like vendor.js) or it can be your main file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var webpack = require('webpack');

module.exports = {
entry: './src',
output: {
// ...
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'main', // Move dependencies to our main file
children: true, // Look for common dependencies in all children,
minChunks: 2, // How many times a dependency must come up before being extracted
}),
],
module: {
// ...
}
};

If we specified per example name: ‘vendor’:

1
2
3
4
5
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
children: true,
minChunks: 2,
}),

Since that chunk doesn’t exist yet, Webpack would have created a builds/vendor.js

To production and beyond

Ok first of all, we’re going to add several plugins to our configuration, but we only want to load them when NODE_ENV equals production so let’s add some logic for that in our configuration. Since it’s just a JS file, that’s easy to do:

1
2
3
4
5
if (production) {
plugins = plugins.concat([
// Production plugins go here
]);
}

References

webpack your bags

ES6编译器问题

发表于 2016-03-26   |   分类于 web前端 , Javascript

Author: ChinSyun Pang
Weibo: arthinking_plus
Posted in: http://www.itzhai.com

通过babel编译ES6

Trying out JavaScript ES6 using Babel

编译器模块引入问题

在使用IDEA的是,如果通过类似这样的方式导出模块:

1
module.exports = AlbumAction;

而通过ES6的模块机制进行引入

1
import AlbumAction from '../../actions/AlbumAction.js';

这个时候IDEA会提示如下错误:

1
Default export is not declared in imported module

好像目前的IDEA(15.0.1)并不能识别兼容混用两种模块使用方式,尝试将导出代码也换成ES6的模块机制的方式,不再报这个错误了:

1
export default AlbumAction;

References

WebStorm says that AppActions is not declared in imported module

ES6详解八:模块(Module)

module.exports 还是 exports?

node.js的module.export 和 export方法的区别

1234…6
arthinking

arthinking

Struggle for HighPay zoom.
主站 http://www.itzhai.com/

120 日志
33 分类
51 标签
itzhai GitHub Twitter Weibo
Creative Commons
© 2016 arthinking
由 Hexo 强力驱动
主题 - NexT.Pisces