后端开发入坑

Java后端学习笔记

术语

三者的关系:
JDK包含JRE,而JRE包含JVM;

  • Java开发工具包(JDK):
    程序员在编写Java程序时使用的软件。
    JDK的安装目录
    1)bin
    最主要的是JDK自带的编译器(javac.exe);
    目前所有的IDE都有自己的编译器,而不用JDK bin目录中自带的。所以,在安装IDE时,你会发现它们只要求你选中JRE路径就OK了。
    2)include
    Java和JVM交互用的头文件;
    3)lib
    类库
    4)jre(bin、lib)
    Java运行时环境;
    jre/bin 中是 JVM,jre/lib 中是JVM工作所需的类库;

总的来说,JDK用于Java程序的开发,而JRE则是只能运行class源文件,而没有编译的功能。

  • Java运行时环境(JRE):
    仅仅有JVM还不能完成 .class类文件的执行,因为在解释 .class的时候JVM需要调用解释所需的类库(存放在 jre/lib 中)。
    JVM和 jre/lib 合起来就称为 JRE。

  • Java虚拟机(JVM):
    它是整个Java实现跨平台功能的核心;
    所有的Java程序,会首先被编译为 .class 的类文件(这种类文件可以在 JVM 上执行)。也就是说,class类文件并不直接与机器的OS交互,而是经过JVM间接的与OS交互,由JVM将程序解释给本地系统来执行。
    JVM通过抽象OS和CPU结构,提供了一种与平台无关的代码执行方法;不同的OS,JVM的具体实现也是互不相同的;JVM并不关心上层的Java源文件,它只关注由源文件生成的 .class 类文件。

  • Java SE、Java EE 和 Java ME
    SE(Standard Edition):
    用于桌面或简单服务器应用的Java平台;
    EE(Enterprise Edition):
    用于复杂服务器应用的Java平台;
    ME(Micro Edition):
    用于手机和其它小型设备的Java平台;

设置JDK

Mac上安装 Java JDK

1)下载JDK:Java SE - Downloads | Oracle Technology Network | Oracle

2)安装JDK
双击 dmg 文件进行安装;
测试JDK是否安装成功:

javac

查看已安装JDK的版本及路径:

/usr/libexec/java_home -V

查看当前JDK版本:

java -version

3)卸载JDK
查看已安装的JDK:

ls /Library/Java/JavaVirtualMachines/

仅仅删除JDK:

sudo rm -rf /Library/Java/JavaVirtualMachines/jdk<version>.jdk

删除JDK的插件plugins:

sudo rm -rf /Library/PreferencePanes/JavaControlPanel.prefPane
sudo rm -rf /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin
sudo rm -rf /Library/LaunchAgents/com.oracle.java.Java-Updater.plist
sudo rm -rf /Library/PrivilegedHelperTools/com.oracle.java.JavaUpdateHelper
sudo rm -rf /Library/LaunchDaemons/com.oracle.java.Helper-Tool.plist
sudo rm -rf /Library/Preferences/com.oracle.java.Helper-Tool.plist

4)管理多版本JDK
修改系统环境变量:

  • JAVA_HOME:JDK的安装目录,它能够使得其它相关环境变量的配置更加简洁。
  • CLASSPATH:它的作用是告诉JRE,在哪些目录下可以找到将要执行的Java程序所需的类或包。
  • PATH:将Java的bin加入到系统路径中,这样在命令行或其它程序就可以直接调用java、javac等命令了。
# 第一次配置
touch ~/.bash_profile
# 已配置过
vi ~/.bash_profile
# 设置相应的JDK
# 设置 JDK8
export JAVA_8_HOME=`/usr/libexec/java_home -v 1.8`
# 设置 JDK10
export JAVA_10_HOME=`/usr/libexec/java_home -v 10`

# 设置默认 JDK(使用 JDK8)
export JAVA_HOME=$JAVA_8_HOME
export CLASSPATH=.:$JAVA_8_HOME/lib/tools.jar:$JAVA_8_HOME/lib/dt.jar

# alias 命令动态切换 jdk 版本
alias JDK_8="export JAVA_HOME=$JAVA_8_HOME ; export CLASSPATH=.:$JAVA_8_HOME/lib/tools.jar:$JAVA_8_HOME/lib/dt.jar"
alias JDK_X="export JAVA_HOME=$JAVA_10_HOME"

刷新环境变量,并查看当前的JDK版本:

source ~/.bash_profile
java -version

5)使用命令行编译并运行Java程序

public class FirstApp
{
        public static void main(String[] args)
        {
                System.out.println("My first Java app!");
        }
}  

编译并运行

javac FirstApp.java
java FirstApp
  • javac 程序是一个Java编译器。它将 .java 源文件编译成 .class 目标文件
  • java 程序启动 JVM,JVM执行编译器放在 .class 目标文件中的字节码
