Servlet 笔记

Servlet 简介

  1. java EE 的规范之一,表现在Java中就是一个接口
  2. javaWeb三大组件 Servlet 程序、Filter 过滤器、Listener 监听器(这个是自带的)
  3. 作用:接收客户端响应、并响应数据给客户端。

手动实现

public class HelloServlet implements Servlet{}

之后重写四个方法init、service、destory

service(ServletRequest servletRequest, ServletResponse servletResponse);

两个参数不能直接使用,他们两个也是接口需要调用实现类分别是,HttpServletRequest、HttpServletResponse;基本不会用

<!-- 给Tomcat配置servlet程序 -->
<servlet>
	<servlet-name>HelloServlet</servlet-name>
    <servlet-class>类地址(程序底层使用反射调用HelloServlet)</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>HelloServlet</servlet-name>
    <url-pattern>/hello</url-pattern>
</servlet-mapping>

生命周期

  1. 执行Servlet构造器方法
  2. 执行init方法

这两步在客户端第一次访问时调用。

  1. service方法
    每次访问都会调用
  2. destroy 方法
    web工程停止时调用

总结:客户段第一次访问开始,web工程停止结束。这是一个生命周期。

继承 HttpServlet 实现

  1. HttpServlet实现了 Servlet ,同时将针对 get 和 post 请求的业务处理分成了两个方法,doGet()和doPost()

  2. 配置 xml 文件,方法不变。

使用idea创建时可以直接使用内置的命令,NEW => create New Servlet

ServletConfig 类

  1. Tomcat 创建自动创建,每个Servlet创建时都会自动创建一个对应的ServletConfig 类。
  2. 会作为 init 方法的参数出现。
    1. Servlet 程序的别名(配置 xml 时我们自己创建的那个)
    2. 获取初始化 init-param
    3. 获取 ServletContext 对象

当重写init方法是一定要 调用 super.init(config);初始化的操作都在符类中进行。直接重写 service 方法时也要这么做。也可以在 HttpServlet 的子类中通过 getServletConfig() 方法获得

ServletContext 类

  1. 它也是一个接口,表示 Servlet 上下文对象
  2. 一个工程只有一个 ServletContext 对象实例
  3. ServletContext 对象是一个域对象。
  4. ServletContext 生命周期:web工程启动时创建结束时销毁。

它可以像 Map 一样存取数据,所有域对象的存、取、删除数据的方法都一样都一样。

存数据 setAttribute()、getAttribute()、removeAttribute();

四个作用:

  1. 获取 web.xml 中配置的上下文参数 context-param
  2. 获取当前的工程路径,格式: /工程路径
  3. 获取工程部署后在服务器硬盘上的绝对路径
  4. 像 Map 一样存取数据

HTTP 协议

  1. 客户端和和服务器之间发送数据所要遵循的一套规定。

  2. HTTP 发送的数据又叫报文

  3. 客户段发给服务器的叫请求

  4. 服务器返回给客户端的叫响应

协议格式
  • GET请求
    key:value 组成 不同键值对有不同的含义
    上学堂课程笔记

  • post请求
    尚学堂post请求

get 请求和 post 请求的区别

直观区别 :
get 的请求参数直接显示在搜索框当中,post 请求的参数隐藏在 body 中,请求头的下面
内部区别:
get 请求有数据大小限制,post 请求的限制可以忽略不计

对于一些不重要的请求参数一般直接使用 get 。对于设计敏感信息的请求使用 post

常用请求头

Accept: 表示客户端可以接收的数据类型
Accpet-Languege: 表示客户端可以接收的语言类型
User-Agent: 表示客户端浏览器的信息
Host: 表示请求时的服务器 ip 和端口号
GET 请求有哪些:

  1. form 标签 method=get
  2. a 标签
  3. link 标签引入 css
  4. Script 标签引入 js 文件
  5. img 标签引入图片
  6. iframe 引入 html 页面
  7. 在浏览器地址栏中输入地址后敲回车

POST 请求有哪些:
form 标签 method=post
post 请求只能通过单击 form 标签的提交按钮发送。

HTTP 响应格式

在这里插入图片描述

响应码

成功 200
请求重定向 302
请求地址错误 404
服务器内部错误 500

MIME 类型说明

MIME 时 HTTP 协议中数据类型。
MIME 全称 “Multipurpose Internet Mail Extensions” 多功能 Internet 邮件扩充服务。MIME 类型的格式是“大类型/小 类型”,并与某一种文件的扩展名相对应。
在这里插入图片描述
在这里插入图片描述
浏览器中查看数据信息
在这里插入图片描述

HttpServletRequest 和 HttpServletResponse

