java学习笔记- web基础六(Servlet)

简介

  • Servlet 是 JavaEE 规范之一。规范就是接口
  • Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器
  • Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端

URL地址到Servlet程序访问

URL地址到Servlet程序访问

生命周期

  1. 执行 Servlet 构造器方法,执行 init 初始化方法,是在第一次访问的时候创建 S ervlet 程序会调用

  2. 执行 service 方法,每次访问都会调用

  3. 执行 destroy 销毁方法,,在 web 工程停止的时候调用

Servlet类的继承体系

Servlet类的继承体系

ServletConfig类

  • Servlet 程序的配置信息类

作用

  • 可以获取 Servlet 程序的别名 servlet-name 的值

  • 获取初始化参数 init-param

  • 获取 ServletContext 对象

xml中配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?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">
<!-- context-param是上下文参数(属于整个web工程)-->
<context-param>
<param-name>username</param-name>
<param-value>root</param-value>
</context-param>
<context-param>
<param-name>password</param-name>
<param-value>123456</param-value>
</context-param>

<!-- servlet标签给Tomcat配置servlet程序-->
<servlet>
<!-- servlet name标签 servlet程序的一个别名(一般为类名) -->
<servlet-name>ServletTest</servlet-name>
<!--servlet class标签 是servlet程序的全类名-->
<servlet-class>com.study.servlet.ServletTest</servlet-class>

<!--init-param 是初始化参数 -->
<init-param>
<!-- param-name 参数名-->
<param-name>username</param-name>
<!-- param-value 参数值-->
<param-value>root</param-value>
</init-param>
</servlet>

<!--servlet-mapping 标签给servlet程序配置访问地址-->
<servlet-mapping>
<!--servlet-name标签的作用告诉服务器 当前配置的地址给那个servlet程序使用-->
<servlet-name>ServletTest</servlet-name>
<!-- url-pattern 标签配置访问地址
/ 在服务器中解析 表示地址为:http://ip:prot/工程路径
/ServletTest 表示地址为:http://ip:port/工程路径/ServletTest
-->
<url-pattern>/ServletTest</url-pattern>
</servlet-mapping>
</web-app>

Servlet:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class ServletTest implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("2. init初始化方法");
//1. 可以获取Servlet程序的别名servlet-name值
System.out.println(" ServletTest程序的别名:" + servletConfig.getServletName());
//2. 获取初始化参数init-param
System.out.println(" 初始化参数username的值:" + servletConfig.getInitParameter("username"));
System.out.println(" 初始化参数url的值:" + servletConfig.getInitParameter("url"));
//3. 获取ServletContext对象
System.out.println(servletConfig.getServletContext());
}
}

httpServlet:

继承httpServlet 进行重写init() 方法需要调用父类的init() 不然后面获取会空指针异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ServletTest2 extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
// 这里需要调用父类的init() 不然后面获取会空指针异常
/**
* public void init(ServletConfig config) throws ServletException {
* this.config = config;
* this.init();
* }
*
* 重写后这里父类GenericServlet中的init() config无法进行保存
*/
super.init(config);
System.out.println("重写init方法,执行一些操作");
}
}

ServletContext类

  • ServletContext 是一个接口,它表示 Servlet 上下文对象
  • 一个 web 工程,只有一个 ServletContext 对象实例
  • ServletContext 对象是一个域对象
  • ServletContext 是在 web 工程部署启动的时候创建。在 web 工程停止的时候销毁

域对象

  • 可以像 Map 一样存取数据的对象,叫域对象

  • 域指的是存取数据的操作范围是整个 web 工程

作用

  • 获取 web.xml 中配置的上下文参数 context-param
  • 获取当前的工程路径,格式: /工程路径
  • 获取工程部署后在服务器硬盘上的绝对路径
  • 像 Map 一样存取数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ServletContext extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 获取web.xml中配置的上下文参数context-param
javax.servlet.ServletContext context = getServletConfig().getServletContext();
String username = context.getInitParameter("username");
System.out.println("ContextServlet的username是:" + username);
System.out.println(" ContextServlet的password是:" + context.getInitParameter("password"));