Tomcat for Mac 的下载与安装
  • 下载:Apache Tomcat® - Welcome!
  • 安装:
    1)解压包,然后将它放入 “/Users/计算机名/Library/…” 目录下,并重命名为 ApacheTomcat(为了之后配置更方便);
    或者
    不修改默认的目录名,而是创建 Tomcat 目录,然后在该目录下创建一个软链接
ln -s apache-tomcat-x.x.x Home

这样,就可以轻松的用 /Library/Tomcat/Home 去访问 tomcat 了。这种做法的好处是,如果以后 tomcat 有了新版本,就直接将 Home 指向新版本即可,其它有关 tomcat 路径引用的配置不需要修改。
2)启动Tomcat

cd /Users/计算机名/Library/ApacheTomcat/bin
./startup.sh
或者
cd /Users/计算机名/Library/Tomcat/Home/bin
./startup.sh

如果出现 “Tomcat started” ,说明Tomcat启动成功;
如果出现 “-bash: ./startup.sh: Permission denied”,需要修改权限

chmod u+x ./*.sh
指令解析:
    u   文件所有者
    +x  添加可执行权限
    ./  当前目录
    *.sh 所有.sh文件 

3)验证安装是否成功
在浏览器地址栏输入:http://localhost:8080,显示如下界面,说明安装成功:
[image:43BD1F00-15AB-481D-B8DA-B4B263D77B38-33499-000098C37CC7D32E/屏幕快照 2018-06-06 上午11.00.48.png]
如果出现 “Tomcat started”,但是无法访问 http://localhost:8080,那么需要重启 tomcat。

必须先 shutdown
./shutdown.sh
然后再 startup
./startup.sh

4)关闭Tomcat

./shutdown.sh

5)查看Tomcat版本信息

sh catalina.sh version

6)Tomcat目录结构

  • bin:存放Tomcat命令
  • conf:存放Tomcat配置信息(server.xml是核心的配置文件)
  • lib:支持Tomcat软件运行的jar包和技术支持包(如 Servlet和JSP)
  • logs:日志信息
  • temp:临时目录
  • webapps:共享资源文件和web应用目录
  • work:Tomcat的运行目录(JSP运行时产生的临时文件就存放在这里)
    7)修改端口号
    服务器的默认端口是8080;
    为了避免与系统端口冲突,必须设置1024以上的端口号,如 8888
cd /Users/计算机名/Library/ApacheTomcat/conf
mvim server.xml
或者
cd /Users/计算机名/Library/Tomcat/Home/conf
mvim server.xml
找到 <Connector port="8080"... 修改 port="8080" 为 8888
重启服务器,设置生效

8)用户名、密码设置

cd /Users/计算机名/Library/ApacheTomcat/conf
mvim tomcat-users.xml
或者 
cd /Users/计算机名/Library/Tomcat/Home/conf
mvim 
在</tomcat-users>中添加如下代码:
<role rolename="manager-gui"/>
<user username="admin" password="1234qwer" roles="manager-gui"/>
重启服务器,设置生效
重新打开 http://localhost:8080 到Tomcat主界面,点击 Manager App 等按钮,输入账号和密码,即可登陆Tomcat
IDEA进行Java开发配置

1)IntelliJ IDEA 版本比较和区别:

  • Ultimate:For web and enterprise development
  • Community:For JVM and Android development

2)配置JDK

Configure -> Project Defaults -> Project Structure
New新建Mac上已安装的JDK

3)IDEA创建javaWeb项目步骤

  • Create New Project
    [image:C1FCAD18-E642-4493-A50F-4BD7DD33609A-33499-0000B1A411B735E2/屏幕快照 2018-06-07 上午9.39.48.png]
    选择对应的Project SDK,然后勾选 Web Application,点击 Next
  • 自定义修改对应的工程名和路径等
    [image:DCCDC5B9-2F6A-4055-803C-276615A0BC8C-33499-0000B1CDD29B3E6F/屏幕快照 2018-06-07 上午9.42.23.png]
  • 优化项目的层次结构
    [image:378104DF-E5F3-4637-8C29-2AD9A7642A8B-33499-0000B1F52F38EA3A/屏幕快照 2018-06-07 上午9.46.00.png]
    WEB-INF文件夹下,分别创建 classes 和 lib 两个文件夹;
    其中,classes 用于存放编译后输出的 .class 文件, lib 用于存放第三方jar包。
  • 配置class文件存放的路径
    [image:936C43F2-0B6E-44EA-A17E-9E75AFEDAF43-33499-0000B24638910952/屏幕快照 2018-06-07 上午9.49.48.png]
    [image:9CF5690A-B7BD-4DC6-A5AE-CEFD5A1EC8BC-33499-0000B24939401DBE/屏幕快照 2018-06-07 上午9.50.28.png]
    [image:6A65997D-5DA4-4A67-A4AC-F42F346184E9-33499-0000B24B26390AB5/屏幕快照 2018-06-07 上午9.51.18.png]
    “Use module compile output path” 中,修改path为 WEB-INF 中创建的 classes 文件夹路径;
  • 配置lib文件存放的路径
    [image:2CF1F7F3-2AB6-4676-A93A-20A68697B3EA-33499-0000B27EB1D36B64/屏幕快照 2018-06-07 上午9.55.41.png]
    [image:C01183BD-6293-4FED-9156-6778020C73E8-33499-0000B2986604BD9D/屏幕快照 2018-06-07 上午9.56.59.png]
    [image:3E885D0D-4EA6-4166-93C7-DD0F35A0D346-33499-0000B29A9BC67B5E/屏幕快照 2018-06-07 上午9.57.14.png]
    Modules -> Dependencies -> + JARs or directories -> 选择WEB-INF中创建的lib文件夹 -> Jar Directory -> 完成

4)IDEA中配置本地服务器(Tomcat)

  • 点击 Edit Configurations...
    [image:AE7A386C-97B8-4DBF-A5BD-D204A8D44643-33499-0000B3161EBA08CE/屏幕快照 2018-06-07 上午10.05.39.png]
  • 添加 Tomcat 本地服务器
    [image:19508F1F-CDAA-416A-AE22-E95C3A52882C-33499-0000B32551C68130/屏幕快照 2018-06-07 上午10.07.31.png]
  • 修改本地Tomcat名字、配置Tomcat路径
    [image:AC90A821-4C2A-4367-BCDE-ACE51A9D342F-33499-0000B344F7855C4D/屏幕快照 2018-06-07 上午10.09.03.png]
  • 添加 Artifact…
    [image:C991AA5D-C0F5-414E-A285-72F2D2EED74D-33499-0000B35AFD329318/屏幕快照 2018-06-07 上午10.11.22.png]
  • 修改index.jsp并运行
    [image:A5819D51-74ED-48BE-94FB-AB14AA2CCC4D-33499-0000B37D535911C2/屏幕快照 2018-06-07 上午10.14.07.png]

::注意:在启动WebApp之前,一定要先关闭本地配置的Tomcat服务器,否则会出现端口号被占用的警告,导致无法显示期望的界面!::
[image:185EF565-F92B-488D-8616-7A8A46F0E107-33499-0000B3B8F8E86860/屏幕快照 2018-06-07 上午10.17.01.png]

构建并运行applet(过去的记忆)

JavaApplet 就是用 Java 编写的小应用程序,可以直接嵌入到网页中,并能够产生特殊的效果。
Applet的工作原理:
含有Applet的网页的HTML文件源代码中带有<applet> 和</applet>这样一对标记。当支持Java的网络浏览器遇到这对标记时,就将下载相应的小应用程序代码并在本地计算机上执行该Applet。

Java的基本程序设计结构

一个简单的Java应用程序
public class FirstSample
{
    public static void main(String[] args)
    {
        System.out.println("Hello, World!");
    }
}
  • 程序分析
    1)Java区分大小写;
    2)关键词 public(访问修饰符 access modifier):
    用于控制程序的其它部分对这段代码的访问级别;
    延伸学习:public、protected、default 和 private
    3)关键字 class:
    表明Java程序中的全部内容都必须包含在类中;
    这里,只需将 类 作为一个加载程序逻辑的容器,程序逻辑定义了应用程序的行为。
    4)Java中类的命名规则:
    必须字母开头,字母和数字的任意组合;
    标准的类命名规范是采用 CamelCase(骆驼命名法)。
    5)Java中,源代码的文件名必须与公共类的名字相同,并用 .java 作为扩展名(注意,一定注意大小写)。
    6)编译 FirstSample.java 源文件:
javac FirstSample.java

编译后,会得到一个包含这个类字节码的目标文件 FirstSample.class
运行 FirstSample 程序:

java FirstSample

注意:请记住,不要添加 .class 扩展名!
7)根据Java语言规范,main() 方法必须声明为 public
请记住:每个Java应用程序都必须有一个main方法,其声明格式如下:

public class /ClassName/
{
    public static void main(String[] args)
    {
        /program statements/
    }
}

8)大括号 { } 的使用规则:
Java中,习惯于把匹配的大括号上下对齐。
9)关键字 static
方便于在没有创建任何对象的前提下,仅仅通过类本身来调用 static (静态)方法/变量。
在 static 方法内部,不能调用非静态方法/变量,反过来是可以的。
10)使用 System.out 对象,并通过 (.)调用了它的 println 方法。
11)Java中的3种注释
单行注释: //
多行注释: /* 和 / (注释不能嵌套)
自动生成文档注释: 以 /
* 开始,以 */ 结束

