什么是HTTP响应
服务器端数据发送回浏览器,称为响应,在浏览器端就可以看到服务器处理的结果,:如下订单成功,预约成功等.
请求:request 响应:response
响应信息的三个组成


响应行、响应头、响应体的格式
目标
- 响应行的格式
- 响应头的格式
- 响应体的格式
响应行
请求行三个部分:请求方式 URI HTTP/1.1
响应行三个部分:协议和版本 状态码 状态描述
HTTP/1.1 200 OK
HTTP/1.1 302 Found
响应头
左边是键,右边是值,中间是冒号
| 响应头信息 | 说明 |
|---|---|
| Location: www.baidu.com | 下一个要跳转的页面 |
| Server:Apache Tomcat | 访问的服务器名字 |
| Content-Encoding: gzip | 服务器数据的压缩格式,服务器的数据压缩过的 |
| Content-Length: 80 | 服务器发送回来的数据长度 |
| Content-Type: text/html; charset=utf-8 | 服务器返回的数据类型,MIME类型 |
| Refresh: 1;url=/hello.html | 过1秒以后跳转到另一个页面 |
| Content-Disposition: attachment; filename=文件名.扩展名 |
文件下载,以附件的方式打开文件 |
响应体
从服务器端发送回来的数据主要有两种:字节数据和字符数据
文本:字符数据,比如:HTML,JS,CSS
图片,音乐,视频,可执行文件,压缩包:字节数据
小结:响应的组成

常见的状态码
目标
- 响应行中常见状态码的含义
- 404与405出现的原因
常见状态码的含义
200
服务器正常响应
HTTP/1.1 200 OK
302
表示页面进行了跳转
HTTP/1.1 302 Found
304
表示浏览器使用了缓存
403
请求服务器,被服务器禁止访问
404
-
页面地址输入错误,注意在tomcat中地址区分大小写
-
不能直接访问WEB-INF下面资源,这下面的资源是受保护,如果直接访问也会出现404错误
-
重定向或转发地址不正确,页面跳转的时候那个跳转到的地址不存在
405
doGet或doPost方法没有重写
500
服务器端代码出现异常
小结
| 状态码 | 含义 |
|---|---|
| 200 | 正确响应 |
| 302 | 页面进行了跳转 |
| 304 | 页面使用了缓存 |
| 404 | 服务器上指定的资源不存在 |
| 405 | 没有重写doGet或doPost方法 |
| 500 | 服务器代码出现异常 |
XML配置方式:创建Servlet
目标
使用web.xml配置方式编写第1个Servlet
什么是Servlet
Servlet与普通的Java程序的区别
- 本质上就是一个Java类
- 所有的类必须直接或间接的实现javax.servlet.Servlet接口
- 必须运行在Tomcat等Web容器中,由Web容器来调用Servlet程序
- 处理浏览器发送的请求,并且将服务器的处理结果响应给浏览器
Tomcat与Servlet的关系

