Java Web开发入门
Web开发入门(Java Web)
gitbook版Thinking in Java (Java 编程思想)
进阶:
WEB请求处理一:浏览器请求发起处理
WEB请求处理二:Nginx请求反向代理
WEB请求处理三:Servlet容器请求处理
WEB请求处理四:Tomcat配置实践
WEB请求处理五:MVC框架请求处理
WEB请求处理六:浏览器HTTP协议漫谈
Tomcat服务器
Eclipse导入Tomcat源码 见Eclipse笔记
tomcat + jboss 整合即可构建完整支持J2EE的容器。
tomcat 支持全部JSP以及Servlet规范。
tomcat的配置见,《轻量级Java EE…》 tomcat是使用Java写成,需要java运行环境。
- tomcat的自动部署web应用: 直接将一个Web应用复制到webapps下即可。
- 利用控制台部署:(tomcat后台自动将文件夹复制到相关目录)
- 利用配置文件
tomcat配置数据源的两种方式:
- 全局数据源:
- 局部数据源:修改自己的Web部署文件
都需要将JDBC驱动复制到tomcat的lib目录下。
一些基础知识:
http://www.sina.com/ 表示url地址
sina.com 是域名
www.sina.com 是主机名
tomcat服务器:Linux中的开启与关闭,可通过已经自定义的脚本tomcatStart和tomcatShut来控制。tomcat控制台用户与密码在tomcat的conf/tomcat-users.xml文件来配置。该密码非常重要,不要透露。
这里偷偷告诉你,用户和密码都是:manager
Web应用和虚拟目录的映射
- Web应用程序:指提供浏览器访问的程序,通常也称为Web应用。
- 一个Web应用由多个静态web资源和动态web资源组成,如:
-
- HTML、CSS、js文件
-
- jsp文件、java程序、支持jar包
-
- 配置文件等
-
- 组成web应用的这些文件通常我们会使用一个目录组织,这个目录称之为:web应用所在目录
- Web应用开发好后,若想提供外界访问,需要把web应用所在目录交给web服务器管理,这个过程称之为虚拟目录的映射(需在配置文件中配置)。
下面是一个web应用:
news/ # web应用所在目录
|
----- index.html
------ 2.html
更改tomcat的server.xml配置文件后需要重启tomcat服务器。
如何设置某个web应用为默认web应用(首页是属于某个web应用的)?见教程04课。
web应用的基本组成结构:
mail
|
|------ html、jsp、css、js等文件
|
|------ WEB-INF/
|
|--- classes/ (Java类)
|
|--- lib/ (jar包)
|
|---- web.xml (web应用的配置文件)
配置虚拟主机:通过配置server.xml中配置 Host标签来配置主机地址和网站路径。
将web应用打包成一个war包: jar -cvf news.war news
;服务器会自动解压该war包。
tomcat中的context就代表了一个web应用。配置context元素的reloadable元素,让tomcat自动加载更新后的web应用。
eclipse中的一个项目中会有一个WebContent
tomcat体系结构
Tomcat Server启动,再启动一个service,再启动多个连接器(不同连接器处理不同请求,比如需要使tomcat和apache集成就需要使用第三个连接器),连接器收到客户端时会启动引擎,引擎会寻找主机(多个网站),主机收到请求找web应用,再找web资源。【可以在server.xml中配置,直接看该文件也可进行理解】
理解:(此处的服务器应该是指安装了tomcat的那台主机)
http://www.sina.com:8080中的www.sina.com的作用
,1.获得服务器的IP地址;2.在http请求头中告诉服务器(服务程序)我需要访问的主机是哪一台。
而如果直接使用
http://192.168.1.1:8080
时服务器(服务程序)不知道你需要访问我的哪一台主机,此时就会使用在配置文件中配置的默认主机(一般为localhost主机)
软件密码学基础和配置tomcat的https连接器
重新认识非对称加密:
公钥 CA 数字签名 私钥
数字证书(由CA为公钥生成的可性证书)也可自己生成证书。数字证书用于出示给用户,用户可以选择安装证书。
数据摘要(MD5算法得到数据摘要(指纹)) 使用私钥加密数据摘要 变成了数字签名
tomcat的体系结构和配置https连接器 公钥 私钥
# keytool是java自带的工具,用于生成数字证书,不受CA认证
keytool -genkey -alias tomcat -keyalg RSA
# -genkey指示产生密钥对, -alias指示别名 -keyalg加密算法
输入keystore密码: #生成的数字证书保存于密钥库中,此密码用于加密密钥库。密钥库可以包含多个密钥,密码为第一次生成密钥库时输入的密码。
您的名字与姓氏是什么? # 必须输入
: #输入你为那个网站生成的证书
下面出现的内容可以不填
...
密钥库文件 keystore默认位于home目录。
之后再tomcat中配置密钥库文件的路径和生成时使用的密码。
然后可以使用https协议进行连接。
另可以参考《Tomcat与Java Web开发技术详解》第29章:在Tomcat中配置SSL
tomcat补充
tomcat补充来自于《Tomcat与Java Web开发技术详解》
Web服务器与Web应用是两个不同的软件系统,它们之间通过一个中介方制定的标准接口进行协作。Servlet就是其中最主要的接口。
- Web服务器可以访问任意一个Web应用中实现Servlet接口的类
- Web应用中用于被Web服务器动态调用的程序代码位于Servlet接口的实现类中
Servlet规范把能够发布和运行JavaWeb应用的Web服务器称为Servlet容器。
tomcat本身也是用Java写成的开源Servlet容器。
tomcat作为运行Servlet的容器,其基本功能是负责接收和解析来自客户的请求,同时把客户的请求传送给相应的Servlet,并把Servlet的响应结果返回给客户。
图:Servlet容器响应客户请求访问特定Servlet的时序图(重要)
时序图中: 对象A到对象B的箭头,表示发送消息,因此也可理解为A调用B的方法。
每个Tomcat组件在server.xml文件中都对应一种配置元素。(具体情况见书)
Tomcat有三种启动方式
Tomcat的启动和关闭脚本都会执行同目录下的catalina.sh脚本;catalina.sh脚本允许输入命令行参数。比如start、run、debug、embedded、stop参数。
Servlet规范规定,JavaWeb应用必须采用固定的目录结构。
开发时可以自行添加一个src目录来存放所有Java源文件。到了Web应用的发布阶段,应该将src目录转移到其他地方。
在运行时,Servlet容器的类加载器先加载classes目录下的类,再加载lib目录下的jar文件中的类。因此如果两个目录下存在同名的类,classes目录下的类具有优先权。
另可参考《Tomcat与Java Web开发技术详解》第2篇:Tomcat配置及第三方实用软件的用法
- Tomcat的控制平台和管理平台
- 安全域
- Tomcat与其他HTTP服务器集成
- 在Tomcat中使用SSI
- Tomcat阀
- 在Tomcat中配置SSL
- Velocity模板语言
- 创建嵌入式Tomcat服务器
HTTP协议
通过telnet发生http请求,来获得服务器的http响应。并通过其测试http 1.0和http 1.1的区别。
对于请求下面的这样一个html页面,浏览器需要向服务器发送5次请求。第一次请求得到整个html页面,后面三次请求获得三个图片和一个js文件。
<img src="1.jpg">
<img src="2.jpg">
<img src="3.jpg">
<script src="1.js">
上面的页面设计的不好,请求多次会加大服务器的压力;优化方法…
IE 浏览器插件httpwatch
Chrome开发者工具的简单使用:
直接在Chrome浏览器中打开开发者工具,切换到"Network"选项卡,然后按F5刷新页面,在该选项卡中就会列出 此次刷新请求的具体资源的详细信息,并会统计进行了多少次请求(在Name栏的底部)。"Name"栏中列出了所有请求资源的名称,点击具体资源会出现几个标签页,点击"Headers"可查看其对应的请求头,点击"Preview"可预览资源…
http请求
请求行、请求头、空行、请求数据(如表单提交数据)
Post /hello.jsp HTTP/1.1
Accept: image/gif,image/jpeg, */*
Referer: http://localhost/login.html
...
Cache-Control: no-cache
username=Tom&password=1234&sublmit=submit # Post方式的请求正文
用户如果没有设置,默认情况下浏览器向服务器发送的都是get请求,例如在浏览器直接输入地址访问,点击超链接等。 如果想使用post请求方式,方法是在表单form标签中指定使用post。
(可以这样理解吗? 首先在浏览器输入网址使用get请求一个页面包含表单的网页,然后我填写好表单后点击提交按钮,并且该表单的源代码中指定了使用post,那么就会使用post提交表单请求)
这样理解最好:
在浏览器中输入一个网址,回车后,此时浏览器向发送了一个Get请求(用于获取页面的源代码??),而浏览器为了加载页面中的脚本和图片等(解析源代码??)又会自行发起请求。比如打开一个Github上的仓库,共发起了100次请求。
发现老师讲的很好。有些东西如果自己摸索会话费很多时间,而且不一定能达到那种程度的理解。要自己快速的动手去实施…来提高速度。可能前提是自己对这方面已经有了些理解。 今天发现多与人交流是可以锻炼自己的思维的。
get 提交的数据有长度限制(数据在请求头的第一行)
post 无限制(在请求头空行下方)
如果要在用户点击超链接时提交数据给服务器,则可直接在超链接的地址后添加?usernaem=fan
的这种get方式。
请求行: GET ...
请求头:
Accept: */* -- 可接收的文件类型
Referer: http://localhost:8080/myhome/index.html -- 从哪个网址进入此页面;可用于设置防盗链
User-Aget: ... -- 客户机软件环境(比如系统,浏览器版本)
Range: 头指示服务器只传输部分Web资源。这个头可以用来实现断点续传功能。
Range:字段可以通过3种格式设置要传输的字节范围
Range: bytes=1000-2000 #
Range: bytes=1000- #1000以后的所有内容
Range: bytes=1000 #传输最后1000个字节
get请求示例:
一般不包含请求正文,因为没有意义。见此处的讨论HTTP GET with request body
GET /hello.htm HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
post请求示例:
包含请求正文
POST /cgi-bin/process.cgi HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE5.01; Windows NT)
Host: www.tutorialspoint.com
Content-Type: application/x-www-form-urlencoded
Content-Length: length
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
licenseID=string&content=string&/paramsXML=string
HTTP响应
HTTP /1.1 200 OK -- 状态行
Server: Microsoft-IIS/5.0 -- 多个响应头(服务器通过这些数据的描述信息,可以通知客户端如何处理它返回的数据)
Date: Thu, 13 Jul 2000 05:46:53 GMT
Content-Type: text/html
Content-Length: 2291
Cache-control: private
-- 一个空行
<HTML> -- 响应正文(实体内容)
<head>
<title>helloapp</title>
</head>
<BODY>
....
</body>
</html>
状态行:
格式:HTTP版本号,状态码
状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为5类:
状态码 | 含义 |
---|---|
100~199 | 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 |
200~299 | 表示成功接收请求并已经完成整个处理过程,常用200 |
300~399 | 为完成请求,客户端需进一步细化请求。例如,请求的资源已经移动一个新地址,常用302(页面不位于此处,请访问别处,重定向),307和304(要求浏览器使用缓存) |
400~499 | 客户端的请求有错误,常用404(无此资源) 403(无权限) |
500~599 | 服务器端出现错误,常用500 |
响应头:
Location: 配合302状态码使用,用于告诉客户端去找谁(实现重定向,通过地址的改变判断是否进行了重定向)。
Content-Encoding: 服务器通过这个头,指示数据的压缩格式
Content-Length:
Content-Type:
Last-Modified: 当前资源的缓存时间。
Refresh: 告诉浏览器隔多长时间刷新一次。(重要,聊天时获取最新数据,刷新实时图表)
Content-Disposition: 告诉浏览器以下载方式打开数据
Expires: 缓存的保存时间,-1和0表示不缓存。
Cache-Control: no-cache -- 控制浏览器不要缓存
Pragma: no-cache -- 控制浏览器不要缓存。 3个都设置缓存(适用不同浏览器)
压缩数据:
- 提高浏览
- 节省费用;对于网络公司,SIP通过出口的流量向其收费。
压缩API:
GZIPOutputSeream流的Write(byte[] buf, int off,int len)方法将字节数组写入压缩输出流,只要将数据给它就可以进行自动压缩。
GZIPOutputSeream为包装流,包装流一般都有缓冲,在缓冲区没有满时是不会将数据写入底层流的,所以才会有下面的gout.close()语句,或使用gout.flush()进行刷新。ByteArrayOutputStream bout = new ByteArrayOutputStream(); GZIPOutputStream gout = new GZIPOutputStream(bout); gout.write(data.getBytes()); gout.close(); byte gzip[] = bout.toByteArray(); //得到压缩后的数据 //通知浏览器返回数据采用压缩格式 response.setHeader("Content-Encoding","gzip"); response.setHeader("Content-Length",gzip.length+""); response.getOutputStream().write(gzip);
刷新数据间隔:
response.setHeader("refresh","3");//每隔3秒刷新一次
response.setHeader("refresh","3;url='http://www.sina.com'"); //每隔3秒刷新到新浪网
缓存介绍:服务器针对Web中的每个资源都会根据其内容生成一个随机Tag,当客户端第二次访问服务器的同一资源时,会带上这之前获得的tag给服务器,服务器根据该tag来判断是让客户端使用缓存还是重新发送新数据给客户端。
其它缓存相关的头,只能做到秒一级的控制。当服务器端数据已经更新但第二次访问与前一次访问时间差小于1秒,如果没有设置ETag缓存头,则服务器会让浏览器使用缓存数据。
ETag:可以进行实时更新。不常用。
HTTP使用头字段
Range可以自行写程序来从服务器进行断点下载,而不使用IE,但需要服务器支持Range。
请求头:
Range: 头指示服务器只传输部分Web资源。这个头可以用来实现断点续传功能。
Range:字段可以通过3种格式设置要传输的字节范围
Range: bytes=1000-2000 #
Range: bytes=1000- #1000以后的所有内容
Range: bytes=1000 #传输最后1000个字节
响应头:
Accept-Ranges: 说明Web服务器是否支持Range
Content-Ranges: 指定了返回的Web资源的字节范围。
以下内容来自《Tomcat与Java Web开发技术详解》
正文部分的MIME类型
HTTP请求及响应的正文部分可以是任意格式的数据,如何保证接收方能看懂发送方发送的正文数据?HTTP协议采用MIME协议来规范正文的数据格式。
MIME(Multipurpose Internet Mail Extension)是指多用在网络上传输的数据。因此,HTTP协议中的请求正文和响应正文也可以看做是邮件。MIME规定了邮件的标准数据格式,从而是的接收方能看得懂发送方发送的邮件。
遵守MIME协议的数据类型统称为MIME类型。在HTTP请求头和HTTP响应头中都有一个Content-type项,用来指定MIME类型。
文件扩展名 | MIME类型 |
---|---|
未知的数据类型或不可识别的扩展名 | content/unknown |
.bin、.exe、.o、.a、.z | application/octet-stream |
application/pdf | |
.zip | application/zip |
.tar | application/x-tar |
.gif | image/gif |
.jpg、.jpeg | image/jpeg |
.htm、.html | text/html |
.text、.c、.h、.txt、.java | text/plain |
.mpg、.mpeg | video/mpeg |
.xml | application/xml |
用Java套接字创建HTTP客户与服务器程序
见书籍《Tomcat与Java Web开发技术详解》孙卫琴
Web发展历程
Web按功能分,其发展历程分为如下阶段:
- 发布静态HTML文档
- 发布静态多媒体信息
- 提供浏览器端与用户的动态交互功能:Java Applet、JavaScript和VBScript
- 提供服务器端与用户的动态交互功能:PHP、ASP、JSP、Servlet、CGI
- 发布基于Web的应用程序,即Web应用:Web应用,只需要通过编程来创建的Web站点,Web应用通过Web服务器来发布。
- 发布Web服务:Web分为可以看做是被客户端远程调用的各种方法,这些方法能处理特定业务逻辑,或者进行复杂运算等。(它采用SOAP作为通信协议,使用XML语言进行通信)
- 推出Web 2.0:Web 2.0并不是现有Web 1.0的纯技术升级版本;它只是针对如何提供、组织及展示Web上的信息而提出的新概念。在Web 1.0中,广大用户主要是Web提供的信息的消费者。而Web 2.0强调全民织网,发动广大民众来共同为Web提供信息来源(同时成为Web信息的制造者)。Web 2.0的范畴如下:Blog、RSS(站点摘要)、Wiki(百科全书)、SNS(社交网络软件)、IM(即时通讯)。
Web服务
Web服务:Web分为可以看做是被客户端远程调用的各种方法,这些方法能处理特定业务逻辑,或者进行复杂运算等。(它采用SOAP作为通信协议,使用XML语言进行通信)
1.请求访问特定Web服务
___________ -------------> ________ 2.调用Web服务
| 客户程序 | | 服务器 | ------> Web服务
----------- <------------- --------
3.返回Web服务的响应结果
Web服务架构采用SOAP(Simple Object Access Protocol,简单对象访问协议)作为通信协议。SOAP协议规定客户与服务器之间一律采用XML语言进行通信。
SOAP协议规定了客户端向服务器端发送的Web服务请求的具体数据格式,以及服务器端向客户端发送的Web服务响应结果的具体数据格式。
要实现Web服务架构,就意味着必须创建基于SOAP协议,负责发布和调用Web服务,以及负责发送Web服务响应结果的服务器,还要创建基于SOAP协议的负责请求访问Web服务的客户程序。
如果Web服务能够坐上Web这辆顺风车,就能轻易在网络上流传起来。
假定Web服务(对应getTime()方法)能返回当前的系统时间,客户端请求访问这个Web服务:
Web服务实际上是借助Web服务器来发布到网络上的。这样就不必创建专门的基于SOAP协议的服务器程序了。
原始请求(请求时间) ----包装为----> SOAP请求 ---包装为---> HTTP请求 (其中SOAP请求变成了HTTP请求的正文部分) ----> 发送给服务器
SOAP响应 ----包装为----> HTTP响应 ----发送给客户端----> 客户端从HTTP响应中的正文中得到SOAP响应结果 -----协议解析器----->解析SOAP响应得打Web服务的**原始响应**(当前时间)
Web的基本功能:提供客户程序与服务器之间的数据传输。
Web服务的基本功能:是客户程序远程调用服务器端的方法。
由于在进行远程方法调用时,客户端与服务器之间也涉及到数据的交换,因此Web服务可以借助Web来传输双方的通信数据。
客户端协议解析器、客户端协议连接器组件,以及服务器端的协议解析器组件可以由第三方软件厂商提供。AXIS就是一个实现了这些组件的开放源代码软件,它相当于为发布和访问Web服务提供了基本的框架。
客户端向服务器端上传文件
在HTML表单中,
<form>
标记的enctype属性的值为默认的"application/x-www-form-urlencoded"。enctype
属性用于指定表单数据的MIME类型,默认值表示表单数据会采用"名字=值"的形式,只有在这种情况下,HTML表单数据才可作为请求参数来处理。对于MIME类型为"multipart/form-data"的HTML表单,这种类型的表单的数据格式化较复杂,无法简单的采用"名字=值"的形式。
HTTP请求和响应的正文部分可以是任意类型的数据
示例:
...
<!-- 请求正文 -->
<form action="servlet/UploadServlet" name="uploadForm" method="POST" enctype="MULTIPART/FORM-DATA">
<table>
<tr> <!-- 文件部分 -->
<td><div align="right">File Path:</div></td>
<td><input type="file" name="filedata" size="30"></td>
</tr>
<tr> <!-- 提交按钮部分 -->
<td><input type="submit" name="submit" value="upload"></td>
<td><input type="reset" name="reset" value="reset"></td>
</tr>
</table>
</form>
...
示例中HTTP请求的正文部分为复合类型,它包含两个子部分:文件部分和提交按钮部分。IE浏览器随机产生一个字符串形式的边界(boundary),在HTTP请求头中,以下代码设定了边界的取值:
Content-Type:multipart/form-data;boundary=-------------------------7d82d920188
其中Content-Type:multipart/form-data;boundary=
用于指定
-------------------------7d82d920188
为随机产生的边界值。
注意:
HTTP请求的正文部分的各个子部分之间用边界来进行分隔。每个子部分由头和正文部分组成,头和正文部分之间用空行分隔。
具体请求信息见书