Java数据类型

1)Java是强类型语言(意味着必须为变量声明类型);
2)Java中的8种基本类型(primitive type):

  • 整型(int 4、short 2、long 8 和 byte 1)
  1. 通常使用 int 和 long,short 和 byte 类型主要用于特定的应用场合;
  2. ::在Java中,整型的范围与运行Java代码的机器无关。(这就解决了软件从一个平台移植到另一平台,或者在同一平台中的不同OS之间进行移植给程序员带来的诸多问题)::
  3. 注意,Java中没有任何无符号(unsigned)形式的整型;
  • 浮点类型(float 4、double 8)
  1. 很多情况下,float 类型的精度不能满足实际需求。所以,一般都采用double 类型;(float 类型用后缀 F/f 标识,double 用 D/d 或 缺省)
  2. 用于表示溢出和出错的三个特殊浮点数值:
    正无穷大 Double.POSITIVE_INFINITY
    负无穷大 Double.NEGATIVE_INFINITY
    NaN Double.NaN
    ::特别说明,不能通过 if(x == Double.NaN) 的方式来检测一个特定值是否等于 Double.NaN ;而需要使用 if (Double.isNaN(x)) 方法。::
  • 字符类型char(用于表示Unicode编码的字符单元)
  1. 之前,char类型用于表示单个字符;如今,有一些Unicode字符需要用两个char值来描述。
  2. char 类型的值可以表示为十六进制值,范围从 \u0000 ~ \uffff;
    ::警告,Unicode转义序列会在解析代码之前得到处理。::
    如:”\u0022+\u0022” 并不会得到字符串 ““+””,而是会得到一个空串“”。
    ::注意,一定要注意注释中的 \u::
    如:// \u000d is a newline 会产生语法错误(\u000d 会替换成换行符)。
  3. 我们强烈建议不要在程序中使用char类型!!!
  • boolean类型(false、true)
    整数值和布尔值之间不能进行相互转换(C++中是可以的);
