Servlet的生命周期方法:
1、被创建:执行init方法,只执行一次
Servlet的init方法,只执行一次,说明一个Servlet在内存中只存在一个对象,Servlet是单例的。多个用户同时访问时,可能存在线程安全问题。所以尽量不要在Servlet中定义成员变量。即使定义了成员变量,也不要去修改值。
2、提供服务:执行service方法,执行多次
每次访问Servlet时,Servlet方法都会被调用一次。
3、被销毁:执行destroy方法,只执行一次
Servlet被销毁时执行。服务器正常关闭时,Servlet被销毁。
HTTP:超文本传输协议(定义了发送数据的格式)
1、基于TCP/IP的高级协议
2、默认端口号:80
3、基于请求/响应模型的:一次请求对应一次响应
4、无状态的:每次请求之间相互独立,不能交互数据
请求消息数据格式
1、请求行(请求url)
请求方式有七种,常用两种,get和post.
2、请求头:客户端浏览器告诉服务器一些信息
请求头名称:请求头值
常见的请求头:
1、User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
可以在服务器端获取该头的信息,解决浏览器兼容问题
2、Referer:告诉服务器,我当前的请求从哪里来。
作用:防盗链、统计工作
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding:gzip, deflate, br, zstd
Accept-Language:zh-CN,zh;q=0.9
Connection:keep-alive
Cookie:JSESSIONID=28245FA9456DE80AD96030E747FDC6A3; Idea-8296eb30=8f993187-84db-4d67-80c1-c79530404e22; JSESSIONID=F3B0CC4700EADE28F10AA839ED527146
Host:localhost:63342
Referer:http://localhost:63342/WebDemo/com/example/html/h1.html?_ijt=oruo1s87g86q88uglbqtih7paj
Sec-Ch-Ua:"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
Sec-Ch-Ua-Mobile:?0
Sec-Ch-Ua-Platform:"Windows"
Sec-Fetch-Dest:document
Sec-Fetch-Mode:navigate
Sec-Fetch-Site:same-origin
Sec-Fetch-User:?1
Upgrade-Insecure-Requests:1
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
3、请求空行:空行就是用来分割post请求头和请求体的。
4、 请求体(正文)
封装POST请求消息的请求参数的。
username: 2433
Request:
1、request对象和response对象的原理
1、request和response对象是由服务器创建的,我们来使用它们
2、request对象是来获取请求消息,response对象是来设置响应消息
2、request对象继承体系结构:ServletRequest(接口)-HttpServletRequest(接口)-org.apache.catalina.connector.RequestFacade类(tomcat实现)
3、request功能:
1、获取请求消息数据
1、获取请求行数据
1、获取请求方式:String getMethod()
2、*获取虚拟目录:String getContextPath():/WebDemo
String getRealPath("文件名"):绝对路径:C:\Users\Administrator\IdeaProjects\WebDemo\target\WebDemo-1.0-SNAPSHOT\LoginServlet
3、获取Servlet路径:String getServletPath():/Login
4、获取get方式请求参数:String getQueryString()
5、*获取请求URL:String getRequestURI():/Login
StringBuffer getReuqestURL():http://localhost:8080/Login
URL:统一资源定位符
URI:统一资源标识符
6、获取协议及版本:String getProtocol():HTTP/1.1
7、获取客户机的IP地址:String getRemoteAddr():0:0:0:0:0:0:0:1
2、获取请求头数据
方法:String getHeader(String name):通过请求头的名称获取请求头的值
Enumeration<String> getHeaderNames():获取所有的请求头名称
3、获取请求体数据
请求体数:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
1、获取流对象
BufferedReader getReader():获取字符输入流,只能操作字符数据
ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据
2、再从流对象中拿数据
BufferedReader reader=req.getReader();
String s = reader.readLine();
2、其他功能
1、获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
1、String getParemeter(String name):根据参数名称获取参数值
2、String getParameterValues(String name):根据参数名称获取其参数值的数组(比如多选框)
3、Enumeration<String> getParemeterNames():获取其所有请求的参数名称
4、Map<String,String[]> getParameterMap():获取所有参数的map集合
//在获取流之前设置,乱码是因为编码和解码所使用的字符集不一致
req.setCharacterEncoding("utf-8");
rep.setContentType("text/html;charset=utf-8");
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
System.out.println(parameterNames.nextElement());
}
System.out.println(req.getParameter("username"));
String[] habits = req.getParameterValues("habit");
for (String habit : habits) {
System.out.println(habit);
}
Map<String, String[]> parameterMap = req.getParameterMap();
for (String s : parameterMap.keySet()) {
System.out.print(s);
String[] values = parameterMap.get(s);
for (String value : values) {
System.out.print(values);
}
System.out.println();
}
2、请求转发:一种在服务器内部的资源跳转方式
1、步骤:
1、通过request对象获取请求转发器对象:RequestDispatcher getRequestDispatcher(String path)
2、使用RequestDispatcher对象来进行转发:forward(ServlerRequest request,ServletResponse response);
RequestDispatcher requestDispatcher=request.getRequestDispatcher("/Tomcat");
requestDispatcher.forward(request,response);
2、特点:
1、浏览器地址栏路径不发生变化
2、只能转发到当前服务器内部的资源中
3、转发是一次请求
3、共享数据
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
1、void setAttribute(String name,Obiect obj):存储数据
2、Object getAttribute(String name):通过键获取值
3、void removeAttribute(String name):通过键移除值对
//LoginServlet
String username = "username";
request.setAttribute("username",username);
RequestDispatcher requestDispatcher=request.getRequestDispatcher("/Tomcat");
requestDispatcher.forward(request,response);
//TomcatServlet
Object username = req.getAttribute("username");
System.out.println(username);
req.removeAttribute("username");
4、获取ServletContext:
ServletContext getServletContext()
Response: 服务器发送给客户端的数据
数据格式:
HTTP/1.1 200
Content-Type: text/html;charset=utf-8
Content-Length: 16
Date: Thu, 28 Mar 2024 09:02:44 GMT
Keep-Alive: timeout=20
Connection: keep-alive
1、响应行:
1、组成:协议/版本 响应状态码 状态码描述
2、响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
1、状态码都是3位数字
2、分类:
1、1xx:服务器接收客户端消息,但没有接收完成,等待一段时间后,发送1xx多状态码
2、2xx:成功。代表状态码:200
3、3xx:重定向。代表:302(重定向),304(访问缓存)
4、4xx:客户端错误。代表:404(请求路径没有对应的资源),405(请求方式没有对应的doxxx方法)
5、5xx:服务端错误。代表:500(服务器内部出现异常)
2、响应头
1、格式:头名称:值
2、常见的响应头:
1、Content-Type:服务器告诉客户端本次响应体数据格式以及编码格式
2、Content-disposition:服务器告诉客户端以什么格式打开响应体数据
值:in-line:默认值,在当前页面内打开
attachment;filename=xxx:以附件形式打开响应体。文件下载
3、响应空行
4、响应体:传输的数据
Response对象:设置响应消息
1、设置响应行
1、格式:HTTP/1.1 200 ok
2、设置状态码:setStature(int sc)
2、设置响应头:setHeader(String name,String value)
3、设置响应体:
1、获取输出流
字符输出流:PrintWriter getWriter()
字节输出流:ServletOutputStream getOutputStream()
2、使用输出流,将数据输出到客户端浏览器
resp.setStatus(200);
resp.setHeader("Content-Type","text/html;charset=utf-8");
PrintWriter writer1 = resp.getWriter();
writer1.write("你好!!");
ServletOutputStream outputStream = resp.getOutputStream();
outputStream.write("你好".getBytes("utf-8"));
1、重定向-资源跳转的方式
//获取虚拟目录的路径
String contextPath = req.getContextPath();
//更改ResponseHeader的Location属性
resp.sendRedirect(contextPath+"/Login");
//访问其他服务器
//resp.sendRedirect("https://www.baidu.com/");
重定向的特点
1、地址栏发生变化
2、重定向可以访问其他站点(服务器)的资源
3、重定向是两次请求。不能使用request对象来共享数据
转发的特点:
1、转发地址栏路径不变
2、转发只能访问当前服务器下的资源
3、转发是一次请求,可以使用request对象来共享数据
路径的写法:
1、路径的分类
1、相对路径:通过相对路径不可以确定唯一资源
如:./index.html
规则:找到当前资源和目标资源之间的相对位置关系
./表示当前目录
../表示上一级目录
2、绝对路径:通过绝对路径可以确定唯一资源
如:http://localhost:8080/WebDemo/response
以/开头的路径
规则:判断定义的路径是给谁用,判断请求将从哪儿发出
给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
建议虚拟目录动态获取:request.getContextPath():例如:重定向
给服务器使用:不需要加虚拟目录。例如:请求转发
2、验证码:
1、本质:图片
2、目的:防止恶意注册
ServletContext对象:
1、概念:代表整个web应用,可以和程序的容器(服务器)来通信
2、获取:
1、通过request对象获取
request.getServletContext();
2、通过HttpServlet获取
this.getServletContext();
ServletContext servletContext = req.getServletContext();
ServletContext servletContext1 = this.getServletContext();
3、功能:
1、获取MIM类型:
MIME类型:在互联网通信过程中定义的一种文件数据类型
格式:大类型/小类型 text/html image/jpeg
获取:String getMimeType(String file)
2、域对象:共享数据
1、setAttribute(String name,Object value)
2、getAttrubute(String name)
3、removeAttribute(String name)
ServletContext对象范围:所有用户所有请求的数据
3、获取文件的真实(服务器)路径
ServletContext servletContext = req.getServletContext();
String mimeType = servletContext.getMimeType("a.html");
System.out.println(mimeType);
servletContext.setAttribute("username","张三");
//java文件的目录和webapp下的文件属于同一级目录
System.out.println(servletContext.getRealPath("WEB-INF/web.xml"));
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取文件真实路径
String filename = request.getParameter("filename");
ServletContext servletContext=request.getServletContext();
String filename1 = servletContext.getRealPath("/img/"+filename);
// 设置文件类型,设置下载文件
String jpg = servletContext.getMimeType(filename);
response.setHeader("content-type",jpg);
//使用URL编码文件名,防止文件名出现中文乱码
response.setHeader("content-disposition", "attachment;filename="+ URLEncoder.encode(filename,"utf-8"));
// 输出文件
ServletOutputStream outputStream = response.getOutputStream();
FileInputStream file=new FileInputStream(filename1);
byte[] bytes =new byte[1024*8];
int len=0;
while ((len = file.read(bytes)) != -1) {
outputStream.write(bytes,0,len);
}
}
//前端代码
<form action="" method="get">
<<a href="/WebDemo/DownloadServlet?filename=1.jpg">图片</a>
<a href="/WebDemo/DownloadServlet?filename=2.mp4">视频</a>
</form>