- 用户发送请求请求Tomcat的8080端口
- 由Tomcat去调用我们写的Servlet,我们的任务就是编写Servlet
- Servlet接受用户的请求,并且处理结果,将结果通过响应发送回浏览器
- 浏览器看到服务器返回的结果,这个网页其实就是Servlet运行的结果
编写Servlet的步骤
- 创建一个类,继承于HttpServlet抽象类(实现了Servlet接口)
- 重写doGet或者doPost方法,分别处理浏览器发送的get或者post请求
- 在web.xml中配置servlet的信息,浏览器才能访问这个Servlet
- 配置类完全限定名(包名,类名)
- 配置Servlet的访问地址,必须以/开头
代码实现步骤
/*
1. 创建一个类,继承于HttpServlet抽象类(实现了Servlet接口)
2. 重写doGet或doPost方法,分别处理浏览器发送的get或post请求
3. 在web.xml中配置servlet的信息,浏览器才能访问这个Servlet
1. 配置类完全限定名(包名.类名)
2. 配置Servlet的访问地址,必须以/开头
*/
public class Demo1Servlet extends HttpServlet {
/**
* 只重写了doGet方法,因为我只用get请求
* @param request 请求对象
* @param response 响应对象
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置服务器响应的数据类型
response.setContentType("text/html;charset=utf-8"); //表示这是一个网页的内容,编码是utf-8
//2.得到响应的打印流,向网页上输出内容
PrintWriter out = response.getWriter();
//3.输出任何文本
out.print("<h1>你好,这是第1个Servlet</h1>");
}
}
- 编辑web.xml中配置servlet,设置访问地址为/demo01
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--
配置servlet
1. 配置类完全限定名(包名.类名)
2. 配置Servlet的访问地址,必须以/开头
-->
<servlet>
<!--配置servlet的名字,servlet不能出现相同的名字-->
<servlet-name>demo1</servlet-name>
<servlet-class>com.itheima.servlet.Demo1Servlet</servlet-class>
</servlet>
<servlet-mapping>
<!--这个名字与上面的名字相同-->
<servlet-name>demo1</servlet-name>
<!--访问地址必须以/开头,否则会导致tomcat加载项目失败,所有的资源都无法访问-->
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
</web-app>
注解的方式:开发Servlet
目标
Servlet3.0以后才支持,使用注解的方式创建Servlet
流程
- 创建1个类,继承于HttpServlet类
- 重写doGet或doPost方法
- 使用@WebServlet指定Servlet的访问地址
具体操作
-
创建Servlet类,使用注解@WebServlet
@WebServlet注解属性 说明 name 可选属性,servlet的名字相当于配置:
<servlet-name>demo1</servlet-name>urlPatterns 访问地址,相当于
<url-pattern>/demo1</url-pattern>value 功能与上面urlPatterns一样,指定当前Servlet访问地址,必须以/开头
-
代码:
package com.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /* 1. 创建1个类,继承于HttpServlet类 2. 重写doGet或doPost方法 3. 使用@WebServlet指定Servlet的访问地址 */ @WebServlet("/demo2") //demo2就是访问地址,必须以/开头 public class Demo2Servlet extends HttpServlet { /** * @param request 请求对象 * @param response 响应对象 */ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.设置响应的类型和编码 response.setContentType("text/html;charset=utf-8"); //2.得到打印流,输出文本 PrintWriter out = response.getWriter(); //3.输出文本 out.print("<h1 style='color:red'>你好,注解的Servlet 3.0</h1>"); } }
Servlet的生命周期
目标
Servlet生命周期有哪些方法
Servlet接口中的方法
每个servlet在tomcat中执行都会依次执行这3个方法,构成了servlet的生命周期
| 方法 | 作用 | 运行次数 |
|---|---|---|
| void init(ServletConfig config) | 初始化的时候执行 | 第1次有用户访问的时候执行1次 |
| void service(ServletRequest req, ServletResponse res) |
服务的方法 | 每次请求和响应都会执行 执行多次 |
| void destroy() | 销毁的方法 | 在服务器关闭的时候执行1次 |
Servlet的生命周期
注:一个Servlet在tomcat容器中只会实例化一次,只会产生一个对象,而且常驻内存,要等到服务器关闭才会销毁。

代码实现
package com.servlet;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
import java.sql.Timestamp;
/*
1. 创建一个类,实现接口javax.servlet.Servlet
2. 重写接口中所有的方法: init() service() destroy()
3. 使用注解@WebServlet("/访问地址")
*/
@WebServlet("/demo3")
public class Demo3LifeCycleServlet implements Servlet {
//初始化方法:Servlet第1次实例化的时候执行1次,因为只会有一个对象,所以只会执行1次
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println(new Timestamp(System.currentTimeMillis()) + " " + this + "被初始化");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 每次请求都会执行
* @param servletRequest 请求
* @param servletResponse 响应
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println(new Timestamp(System.currentTimeMillis()) + " 执行service方法");
}
@Override
public String getServletInfo() {
return null;
}
/**
* 服务器关闭的时候执行1次
*/
@Override
public void destroy() {
System.out.println(new Timestamp(System.currentTimeMillis()) + " " + this + " 被销毁");
}
}
Servlet映射多个路径
目标
如何配置1个Servlet有多个访问地址
配置方式
- 写多个url-pattern,每个url-pattern是一个访问地址
<servlet>
<!--配置servlet的名字,servlet不能出现相同的名字-->
<servlet-name>demo1</servlet-name>
<servlet-class>com.itheima.servlet.Demo1Servlet</servlet-class>
</servlet>
<servlet-mapping>
<!--这个名字与上面的名字相同-->
<servlet-name>demo1</servlet-name>
<!--访问地址必须以/开头,否则会导致tomcat加载项目失败,所有的资源都无法访问-->
<!--可以配置多个访问地址,多个地址不能相同-->
<url-pattern>/demo1</url-pattern>
<url-pattern>/demo100</url-pattern>
</servlet-mapping>
- 可以配置多个servlet-mapping,对应同一个servlet-name
<servlet>
<!--配置servlet的名字,servlet不能出现相同的名字-->
<servlet-name>demo1</servlet-name>
<servlet-class>com.itheima.servlet.Demo1Servlet</servlet-class>
</servlet>
<servlet-mapping>
<!--这个名字与上面的名字相同-->
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<!--这个名字与上面的名字相同-->
<servlet-name>demo1</servlet-name>
<url-pattern>/demo99</url-pattern>
</servlet-mapping>
注解方式
value属性和urlPatterns属性都是一个字符串的数组,可以指定多个访问地址
@WebServlet({"/demo2","/demo200"})
@WebServlet(name = "demo2", urlPatterns = {"/demo2","/demo200"})
小结
如何在servlet中配置多个访问地址?
配置文件的方式
- 配置多个url-pattern
- 一个servlet对应多个servlet-mapping配置
注解的方式
- @WebServlet({"/地址","/地址"})
- @WebServlet(name="名字", urlPatterns={"/地址","/地址"})
url-pattern的通配符
目标
访问地址不但可以指定多个,还可以使用通配符,可以自动匹配多个地址
介绍
- 什么是通配符:
可以匹配多个字符的符号
- 两种通配符的格式:
| 通配符格式 | 说明 |
|---|---|
| /开头 | 匹配所有的文件: /* 匹配某个目录下所有的文件:/目录名/* |
| *.扩展名 | 匹配某种后缀名结尾的访问地址,如:*.do |
-
代码
package com.servlet; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /* 匹配原则: 1. Servlet之间最佳匹配原则,如果已经有的servlet访问地址更加精确的匹配,它会执行精确匹配的servlet 2. 如果某个servlet使用/*的访问地址,会导致所有的静态页面都不能访问,因为所有的静态页面,tomcat都有一个默认的servlet去处理 3. 不能使用:同时以/开头和以扩展名结尾的地址,这是错误的 IllegalArgumentException: Invalid <url-pattern> [/*.do] in servlet mapping 4. 如果既匹配/开头的地址,又匹配扩展名结尾的地址,优先匹配/开头 */ //@WebServlet("/*") //匹配所有的地址 //@WebServlet("/admin/*") //匹配某个目录下所有的资源 //@WebServlet("*.do") //如果出现了扩展名结尾的通配符,不能以/开头 //@WebServlet("/*.do") //同时出现/开头和扩展名结尾,这是一个错误的地址,导致tomcat加载这个servlet失败,所有的资源无法访问 public class Demo4PathServlet extends HttpServlet { //重写doGet方法 @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.设置响应类型和编码 response.setContentType("text/html;charset=utf-8"); //2.得到打印流 PrintWriter out = response.getWriter(); //3.输出内容 out.print("<h2>通配符的使用</h2>"); } }
面试题
创建2个Servlet,一个Servlet1,一个Servlet2,在下列情况下,访问哪个Servlet
| 请求URL | Servlet1 | Servlet2 | 访问哪个 |
|---|---|---|---|
| /abc/a.html | /abc/* | /* | servlet1,最佳匹配 |
| /abc | /abc/* | /abc | servlet2,最佳匹配 |
| /abc/a.do | /abc/* | *.do | servlet1,/的优先级更高 |
| /a.do | /* | *.do | servlet1,/的优先级更高 |
| /xxx/yyy/a.do | /* | *.do | servlet1,/的优先级更高 |
小结
- 优先级:/开头的优先级高于扩展名结尾的访问地址优先级
- 匹配原则:最佳匹配原则,哪个更接近访问地址,就匹配哪个
- Servlet中不能同时出现/开头和扩展名结尾的访问地址,否则会导致服务器加载异常
Servlet的执行流程
目标
了解tomcat的执行过程
Tomcat的执行过程

| 1. 每个tomcat中可以部署多个项目的,如:one, two |
|---|
| 2. 每个项目中有多个servlet,每个servlet有不同的访问地址 |
| 3. 在所有的类对象中找有@WebServlet("/demo1")注解的类对象 |
| 4. 对Demo这个Servlet通过反射实例化 |
| 5. tomcat创建请求和响应对象 |
| 6. 调用service()方法,并且将请求和响应对象传递进去 |
| 7. 执行service()方法,并且调用子类中doGet或doPost方法 |
| 8. 最后执行我们的doGet或doPost方法,并且处理数据 |
| 9. 数据处理完毕以后发送响应回到浏览器 |
小结
-
Servlet对象是通过什么技术实例化的?
servlet对象是tomcat通过反射来实例化的 -
request和response对象从哪里来?
由tomcat创建,并且通过service()方法传递进来 -
service方法做了什么?
调用子类中doGet或doPost方法
load-on-startup参数
目标
学习load-on-startup参数使用
作用
- 为什么要使用这个配置?
在默认的情况下,Servlet是用户第一次请求的时候实例化
有时我们希望tomcat启动的时候就实例化这个servlet,而不是等到有人访问的时候才实例化。
使用load-on-startup参数
-
参数的使用说明:
如果没有这个参数或这个参数是负数,由web容器自由加载 如果这个参数是正整数或0,小的数在前面加载 数字就是加载的先后顺序
案例
需求
在一个Servlet中的init方法中直接输出一句话到控制台上,比较加不加的<load-on-startup>的区别
代码
使用配置的方式:web.xml
<servlet>
<servlet-name>demo6</servlet-name>
<servlet-class>com.itheima.servlet.Demo6HttpServlet</servlet-class>
<!--tomcat启动时候就初始化这个servlet-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>demo6</servlet-name>
<url-pattern>/demo6</url-pattern>
</servlet-mapping>
使用注解的方式:servlet
@WebServlet(name = "demo6", urlPatterns = "/demo6", loadOnStartup = 1)
代码
/*
loadOnStartup 表示tomcat启动就加载这个servlet
*/
//@WebServlet(name = "demo6", urlPatterns = "/demo6", loadOnStartup = 1)
public class Demo6HttpServlet extends HttpServlet {
//重写了生命周期中方法,在servlet第1次实例化的时候
@Override
public void init() throws ServletException {
System.out.println(new Timestamp(System.currentTimeMillis()) + " 这是第一次");
}
/**
* 如果直接在浏览器上输入地址访问的方式:doGet方法
* 只有表单提交使用post方式的时候,才会执行doPost方法,除此之外所有的都是doGet方法
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应类型和编码
response.setContentType("text/html;charset=utf-8");
//得到打印流
PrintWriter out = response.getWriter();
out.print("你好,我是servlet");
}
}
小结
这个参数的使用是什么?
在tomcat启动的时候加载当前的这个servlet