//2. 获取当前的工程路径,格式:/工程路径
String contextPath = context.getContextPath();
System.out.println(" 当前工程路径是:" + contextPath);
//3. 获取工程部署后再服务器硬盘上的绝对路径
/**
* / 被服务器解析地址为:http://ip:port/工程名/ 映射到IDEA代码的web目录
*/
System.out.println(" 工程部署的绝对路径是:" + context.getRealPath("/"));
System.out.println(" 工程部署的绝对路径是:" + context.getRealPath("/css"));
}
}

xml:

1
2
3
4
5
6
7
8
9
10
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
<!--context-param 是上下文参数(它属于整个 web 工程)-->
<context-param>
<param-name>password</param-name>
<param-value>root</param-value>
</context-param>

HTTP协议

  • 客户端和服务器之间通信时,发送的数据,需要遵守的规则,叫 HTTP 协议

  • HTTP 协议中的数据又叫报文

请求的HTTP格式

GET请求

请求行
  • 请求的方式,如 GET或POST

  • 请求的资源路径[+?+请求参数]

  • 请求的协议的版本号 HTTP/1.1

请求头
  • key : value 组成 ,不同的键值对,表示不同的含义

GET请求HTTP协议内容

那些为GET请求
  • form 标签 method=get

  • a 标签

  • link 标签引入 css

  • Script 标签引入 js 文件

  • img 标签引入图片

  • iframe 引入 html 页面

  • 在浏览器地址栏中输入地址后敲回车

POST请求

请求行
  • 请求的方式 POST

  • 请求的资源路径[+?+请求参数]

  • 请求的协议的版本号 HTTP/1.1

请求头
  • key : value 不同的请求头,有不同的含义

  • 空行

请求体
  • 发送给服务器的数据

POST请求的HTTP协议内容

常用请求头说明

  • Accept: 表示客户端可以接收的数据类型

  • Accpet-Languege: 表示客户端可以接收的语言类型

  • User-Agent: 表示客户端浏览器的信息

  • Host: 表示请求时的服务器 ip 和端口号

那些为POST请求

  • form 标签 method=post

响应的HTTP协议格式

响应行

  • 响应的协议和版本号

  • 响应状态码

  • 响应状态描述符

响应头

  • key : value 不同的响应头,有其不同含义

  • 空行

响应体

  • 回传给客户端的数据

响应的HTTP协议内容

常用响应码

  • 200 表示请求成功
  • 302 表示请求重定向
  • 404 表示请求服务器已经收到了,但是你要的数据不存在(请求地址错误)
  • 500 表示服务器已经收到请求,但是服务器内部错误(代码错误)

MIME类型

  • MIME 是 HTTP 协议中数据类型,
  • 英文全称是”Multipurpose Internet Mail Extensions” 多功能 Internet 邮件扩充服务
  • 格式是“大类型/小类型”,并与某一种文件的扩展名相对应
文件 MIME类型
超文本标记语言文本 .html , .htm text/html
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
GIF图形 .gif image/gif
JEPG图形 .jpeg,.jpg image/jpeg
au声音文件 .au audio/basic
MIDI 音乐文件 mid,.midi audio/midi,audio/x-midi
RealAudio 音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG 文件 .mpg,.mpeg video/mpeg
AVI 文件 .avi video/x-msvideo
GZIP 文件 .gz application/x-gzip
TAR 文件 .tar application/x-tar

HttpServletRequest 类

作用

  • 通过HttpServletRequest对象获取请求的信息

常用方法

1
2
3
4
5
6
7
8
9
10
getRequestURI() 获取请求的资源路径
getRequestURL() 获取请求的统一资源定位符(绝对路径)
getRemoteHost() 获取客户端的 ip 地址
getHeader() 获取请求头
getParameter() 获取请求的参数
getParameterValues() 获取请求的参数(多个值的时候使用)
getMethod() 获取请求的方式 GET 或 POST
setAttribute(key, value); 设置域数据
getAttribute(key); 获取域数据
getRequestDispatcher() 获取请求转发对象

doGet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class ResponseISOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 返回中文显示不对解决方案一
System.out.println(resp.getCharacterEncoding());//默认是ISO-8859-1
// 设置服务器的字符集为UTF-8
// resp.setCharacterEncoding("UTF-8");
// // 通过响应头 设置浏览器的字符集为 UTF-8
// resp.setHeader("Content-Type","text/html;charset=UTF-8");
// 方案二
// 需要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
//返回数据给客户端
PrintWriter writer = resp.getWriter();
writer.write("你哈");//这里输入中文会无法显示
}
}

