Skip to content

Commit

Permalink
auto commit
Browse files Browse the repository at this point in the history
  • Loading branch information
CyC2018 committed Jul 19, 2018
1 parent c971833 commit d6a733c
Show file tree
Hide file tree
Showing 14 changed files with 275 additions and 202 deletions.
20 changes: 10 additions & 10 deletions notes/HTTP.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@

## URL

- URI(Uniform Resource Indentifier,统一资源标识符)
- URI(Uniform Resource Identifier,统一资源标识符)
- URL(Uniform Resource Locator,统一资源定位符)
- URN(Uniform Resource Name,统一资源名称),例如 urn:isbn:0-486-27557-4。

Expand Down Expand Up @@ -232,7 +232,7 @@ CONNECT www.example.com:443 HTTP/1.1

- **500 Internal Server Error** :服务器正在执行请求时发生错误。

- **503 Service Unavilable** :服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
- **503 Service Unavailable** :服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。

# 四、HTTP 首部

Expand Down Expand Up @@ -313,16 +313,16 @@ CONNECT www.example.com:443 HTTP/1.1

HTTP 协议是无状态的,主要是为了让 HTTP 协议尽可能简单,使得它能够处理大量事务。HTTP/1.1 引入 Cookie 来保存状态信息。

Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。它用于告知服务端两个请求是否来自同一浏览器,并保持用户的登录状态。
Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带上,用于告知服务端两个请求是否来自同一浏览器。由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销(尤其是在移动环境下)。

Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API (本地存储和会话存储)或 IndexedDB。

### 1. 用途

- 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
- 个性化设置(如用户自定义设置、主题等)
- 浏览器行为跟踪(如跟踪分析用户行为等)

Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。由于服务器指定 Cookie 后,浏览器的每次请求都会携带 Cookie 数据,会带来额外的性能开销(尤其是在移动环境下)。新的浏览器 API 已经允许开发者直接将数据存储到本地,如使用 Web storage API (本地存储和会话存储)或 IndexedDB。

### 2. 创建过程

服务器发送的响应报文包含 Set-Cookie 首部字段,客户端得到响应报文后把 Cookie 内容保存到浏览器中。
Expand Down Expand Up @@ -367,7 +367,7 @@ console.log(document.cookie);

标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端。但即便设置了 Secure 标记,敏感信息也不应该通过 Cookie 传输,因为 Cookie 有其固有的不安全性,Secure 标记也无法提供确实的安全保障。

标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。因为跨域脚本 (XSS) 攻击常常使用 JavaScript 的 `Document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。
标记为 HttpOnly 的 Cookie 不能被 JavaScript 脚本调用。因为跨站脚本攻击 (XSS) 常常使用 JavaScript 的 `Document.cookie` API 窃取用户的 Cookie 信息,因此使用 HttpOnly 标记可以在一定程度上避免 XSS 攻击。

```html
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
Expand All @@ -387,7 +387,7 @@ Path 标识指定了主机下的哪些路径可以接受 Cookie(该 URL 路径

除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。

Session 可以存储在服务器上的文件、数据库或者内存中,现在最常见的是将 Session 存储在内存型数据库中,比如 Redis。
Session 可以存储在服务器上的文件、数据库或者内存中。也可以将 Session 存储在内存型数据库中,比如 Redis。

使用 Session 维护用户登录的过程如下:

Expand Down Expand Up @@ -485,7 +485,7 @@ ETag: "82e22293907ce725faf67773957acd12"
If-None-Match: "82e22293907ce725faf67773957acd12"
```

Last-Modified 首部字段也可以用于缓存验证,它包含在源服务器发送的响应报文中,指示源服务器对资源的最后修改时间。但是它是一种弱校验器,因为只能精确到一秒,所以它通常作为 ETag 的备用方案。如果响应首部字段里含有这个信息,客户端可以在后续的请求中带上 If-Modified-Since 来验证缓存。服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 OK。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 Not Modified 响应
Last-Modified 首部字段也可以用于缓存验证,它包含在源服务器发送的响应报文中,指示源服务器对资源的最后修改时间。但是它是一种弱校验器,因为只能精确到一秒,所以它通常作为 ETag 的备用方案。如果响应首部字段里含有这个信息,客户端可以在后续的请求中带上 If-Modified-Since 来验证缓存。服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 OK。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 Not Modified 响应

```html
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
Expand All @@ -507,7 +507,7 @@ If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT

### 2. 流水线

默认情况下,HTTP 请求是按顺序发出的,下一个请求只有在当前请求收到应答过后才会被发出。由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。
默认情况下,HTTP 请求是按顺序发出的,下一个请求只有在当前请求收到相应之后才会被发出。由于会受到网络延迟和带宽的限制,在下一个请求被发送到服务器之前,可能需要等待很长时间。

流水线是在同一条长连接上发出连续的请求,而不用等待响应返回,这样可以避免连接延迟。

Expand Down Expand Up @@ -627,7 +627,7 @@ HTTP/1.1 使用虚拟主机技术,使得一台服务器拥有多个域名,
- 网络访问控制
- 访问日志记录

代理服务器分为正向代理和反向代理两种,用户察觉得到正向代理的存在而反向代理一般位于内部网络中,用户察觉不到。
代理服务器分为正向代理和反向代理两种,用户察觉得到正向代理的存在而反向代理一般位于内部网络中,用户察觉不到。

<div align="center"> <img src="../pics//a314bb79-5b18-4e63-a976-3448bffa6f1b.png" width=""/> </div><br>

Expand Down
62 changes: 35 additions & 27 deletions notes/Java IO.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public static void listAllFiles(File dir)
System.out.println(dir.getName());
return;
}
for (File file : Objects.requireNonNull(dir.listFiles())) {
for (File file : dir.listFiles()) {
listAllFiles(file);
}
}
Expand All @@ -65,8 +65,9 @@ public static void copyFile(String src, String dist) throws IOException
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dist);
byte[] buffer = new byte[20 * 1024];
/* read() 最多读取 buffer.length 个字节
返回的是实际读取的个数,返回 -1 的时候表示读到 eof,即文件尾 */
// read() 最多读取 buffer.length 个字节
// 返回的是实际读取的个数
// 返回 -1 的时候表示读到 eof,即文件尾
while (in.read(buffer, 0, buffer.length) != -1) {
out.write(buffer);
}
Expand All @@ -82,7 +83,7 @@ Java I/O 使用了装饰者模式来实现。以 InputStream 为例,InputStrea
实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。

