传智播客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为例:<>念着typeof 例, List 就是 List typeof String List中的E称为类型参数变量 方法定义参数形式参数 List中的Integer称为实际类型参数 整个List称为泛型类型 GenericType 整个List称为参数化的泛型类型

4. 泛型的使用 1)使用带泛型的类时,在创建对象时可以为泛型指定实际类型参数,指定的具体类型相当于给泛型传参 2)子类在继承父类的时候,可以为父类定义的泛型指定实际类型参数 class B class A extends B 通过子类A获得的父类类型就是一个参数化的类型 3)调用方法时传入参数的具体类型将作为方法中泛型的实际类型

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 文件中做映射 HelloWorldServlet cn.itcast.servlet.HelloWorldServlet HelloWorldServlet /HelloWorldServlet 注意: servlet 对象一旦创建就会驻留在内存中,为所有的请求服务, servlet 对象什么时候销毁? 直到服务器关闭时或web应用被移除才销毁

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 元素

元素下可以配置< load-on-startup>子元素, 配置方式如下:

1

如果一个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文件 文件名就是 虚拟目录

多级目录配置 aaa#bbb.xml 对应 /aaa/bbb

16

如果文件名 是 ROOT.xml 那就是配置了缺省的web应用, 访问时不需要输入 虚拟目录

2. web.xml

Web.xml的作用: 管理 web 应用下所有的web资源

通俗地讲,一个web应用下所有的web资源如何被外界访问都需要在此文件下做映射 包括咱们后面学的Servlet jsp 都需要在这个文件中做映射

实验: 配置web应用的 首页

在 web 应用下新建目录 WEB-INF ,在此目录下 新建 web.xml 文件 itcast.html 3. 域名解析

一个完整 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 My JSP 'index.jsp' starting page hello

1. 状态行 HTTP/1.1 404 Not Found

协议版本: 目前普遍采用的都是http1.1 响应状态码: 说明服务器的响应状态

常用状态码 状态码 100~199 200~299 300~399 400~499 500~599 含义 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 表示成功接收请求并已完成整个处理过程,常用200 为完成请求,客户需进一步细化请求。例如,请求的资源已经移动一个新地址,常用302、307和304 客户端的请求有错误,常用404 服务器端出现错误,常用 500

200: 一切OK

302\\307 请求重定向,你访问我,我通知你访问另一个资源 304 通知浏览器去读缓存

404 找不到资源 ,客户端的请求有错误

500 服务器程序出错(服务器端的程序抛异常了)

21

2. 响应消息头 服务器向浏览器说明情况(处理结果)

Location: http://www.it315.org/index.jsp 通知浏览器去访问另一个资源 Server:apache tomcat 说明服务器 Content-Encoding: gzip 通知浏览器数据的压缩格式 Content-Length: 80 通知浏览器发送数据的长度 Content-Language: zh-cn 通知浏览器语言环境 Content-Type: text/html; charset=GB2312 通知浏览器文件的格式和编码 Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT 告诉浏览器文件的修改时间 Refresh: 1;url=http://www.it315.org 通知浏览器自动刷新

Content-Disposition: attachment; filename=aaa.zip 通知浏览器以下载的方式打开资源 Set-Cookie:SS=Q0=5Lb_nQ; path=/search 发cookie Expires: -1//3种禁止缓存的头字段 Cache-Control: no-cache Pragma: no-cache

Connection: close/Keep-Alive 连接状态 Date: Tue, 11 Jul 2000 18:23:51 GMT 系统时间

3. 实体内容(响应消息体)

一般为服务器发送给ie浏览器的页面数据

六、 https 协议

1. https 是一种加密协议 能保证数据的安全 2. 不对称加密 对称加密 3. https

1) 制作数字证书

keytool -genkey -alias tomcat -keyalg RSA

2) 将证书拷贝至 tomcat\\conf

3) 修改server.xml 文件 配置https 连接器

22

maxThreads=\ clientAuth=\ keystoreFile=\4) 重启服务器 打开ie访问 https://localhost:8443 5) ie 中安装证书

继续浏览

查看证书

23

安装证书

删除证书:

24

Lesson 5

一、 ServletConfig 对象

作用 : 封装 Servlet 初始化参数

1. 可以在 web.xml 文件中 Servlet 元素下 为Servlet配置初始化参数 name aaaa 2. web 容器在初始化Servlet时,会将初始化参数封装到一个 ServletConfig 对象中,传给init方法 3. 我们在Servlet 中覆写 init方法,就可以获得ServletConfig

4. 父类 GenericServlet 中定义了一个成员变量用于记住此对象,并提供了 getServletConfig 方法 我们可以直接调用此方法 获得 config对象

5. 再调用 getInitParameter(name) 方法获得想要配置项 // 指定编码 // 获得ServletConfig 对象 ServletConfig config = getServletConfig(); String encoding = config.getInitParameter(\ 25