if (x = 0) {} // 不能通过编译(整数表达式 x = 0 不能转换为布尔值)
变量

1)不提倡在一行中声明多个变量;

int i, j;   // 不提倡

2)声明一个变量之后,必须用赋值语句对变量进行显式初始化;
::在Java中,不区分变量的声明与定义;::

// C/C++
int i = 10; // 定义
extern int i;   // 声明
常量

1)Java中,使用关键字final指示常量;习惯上,常量名使用全大写。

final double CM_PER_INCH = 2.54;

2)类常量(可以在一个类中的多个方法中使用):static final

public class Sample
{
    public static final double CM_PER_INCH = 2.54;

    public static void main(String[] args)
    {
        System.out.println("1 inch is " + CM_PER_INCH + "cm");
    }
}
运算符

注意,整数被0除,将会产生一个异常;而浮点数被0除将会得到无穷大或NaN结果。

100/0;  // 异常
88.8/0; // 无穷大 或 NaN
数学函数
  • Math类函数
    如:floorMod
import static java.lang.Math.*;

public class FirstApp
{
    public static void main(String[] args)
    {
        int result = (-5)%2;
        System.out.println("(-5)%2 is equal: " + result);

        int fmResult = floorMod(-5, 2);
        System.out.println("Math.floorMod(-5, 2) is equal: " + fmResult);   
    }
}
强制类型转换

::警告:如果试图将一个数值做强制类型转换,而又超出了目标类型的表示范围,结果将会被截断成一个不同的值。::
::如:(byte)300 的实际值为 44::

关系运算符和位运算符

1)==、!=、>、<=、&&、|| 、!和 三元操作符 ? :
其中,&& 和 || 是按照“短路”方式求值的(也就是,如果第一个操作已确定表达式的值,那么就不计算第二个操作数了);
2)&、|、^ 和 ~
::注意,当位运算符 & 和 | 应用在boolean上时,不采用“短路”方式求值。(也就是说,得到计算结果之前,两个操作数都需要计算)::
3)>>、<< 和 >>> 移位运算符
::警告:移位运算符的右操作数要完成 模32 的运算(如果左操作数是long型,需要对右操作数做 模64 运算)。::
如:1 << 35 的值等同于 1 << 3,也就是 8
::>> 和 >>> 的区别:::
::>>> 运算符用0填充高位,而 >> 用符号位填充高位。::

字符串

1)Java没有内置的字符串类型,而是在标准Java类库中提供了一个预定义类

String nilStr = ""; // 空串
String greeting = "Hello String!";
String subS = greeting.subString(0, 3); // "Hel"
// 注意,subString方法的第二个参数表示,不想复制的第一个位置。

2)拼接字符串
当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串(任何一个Java对象都可以转换成字符串)。

int age = 30;
String rating = "PG" + age;

String all = String.join(" /", "N", "B", "A");
// 输出:"N /B /A"

3)字符串比较
注意,一定不要使用 == 运算符检测两个字符串是否相等。

s1.equals(s2)
"Hello".equals(greeting)
"Hello".equalsIgnoreCase("hello")

4)空串”” 和 null串

// 判断空串
if (str.length() == 0)
// 或
if (str.equals(""))
// 判断null串
if (str == null)

5)构建字符串
采用字符串拼接的方式,效率比较低(因为每次连接字符串,都会构建一个新的String对象)。

StringBuilder builder = new StringBuilder();
builder.append("abc");
builder.append("XYZ");
String completedStr = builder.toString();
System.out.println(completedStr);       // abcXYZ

6)String API

