Java 语言的 Exception

定义:
An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

类继承关系:
Object
--Throwable .............................. 鼻祖, 所有 exception 的祖先
----Error .................................... 程序外部问题, 无法预期, 不可恢复
----Exception ............................. 除 RuntimeException 外, 都可预期, 可恢复
------RuntimeException ............. 程序内部问题, 无法预期, 不可恢复

不可预期的 Error 和 RuntimeException 都是不强制需要 try 或 throws 声明捕获的.
除了 Error 和 RuntimeException, 及其之类之外, 都需要 try 或 throws 声明捕获, 包括 throw 的 Throwable.

Error 和 RuntimeException, 及其子类被认为是 unchecked exception, 其他被认为是 checked exception, checked exception 都必须被声明捕获.

除了 try-catch-finally 块之外, Java SE 7 引入了 try-with-resources 语句, 这种新的语句特别使用于可以 Closeable 的 resources. 凡是实现 java.io.Closeable 接口的对象, 都可以通过这种语句来自动 close resource;

try (BufferedReader br = new BufferedReader(new FileReader("a.txt"))) {
    br.readLine();
}

当然 try 后面的括号中可以 声明多个 resource, 用;分开就行.
同时, 它仍然还可以跟 catch, finally 块.

Java SE 7 还引入了下面的语句:

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

一般的try语句, 必须有 catch 或者 finally 跟随, 但是 try-with-resource 语句之后, 就不必了.

Mac 下的 java 安装路径

Mac 上的 Java 安装过好多次 JDK 1.7 但是等到真正在 eclipse 里面切换系统 library 的时候, 却找不到它了, 只在下面的路径看到系统默认的 JDK 1.6

/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/

在 stackoverflow 上查到如下命令:

/usr/libexec/java_home -v 1.7

发现原来另外安装的 JDK 1.7 在下面这个位置:

superman:~ root$ /usr/libexec/java_home -v 1.7
/Library/Java/JavaVirtualMachines/jdk1.7.0_60.jdk/Contents/Home

参考: Where is Java 7 Installed on Mac OS X?

用户注册, 登录, 密码的存储

以下的思路中有的是说的注册过程, 有的是登录的过程, 大概类似, 注册存储到 DB, 验证只是对比结果.
对于单向加密算法, 用的比较多的是 md5 或者 SHA1, 这里以 md5 为例.

最简单, 最原始:
客户端 密码: 123456 -------------> 服务器端 存储到数据库 123456

服务器端加密存储
客户端 密码: 123456 -------------> 服务器端 加密后存储到数据库 md5(123456)

客户端加密 再传输
客户端 先加密: md5(123456) -------------> 服务器端 直接存储到数据库 md5(123456)

加盐 加密 再传输
客户端 获得 salt <-----------------------服务器端 给 salt
客户端 先加盐, 再加密: md5(123456 + salt) -------------> 服务器端 直接存储到数据库 md5(123456 + salt)

加盐 加密 再 https 传输 (安全通道)
客户端 <----------- 建立 ssl 安全通道 ---------------> 服务器端
客户端 获得 salt <-----------https---------服务器端 给 salt
客户端 先加盐, 再加密: md5(123456 + slat) -----https-----> 服务器端 直接存储到数据库 md5(123456 + salt)

加盐 加密 再 https 传输 (安全通道) 一用户一盐
客户端 <----------- 建立 ssl 安全通道 ---------------> 服务器端
客户端 获得本用户的 salt <---------https-------服务器端 从盐表获取当前用户的salt (盐表单独 server, 单独数据, 单独表)
客户端 先加盐, 再加密: md5(123456 + slat) ----https-------> 服务器端 直接存储到数据库 md5(123456 + salt)

加盐 加密 再 https 传输 (安全通道) 一用户一盐 双因子认证
客户端 <----------- 建立 ssl 安全通道 ---------------> 服务器端
客户端 获得本用户的 salt <---------https-------服务器端 从盐表获取当前用户的salt (盐表单独 server, 单独数据, 单独表)
客户端 获得第二个因子, 如 短信验证码, hard token, soft token, 邮箱获取验证码 <==另外方式===> 服务器端
客户端 先加盐, 再加密: md5(123456 + slat) 第二个因子 ----https-------> 服务器端 双因子 认证 加密后密码 + 第二因子

Java 正则表达式

正则表达式除了查看是否匹配之外, 还可以获取匹配的内容, 甚至修改, 替换匹配的内容.

Java 的正则表达式只有3个类, 都在 java.util.regex 包下面: Pattern, Matcher, 和 PatternSyntaxException.

  1. Pattern 是一个正则表达式的编译后表示, 只能通过它的 compile 静态方法获得;
  2. Matcher 就是一个执行正则表达式的引擎, 可以不断的查询, 检索输入的字符串. 它只能通过 pattern 的 matcher 方法获得;
  3. PatternSyntaxException 不同于一般的 exception, 它能提供更过与表达式匹配相关的错误信息;

字符类的例子

  • [abc]................a, b, or c (simple class)
  • [^abc]..............Any character except a, b, or c (negation)
  • [a-zA-Z]...........a through z, or A through Z, inclusive (range)
  • [a-d[m-p]]........a through d, or m through p: [a-dm-p] (union)
  • [a-z&&[def]].....d, e, or f (intersection)
  • [a-z&&[^bc]]....a through z, except for b and c: [ad-z] (subtraction)
  • [a-z&&[^m-p]]..a through z, and not m through p: [a-lq-z]

预先定义的字符类:

  • .------Any character (may or may not match line terminators)
  • \d----A digit: [0-9]
  • \D----A non-digit: [^0-9]
  • \s----A whitespace character: [ \t\n\x0B\f\r]
  • \S---A non-whitespace character: [^\s]
  • \w---A word character: [a-zA-Z_0-9]
  • \W---A non-word character: [^\w]

数量限定:

  • X?.................once or not at all
  • X*..................zero or more times
  • X+.................one or more times
  • X{n}...............exactly n times
  • X{n,}..............at least n times
  • X{n,m}...........at least n but not more than m times

要注意 0长度匹配 问题

边界匹配:

  • ^...........The beginning of a line
  • $...........The end of a line
  • \b..........A word boundary
  • \B..........A non-word boundary
  • \A..........The beginning of the input
  • \G..........The end of the previous match
  • \Z..........The end of the input but for the final terminator, if any
  • \z...........The end of the input

((A)(B(C))) 前面这个表达式有4 个分组.

Java 语言的正则表达式和 Perl 语言的最相近.

java.lang.String 的这4个方法都支持正则表达式: matches, split, replaceAll, replaceFirst. replace 方法不支持;

BackReference: 在后面要引用前面提到的分组:

在正则表达式中用 \ 后面跟数字, 代表引用表达式中第一个分组, 比如下面例子中的 \1 代表要再次出现前面的第一个一样的分组.
Pattern pattern2 = Pattern.compile("(\\d\\d)(\\w)\\1");
Matcher matcher2 = pattern2.matcher("12a12");
System.out.println(matcher2.find());
matcher2 = pattern2.matcher("12b13");
System.out.println(matcher2.find());

在 String 的 replaceAll replaceFirst 中可以使用 $后面跟数字代表正则表达式前面提到的分组, 下面例子中使用第1,3个分组替换原来
System.out.println("22:12".matches("(\\d\\d)(:)(\\d\\d)"));
System.out.println("22:12".replaceAll("(\\d\\d)(:)(\\d\\d)", "$1$3"));

参考:
Oracle Java2e Trail
Java Regex - Tutorial