System.out.println(\二、 ServletContext 对象 :ServletContext 被称为 servlet的上下文 1. ServletContext对象代表整个web应用

2. ServletContext对象是一个“域”对象(即:可以存储数据的对象)

ServletContext对象的内部维护了一个map集合, key是String类型 value是Object类型 class ServletContext { private Map map ; }

3. ServletContext 作为域对象, 多个Servlet 可以共享数据 Servlet6 // 1. 获得ServletContext 对象 ServletContext context = getServletContext(); // 2. 存入域 context.setAttribute(―name‖, ―zhangsan‖); Servlet7 // 获得 context 域, getAttribute String name = (String) getServletContext().getAttribute(\4.获取web应用的初始化参数 getContext().getInitParameter(―name‖);

5. 统计一个web应用的访问量

在 context 域中维护一个count变量 访问Servlet时,取出变量 加1

6. 实现请求转发

实现请求转发需要用到 转发对象 RequestDispatcher,RequestDispatcher有一个 forward 方法能转发请求 7. 如何读取工程中的文件(分两种情况) 7.1. 读取web工程下的资源文件 // 获得绝对路径 String realPath = ServletContext.getRealPath(相对web应用的路径); 注意URL url = ServletContext.getResource(); web的url // 获得与文件关联的流 InputStream in= ServletContext.getResourceAsStream(―WEB-INF/classes/config.properties‖; 7.2 读取java工程下的文件 // 不能相对虚拟机目录 不能用绝对路径 // 只能类加载的方式读

// 获得 流 ClassLoader classLoader = Demo.class.getClassLoader(); InputStream in = classLoader.getResourceAsStream(\// 获得绝对路径 26

URL url = Demo.class.getClassLoader().getResource(\String path = url.getPath();

类加载方式 缺点

1) 不能读取类路径以外文件

2) 由于需要加载到内存,不能读大文件 3) web工程中如果用类加载的方式读

类加载实际上读取的是内存中加载的文件,此时将读不到硬盘上资源文件的修改 解决办法: 通过绝对路径去读硬盘上的文件 避开内存的文件 例如: Demo.Class.getClassLoader().getResource(\

三、 Servlet缓存

HttpServlet 的 Service()方法中的代码 // 调用方法 long lastModified = getLastModified(req); // 如果为 -1 ,就直接放行,给最新的 if (lastModified == -1) { doGet(req, resp); } // 方法返回不是-1 else { // 读取IE发送的头If-Modified-Since long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); // 拿着客户端的时间头和方法的返回值比较 if (ifModifiedSince < (lastModified / 1000 * 1000)) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less // 方法的返回值大于ie发送过来的时间头 // 重新向浏览器发送了一个时间头 maybeSetLastModified(resp, lastModified); // 放行, 发送页面 doGet(req, resp); } else { // 方法的返回值没有大于ie发送过来的时间头 // 发送 304 状态码,让用户去读缓存 resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } }

27

Lesson 6 一、中文乱码问题

1. 出现乱码的原因

1) 在计算机中数据以二进制的形式进行存储的, 数据的传输也是通二进制的形式 2)需要存字符,会出现字符与字节之间的转换 (输入字符 读到的字符) 3) 字符和字节之间如何实现转换? 都是通过查码表

4) 字符到字节是编码,字节到字符是解码, 编码和解码用到了不同码表就会出现乱码问题2. 解决乱码

1) 拿到乱码基本上都是由于解码错误导致的, 解决办法,重新编码再解码 2) 以后将文件交给解析器,出现乱码,首先想到是否通知别人文件的编码格式

Servlet对象 一旦创建就驻留在内存,

Request和response对象,web容器会针对每次用户的请求创建一个request和response 请求结束,响应发给ie。 Request和response对象就会立即被销毁

二、 Response 对象

1. response getWriter方法获得字符流,用于向浏览器输出字符数据

28

中文乱码问题

Response 中国 Tomcat web容器 中国 默认编码 iso-8859-1 63 63 utf-8 989789 IE 浏览器 63 63 –> ?? gb2312 解错码 Servlet getWriter().write(―中国‖) 2. 文件下载

文件名中文乱码问题

由于文件名是跟着 content-disposition 头发送给浏览器的

凡是http头的数据都会经过 url 编码, 编成全世界通用的符号,这样传输过程中才不会乱码 3. 请求重定向

发送 302 状态码和 location 头 ie向浏览器发送了两次请求 第一次直接请求资源,第二次重定向的页面 地址栏是有变化

4. getWriter 和 getOutputStream 不能同时使用,有冲突 response的流我们不用关闭,交给web容器去管理

三、 Request 对象

1. request 帮助我们取获取 ie 浏览器发送给 服务器的请求消息 (请求行 消息头 消息体) 2. request 获得请求参数: getParameter() 和 getParameterValues()

29

3. request 中文参数乱码问题

IE 老张 url编码 utf-8 è????? tomcat web容器 è????? request对象 解码 iso-8859-1 è

本文来源:https://www.bwwdw.com/article/j3ew.html

Top