Web下文件下载

下载中文名文件,这个场景在很多Web下经常遇到。

普遍思路,保存文件重命名,记录下原文件名,待用户下载时,response header种设置下原文件名。

需要注意的是,考虑到浏览器兼容问题,文件名不仅要URLEncode编码处理,还需要遵循RFC 2231,参数Key后增加星号,Value前面为字符集和单引号中的语言,比如

1
Content-disposition: attachment;filename*=utf-8'zh_cn'%e4%b8%ad%e6%96%87.pdf

Java中的单例模式

单例模式是Java设计模式中相当经典的了,平时工作接触的也只有懒汉、饿汉之类的,之前阿里面试中也被问到这个问题,今天就总结一下。

饿汉式

1
2
3
4
5
6
7
8
9
10
public class Singleton {
    private final static Singleton INSTANCE = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

一般不希望在类加载时就创建对象,改进后:

简单实现线程安全的懒汉式

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {
    private static Singleton instance;

    private Singleton() {
    }

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

上面例子的性能不太理想,其实只需第一次调用时同步,利用JDK1.5中volatile关键字改进后:

全文

Java中常用的时间格式化注意点

平时工作中或多或少都会遇到时间格式化的问题,传统思路都利用java.text.SimpleDateFormat,然后根据业务场景写几个Pattern去处理。

之前接触到项目中一般都会提供一个工具类,既然是工具类,那就按套路了,上面声明几个不同格式的Pattern实例,下面写几个static方法,然后处理下异常之类的。

这样的好处是避免方法调用时去new SimpleDateFormat,从而创建大量的实例对象,毕竟SimpleDateFormat类初始化代价不小,父类DateFormat中成员变量包含Calendar等。

但恰恰就因为这个成员变量,并且format方法又没有同步,所以这个工具类在多线程下风险很高。

全文

常用浏览器下调试

2015-9-9更新:
Android设备进入开发者选项,启用USB调试后,Terminal输入

1
2
3
heshuai-MacBookPro:~ heshuai$ adb devices
List of devices attached
01ce8d6a1858745f	device

检查设备是否成功连接,然后在Chrome 45在地址栏输入 chrome://inspect/

chrome://inspect/
应该能看到当前连接的设备,找到要调试页面,点击inspect即可

注:无需安装Chrome(Android 版)


Safari下显示开发者调试工具方法:
Preferences - Advanced - Show Develop menu in menu bar

Firefox本身包含开发者工具,当然Firebug插件大家更常用。

Chrome下默认的Inspect Element(以下测试均在Chrome Version 36.0.1985.125下)

Console

使用alert调试在迭代输出时很不方便,这时利用log可以很直观的观察运行状态。

1
2
3
4
> console.log('hello world');
  hello world
> console.warn('warning info');
> console.warn('error message')

平时在Sources标签下对JS方法设置断点Debug时,可以查看作用域内的变量,也可以利用在Console中直接输入变量名查看。

全文

HTTP常见乱码问题

众所周知,乱码问题源于编码不一致,往往在平时开发中容易忽略指明编码,而依赖于默认编码。

常用编码

ASCII

计算机存储的最小单位是byte,即8位,其中最高位为0,剩下7位定义了128个字符。

ISO-8859-1 Latin-1 Windows-1252

ISO 8859-1,又称Latin-1,以ASCII为基础,单字节编码,在空置的0xA0-0xFF的范围内,加入96个字母及符号,供使用附加符号的拉丁字母语言使用。

GB2312 GBK GB18030 Big5

中文大陆地区的三个主要编码GB2312,GBK,GB18030,有时间先后关系,表示的字符数越来越多,且后面的兼容前面的。
GB2312和GBK都是用两个字节表示,GBK是对GB2312的扩展,这样GBK在支持简体中文的同时也支持繁体中文,而GB18030则使用两个或四个字节表示,包括了部分少数民族字符,现时中华人民共和国官方强制使用GB18030标准。
Big5是针对繁体中文的,广泛用于台湾香港等地。

Unicode UTF-32 UTF-16 UTF-8

Unicode给所有字符分配了唯一数字编号,并没有规定这个编号怎么对应到二进制,具体的实现方案主要有UTF-32,UTF-16和UTF-8。
UTF-8是可变长字符编码,比如一般的英文字符只需要一个字节,而中文则每个字符占用三个字节。
UTF-16两个字节或者四个字节,所以从字节的角度来看无法和ASCII实现兼容,Java使用UTF-16作为字符的内码。
UTF-32固定四个字节,对于部分字符会造成空间浪费。

总结

  1. 比如使用Spring MVC时需要配置org.springframework.http.converter.StringHttpMessageConverter的defaultCharset;
  2. 还有使用HttpClient时注意响应中ByteArray反序列化时也要指明charsetName,否则读取JVM参数file.encoding;
  3. 一般输入输出流尽量指明编码,防止出现环境不一样导致乱码问题。

龙泉驾校约车脚本

最近该学科目二,可一连几天都约不上车,开始琢磨写个脚本,看有没有效果。

抱怨驾校也是徒劳,谁让当时图便宜呢。脚本也是参考了其他同学的代码,调整后不是特别完善,不过龙泉的校友还是可以参考。

下面是执行脚本,其中有些参数根据自己情况填写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# !/usr/bin/python
# -*- coding: utf-8 -*-

import lqjx
import sys
import time
import logging

logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')

#约车时段,全部、上午8-12、下午1-5、晚上5-8
xnsd = ("-1", "812", "15", "58")
#指定想约的教练
jlcbh = ""
uname = ""
passwd = ""

if __name__ == "__main__":
    lq = lqjx.LQJX()
    try:
        if lq.login(uname, passwd):
            while 1:
                cars = lq.get_bookable_car(xnsd[1])
                if 'null_0' in cars:
                    logging.info('没到时间或者没有可预订车辆!')
                else:
                    result = lq.order_car(xnsd[1], jlcbh)
                    print result
                    if u'成功' in result:
                        logging.info('\n 预定成功!')
                        sys.exit(0)
                #增加间隔时间,防止频繁请求,账号被封
                time.sleep(30)
    except KeyboardInterrupt:
        lq.logout()
        logging.info('退出约车系统!')

下面是核心模块:

全文

翻墙

更新:提供新版hosts下载,大家自测。


最近Google访问不了,各种403和连接被重置。

这给平时工作带来很大的不便,至于原因大家心知肚明。

之前由于改过hosts,遇到Google被墙对自己影响不大,但这次彻底歇菜了。

选择VPN还得取决所在网络环境,L2TP方式经常连接不上,所以暂时先Pass。看微博上有推荐用SSH代理,去淘宝上搜了一家,10块一月,感觉价格可以接受,还是香港主机,下单吧。

跟大家分享Mac下的方法,首先打开终端输入

1
ssh -qTfnNv -D 7070 username@host

输入密码后在网络设置中增加代理,这里选择SOCKS Proxy,输入127.0.0.1:7070后点击应用。

增加代理

现在,打开浏览器试试吧!

Git日常操作

平时使用git依赖于IDE图形化界面插件,用起来倒没什么问题,但觉得还是有必要总结下常用的git命令,点击查看Git中文文档

  1. 一般我们clone已有的项目,默认就是git协议,URL后面可以指定目录:
    1
    
    $ git clone git@github.com:liubaing/galaxy.git galaxy
    

如果本地已经存在的项目

1
$ git init

这时我们发现本地仓库有个隐藏目录.git,里面通常会有:

工作目录(working directory)我们实际持有的文件;
缓存区(index/stage)临时保存我们所做的修改;
HEAD指向我们最后一次提交的结果。

整个变化过程是这样的:working directory -> “git add” -> index -> “git commit” -> HEAD

全文

Linode退钱

之前用过一段时间Linode,不过由于种种原因(其实就是懒)不想继续维护了,Remove掉主机后,它会自动结算剩余金额。也不想让钱那么寂寞的呆在账户里,琢磨怎么退还到信用卡里。

方法是登录Linode后给Linode客服发ticket申请退款。我直接写了一句I don't have time to maintain it and kindly need money,提交,等着收钱。然后客服回复后,退款自生成之日起,要3到5天才能到你的信用卡账户。

退款后,如果你觉得这个账户没有继续存在的必要,那么可以在account选项卡页面的最底部,找到Cancel this Account链接,点击即可。