HttpServletRequest 类

方法作用
getRequestURI()获取请求的资源路径
getRequestURL()获取请求的统一资源定位符
getRequestHost()获取客户段端的ip地址
getHeader()获取请求头
String[] getParameterValues(String name)获取请求的多个参数,一个请求有多个值
String getParameter(String name)获取请求参数
String getMethod()获取请求的方式 GET 和 POST
setAttribute(key, value)设置域数据
getAttribute(key)获取域数据
getRequestDispathher(String path)获取请求转发对象
Request、Response的生命周期
  1. tomcat收到请求后,创建Request和Response两个对象,数据传递给Servlet
  2. 浏览器接收到返回消息后,tomcat销毁Request和Response两个对象,同时销毁这两个对象所获得的信息。
    简单来说:就是一次请求和响应。
解决doGet请求乱码的问题:
String name = req.getParameter("username");
//先以 iso8859-1 进行编码
//再以 utf-8 进行解码
username = new String(name.getBytes("iso8859-1"), "UTF-8");
解决POST请求乱码的问题
//设置请求体的字符集为 utf8 来解决乱码的问题
req.setCharacterEncoding("UTF-8");
// 获取请求
	.....
请求转发
  1. 从一个资源跳到另一个资源
  2. 请求转发只请求一次,跳转到的所有资源共享一次请求的参数。
  3. 浏览器中的地址不会发送变化
  4. 可以转发到WET-INF目录下
  5. 不可以访问工程以外的资源
    在这里插入图片描述
//获得资源2的地址
RequestDispatcher rd = req.getRequestDispatcher("/servlet2");
//开始跳转
rd.forward(req, resp);//向下一个资源传递参数

请求转发过程中的为方便跳转可以使用<base>标签,用于定义标签中所有路径的基准。

<base href="http://localhost:8080/book/">
<form action="/index.html">
<!--以上就相当于-->
<form action="http://localhost:8080/book/index.html">
Web 中的路径

相对路径:
. 表示当前路径
… 表示上一级
path 表示当前路径/path

绝对路径:
http://ip:port/工程路径/资源路径

再web中 / 是一种绝对路径
页面中的 / 被浏览器解析,得到的地址就是:http://ip:port/
<a hreg="/">

服务器中 / 解析,得到的地址就是:http://ip:port/工程路径

<url-pattern>/servlet1</url-pattern>
servletContext.getRealPath("/");
request.getRequestDispatcher("/");

HttpServletResponse 类

HttpServletResponse 类的作用

和 httpServletRequest 一样每次 Tomcat 接收到浏览器的请求就会创建一个 Response 对象传递给 Servlet 去使用。httpServletRequest 表示请求发送的数据,HttpServletResponse 表示响应发送的数据。
相向客户端发送的数据都可以通过 HttpServletResponse 对象来进行设置。

数据传输流
作用
getOutputStream用于响应下载二进制文件
getWriter用于响应下载文本文件

两个流只能使用一个,否则会有问题。

PrintWriter pw = resp.getWriter();
pw.write("Hello World");

//下载二进制文件就直接接入IO
OutputStream os = resp.getOutputStream();
解决响应乱码的问题

方法一:(很少人用)

//设置服务器字符集为utf8
resp.setCharacterEncoding("utf8");
//通过响应头,设置浏览器也使用 utf-8
resp.setHeader("Content-Type","text/html; charset=UTF-8");

方法二:(常用)

resp.setContentType("text/html:charset=UTF-8");

这个方法可以同时设置,服务器和客户端都使用 UTF-8 字符集

请求重定向

和请求转发的不同,请求重定向会进行两次请求,浏览器的访问地址会发生变化。这样就可以防止刷新时同一个请求重复发送
在这里插入图片描述
第一种写法

//设置状态码为302,表示重定向
resp.setStatus(302);
//设置响应头,说明 新的地址再哪里
resp.setHeader("Location","http://localhost:8080");

第二种写法(推荐使用)

resp.sendRedirect("http://localhost:8080");

服务器与客户端之间的文件互传

文件上传
  1. 要在 form 标签中使用 post 方法请求。
  2. form 标签的 encType 属性值必须为 multipart/form-data 值
  3. 在 form 标签中使用<input type="file">添加上传的文件
  4. 编写服务器代码接收,处理文件上传数据。

这里的 encType="multipart/form-data" 是 form 标签的属性表示提交的数据,是以多段(每一个表单项一个数据段)的形式进行拼接,然后以二进制流的形式发送给服务器。

文件上传,HTTP协议说明。

在这里插入图片描述

文件上传 api

