一、
HTTP协议:组成部分及每部分的详细分解
- 概念:
- Web服务器和Web客户端交互的规则,就是HTTP协议
- HTTP是HyperText Transfer Protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程及数据本身的格式。
- HTTP协议是学习JavaWEB开发的基石,不深入了解HTTP协议,就不能说掌握了WEB开发,更无法管理和维护一些复杂的WEB站点。
- HTTP协议的版本
- HTTP/1.0
- 图示
- 如图所示,它分四个过程,建立连接、发送请求信息、发送响应信息、关闭连接。
- 浏览器与WEB服务器的连接过程是短暂的,每次连接只处理一个请求和响应。对每一个页面的访问,浏览器与WEB服务器都要建立一次单独的连接。
- 浏览器到WEB服务器之间的所有通讯都是完全独立分开的请求和响应。每次请求响应结束都会断开连接。
- 无状态,
- HIIP/1.0的缺点:
- 一次交互结束后断开连接,第二次交换重新建立连接。建立连接需要消耗很多资源。
- HTTP/1.1
- 图示
- 如图所示,在一次连接中可以与服务器多次交互。
- HTTP/1.1中增加了更多的消息头
- Tip
- 每一次访问html文件,如果标签中含有src这样的属性,浏览器都将重新发送请求(自动)。
- <img src=""/>
- <script src=""/>
- <link href=""/>
- html文件只能包含文本。
- 每一次访问html文件,如果标签中含有src这样的属性,浏览器都将重新发送请求(自动)。
- HTTP/1.0
- HTTP协议组成部分
- 请求部分
- 请求行
- 必须位于第一行
- 举例:GET /App1/1.html HTTP/1.1: 请求方式 URI 协议
- 请求方式:
-
- 默认为GET,表单中的数据会出现在地址栏中,不会出现在请求正文中。不安全,且长度小于1k。
- POST:表单中的数据会出现在请求正文中。长度无限
- URI
- 协议
- 请求消息头
- 从第二行开始至第一个空行结束
- 常用请求消息头:
- Accept: */*
-
- 浏览器可接受的MIME(协议)类型(MIME Type:Tomcat\conf\web.xml有文件类型与MIME类型的对应关系)
- MIME(协议)类型:大类型/具体类型,如html--->text/html,jpg----->image/jpeg等
- Accept-Language: zh-cn
-
- 浏览器所希望的语言种类
- Accept-Encoding: gzip, deflate
-
- 浏览器能够进行解码的数据编码方式,比如gzip
- Accept-Charset:
-
- 浏览器通过这个头告诉服务器,它支持哪种字符集
- User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
-
- 浏览器类型.
- Host: localhost:8080
-
- 初始URL中的主机和端口
- Connection: Keep-Alive
- Referer:值是一个URL。表示当前页面是由哪个页面转过来的。(防盗链;广告效果)
- Content-Type:内容类型(请求正文的MIME类型)Content-Type: application/x-www-form-urlencoded对应表单的enctype="application/x-www-form-urlencoded"属性。
- If-Modified-Since:是一个时间。利用这个头与服务器的文件进行比对,如果一致,则从缓存中直接读取文件。
- Content-Length:表示请求消息正文的长度
- Cookie:这是最重要的请求头信息之一
- 请求正文
- 请求行
- 响应部分
- 状态行
- 必须位于第一行
- 举例:HTTP/1.1 200 OK 协议、响应码、响应码描述
- 响应码(目前仅使用了30个左右),100-600
-
- 状态码 含义
- 100~199 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程
- 200~299 表示成功接收请求并已完成整个处理过程
- 300~399 为完成请求,客户需进一步细化请求。例如,请求的资源已经移动一个新地址
- 400~499 客户端的请求有错误
- 500~599 服务器端出现错误
- 常用响应码
-
- 200(正常)
- 表示一切正常,返回的是正常请求结果
- 302/307(临时重定向)
- 指出被请求的文档已被临时移动到别处,此文档的新的URL在Location响应头中给出。
- 304(未修改)
- 表示客户机缓存的版本是最新的,客户机可以继续使用它,无需到服务器请求。
- 404(找不到)
- 服务器上不存在客户机所请求的资源。
- 500(服务器内部错误)
- 服务器端的程序发生错误
- 响应消息头
- 从第二行开始至第一个空行结束
- 常用消息头:
-
- Location:指示新的资源的位置,常与302一起使用
- Server:http://www.it315.org/index.jsp指示服务器的类型
- Content-Encoding:gzip,服务器发送的数据采用的编码类型。
- Content-length:80告诉浏览器正文的长度
- Content-language:zh-cn 服务器发送的文本的语言
- Content-Type: text/html;charset = GB2312 服务器发送的内容的MIME类型
- Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT文件的最后修改时间
- Refresh: 1,(url=http://www.it315.org) 指示客户端刷新频率,单位是秒。括号中代表刷新时转向别的url
- Content-Disposition: attachment;filename = aaa.zip指示客户端下载文件
- Set-Cookie:SS=Q0=5Lb_nQ; path=/search服务器端发送的Cookie
- 以下3个头通知客户端不要缓存
-
- Expires:-1;
-
- 大于0代表缓存多长时间。
- Cache-Control:no-cache(1.1) //HTTP1.1
- Pragma:no-cache(1.0) //HTTP1.0
- response.setHeader("Expires", "-1");//时间,毫秒值
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
- 响应正文
- 状态行
- 请求部分
二、Servlet
- Servlet概述
- 是什么:
- 开发动态web资源的技术
- Servlet是运行在服务端的程序,是被容器如Tomcat调用的,用于响应客户端的请求
-
J2EE定义的是一系列的标准,没有提供实现,没有提供jar包。Tomcat中的servlet-api.jar实现了J2EE的API标准。
- SUN公司在其API中提供了一个servlet接口,用户若像开发一个动态web资源(即开发一个Java程序向浏览器输出数据),需要完成一下2个步骤
- 编写一个Java类,实现servlet
- 把Java类部署到web服务器中
- 怎么访问Servlet
- 客户端想访问Servlet需要通过URL,所以需要把Servlet程序映射成一个URL,是通过web.xml中的<servlet>和<servlet-mapping>标签实现的。
- <servlet>元素用于注册Servlet,它包含两个主要的子元素<servlet-name>和<servlet-class>,
- <servlet-name>设置注册名,
- <servlet-class>设置Servlet的完整类名。
- <servlet-mapping>用于映射一个已注册的Servlet的对外访问的路径
- <servlet-name>指定注册名,
- <url-pattern>设置对外访问路径
- servlet在web应用中的位置
- 是什么:
-
编写Servlet的开发步骤, 第一个方法:实现javax.servlet.Servlet接口- 自定义一个标准的JavaWeb应用目录,应用名为FirstApp
- FirstApp
- WEB-INF
- classes
- lib
- web.xml
- 编写一个类,实现javax.servlet.Servlet接口
- import javax.servlet.*;
- import java.io.*;
- public class HelloServlet implements Servlet{
- public void destroy(){}
- public String getServletInfo(){
- return null;
- }
- public void service(ServletRequest req,
- ServletResponse res)
- throws ServletException,
- IOException{
- String data = "hello servlet";
- res.getOutputStream().write(data.getBytes());
- }
- public ServletConfig getServletConfig(){return null;}
- public void init(ServletConfig config)
- throws ServletException
- {}
- }
- 进入HelloServlet的目录,执行javac -d .HelloServlet.java进行编译(要把servlet-api.jar加入到classpath中)
- Servlet映射到某个地址上:修改web.xml
- <servlet>
- <servlet-name>HelloServlet</servlet-name>
- <servlet-class>com.itheima.HelloServlet</servlet-class>
- </servlet>
- <servlet-mapping>
- <servlet-name>HelloServlet</servlet-name>
- <url-pattern>/HelloServlet</url-pattern>
- </servlet-mapping>
- 部署到Tomcat中
- 访问地址:http://localhost:8080/FirstApp/HelloServlet
- 自定义一个标准的JavaWeb应用目录,应用名为FirstApp
- 编写Servlet的开发步骤, 第二个方法:继承javax.servlet.GenricServlet或 HttpServlet
- Servlet接口SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。
- HttpServlet指能够处理HTTP请求的servlet,推荐继承这个类而不是实现Servlet接口。
- 如果是与HTTP协议有关,也可以继承javax.servlet.http.HttpServlet,至少要覆盖doXXX方法。
- 不能覆盖service方法, HttpServlet覆盖了service方法, 他有标准实现。
- 该方法体内的代码会自动判断用户的请求方式,
- 如为GET请求,则调用HttpServlet的doGet方法,
- 如为Post请求,则调用doPost方法。
- 因此,开发人员在编写Servlet时,通常只需要覆写doGet或doPost方法,而不要去覆写service方法。
- Servlet的执行流程
- servlet运行流程图
-
首先Servlet被部署到Web容器中,当客户端发送调用这个Servlet的请求到达Web容器时,Web容器会先判断所调用的Servlet实例是否存在。
如果不存在,就装载当前所调用的Servlet并调用构造方法生成这个Servlet的实例,其次再调用这个实例的init()方法(init()这个方法只会在Servlet初始化的时候调用一次,除非这个Servlet被重新部署)进行初始化,然后新创建一个线程,并在新建线程中调用这个实例的service()方法,service()方法再根据请求的具体类型调用doGet()、doPost()等方法,然后生成动态的回复内容,最后服务器发送回复内容给客户端的浏览器。
如果存在,就直接新创建一个线程,并在新建线程中调用这个实例的service()方法,service()方法再根据请求的具体类型调用doGet()、doPost()等方法,然后生成动态的回复内容,最后服务器发送回复内容给客户端的浏览器。
当Servlet不再需要使用的时候,比如其所在的Web应用被卸载或Web服务器关闭时,它就会被卸载掉,卸载前调用destory()方法,完成所有相关资源的释放。
- Tip:
- servlet-api.jar:
- 含两个包:
- javax.servlet.*:通用的类放在此处,与具体协议无关
- javax.servlet.http.*:专门服务于HTTP协议。
- Tip:
- 修改MyEclipse生成的Servlet模板:
- MyEclipse8.5:在安装目录中搜索*wizard*(com.genuitec.eclipse.wizards_8.5.0.me201003052220.jar)的文件,打开,找到Servlet.java文件,修改即可(注意:修改前先备份,推出MyEclipse)
- Servlet的生命周期
- 默认情况下,Servlet类在浏览器第一次访问时才会被容器实例化,并接着调用init方法进行初始化。
- 针对用户的每次访问,只初始化一次,但service方法会调用多次。
- 如何得到Servlet中的配置参数:ServletConfig
- 希望在容器加载应用时就初始化Servlet?
- 解决办法:
- <servlet>
- <servlet-name>HelloServlet</servlet-name>
- <servlet-class>com.itheima.HelloServlet</servlet-class>
- <load-on-startup>2</load-on-startup> //取值自然整数,标识了Servlet的加载顺序,尽量从2开始
- </servlet>
- <servlet-mapping>
- <servlet-name>HelloServlet</servlet-name>
- <url-pattern>/HelloServlet</url-pattern>
- </servlet-mapping>
- Tip:Servlet的映射细节
- a、同一个Servlet可以被映射到多个URL地址上
- b、Servlet的映射支持通配符*
- 通配符写法有2种:
- 以*开头,以扩展名结尾,比如*.do
- 以/开头,以*结尾,比如/action/*
- 知识点:使用通配符时,如果找到多个匹配,到底执行的是哪个Servlet原则:绝对匹配--->从前往后匹配---->/开头的匹配优先级高
- 如果某个Servlet的映射路径为一个"/",那么称之为默认Servlet。负责处理没有的配置。
- 当访问Tomcat服务器中的某个静态HTML文件和图片时,实际上是在访问这个缺省Servlet。
- 线程安全问题
- 实现javax.servlet.SingleThreadModel的Servlet有两种解决线程安全问题的办法:(不同的服务器不同)
- 对资源进行同步处理(不可行),会造成排队。
- 搞了多个Servlet的对象为您服务(不可行):Tomcat的实现了此种方式。
- 避免资源冲突的原则:尽量使用局部变量;实在局部不了的,一定要做同步处理。同步代码块尽量包围少的代码。
- 在Servlet尽量使用局部变量。
- 也可以使用ServletContext解决资源冲突。
- 实现javax.servlet.SingleThreadModel的Servlet有两种解决线程安全问题的办法:(不同的服务器不同)
- ServletContext
- ServletContext:当容器加载JavaWeb应用时,会为每一个JavaWeb应用创建对应的 S ervletContext对象(每个应用只有一个)。
- 获取ServletContext对象的引用:ServletConfig.getServletContext(
- ServletContext还是一个域对象:域对象实际上其内部维护了一个Map<String,Object>
- 它的生命周期是整个web应用的生命周期。
- 用途:
- 实现Servlet间的数据共享
- 多个Servlet通过ServletContext对象实现数据共享。这是因为ServletContext是一个域对象,内部维护了一个Map<String,Object>集合, 利用ServletContext对象存入需要共享的数据
- 方法:
- setAttribute(String name,Object object):把一个对象和一个属性名绑定,将这个对象存储在ServletContext中;
- getAttribute(String name):根据指定的属性名返回所绑定的对象;
- removeAttribute(String name):根据给定的属性名从ServletContext中删除相应的操作;
- getAttributeNames():返回Enumeration对象,它包含了存储在ServletContext对象中的所有属性名。
- 请求转发
- ServletContext.getRequestDispatcher(Stiring path)得到请求分发器:RequestDispathcher
- 这里path路径必须以“/”开头,“/”代表当前应用,比如/day05 使用/就可以省略应用名。
- 特点:原来用户请求的地址不变,响应由目标响应的。比如请求servlet1,servlet1转发给了servlet2,servlet2
- 读取资源文件的三种方式
- properties和xml配置文件的读取
- 方式一、使用ServletContext.getRealPath(String filePath)读取资源文件。
- path路径必须以"/"开头,"/"就代表当前应用。
- 作用:getRealPath:得到指定相对路径path资源的实际存放路径(部署绝对路径)
- 方式二、ResourceBundle:非Web环境下。专门读取*.properties文件的。只能读取类路径下的资源文件。
- 方式三、类加载器:ClassLoader:非Web环境下,读取任何资源文件。只能读取类路径下的资源文件。
- 实现Servlet间的数据共享
-
Servlet_API核心 UML类图
- HttpServlet(抽象类) ---继承---> GenericServlet(抽象类) ---实现---> Servlet(接口) ,ServletConfig(接口), Serializable(接口)