```java
FileInputStream fileInputStream = new FileInputStream("file/1.txt");
FileInputStream fileInputStream = new FileInputStream(filePath);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
```

Expand All @@ -92,22 +93,25 @@ DataInputStream 装饰者提供了对更多数据类型进行输入的操作,

不管是磁盘还是网络传输,最小的存储单元都是字节,而不是字符。但是在程序中操作的通常是字符形式的数据,因此需要提供对字符进行操作的方法。

- InputStreamReader 实现从文本文件的字节流解码成字符流
- OutputStreamWriter 实现字符流编码成为文本文件的字节流
- InputStreamReader 实现从字节流解码成字符流
- OutputStreamWriter 实现字符流编码成为字节流

逐行输出文本文件的内容:

```java
FileReader fileReader = new FileReader("file/1.txt");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
public static void readFileContent(String filePath) throws IOException
{
FileReader fileReader = new FileReader(filePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
// 装饰者模式使得 BufferedReader 组合了一个 Reader 对象
// 在调用 BufferedReader 的 close() 方法时会去调用 fileReader 的 close() 方法
// 因此只要一个 close() 调用即可
bufferedReader.close();
}
/* 装饰者模式使得 BufferedReader 组合了一个 Reader 对象
在调用 BufferedReader 的 close() 方法时会去调用 fileReader 的 close() 方法
因此只要一个 close() 调用即可 */
bufferedReader.close();
```

