传智播客java - web笔记全套
更新时间:2024-01-29 13:50:01 阅读量: 教育文库 文档下载
Lesson 1
一、eclipse工具的使用
1. java代码的位置
1) 选择工作空间 workspace 选择一个文件夹存放程序(代码) 不要用中文和空格 2) 新建一个java 工程(Project)
3) 建包 建类
2. 快捷键
alt + / : 代码自动补齐,需要配置的 打开preferences(首选项), 搜keys,打开快捷键配置面板 搜 alt+/ ,取消绑定 搜 content assist ,取消原先的绑定,配置成alt+/
ctrl+1: 错误自动修复, 注意,放行的红叉是可修复的,圆形的是不可修复的 导包的三种方式:
1)将类名敲完整,按下alt+/ 进行补齐,会自动导包 2) ctrl+1,修正错误
3) ctrl+shift+o 整理包,导入需要的包,去掉多余的导包语句 ctrl+shift+f : 代码格式化 ctrl+2,L 自动声明变量
shift+enter 光标直接进入下一行 ctrl+alt+方向键(向上向下) 复制行 alt+ 方向键(向上向下) 移动当前行
3. 断点调试
1) 可以对程序进行调试
在行的开头双击左键打断点,用debug方式来运行程序,程序就会停留在断点位置
F5 跳入(step into) 跳入方法内部 F6 跳过, 让当前行运行 F7跳出 返回上一层程序 resume 直接运行到下一个断点
2) 查看源代码建议使用断点调试的方式,注意当前运行环境需要包含源码
4. junit单元测试
1) 写一个java类, 声明测试方式 修饰符为 public void , 在方法前面加注解,(@Test) 此方法就可以进行测试了(交给junit运行) 2) 需要在测试方法前做初始化工作
写一个静态方法 public static void init() 在方法前加注解 @BeforeClass 3) 需要在测试后释放资源 写一个静态方法
在方法前加注解 @AfterClass
1
二、jdk5新特性
1. 静态导入
1) 导入类的静态属性 import static java.lang.System.out; out.println(\ 2) 导入类的静态方法 import static java.lang.Math.*; // 导入Math类的所有静态成员 int num = abs(-10);
2. 增强for循环
1) 作用: 对存储对象的容器进行迭代 2) jdk5以前怎么迭代 3) 增强for循环迭代数组
String [] arr = {\// 传统方式 for(int i=0; i
int --> Integer byte --> Byte short --> Short long --> Long char --> Character double --> Double float --> Float
boolean --> Boolean
2
1) Integer x = 1; x = x + 1; 经历了什么过程? 装箱? 拆箱 ? 装箱
2) 为了优化,虚拟机为包装类提供了缓冲池, Integer池的大小 -128~127 一个字节的大小 3) String池 Java为了优化字符串操作 提供了一个缓冲池 面试题: String s = “abc” 和 String s = new String(“abc”) 的区别 String s = new String(“abc”) 创建了几个对象 String s = “a” + “b” + “c” + “d” 创建了几个对象 String s1 = “a” String s2 = “b” String s3 = s1 + s2; s3==”ab”? /*1. String s = \, 虚拟机首先会检查String池里有没有\对象(通过equals方法)
3
// 如果有,直接返回引用,如果没有,会在池里创建一个“abc”对象,并返回引用 String s1 = \String s2 = \System.out.println(s1==s2); // result: true */ /* 2. String str = new String(\// 此时,负责检查并维护缓冲池,其实堆内存的对象是缓冲池中\对象的一个拷贝 String s1 = new String(\String s2 = new String(\System.out.println(s1==s2); // result: false */ /* 3. String s = \编译器有个合并已知量的优化功能 // 在编译阶段就把\合并为 ”abcd“ String s = \System.out.println(s==\*/ /* 4. String s1 = \// String是常量,不能相加的,java如何实现的? StringBuilder sb = new StringBuidler(s1); sb.append(s2); s3 = sb.toString(); 也就是说实际上s3是方法返回的String对象 凡是方法返回的字符串对象都是在堆内存的 */ String s1 = \ String s2 = \ String s3 = s1 + s2; // 堆内存的对象 System.out.println(s3==\不管缓冲池是否有\都会在堆内存创建一个\对象,返回引用 // String s = \
4) 单列集合 Collection
List list = new ArrayList(); list.add(\list.add(\list.add(\ // 传统方式1 /* 1.获得迭代器 Iterator iter = list.iterator(); // 2.循环判断迭代器是否有下一个 while(iter.hasNext()) { } */ // 传统方式2 for(Iterator iter=list.iterator(); iter.hasNext(); ) { } System.out.println(\// 增强for循环, 没有使用泛型的集合能不能使用增强for循环迭代?能 for(Object obj : list) { } String s = (String) obj; System.out.println(s); String s = (String) iter.next(); System.out.println(s); String str = (String) iter.next(); // 将迭代器的指针移向下一个,并将迭代当前指向的元素返回 System.out.println(str);
5) 双列集合 Map
Map map = new HashMap(); map.put(\map.put(\map.put(\ // 传统方式迭代1 // 1. 获得所有的key Set keys = map.keySet(); // 2.迭代keys获得所有的key Iterator iter = keys.iterator(); while(iter.hasNext()) { } System.out.println(\ 4 String key = (String) iter.next(); // a b c // 3.根据key获得对应的value String value = (String) map.get(key); System.out.println(key + \ // 传统方式2,必须掌握这种方式 // 1.获得所有的键值对Entry对象 Set entrys = map.entrySet(); // 2.迭代出所有的entry iter = entrys.iterator(); while(iter.hasNext()) { } System.out.println(\System.out.println(\增强for循环迭代,\// 增强for循环迭代, // 原则上map集合是无法使用增强for循环来迭代的, // 因为增强for循环只能针对实现了Iterable接口的集合进行迭代 // Iterable是jdk5中新定义的接口,就一个方法iterator方法 // 只有实现了Iterable接口的类,才能保证一定有iterator方法 // java有这样的限定是因为增强for循环内部还是用迭代器实现的 // 而实际上,我们可以通过某种方式来使用增强for循环 for(Object obj : map.entrySet()) { } // obj 依次表示Entry Map.Entry entry = (Entry) obj; System.out.println(entry.getKey() + \Map.Entry entry = (Entry) iter.next(); // 分别获得key和value String key = (String) entry.getKey(); String value = (String) entry.getValue(); System.out.println(key + \6)集合迭代注意问题
// 在使用迭代器迭代集合的过程中,不能对集合进行增删操作 @Test public void test4() {
List list = new ArrayList(); list.add(\list.add(\list.add(\Iterator iter = list.iterator(); while(iter.hasNext()) { String name = (String) iter.next(); if(\ // 从集合中删掉 //list.remove(name); // 迭代过程中删除元素需要调用迭代器的方法 iter.remove(); // 删除我迭代的集合被我迭代的最后一个元素 5
} } } // 1 2 4 System.out.println(list.size()); @Test public void test5() { } List list = new ArrayList(); list.add(\list.add(\ // 使用ListIterator迭代器 ListIterator listIterator = list.listIterator(); while(listIterator.hasNext()) { } System.out.println(list.size()); listIterator.next(); // 迭代过程中增加元素 listIterator.add(\7) 增强for循环注意问题
//在使用增强for循环时,不能对元素进行赋值 int[] arr = {1,2,3}; for(int num : arr) { } System.out.println(arr[1]); num = 0; 4. 可变参数
1) jdk5中方法的形参可以定义为可变参数,传入实参个数可变 // 设计一个方法求n个数的和 public static int getSum(int... arr) { } // 可变参数在方法中仍被看做一个数组 int sum = 0; for(int num : arr) sum += num; return sum; 2)Arrays.asList为例演示传入不同参数的情况
6
// list长度为3 List list = Arrays.asList(\// list长度为1, 因为考虑1.4语法 String[] arr = {\List list = Arrays.asList(arr); // 同时符合1.4和1.5的语法,此时会优先考虑1.4的语法 // 原因是有了新功能要保证以前的代码不出错,向后兼容 // 现在就需要将arr作为一个元素存入集合 Object obj = arr; List list2 = Arrays.asList(obj); // 此时只符合1.5的语法,不符合1.4的语法,没有歧义 // 优先考虑1.4,所以数组会拆开 List list3 = Arrays.asList(new Object[]{arr}); //System.out.println(list3.size()); // 基本数据类型数组只符合1.5的语法 int[] nums = {1,2,3}; list = Arrays.asList(nums); System.out.println(list.size()); 5. 枚举
问题:对象的某个属性的值不能是任意的,必须为固定的一组取值其中的某一个 解决办法:
1) 在setGrade方法中做判断,不符合格式要求就抛出异常
2) 直接限定用户的选择,通过自定义类模拟枚举的方式来限定用户的输入 写一个Grade类,私有构造函数,对外提供5个静态的常量表示类的实例 3) jdk5中新定义了枚举类型,专门用于解决此类问题
4) 枚举就是一个特殊的java类,可以定义属性、方法、构造函数、实现接口、继承类 //枚举类就是一个java类,也可以声明属性,方法,构造函数 public enum Grade4 { } //枚举类就是一个java类, 也可以继承抽象和实现接口 public enum Grade5 {
A(\private String value; private Grade4(String value) { } public String getValue() { } return value; this.value = value; // 抽象类不能创建实例对象 A(\ } 7
// new了一个Grade5的子类实例 public String toLocaleString() { return \优\} } ,B(\ } ,C(\ } ,D(\ } ,E(\ }; private String value; private Grade5(String value) { } public String getValue() { } // 对外提供一个方法,返回枚举的本地信息 // 一个方法不知道如何实现,可以定义为抽象的 public abstract String toLocaleString(); return value; this.value = value; // new了一个Grade5的子类实例 public String toLocaleString() { return \不及格\} // new了一个Grade5的子类实例 public String toLocaleString() { return \差\} // new了一个Grade5的子类实例 public String toLocaleString() { return \中\} // new了一个Grade5的子类实例 public String toLocaleString() { return \良\} ? 练习:请编写一个关于星期几的枚举WeekDay,要求:
? 枚举值:Mon,Tue,Wed,Thu,Fri,Sat,Sun 星期一。。。。星期日 ? 该枚举要有一个方法,调用该方法返回中文格式的星期。
8
6. 反射
1)java代码的阶段:一段java代码在程序运行期间会经历三个阶段: source-->class-->runtime 2) Class 对象: 在java中用一个Class对象来表示一个java类的class阶段
Class对象封装了一个java类中定义的成员变量、成员方法、构造方法、类名、包名等 获得class对象的三种方式和区别: // 1. 根据给定的类名来获得 用于类加载 String classname = \// 来自配置文件 Class clazz = Class.forName(classname); // 此对象代表Person.class // 2. 如果拿到了对象,不知道是什么类型 用于获得对象的类型 Object obj = new Person(); Class clazz1 = obj.getClass(); // 获得对象具体的类型 // 3. 如果是明确地获得某个类的Class对象 主要用于传参 Class clazz2 = Person.class; // 在java中所有的类型都会对应一个Class对象 int Integer Class intClazz = int.class; Class intarrClazz = int[].class; Class voidClazz = void.class; 3)反射
反射就是获得一个java类的各个组成部分 // 反射类的成员方法 Class clazz = Person.class; Method method = clazz.getMethod(methodName, new Class[]{paramClazz1, paramClazz2}); method.invoke(); // 反射类的构造函数 Constructor con = clazz.getConstructor(new Class[]{paramClazz1, paramClazz2,...}) con.newInstance(params...) // 反射类的属性 Field field = clazz.getField(fieldName); field.setAccessible(true); field.setObject(value); 4) 反射用在哪里
到底框架是什么? 框架就是将开发中大量重复的代码集中起来写个通用的程序 框架就是用反射来实现的, 框架需要现在的类调用将来写的类
框架是将来的程序员调用的,框架不能实现完整的功能,框架只是一些一些通用的代码; 框架要依赖将来写的类来运行.
现在写的类要调用将来写的类,我们先针对接口进行调用,将来的类需要实现接口,那么方法就固定了 但是将来写的类的类名我们无法获知,这时就需要调用者通过配置文件告诉框架具体的类名
9
7. 泛型
1) 泛型是一种可变化的类型, 类型不确定,需要调用者来指定
2) 用途: 一个类的多个成员方法用到的参数类型或返回值类型都是未知的类型,但又需要是同一个类型,就可将方法的 参数类型定义为泛型,此泛型必须在类上先予以声明才能在方法中使用 一个方法的多个参数和返回值需要是同一个类型,也可以用泛型来解决,在方法返回值前面声明泛型
泛型的细节:
1) 泛型到底代表什么类型取决于调用者传入的类型,如果没传,默认是Object类型 2) 使用带泛型的类创建对象时, 等式两边指定的泛型必须一致 原因: 编译器检查对象调用方法时只看变量,然而程序运行期间调用方法时就要考虑对象具体类型了 3) 等式两边可以在任意一边使用泛型 在另一边不使用 (考虑向后兼容)
3. 泛型的基本概念
以List
4. 泛型的使用 1)使用带泛型的类时,在创建对象时可以为泛型指定实际类型参数,指定的具体类型相当于给泛型传参 2)子类在继承父类的时候,可以为父类定义的泛型指定实际类型参数 class B
10
Lesson 2 Servlet(超级重要)
1. javaweb 学什么
用 java 语言开发动态的web资源,接下来就是介绍如何开发动态的web资源 对于java程序员而言,所谓动态web资源就是?可以运行在服务器上的java程序 2. 实现服务器管理java程序
开发人员写好一个java类,到底有哪些方法tomcat服务器是不可能知道的 tomcat服务器欲执行我们编写的java类, 就需要知道我们的java类有哪些方法,然后在适当的时间调用这些方法, 所以我们在写的java程序要想运行在服务器上,就必须要实现一个特殊的接口 Servlet.java
interface Servlet { ... } Servlet接口中就定义了可以被tomcat服务器调用的java方法 通常来讲,我们将实现了Servlet接口的java类称之为 Servlet 编写好的Servlet需要在web.xml文件中做配置, 才能供外界访问
3. 实现第一个Servlet程序
3.1 写一个java类实现Servlet接口 package cn.itcast.servlet; import java.io.*; import javax.servlet.*; public class HelloWorldServlet extends GenericServlet { // 实现 service 方法 public void service(ServletRequest request,ServletResponse response) throws ServletException,java.io.IOException { // 向浏览器输出一句话 PrintWriter out = response.getWriter(); out.write(\ } public void init()throws ServletException { // 初始化 servlet 时被调用 System.out.println(\ } public void destroy() { // 摧毁 servlet 时被调用 System.out.println(\ } }
3.2. 导入 servlet jar包
set classpath=%classpath%;D:\\apache-tomcat-6.0.20\\lib\\servlet-api.jar
11
3.3. 编译带包的类
javac -d . HelloWorldServlet.java
3.4. 将包拷贝至 day05/WEB-INF/classes 目录下 --> 发布 web 工程
3.5. 在 web.xml 文件中做映射
3.6. Servlet 执行流程图
12
http://localhost:8080/day05/...ServletIE浏览器服务器Servlet1: 找windows或dns解析出ip2: 向服务器发送请求3: 解析出主机名4: 解析出虚拟目录(上下文路径)-day055: 找到一个对应web应用6: 解析出用户访问的资源名,找web.xml,找出对应的Servlet类名7: 反射创建Servlet对象,调用init方法requesrt8: 调用service方法response9: 向response对象输出一句话,service方法就返回10: service方法返回11: 从response中取出响应消息,发送给IE浏览器4. 用 eclipse 工具开发 Servlet
4.1. 建一个 web project
4.2. 在src下建包,创建一个java类实现Servlet接口 4.3 在 Webroot\\WEB-INF\\web.xml 做 servlet 映射 4.4 配置 tomcat 服务器 window--> preferences --> tomcat6.x 4.5 将web工程发布至tomcat 服务器 发布的web应用名称可以配置: web工程右键 选properties-->myeclipse-->web 默认情况使用工程名作为发布后的web应用名 4.6 启动tomcat服务器运行程序
13
5. HttpServlet对象
一般来讲我们开发一个Servlet会去继承 HttpServlet
在 eclipse 下开发Servlet 可以直接新建一个Servlet, 覆写 HttpServlet 的 doGet和doPost方法 继承 HttpServlet 的原因是: HttpServlet实现了service方法,将ServletRequst和ServletResponse
强转为子类 HttpServletRequest和HttpServletResponse,让我们用起来更加方便,同时,在service方法中,它判断了请求方式,根据请求方式来调用 doGet 和 doPost
二、 Servlet 细节
1. * 号统配符
一个Servlet可以映射为多个路径
在映射 Servlet 路径时可以使用?/*‘ 或 ?*.扩展名‘ 的形式 注意: 两者不能同时使用 /* 具有较高的优先级 2. load-on-startup 元素
如果一个Servlet配置了该项,web容器会在web应用被加载时就初始化该Servlet,数字越小则越先初始化3. tomcat\\conf\\web.xml
服务器下所有web 应用中的web.xml 都会自动继承该文件中所有的配置 http://localhost:8080/day05/a.html a.html是资源名 上面的url访问的url在web.xml文件中并没有配置
此时会去访问缺省的Servlet,在tomcat\\conf\\web.xml文件中就配置了一个缺省的DefaultServlet DefaultServlet帮我们去web应用下读取 a.html 文件,并打给浏览器,如果没有发送 404 页面 也就说,我们通过ie访问服务器访问的都是 Servlet 4. Servlet线程安全问题
解决Servlet线程安全问题: 加上同步的锁(lock) 实现SingleThreadModel接口的Servlet
服务器会做判断,当有请求过来,如果Servlet对象忙着呢,服务器会再创建一个Servlet对象为用户 提供服务,如果Servlet闲置,就直接提供服务
这样的方式实际上是回避了线程安全问题, 单线程访问Servlet, 这样的方式不可取
Lesson 3
一、 WEB 服务器 1. 基本概念
WEB在英语中即表示网页的意思,它用于表示Internet主机上供外界访问的资源以及超链接所组成的链表 放在internet网上供外界访问的文件或程序被称为web资源 web资源被分为:
静态web资源: html、css、jpg 动态web资源:Servlet、Jsp
14
2. 什么是 WEB 服务器?就是一台电脑,安装了一个服务器软件 3. 为什么需要安装 WEB 服务器
思考问题: 从一台计算机的 IE 浏览器如何去访问另一台计算机中的文件 3.1 两台计算机是如何实现通讯的? IP地址(计算机的唯一标识)
IPV4 4个字节的整数,每个字节以 点号 隔开 192.168.1.100 每个字节的取值 0~255 在计算机中程序会绑定在某一个端口 0~65535 尽量用 1024 以上的 连接一台计算机就需要输入 ip 地址和端口号 作为接收方, 应该绑定ip,监听指定的端口
3.2 在本地写程序添加一个服务,供别人来访问, 假设监听 8888 端口 3.3 编码实现了一个本地服务器程序 作用: 管理本地的资源,只要将html页面放到指定的目录下,外界就可以访问了
3.4 安装服务器的目的: 开发好的web资源可以发布到服务器上,这样外界就可以通过浏览器访问了
源程序: MyServer.java
// ServerSocket 对象可以监听端口 ServerSocket serversocket = new ServerSocket(6666); while(true) { Socket socket = serversocket.accept(); // 等待客户端的连接请求,一旦有请求过来,就结束阻塞,返回客户端对象 // 一旦有客户来访问, 就另开一个新线程去提供服务, main线程继续等待下一个客户的连接 new Thread(new MyService(socket)).start(); } MyService.java // 提供服务 InputStream in = socket.getInputStream(); Thread.sleep(200); int len = in.available(); // 估计此流不受阻塞能读取的字节数 byte[] buffer = new byte[len]; in.read(buffer); String request = new String(buffer); // 截取第一行 String firstLine = request.substring(0, request.indexOf(\String uriName = firstLine.split(\OutputStream out = socket.getOutputStream(); // 根据需要访问的资源创建 File 对象 File file = new File(\if(!file.exists()) { out.write(\对不起!您访问的资源不存在!别瞎搞!!\ out.close(); return ; } // 从文件读, 往浏览器写 FileInputStream fis = new FileInputStream(file); 15
buffer = new byte[1024]; while ((len = fis.read(buffer)) > 0) { out.write(buffer, 0, len); } socket.close(); 二、Tomcat 服务器的安装和配置
1. 使用 tomcat6.0.20.rar 文件解压即完成安装 2. tomcat 就是一个java程序,一定会用到 jre 所以需要配置环境变量 java_home 配置成jdk的安装目录 c:\\jdk1.6 tomcat的启动是通过 startup.bat 文件, 实际上 startup.bat 中是去调用 catalina.bat 文件, 而且是通过 êtalina_home%\\bin\\catalina.bat 去找 所以为了保证服务器启动正常, 需要配置 catalina_home 环境变量为 tomcat的安装目录 3. tomcat 的目录结构
bin : 存放一些执行文件
conf : 存放服务器的配置文件
lib : 存放tomcat 所依赖的 jar 文件 logs: 存放日志文件 temp: 存放临时文件
webapps: web applications 存放所有的web应用程序(web资源) work: tomcat 的工作目录, jsp翻译成的Servlet就在这个目录下 4. web应用
多个web资源存放在一个目录下即为一个web应用(web应用程序、web工程) web 应用的目录结构 静态web资源直接放在目录下 java 类放在classes目录下 web.xml 文件负责管理web应用下所有的web资源 所有jar包放在lib目录下
三、 WEB 应用的映射
1. 虚拟目录 一个web应用(服务器上一个目录) 需要供外界访问的路径,需要映射虚拟目录
在 tomcat6 中,放在webapps下的web应用,服务器会自动做映射(将文件夹名称作为虚拟路径) 对于 webapps 目录外的web应用需要手动映射虚拟路径 1.1. 在 server.xml 文件可以配置
1.2. 在 %tomcat目录%\\conf\\catalina\\localhost 下写一个 xml文件 文件名就是 虚拟目录
16
如果文件名 是 ROOT.xml 那就是配置了缺省的web应用, 访问时不需要输入 虚拟目录
2. web.xml
Web.xml的作用: 管理 web 应用下所有的web资源
通俗地讲,一个web应用下所有的web资源如何被外界访问都需要在此文件下做映射 包括咱们后面学的Servlet jsp 都需要在这个文件中做映射
实验: 配置web应用的 首页
在 web 应用下新建目录 WEB-INF ,在此目录下 新建 web.xml 文件
一个完整 url
http:\\\\www.sina.com:80\\itcast\\index.jsp
协议名 主机名 端口号 资源名 (uri) IE 访问服务器的原理,
在IE中输入的地址中包含域名,域名就需要被翻译成服务器的IP,才能访问到服务器
17
IE 浏览器 www.sina.com sina 服务器 看windows 是否注册了该 主机名 DNS服务器 (网络服务商) 解析域名,获得一个 IP 4. web应用映射的练习: 新建一个 web 应用 配置成缺省的web应用 配置首页
配置tomcat监听端口为80 在 windows 中注册主机名 5. 虚拟主机
服务器允许在一个IP上配置多个主机,即虚拟主机 http://www.sina.com:80/index.html 中的 www.sina.com 起了两个作用: 找DNS服务器,作为域名被解析为IP 通过Host头告诉服务器访问的主机名
配置方式: 在 server.xml 文件中配置Host元素,需要指定name(主机名)、appBase(默认web应用存放目录) appBase目录下所有的web应用,tomcat会自动映射虚拟路径 做实验: 给新配置的虚拟主机配置缺省的web应用 18 分析web资源访问过程 http://www.sohu.com/abc/a.html 访问一个 a.html 静态web资源, IE 做了什么事 1) 将 www.sohu.com 作为域名发送给DNS , 解析成 IP 地址, 访问一台服务器 2) 发送 Host 头(www.sohu.com),告诉服务器我要访问的虚拟主机 ,服务器拿着Host头找匹配的Host元素 3) 将abc作为虚拟目录,告诉服务器我要访问的web应用 ,服务器拿着 abc 找匹配的web应用 4) 将 a.html 作为资源名, 告诉服务器我要访问的 web 资源, 服务器拿着 a.html 去web.xml文件中找映射 虚拟目录对应是一个web应用的目录,所以虚拟目录也被我们称作web应用路径(web应用的上下文contextpath) 三、http协议 1. tcp/ip 协议: 网络通信协议(连接) ip 协议 : 127.0.0.1 ip地址对应一台计算机 (互联网层) tcp 高级协议: 三次握手, 发送请求、返回响应、传输数据 2. http 协议是建立在 tcp协议的基础之上 (应用层) 3. Http协议的版本 (w3c) Http1.0 : 建立连接,发送一次请求就断开 Http1.1 :建立连接,可以无限次发送请求 (传输层) 19 四、 http请求消息 http请求消息内容: 包括一个请求行、若干消息头、以及实体内容,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。 请求行 POST /itcast/ HTTP/1.1 消息头 Accept: image/gif, image/x-xbitmap, */* Referer: http://localhost:8080/itcast/ Accept-Language: zh-CN,en-GB;q=0.8,ar-YE;q=0.7,ja-JP;q=0.5,de-CH;q=0.3,en-US;q=0.2 Content-Type: application/x-www-form-urlencoded UA-CPU: x86 Accept-Encoding: gzip, deflate User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB6.5; CIBA) Host: localhost:8080 Content-Length: 33 Connection: Keep-Alive Cache-Control: no-cache Cookie: JSESSIONID=B0B3FB4FFB0315B3D3C620548DD4E1EB 空一行 消息体 username=zhangsan&password=123456 1. 请求行 GET /itcast/a.html HTTP/1.1 GET 为请求方式 : get方式的请求参数直接跟在url后面,例如:/itcast/a.html?username=aaa&password=111 POST方式: post方式请求参数放在消息体中传输,相对安全,get大小限制1K,post 无数据量限制 2. 请求消息头 : IE浏览器用于向服务器说明情况的(浏览器使用环境) Accept: text/html,image/* 说明浏览器接受的数据类型 Accept-Charset: ISO-8859-1 说明浏览器使用的字符编码 Accept-Encoding: gzip,compress 说明浏览器支持的压缩格式 Accept-Language: en-us,zh-cn 说明浏览器的语言环境 Host: www.it315.org:80 说明浏览器要访问的主机名 If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT 文件的修改事件,用于做缓存 Referer: http://www.it315.org/index.jsp 说明请求来自哪里,防盗链 (做实验) User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) 说明浏览器内核 Cookie 向服务器发送Cookie Connection: close/Keep-Alive 说明连接状态 Date: Tue, 11 Jul 2000 18:23:51 GMT 客户端计算机时间 3. 实体内容(消息体) 浏览器向服务器发送的数据,例如上传的文件、提交的表单等 20 五、http响应消息 http响应消息的内容包括: 一个状态行(类比 http请求信息的‖请求行‖)、若干消息头、以及实体内容 ,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开。 HTTP/1.1 200 OK Server: Apache-Coyote/1.1 Content-Type: text/html;charset=GB18030 Content-Length: 766 Date: Thu, 07 Jul 2011 15:40:02 GMT