Servlet & HTTP
Servlet:server applet
概念
# 运行在服务器端的小程序
* Servlet 就是一个接口,定义了 Java类被浏览器访问(被 Tomcat 识别)的规则
* 将来我们自定义一个类,实现 Servlet接口,复写方法
快速入门
1)创建 JavaEE 项目
2)定义一个类,实现 Servlet 接口
* public class ServletDemo1 implements Servlet
3)实现接口中的抽象方法
4)配置 Servlet
* 在 web.xml 中配置:
<servlet>
<servlet-name>demo1</servlet-name>
<servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
执行原理
1) 当服务器接收到客户端浏览器的请求后,会解析请求 URL 路径,获取访问的 Servlet 的资源路径
2) 查找 web.xml 文件,是否有对应的 <url-pattern> 标签体内容
3)如果有,则找到对应的 <servlet-class> 全类名
4)tomcat 会将字节码文件加载进内存,并且创建其对象
5)调用其方法
Servlet 中的生命周期方法
# 被创建:执行 init() 方法,只执行一次
* 默认情况下,第一次被访问时,Servlet被创建
* 可以配置执行 Servlet 的创建时机
* 在 <servlet>标签下配置
1)第一次被访问时创建:<load-on-startup>的值为负数,默认值即为 -1
2)在服务器启动时创建:<load-on-startup>的值为0或正数
* Servlet 的 init() 方法,只执行一次,说明一个 Servlet在内存中只存在一个对象,Servlet 是单例的
* 多个用户同时访问时,可能存在线程安全问题
* 解决:尽量不要在 Servlet 中定义成员变量,即使定义了成员变量,也不要修改值
# 提供服务:执行 service() 方法,可执行多次
* 每次访问 Servlet时,service() 方法都会被调用一次
# 被销毁:执行 destroy() 方法,只执行一次
* 在服务器正常关闭时,执行 destroy() 方法,销毁 Servlet,释放资源
package cn.itcast.web.servlet; import javax.servlet.*; import java.io.IOException; /** * Servlet的方法 */ public class ServletDemo2 implements Servlet { /** * 初始化方法,在Servlet被创建时执行,只会执行一次 * @param servletConfig * @throws ServletException */ @Override public void init(ServletConfig servletConfig) throws ServletException { System.out.println("init...."); } /** * 获取ServletConfig对象,即配置对象 * @return */ @Override public ServletConfig getServletConfig() { return null; } /** * 提供服务的方法,每一次Servlet被访问时执行,能执行多次 * @param servletRequest * @param servletResponse * @throws ServletException * @throws IOException */ @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("service..."); } /** * 获取Servlet的相关信息:版本,作者等 * @return */ @Override public String getServletInfo() { return null; } /** * 销毁方法,在服务器被正常关闭时执行,只会执行一次 */ @Override public void destroy() { System.out.println("destroy..."); } }
Servlet 3.0
# 好处:
* 支持注解配置,可以不需要 web.xml 了
# 步骤:
1)创建 JavaEE项目,选择 Servlet的版本在 3.0以上
2)定义一个类,实现 Servlet 接口
3)复写方法
4)在类上使用 @webServlet 注解进行配置
@WebServlet(urlPatterns = "/demo3")
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
String name() default ""; // 相当于 <Server-name>
String[] value() default {}; // 代表 urlPatterns() 属性配置
String[] urlPatterns() default {}; // 相当于 <url-pattern>
int loadOnStartup() default -1; // 相当于 <load-on-startup>
WebInitParam[] initParams() default {};
boolean asyncSupported() default false;
String smallIcon() default "";
String largeIcon() default "";
String description() default "";
String displayName() default "";
}
Servlet 体系结构
Servlet - - - 接口
|
GenericServlet - - - 抽象类
|
HttpServlet - - - 抽象类
# GenericServlet:将 Servlet 接口中其他的方法做了默认空实现,只将 service() 方法作为抽象
* 将来定义 Servlet 类时,可以继承 GenericServlet 类,实现 service() 方法即可
# HttpServlet:对 http 协议的一种封装,简化操作
* 定义类继承 HttpServlet
* 复写 doGet() / doPost() 方法
Servlet 相关配置
# IDEA 会为每一个 Tomcat 部署的项目单独建立一份配置文件
* 查看控制台的 log :Using CATALINA_BASE: "C:\Users\DELL\.IntelliJIdea2019.2\system\tomcat\_JavaWeb"
# 工作空间项目 和 Tomcat部署的 web项目
* Tomcat真正访问的是 “Tomcat部署的 web项目”,它对应着 “工作空间项目” 的 web目录下的所有资源
* WEB-INF 目录下的资源不能被浏览器直接访问
# urlpattern:Servlet访问路径
* 一个 Servlet可以定义多个访问路径:@webServlet({"/demo4", "/d4", "/dd4"})
* 路径定义规则:
1)/xxx:路径匹配
2)/xxx/xxx:多次路径匹配,目录结构
3)*.do:扩展名匹配
HTTP
概念
# Hyper Text Transfer Protocol 超文本传输协议
* 传输协议:定义了客户端和服务器端通信时,发送的数据格式
# 特点:
1)基于 TCP/IP 的高级协议
2)默认端口号:80
3)基于请求/响应模型,一次请求对应一次响应
4)无状态的:每次请求之间相互独立,不能交互数据
# 历史版本:
* 1.0:每一次请求都会建立新的连接
* 1.1:复用连接
请求消息
# 请求行
* 格式:请求方式 请求 url 请求协议/版本
* 如: GET /login.html HTTP/1.1
# 请求方式:
* HTTP协议中一共有7种请求方式,常用的有2种
* GET:
1)请求参数在请求行中,在 url 的末端
2)请求的 url 长度有限制
3)不太安全
* POST:
1)请求参数在请求体种
2)请求的 url 长度没有限制
3)相对安全
# 请求头:客户端浏览器告诉服务器的一些信息
* 格式: 请求头名称:请求头值
# 常见的请求头:
1)User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
* 可以在服务器端获取该头的信息,解决浏览器的兼容性问题
2)Referer:http://localhost/login.html
* 告诉服务器,当前请求从哪里来
* 作用:
① 防止盗取链接
② 方便统计
# 请求空行
* 空行,就是用于分割 POST 请求的请求头和请求体的
# 请求体(正文)
* 封装 POST 请求消息的请求参数
# 整体字符串格式:
POST /login.html HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Accept-Encoding: gzip, deflate Referer: http://localhost/login.html Connection: keep-alive Upgrade-Insecure-Requests: 1 username=zhangsan
响应消息数据格式
# 响应行:
* 格式:协议/版本 响应状态码 状态码描述
* 响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态。
* 状态码都是 3位数字
* 分类:
1)1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx状态码
2)2xx:成功。代表:200
3)3xx:重定向。代表:302(重定向),304(访问缓存)
4)4xx:客户端错误。代表:404(请求路径没有对应的资源),405(请求方式没有对象的doXxx()方法)
5)5xx:服务器端错误。代表:500(服务器内部出现异常)
# 响应头:
* 格式:头名称:值
* 常见的响应头:
1)Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
2)Content-disposition:服务器告诉客户端以什么格式打开响应体数据
* in-line:默认值,在当前页面打开
* attachment;filename=xxx:以附件形式打开响应体,文件下载
# 响应空行
# 响应体:传输的数据
# 字符串格式
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 101
Date: Wed, 06 Jun 2018 07:08:42 GMT
<html>
<head>
<title>$Title$</title>
</head>
<body>
hello , response
</body>
</html>