输入输出
  • 读取输入
    1)构造 Scanner 对象:
import java.util.*;

// 构造 Scanner 对象,并与“标准输入流” System.in 关联
Scanner in = new Scanner(System.in);
// 使用 nextLine() 方法,是因为在输入行中可以包含空格;
// 如果想要读取一个单词(以空白符为分隔符),可使用 next() 方法;
System.out.print("What is your name? ");
String name = in.nextLine();
// 读取整数 nextInt();
// 读取浮点数 nextDouble();
System.out.print("How old are you? ");
int age = in.nextInt();

System.out.println("Hello " + name + ". Next year, you'll be " + (age + 1));

注意,Scanner 类的输入是可见的,所以不适用于从控制台读取密码。
2)Console 类

import java.io.Console;

Console cons = System.console();
String username = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password: ");

cons.printf("username is %s and password is %s\n", username, String.valueOf(passwd));

::为了安全起见,返回的密码存放在一维字符数组中,而不是字符串中。::
::在对密码进行处理后,应该马上用一个填充值覆盖数组元素。::

Console 和 Scanner 类比较:Console类每次只能读取一行输入,而没有能够去读一个单词或一个数值的方法。

  • 格式化输出
System.out.printf();

::注释,可以使用 %s 转换符格式任意的对象。::

使用String类的静态方法 String.format 来创建一个格式化的字符串:

String message = String.format("Hello, %s.\nNext year, you'll be %d", name, age);
  • 文件输入与输出
控制流程

::Java中的控制流程,没有goto语句,但是 break 语句可以带标签。::

  • 块(block)作用域
    1)块block 是指用 {} 括起来的若干条Java语句;
    2)块 确定了变量的作用域;
    3)块 可以嵌套;
    ::警告,不能在嵌套的 块block 中声明同名的变量(C++ 中可以)。::
public static void main()
{
    int n = 2;
    ...
    {
        int n = 4;  // Error: redefine n in inner block
        ...
    }
}
  • 条件语句
if (/condition/)
{
    /statement1/
    ...
}
else
    /statement/
  • 循环
while (/condition/) /statement/ 
// or
do /statement/ while (/condition/);
// or
for (;;)
{
    /statement1/
    ...
}
// or 通用for循环(for each循环)
for (/variable/ : /collection/)
{
    /statement/
}
  • 多重选择:switch语句
switch (/tag/)
{
    case /value1/:
        ...
        break;
    case /value2/:
        ...
        break;
    default:
        ...
        break;
}

case标签tag的类型:
1)char、byte、short或int等常量表达式;
2)枚举常量;
3)字符串字面量;

大数值
  • BigInteger:实现了任意精度的整数运算。
// valueOf() 静态方法
BigInteger a = BigInteger.valueOf(100);
// + 和 * 算数运算的实现
BigInteger b = BigInteger.valueOf(a+10);
BigInteger c = a.add(b);    // c = a+b
BigInteger d = c.multiply(a.add(b));    // d = c*(a+b)
  • BigDecimal:实现了任意精度的浮点数运算。
数组
  • 数组的声明与创建
int[] a;    // 推荐
// 或
int a[];
// 创建
int[] a = new int[100];

数组创建成功后,不同类型的数组,会有不同的初始化值:
1)数字数组 -> 0
2)boolean数组 -> false
3)对象数组 -> null

String[] names = new String[10];        // 所有字符串都为null

::数组一旦创建,就不能在改变它的大小(可以改变每个数组的元素)。::
::如果需要扩展数组的大小,需要使用 -> 数组列表(array list)::

  • for each 循环:循环变量将会遍历数组中的每一个元素,而不需要使用下标。
for (String element : names)
    System.out.println(element);
  • 数组初始化及匿名数组
int[] smallPrimes = {1, 5, 3, 9};

// 匿名数组
smallPrimes = new int[] {2, 8, 10, 4};  // 这种语法形式可以在不创建新变量的情况下重新初始化一个数组

::Java中,允许数组长度为0。这在编写一个返回值为数组的方法,结果恰巧为空时,非常有用!::

new elementType[0];
  • 数组拷贝
    1)直接拷贝(两个变量引用同一数组)
int[] smallPrimes = {1, 3, 5, 7};
int[] luckyNumbers = smallPrimes;
luckyNumbers[1] = 4;    // 现在 smallPrimes[1] 也是 4

System.out.printf("luckyNumbers[1] is %d, smallPrimes[1] is %d.\n", luckyNumbers[1], smallPrimes[1]);

2)使用Arrays类的copyOf静态方法

int[] smallPrimes = {1, 3, 5, 7};
int[] luckyNumbers = Arrays.copyOf(smallPrimes, smallPrimes.length);
luckyNumbers[1] = 4;    // 现在 smallPrimes[1] 依旧是 3
  • 多维数组