POST请求中文乱码解决

1
2
// 设置请求体的字符集为 UTF-8,从而解决 post 请求的中文乱码问题
req.setCharacterEncoding("UTF-8");

请求转发

  • 服务器收到请求后,从一次资源跳转到另一个资源的操作

请求转发

Servlet1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 请求转发可以访问 WEB-INF下的内容
// 请求转发浏览器中地址栏的地址不变
// 获取请求的参数
String username = req.getParameter("username");
System.out.println("在servlet1(柜台1) 查看参数(材料):" + username);
// 盖章 并传递到servlet2去查看
req.setAttribute("key","servlet1的章");
// 问路 servlet2(柜台2)怎么走
/**
* 这里必须为 /开头 因为/被解析为 http://ip:port/工程名/ 映射到IDEA代码的web目录
*/
RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");
// 请求转发
requestDispatcher.forward(req,resp);
}
}

Servlet2:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取请求的参数
String username = req.getParameter("username");
System.out.println("在servlet2(柜台2) 查看参数(材料):" + username);
// 查看柜台1servlet1的章
Object key = req.getAttribute("key");
System.out.println("柜台1是否有章" + key);
// 处理柜台2的任务
System.out.println("处理柜台2的任务");
}
}

特点

  • 浏览器地址栏没有变化
  • 是一次请求
  • 共享Request域中的数据
  • 可以转发到WEB-INF目录下
  • 不可以访问工程外的资源

base标签

base标签作用

1
2
3
<!--base 标签设置页面相对路径工作时参照的地址
href 属性就是参数的地址值-->
<base href="http://localhost:8080/07_servlet/a/b/">

web中的相对路径和绝对路径

在实际开发中,路径都使用绝对路径,而不简单的使用相对路径

1、绝对路径

2、base+相对

相对路径

  • . :表示当前目录

  • .. :表示上一级目录

  • 资源名 :表示当前目录/资源名

绝对路径

/斜杠意义

1
<a href="/">斜杠</a>
1
2
3
<url-pattern>/servlet1</url-pattern>
servletContext.getRealPath(“/”);
request.getRequestDispatcher(“/”);
  • 特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到 http://ip:port/

HttpServletResponse 类

  • 返回给客户端的信息,都可以通过 HttpServletResponse 对象来进行设置

输出流

二者只能使用其一,否则报错

  • 字节流 getOutputStream(); 常用于下载(传递二进制数据)
  • 字符流 getWriter(); 常用于回传字符串(常用)
  • 网客户端回传数据:
1
2
3
4
5
6
7
8
public class ResponseIOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
// 要求 : 往客户端回传 字符串 数据。
PrintWriter writer = resp.getWriter();
writer.write("response's content!!!");
}
}

响应乱码问题解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ResponseISOServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 返回中文显示不对解决方案一
System.out.println(resp.getCharacterEncoding());//默认是ISO-8859-1
// 设置服务器的字符集为UTF-8
// resp.setCharacterEncoding("UTF-8");
// // 通过响应头 设置浏览器的字符集为 UTF-8
// resp.setHeader("Content-Type","text/html;charset=UTF-8");

// 方案二
// 需要在获取流对象之前调用才有效
resp.setContentType("text/html; charset=UTF-8");
//返回数据给客户端
PrintWriter writer = resp.getWriter();
writer.write("你好");//这里输入中文会无法显示
}
}

请求重定向

  • 请求重定向,是指客户端给服务器发请求,然后服务器告诉客户端说。我给你一些地址。你去新地址访问。叫请求重定向(因为之前的地址可能已经被废弃)

请求重定向

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Response1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 请求重定向第一种方案(不推荐)
// //设置为状态为 302
// resp.setStatus(302);
// // 设置响应头 将新的路径发送给客户端
// resp.setHeader("Location", "http://localhost:8888/07_servlet/response2");

// 第二种 (推荐)
resp.sendRedirect("http://localhost:8888/07_servlet/response2");
}
}

特点

  • 浏览器地址会发生变化
  • 两次请求
  • 不共享Request中数据
  • 不能访问WEB-INF下的资源
  • 可以访问工程外的资源