主要接收用的包是 commons-fileupload.jar ,此包依赖依赖 commons-io.jar 这个包,阴因此两个要一起导入。
commons-fileupload
commons-io

文件上传 api 的使用
  1. 使用的类
    • ServletFileUpload 类,用于解析上传的数据
    • FileItem 类,表示每一个表单项
  2. 使用的方法
    • boolean ServletFileUpload.isMultipartContent(HttpServletRequest request);判断上传的数据格式是否是多端格式。
    • public List<FileItem> parseRequest(HttpServletRequest request)解析上传的数据
    • boolean FileItem.isFormField() 判断当前表单项,是普通表单项,还是上传的文件。普通表单项返回true,文件类型返回 false
    • String FileItem.getFieldName() 获取表单项的 name 属性值
    • String FileItem.getString() 获取当前表单项的值。
    • String FileItem.getName() 获取表单项的文件名
    • void FileItem.write(file) 将上传的文件写到 参数 file 所指向的硬盘位置。
文件上传完整代码
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

	//1 先判断上传的数据是否多段数据(只有是多段的数据,才是文件上传的) 
	if (ServletFileUpload.isMultipartContent(req)) { 
	// 创建 FileItemFactory 工厂实现类 
	FileItemFactory fileItemFactory = new DiskFileItemFactory(); /
	/ 创建用于解析上传数据的工具类 ServletFileUploadServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory); 
	try {
		// 解析上传的数据,得到每一个表单项 
		FileItem List<FileItem> list = servletFileUpload.parseRequest(req); 
		// 循环判断,每一个表单项,是普通类型,还是上传的文件
		for (FileItem fileItem : list) { 
			if (fileItem.isFormField()) { 
			// 普通表单项 
			System.out.println("表单项的 name 属性值:" + fileItem.getFieldName()); 
			// 参数 UTF-8.解决乱码问题 
			System.out.println("表单项的 value 属性值:" + fileItem.getString("UTF-8")); 
			} else { 
				// 上传的文件 
				System.out.println("表单项的 name 属性值:" + fileItem.getFieldName()); 
				System.out.println("上传的文件名:" + fileItem.getName()); 		
				fileItem.write(new File("e:\\" + fileItem.getName())); 
			} 
		} 
	} catch (Exception e) { 
		e.printStackTrace(); 
	} 
}
文件下载

下载所使用的 api :
response.getOutputStream(OutputStream os);
获得文件输出流
ServletContext.getResourceAsStream(String path);
ServletContext.getMimeType();
获得文件的类型
response.setContextType();

response.setHeader("Content-Disposition", "attachment; fileName=1.jpg");
Content-Disposition这个响应头告诉浏览器,这是需要下载的。而 attachment 表示附件,也就是下载的一个文件。fileName=后面, 表示下载的文件名。

乱码问题

中文如果有中文,不同浏览器处理的方式不同,部分浏览器就会出现乱码。

解决方法
  1. URLEncoder() 解决IE 谷歌浏览器的乱码问题。
// 把中文名进行 UTF-8 编码操作。 
String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8"); 
// 然后把编码后的字符串设置到响应头中 
response.setHeader("Content-Disposition", str);
  1. 通过 Base64 编码解决火狐浏览器的乱码问题
    火狐浏览器比较特殊处理使用 base64编码 响应的中文名。编码过程
// 使用下面的格式进行 BASE64 编码后 
String str = "attachment; fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?="; 
// 设置到响应头中 
response.setHeader("Content-Disposition", str);

使用以上程序处理后的 str 的打印的结果为:
Content-Disposition: attachment; filename==?utf-8?B?xxxxx?=
xxxxx 就是通过 base64 编码生成的数字。一般格式为 \x二位十六进制数字\x二位十六进制数字\x二位十六进制数字

最终方案

访问服务器的往往不会是一种固定的浏览器。如何解决所有问题哪?浏览器在发来请求的时候就会有一条数据称为User-Agent:.....................每个浏览器都不同,通过它就可以区分不同的浏览器来解决问题

String ua = request.getHeader("User-Agent"); 
// 判断是否是火狐浏览器 
if (ua.contains("Firefox")) { 
	// 使用下面的格式进行 BASE64 编码后 
	String str = "attachment; fileName=" + "=?utf-8?B?" + new BASE64Encoder().encode("中文.jpg".getBytes("utf-8")) + "?="; 
	// 设置到响应头中 
	response.setHeader("Content-Disposition", str); 
} else {
	// 把中文名进行 UTF-8 编码操作。 
	String str = "attachment; fileName=" + URLEncoder.encode("中文.jpg", "UTF-8"); 
	// 然后把编码后的字符串设置到响应头中 
	response.setHeader("Content-Disposition", str); 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值