// 声明
int[][] magicSquare;
// 初始化
magicSquare = new int[2][3];
// 声明并初始化
int[][] magicSquare = 
{
    {1, 2, 3},
    {7, 8, 9},
};
  • 不规则数组:数组的每一行有不同的长度。
    ::Java实际上没有多维数组,只有一维数组。多维数组被解释为“数组的数组”::
for (int i = 0; i < odds.length; i++)
    for (int j = 0; j < odds[i].length; j++)
    {
        ...
        odds[i][j] = x;
    }

对象与类

Web基础

Http协议

关于Http协议

  • HTTP简介
    1)HTTP(Hyper Text Transfer Protocol)
    用于从WWW服务器传输超文本到本地浏览器的传输协议。
    2)
    HTTP是基于 TCP/IP 通信协议来传递数据;
    HTTP是一个属于应用层的面向对象协议;
    HTTP协议工作于 客户端-服务器(C-S) 架构上;
  • HTTP主要特点
    1)简单快速:C -> S 请求服务时,只需传送“请求方法”和“路径”(如:GET、POST、HEAD等,每种方法规定了C和S间不同的联系类型)。
    2)灵活:HTTP允许传送任意类型的数据对象(类型由 Content-Type 标记)。
    3)无连接:无连接的含义是,限制每次连接只处理一个请求(S处理完C的请求,并收到C的应答后,立即断开连接)。
    4)无状态:HTTP协议是无状态协议。
  • HTTP之URL
    1)HTTP使用 URI(Uniform Resource Identifiers)统一资源标识符 来传输数据和建立连接。
    2)URL(Uniform Resource Locator)统一资源定位符 是一种特殊类型的 URI,包含了用于查找某个资源的足够信息。
    3)分析URL:
    http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name

协议部分:“http:” (常见协议还有 FTP、HTTPS等); “//”是分隔符。
域名部分:“www.aspxfans.com” (也可使用IP地址作为域名使用)。
端口部分:跟在域名后的就是端口(域名和端口号之间用 “:” 分割);端口不 是URL中必须的,如果缺省,将采用默认端口。
虚拟目录部分:从域名后第一个 “/” 开始到最后一个 “/” 为止(可缺省)。
文件名部分:从域名后的最后一个 “/” 开始到 “?” 为止(可缺省);如果没有 “?”,那么到 “#” 为止;如果都没有,那么到结束,都是文件名部 分。
参数部分:从 “?” 开始到 “#” 为止,之间的部分都是参数部分(参数之间用 “&” 分割)。
锚部分:从 “#” 开始到最后,都是锚部分。

  • HTTP之请求消息Request
    [image:20CBD126-E11A-45C7-9F53-8285DE7C240C-33499-0000E7906F29D35F/2964446-fdfb1a8fce8de946.png]
    POST请求例子(使用Charles抓取的request):
POST / HTTP1.1
Host:www.wrox.com
User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
Content-Type:application/x-www-form-urlencoded
Content-Length:40
Connection: Keep-Alive

name=Professional%20Ajax&publisher=Wiley

请求行:用来表明请求类型,访问的资源以及使用的HTTP版本。
请求头:用来说明服务器要使用的附加信息。
空行:请求头后面的空行是必须的。
请求数据:也叫主体,可以添加任意数据。

  • HTTP之响应消息Response
    [image:25FC2229-9FA7-4E43-A3F0-15FF3461BCE0-33499-0000E80F450B99B3/2964446-1c4cab46f270d8ee.jpg]
    HTTP响应例子:
HTTP/1.1 200 OK
Date: Fri, 22 May 2009 06:07:21 GMT
Content-Type: text/html; charset=UTF-8

<html>
      <head></head>
      <body>
            <!--body goes here-->
      </body>
</html>

状态行:由 HTTP协议版本号,状态码,状态消息 三部分组成。
消息报头:用来说明客户端要使用的一些附加信息。
空行:消息报头后的空行是必须的。
响应正文:服务器返回给客户端的文本信息。

  • HTTP之状态码
    1xx:指示信息 -> 表示请求已接收,继续处理
    2xx:成功 -> 表示请求已被成功接收、理解、接受
    3xx:重定向 -> 要完成请求必须进行更进一步的操作
    4xx:客户端错误 -> 请求有语法错误或请求无法实现
    5xx:服务器端错误 -> 服务器未能实现合法的请求
    常见状态码:
200 OK                        //客户端请求成功
400 Bad Request               //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized              //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 
403 Forbidden                 //服务器收到请求,但是拒绝提供服务
404 Not Found                 //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error        //服务器发生不可预期的错误
503 Server Unavailable        //服务器当前不能处理客户端的请求,一段时间后可能恢复正常
  • HTTP请求方法
GET     请求指定的页面信息,并返回实体主体。
HEAD        类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
POST        向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
PUT     从客户端向服务器传送的数据取代指定的文档的内容。
DELETE  请求服务器删除指定的页面。
CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
OPTIONS 允许客户端查看服务器的性能。
TRACE       回显服务器收到的请求,主要用于测试或诊断。
  • HTTP工作原理
    1)HTTP协议 定义了Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。
    2)HTTP协议 采用了 请求/响应 模型。
    3)HTTP 请求/响应 步骤:
1. 客户端连接到Web服务器
一个HTTP客户端(通常是浏览器),向Web服务器请求解析URL中的域名对应的IP地址;然后根据IP地址和HTTP端口(默认是80)建立一个TCP套接字连接。
2. 发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个请求报文(一个请求报文 由 请求行、请求头、空行 和 请求数据 4部分组成)。
3. 服务器接收请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取(一个响应 由 状态行、响应头部、空行 和 响应数据 4部分组成)。
4. 释放TCP连接
如果 connection 模式为 close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;
如果 connection 模式为 keepalive,则该连接会保持一段时间,在该时间段内,可以继续接收请求。
5. 客户端浏览器解析HTML内容
客户端首先解析状态行,查看表明HTTP请求成功与否的状态代码;
然后解析每一个响应头。
  • GET和POST请求的区别
    GET请求:
GET /books/?sex=man&name=Professional HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive

::注意,最后一行是空行::

POST请求:

POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive

name=Professional%20Ajax&publisher=Wiley

1)
GET提交,请求的数据会附在URL之后(就是把数据放在 HTTP协议头中),用 “?” 分割URL和传输的数据,参数间用 “&” 连接;
POST提交,请求的数据放置在HTTP的请求主体中;
::因此,GET提交的数据会在地址栏中显示,而POST提交不会。::
2)传输数据的大小:
::首先声明,HTTP协议没有对传输的数据大小进行限制,也没有对URL长度进行限制。::
在实际的开发中,URL和传输数据的大小都存在限制。
GET:特定浏览器和服务器对URL长度有限制
POST:Web服务器会规定对post提交的数据大小进行限制
3)
GET:方式通过Request.QueryString来取得变量的值;
POST:方式通过Request.Form来获取变量的值。
4)安全性:
POST的安全性高于GET。
比如,通过GET提交数据,用户名和密码会将明文显示在URL上
5)get、post和soap
get:请求参数是作为一个key/value对的序列(查询字符串)附加到URL上,并且查询字符串的长度受到Web浏览器和服务器的限制。因此,不适合传输大型数据集,同时它很不安全。
Post:请求参数放置在请求主体中,因此必须将Content-type设置为application/x-www-form-urlencoded。它不支持复杂数据类型。
Soap:post请求的一个专用版本,遵循一种特殊的xml消息格式。因此,Content-type设置为: text/xml,任何数据都可以xml化。

HTTP协议定义了很多与服务器交互的方法,最基本的有:
GET、POST、PUT和DELETE
一个URL地址用于描述网络上的一个资源,而HTTP中GET、POST、PUT、DELETE分别对应着对这个资源的 查、改、增、删 4个操作。

::GET一般用于 获取/查询 资源信息;而POST一般用于更新资源信息。::

TCP协议详解

TCP协议详解

  • TCP/IP协议的由来
在世界各地,每台电脑运行着各自不同的操作系统为我们服务,它们在表达同一信息的时候所使用的方法千差万别。
这就好像圣经中,上帝打乱了世界各地人的口音,让彼此无法正常合作一样。
于是,人们就想方设法的将电脑连接到了一起。
但是,简单的将电脑连接到一起还远远不够,就好像语言不通的两个人见面了,也同样是不能交流信息。
TCP/IP因此而生。
TCP/IP不是一个协议,而是一个协议族的统称。
  • TCP/IP协议分层
    [image:E33A019E-9340-4525-9892-9E87F66199D3-33499-0000F201CA36F783/2964446-1fd7a0f3216c0530.jpg]
    1)应用层:向用户提供了一组常用的应用程序。
    2)传输层:提供应用程序间的通信。
    功能:
    一、格式化信息流
    二、提供可靠传输(传输层协议规定,接收端必须发回确认,并且假如分组丢失,必须重新发送)
    3)网络层:负责相邻计算机之间的通信
    功能:
    一、处理来自传输层的分组发送请求:收到请求后,将分组装入IP数据报,填充报头,选择去往信宿机的路径,然后将数据报发往适当的网络接口。
    二、处理输入数据报:首先检查其合法性,然后进行寻径。假如该数据报已到达信宿机,则去掉报头,将剩下部分交给适当的传输协议;假如该数据报尚未到达信宿,则转发该数据报。
    三、处理路径、流控、拥塞等问题。
    4)网络接口层
    这是TCP/IP软件的最低层,负责接收IP数据报并通过网络发送之,或者从网络上接收物理帧,抽出IP数据报,交给IP层。

  • IP、IP地址 和 IP路由器
    1)IP用于计算机之间的通信;
    2)IP是无连接的通信协议;
    3)通过IP,消息(或其它数据)被分割成小的独立的包,并通过Internet在计算机之间传送;
    4)每台计算机必须有一个IP地址,才能够连入Internet,作为网络中的一个节点;
    5)注意,IP地址是 网络号+主机号 的组合;
    6)当一个 IP 包从一台计算机被发送,它会到达一个 IP 路由器;
    IPI路由器负责将这个包(直接地或通过其它路由器)路由至它的目的地;
    在一个相同的通信中,一个IP包所经由的路径可能会和其他的包不同,而路由器负责根据通信量、网络中的错误或者其它参数,来进行正确地寻址。

  • TCP
    1)TCP用于应用程序间的通信;
    2)当应用程序希望通过TCP与另一应用程序通信时,它会发送一个通信请求(这个请求必须被送到一个确切的地址)。
    在双方“握手”之后,TCP 将在两个应用程序之间建立一个全双工 (full-duplex) 的通信。

  • 域名
    1)12位的阿拉伯数字;
    2)使用名字作为域名,比如 www.jd.com
    3)DNS服务器负责将 域名 翻译成 TCP/IP地址,同时负责使用新的域名信息更新彼此的系统。

  • TCP/IP
    1)TCP/IP 意味着 TCP 和 IP 在一起协同工作。
    2)TCP 负责应用软件(比如你的浏览器)和网络软件之间的通信;
    IP 负责计算机之间的通信。
    3)TCP 负责将数据分割并装入 IP 包,然后在它们到达的时候重新组合它们;
    IP 负责将包发送至接受者。

  • TCP三次握手
    1)6位标志域