编码就是把字符转换为字节,而解码是把字节重新组合成字符。
Expand Down Expand Up @@ -216,8 +220,10 @@ InetAddress.getByAddress(byte[] address);
public static void main(String[] args) throws IOException
{
URL url = new URL("http://www.baidu.com");
InputStream is = url.openStream(); /* 字节流 */
InputStreamReader isr = new InputStreamReader(is, "utf-8"); /* 字符流 */
// 字节流
InputStream is = url.openStream();
// 字符流
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while (line != null) {
Expand Down Expand Up @@ -253,7 +259,7 @@ public static void main(String[] args) throws IOException

I/O 与 NIO 最重要的区别是数据打包和传输的方式,I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。

面向流的 I/O 一次处理一个字节数据一个输入流产生一个字节数据,一个输出流消费一个字节数据。为流式数据创建过滤器非常容易,链接几个过滤器,以便每个过滤器只负责复杂处理机制的一部分。不利的一面是,面向流的 I/O 通常相当慢。
面向流的 I/O 一次处理一个字节数据一个输入流产生一个字节数据,一个输出流消费一个字节数据。为流式数据创建过滤器非常容易,链接几个过滤器,以便每个过滤器只负责复杂处理机制的一部分。不利的一面是,面向流的 I/O 通常相当慢。

面向块的 I/O 一次处理一个数据块,按块处理数据比按流处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。

Expand Down Expand Up @@ -325,7 +331,7 @@ I/O 包和 NIO 已经很好地集成了,java.io.\* 已经以 NIO 为基础重
```java
public static void fastCopy(String src, String dist) throws IOException
{
FileInputStream fin = new FileInputStream(src); /* 获得源文件的输入字节流 */
FileInputStream fin = new FileInputStream(src); /* 获取源文件的输入字节流 */
FileChannel fcin = fin.getChannel(); /* 获取输入字节流的文件通道 */
FileOutputStream fout = new FileOutputStream(dist); /* 获取目标文件的输出字节流 */
FileChannel fcout = fout.getChannel(); /* 获取输出字节流的通道 */
Expand All @@ -344,10 +350,16 @@ public static void fastCopy(String src, String dist) throws IOException

## 选择器

一个线程 Thread 使用一个选择器 Selector 通过轮询的方式去监听多个通道 Channel 上的事件,从而让一个线程就可以处理多个事件。
NIO 常常被叫做非阻塞 IO,主要是因为 NIO 在网络通信中的非阻塞特性被广泛使用。

NIO 实现了 IO 多路复用中的 Reactor 模型,一个线程 Thread 使用一个选择器 Selector 通过轮询的方式去监听多个通道 Channel 上的事件,从而让一个线程就可以处理多个事件。

通过配置监听的通道 Channel 为非阻塞,那么当 Channel 上的 IO 事件还未到达时,就不会进入阻塞状态一直等待,而是继续轮询其它 Channel,找到 IO 事件已经到达的 Channel 执行。

因为创建和切换线程的开销很大,因此使用一个线程来处理多个事件而不是一个线程处理一个事件具有更好的性能。

应该注意的是,只有套接字 Channel 才能配置为非阻塞,而 FileChannel 不能,为 FileChannel 配置非阻塞也没有意义。

<div align="center"> <img src="../pics//4d930e22-f493-49ae-8dff-ea21cd6895dc.png"/> </div><br>

### 1. 创建选择器
Expand Down Expand Up @@ -394,7 +406,7 @@ int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
int num = selector.select();
```

使用 select() 来监听事件到达,它会一直阻塞直到有至少一个事件到达。
使用 select() 来监听到达的事件,它会一直阻塞直到有至少一个事件到达。

### 4. 获取到达的事件

Expand Down Expand Up @@ -514,10 +526,6 @@ public class NIOClient

内存映射文件 I/O 是一种读和写文件数据的方法,它可以比常规的基于流或者基于通道的 I/O 快得多。

只有文件中实际读取或者写入的部分才会映射到内存中。

现代操作系统一般会根据需要将文件的部分映射为内存的部分,从而实现文件系统。Java 内存映射机制只不过是在底层操作系统中可以采用这种机制时,提供了对该机制的访问。

向内存映射文件写入可能是危险的,仅只是改变数组的单个元素这样的简单操作,就可能会直接修改磁盘上的文件。修改数据与将数据保存到磁盘是没有分开的。

下面代码行将文件的前 1024 个字节映射到内存中,map() 方法返回一个 MappedByteBuffer,它是 ByteBuffer 的子类。因此,您可以像使用其他任何 ByteBuffer 一样使用新映射的缓冲区,操作系统会在需要时负责执行映射。
Expand All @@ -530,8 +538,8 @@ MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, 1024);

NIO 与普通 I/O 的区别主要有以下两点:

- NIO 是非阻塞的。应当注意,FileChannel 不能切换到非阻塞模式,套接字 Channel 可以。
- NIO 面向块,I/O 面向流
- NIO 是非阻塞的
- NIO 面向块,I/O 面向流

# 八、参考资料

Expand Down
8 changes: 4 additions & 4 deletions notes/Java 基础.md
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ System.out.println(InterfaceExample.x);
使用抽象类:

- 需要在几个相关的类中共享代码。
- 需要能控制继承来的方法和域的访问权限,而不是都为 public
- 需要能控制继承来的成员的访问权限,而不是都为 public
- 需要继承非静态(non-static)和非常量(non-final)字段。

使用接口:
Expand Down Expand Up @@ -763,10 +763,10 @@ try {
```

```html
java.lang.CloneNotSupportedException: CloneTest
java.lang.CloneNotSupportedException: CloneExample
```

以上抛出了 CloneNotSupportedException,这是因为 CloneTest 没有实现 Cloneable 接口。
以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接口。

```java
public class CloneExample implements Cloneable {
Expand Down Expand Up @@ -1112,7 +1112,7 @@ Reflection is powerful, but should not be used indiscriminately. If it is possib
Throwable 可以用来表示任何可以作为异常抛出的类,分为两种: **Error** 和 **Exception**。其中 Error 用来表示 JVM 无法处理的错误,Exception 分为两种:

- **受检异常** :需要用 try...catch... 语句捕获并进行处理,并且可以从异常中恢复;
- **非受检异常** :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序奔溃并且无法恢复
- **非受检异常** :是程序运行时错误,例如除 0 会引发 Arithmetic Exception,此时程序崩溃并且无法恢复

<div align="center"> <img src="../pics//PPjwP.png" width="600"/> </div><br>

Expand Down
28 changes: 28 additions & 0 deletions notes/Java 容器.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,34 @@ List<String> synList = Collections.synchronizedList(list);
List<String> list = new CopyOnWriteArrayList<>();
```

CopyOnWriteArrayList 是一种 CopyOnWrite 容器,从以下源码看出:读取元素是从原数组读取;添加元素是在复制的新数组上。读写分离,因而可以在并发条件下进行不加锁的读取,读取效率高,适用于读操作远大于写操作的场景。

```java
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}

final void setArray(Object[] a) {
array = a;
}

@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
```

## LinkedList

### 1. 概览
Expand Down
Loading

0 comments on commit d6a733c

Please sign in to comment.