URG:紧急标志(“1”表明该位有效)
ACK:确认标志
PSH:推标志(该标志置位时,接收端不将该数据进行队列处理,而是尽可能快地将数据转由应用处理)
RST:复位标志(用于复位相应的TCP连接)
SYN:同步标志(该标志仅在三次握手建立TCP连接时有效)
FIN:结束标志

2)所谓三次握手(Three-Way Handshake)即建立TCP连接
[image:1F08A71C-0279-47D9-8DE2-0AB00132ECE9-33499-0000F4FF95386F88/2964446-aa923712d5218eeb.png]
建立一个TCP连接时,需要 Client 和 Server 总共发送 3 个包以确认连接的建立(在 socket 编程中,这一过程有客户端执行 connect 来触发)。

  1. 第一次握手:Client 将标志位 SYN 置为 1,并随机产生一个值 seq = J,然后发送该数据包给 Server。此时,Client 进入 SYN_SENT 状态,等待 Server 确认。
  2. 第二次握手:Server 收到数据包后,由标志位 SYN=1 知道 Client 请求建立连接。于是,Server 将标志位 SYN 和 ACK 都置为 1,ack = J+1,并随机产生一个值 seq = K,然后发送数据包给 Client 以确认连接请求。此时,Server 进入 SYN_RCVD 状态。
  3. 第三次握手:Client 收到确认后,检查 ack 是否等于 J+1,ACK是否等于 1。如果都正确,就将标志位 ACK 置为 1,ack = K+1,然后将数据包发送给 Server。 Server 端检查 ack 是否等于 K+1,ACK 是否等于 1。如果都正确,则连接建立成功。
    此时,Client 和 Server 都进入 ESTABLISHED 状态,完成第三次握手。
    随后,Client 和 Server 之间就可以开始传输数据了。

SYN攻击:
在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect)。此时,Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。
SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认。由于源地址是不存在的,因此Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。
SYN攻击时一种典型的DDOS攻击。检测SYN攻击的方式:即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了。
检测SYN攻击的终端指令:
#netstat -nap | grep SYN_RECV

  • TCP四次挥手
    1)所谓四次挥手(Four-Way Wavehand)即终止TCP连接
    [image:7DB66895-82F6-4ECE-A250-C3FE0003FC10-33499-0000F6628BAFE971/2964446-2b9562b3a8b72fb2.png]
    断开一个TCP连接时,需要 Client 和 Server 总共发送 4 个包以确认连接的断开(在socket编程中,这一过程由客户端或服务端任一方执行close来触发)。
    ::由于TCP连接是双全工的,因此每个方向都必须要单独进行关闭。::
    1)第一次挥手:Client 发送一个 FIN,用来关闭 Client 到 Server 的数据传送。此时 Client 进入 FIN_WAIT_1 状态。
    2)第二次挥手:Server 收到FIN后,发送一个ACK给 Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),此时Server 进入 CLOSE_WAIT状态。
    3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
    4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,100评论 18 139
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,015评论 11 349
  • 每一次思绪的凌乱,都是记忆的选择性缅怀祭奠。 ——题记 喧嚣的城市,灰沉的暮色,时间在钟上停止,然后往事开始入侵。...
    开心爱阅读007阅读 308评论 2 2
  • 先说两个例子。 第一个例子,我前段时间参加公司针对建设欧洲分支机构的进度汇报。负责人在汇报中提到了原本定位为研发中...
    陈天寀阅读 864评论 6 9
  • 关于如何学习Vue,Vue的缔造者尤雨溪前辈曾经在知乎发表过一篇新手向:Vue 2.0 的建议学习顺序。笔者推荐使...
    HW_____T阅读 359评论 0 0