Server applet : 运行在服务器端的小程序
public class ServletDemo implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
1.1 Servlet生命周期
-
init
-
初始化方法 : 在Servlet被创建时执行,只会执行一次
-
-
service
-
每一次Servlet被访问时,执行.执行多次
-
-
destory
-
在服务器正常关闭时执行,执行一次.
-
-
getServletConfig
-
获取Servlet的配置对象
-
-
getServletInfo
-
获取Servlet的一些信息,版本,作者等等.
-
@WebServlet("/httpServletTest")
public class HttpServletDemo extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
2 超文本传输协议 Http
2.1 简介
-
传输协议 : 定义了 , 客户端和服务器端通信时,发送数据的格式
-
特点
-
基于TCP/IP的高级协议
-
默认端口号为80
-
基于请求/相应模型的 : 一次请求对应一次相应
-
无状态的 : 每次请求之间相互独立,不能交互数据
-
-
历史版本
-
1.0 : 每一次请求响应都会建立新的连接
-
1.1 : 复用连接
-
| 请求方式 | 请求url | 请求协议/版本 |
|---|---|---|
| Get | 百度一下,你就知道 | HTTP/1.1 |
-
请求方式 :
-
HTTP协议中一共有7种请求方式,常用有两种
-
GET :
-
请求参数在请求行中 , 在url后 (?name=aoligei&age=22)
-
请求的url长度是有限制的
-
不太安全
-
-
POST :
-
请求参数在请求体中
-
请求的url长度没有限制的
-
相对安全
-
-
-
-
高级浏览器解析之后的结果 :
请求头 : (客户端浏览器告诉服务器自身的一些信息)
-
高级浏览器解析之后的结果
User-Agent : 浏览器告诉服务器,我访问你使用的浏览器版本信息
-
可以在服务器端获取该头信息,解决浏览器的兼容问题
-
Accept : 告诉服务器,我作为浏览器,我可以接受你给我什么样的相应的信息格式
-
Accept-Language : 告诉服务器,我作为浏览器,我支持的语言环境
-
Accept-Encoding : 告诉服务器,我作为浏览器,我支持的压缩
-
Referer : 告诉服务器,当前请求从哪里来(where i comes)
-
作用
-
防盗链
-
-
统计工作
-
Connection : 这个链接可以被复用
2.2.3 请求空行
空行 : 分隔请求头和请求体
2.2.4 请求体(正文 )-
封装POST请求的请求体的
-
get方式没有请求体
-
请求消息的原始格式
2.3 Request
-
request对象和response对象的原理
-
request和respnse对象是由服务器创建,我们来使用他们
-
request对象是来获取请求消息,respinse对象是来设置相应消息的
request对象和response对象的原理
-
request和respnse对象是由服务器创建,我们来使用他们
-
request对象是来获取请求消息,respinse对象是来设置相应消息的
2.3.1 request对象继承体系结构
ServletRequest -- 接口
| extends
HttpServletRequest -- 接口
| implements
org.apache.catalina.connector.RequestFacade 类 (tomcat实现)
2.3.2 功能
2.3.2.1 获取请求行数据
-
获取请求行数据 : GET /day14/demo1?name=zhangsan HTTP/1.1
-
获取请求方式 : GET
-
request.getMethod();
-
-
获取虚拟目录 : /day14
-
request.getContextPath();
-
-
获取Servlet路径 : /demo1
-
request.getServletPath();
-
-
获取get方式请求参数 : name=zhangsan
-
request.getQueryString();
-
-
获取请求URI /day14/demo1
-
request.getRequestURI();
-
request.getRequestURL();
-
http://localhost/day/demo1
-
-
-
获取协议以及版本 : HTTP/1.1
-
request.getProtocol();
-
-
获取客户机的IP地址 :
-
request.getRemoteAddr();
-
-
2.3.2.2 获取请求头数据
-
获取请求头数据
-
通过请求头的名称获取请求头的值
-
request.getHeader(String name)
-
request.getHeader("referer");//如果是直接通过浏览器地址栏输入的方式是获取不到referer头信息的(同过其他方式,比如超链接)
-
-
获取所有请求头的名称
-
Enumeration
request.getHeaderNames
-
-
2.3.2.3 获取请求体数据
-
获取请求体数据
-
只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数
-
步骤
-
获取流对象
-
BufferedReader getReader() : 获取字符输入流,只能操作字符数据
-
ServletInputStream getInputStream() : 获取字节输入流,可以操作所有类型数据
-
-
再从流对象中拿数据
-
-
@PostMapping("/test")
public String test(HttpServletRequest request) throws IOException {
//1.获取字符流
BufferedReader br = request.getReader();
//2.读取数据
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
return "项目启动test";
}
2.3.2.4 获取请求参数通用方式
-
获取请求参数通用方式
-
根据参数名称获取参数值
-
request.getParameter(String name)
-
-
根据参数名称获取参数值的数组 (比如?hobby=swiming&hobby=basketball)
-
String[ ] request.getParameterValues(String name)
-
-
获取所有所有请求的参数名称
-
Enumeration
getParameterNames():
-
-
获取所有参数的map集合
-
Map
getParamterMap()
-
-
@PostMapping("/test")
public String test(HttpServletRequest request) throws IOException {
//获取参数age
String age = request.getParameter("age");
System.out.println("age===>"+age);
//获取参数hobby参数数组
String[] bobbies = request.getParameterValues("bobby");
for (String bobby : bobbies) {
System.out.println("hobby===>"+bobby);
}
//获取所有参数名
Enumeration parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()) {
System.out.println("参数名为"+parameterNames.nextElement());
}
//获取参数键值对
Map parameterMap = request.getParameterMap();
String[] ages = parameterMap.get("age");
for (String s : ages) {
System.out.println(s);
}
String[] bobbies1 = parameterMap.get("bobby");
for (String s : bobbies1) {
System.out.println(s);
}
return "项目启动test";
}
POST请求方式乱码问题
-
设置流的字符集
request.setCharacterEncoding("utf-8");
2.3.2.5 请求转发
-
请求转发 : 一种在服务器内部的资源跳转方式
-
步骤
-
通过request对象获取请求转发器对象 : RequestDispatcher getRequestDispatcher(String path)
-
使用RequestDispatcher对象来进行转发 : forward(ServletRequest request,ServletResponse response)
-
-
特点
-
浏览器地址栏路径不发生变化
-
只能转发到当前服务器内部资源
-
转发是一次请求
-
-
@RestController
public class TestController {
@PostMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("test");
//转到其他URL
//RequestDispatcher requestDispatcher = request.getRequestDispatcher("toDestination");
//requestDispatcher.forward(request, response);
request.getRequestDispatcher("toDestination").forward(request, response);
}
@PostMapping("/toDestination")
public void toDestination(){
System.out.println("redirect to ReachDestination");
}
}
2.3.2.6 共享数据
-
共享数据
-
域对象 : 一个有作用范围的对象,可以在范围内共享数据
-
request域 : 代表一次请求的范围,一般用于一次请求转发的多个资源中共享数据
-
方法 :
-
void setAttribute(String name,Object obj) : 存储数据
-
Object getAttribute(String name) : 通过键获取值
-
void removeAttribute(String name) : 通过键移除键值对
@RestController
public class TestController {
@PostMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("test");
//转到其他URL
//RequestDispatcher requestDispatcher = request.getRequestDispatcher("toDestination");
//requestDispatcher.forward(request, response);
request.setAttribute("messageKey", "messagevalue");
request.getRequestDispatcher("toDestination").forward(request, response);
}
@PostMapping("/toDestination")
public void toDestination(HttpServletRequest request){
System.out.println("redirect to ReachDestination");
System.out.println(request.getAttribute("messageKey"));
}
}
2.3.2.7 获取ServletContext
2.3.2.7 获取ServletContext
-
获取ServletContext
@RestController
public class TestController {
@PostMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext servletContext = request.getServletContext();
System.out.println(servletContext);
}
}
2.4 Response
-
数据格式
-
相应行
-
响应头
-
响应空行
-
响应体
-
响应字符串格式
数据格式
-
相应行
-
响应头
-
响应空行
-
响应体
响应字符串格式
响应行
-
组成 : 协议/版本 响应状态码 状态码描述
-
状态码 : 都是三位数字
-
分类 :
-
1xx : 服务器接收客户端消息,但是没有接受完成,等待一段时间之后,发送1xx等状态码
-
2xx : 成功.代表:200
-
3xx :重定向.代表 : 302(重定向) : 客户端访问A , A说我办不了,去找C吧. 304:访问缓存.(图片)
-
-
-
4xx : 客户端错误. 典型 : 404 请求路径没有对应资源 : 405 请求方式不匹配
-
5xx : 服务器端错误 典型 : 500
响应头
-
格式 : 头名称 : 值
-
常见的响应头 :
-
Content-Type : 服务器告诉客户端本次响应体数据格式以及编码格式
-
Content-disposition : 服务器告诉客户端以什么格式打开响应体数据,值有如下
-
in-line : 默认值,在当前页面打开
-
attachment;filename=xxx :以附件形式打开响应体.文件下载.
-
-
Content - Length :页面字符长度
-
响应体 : 传输的数据
2.4.1 response对象功能2.4.1.1 设置相应行
-
设置相应行
-
设置状态码 : void setStatus(int StatusCode)
-
2.4.1.2 设置响应头
-
设置响应头
-
void setHeadr(String ,name,String value)
-
2.4.1.3 设置响应体
-
使用步骤
-
获取输出流
-
字符输出流
-
PrintWriter getWriter();
-
-
字节输出流
-
ServletOutPutStream getOutputStream();
-
-
-
使用输出流
-
将数据输出到客户端浏览器
-
-
-
重定向 : 资源跳转的方式
-
访问A资源,A告诉浏览器重定向,状态码302
-
告诉浏览器B资源的路径,响应头location:B资源的路径
-
@RestController
public class TestController {
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("servlet A");
//设置状态码 302
response.setStatus(302);
//2.设置响应头
response.setHeader("location", "/redirect");
}
@GetMapping("/redirect")
public void test2(HttpServletRequest request, HttpServletResponse response){
System.out.println("servlet B");
}
}
简化 response.sendRedirect(String url);
@RestController
public class TestController {
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("servlet A");
//简化
response.sendRedirect("/redirect");
}
@GetMapping("/redirect")
public void test2(HttpServletRequest request, HttpServletResponse response){
System.out.println("servlet B");
}
}
-
重定向的特点
-
地址栏发送变化
-
重定向可以访问其他站点(服务器)的资源
-
重定向是两次请求.不能使用requse对象t共享数据
-
-
路径
-
分类
-
相对路径 : 通过相对路径不可以确定唯一资源
-
绝对路径 : 通过绝对路径可以确定唯一资源
-
如htttp://www.baidu.com /day15/responseDemo2
-
动态获取虚拟目录 : request.getContextPath();
-
-
-
2.4.3 服务器输出字节数据到浏览器案例
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取字符输出流
PrintWriter writer = response.getWriter();
writer.write("hello print writer");
}
中文乱码问题
-
原因 : 编码和解码使用的字符集不一致
-
解决 : 设置浏览器编码格式,并告知浏览器使用这种编码规则
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取流对象之前,设置流的默认编码 : ISO-8859-1 GBK
//response.setCharacterEncoding("utf-8");
//告诉浏览器,服务器发送的消息体数据的编码.建议浏览器使用该编码解码
response.setHeader("content-type", "text/html;charset=utf-8");
//1.获取字符输出流
PrintWriter writer = response.getWriter();
writer.write("你好 print writer");
}
简化 : 使用response的方法 setContentType
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//1.获取字符输出流
PrintWriter writer = response.getWriter();
writer.write("你好 print writer");
}
2.4.4 服务器输出字节数据到浏览器案例
-
步骤
-
获取字节输出流
-
输出数据
-
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write("你还".getBytes());
}
2.4.5 验证码
-
创建一对象,在内存中的图片(验证码图片对象)
-
美化图片
-
将图片输出到页面
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width = 200;
int height = 100;
//创建一对象,在内存中的图片(验证码图片对象)
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//将图片输出到页面展示
ImageIO.write(image, "jpg", response.getOutputStream());
}
2.5 ServletContext
-
概念 : 代表整个web应用,可以和程序的容器(服务器)来通信
-
获取
-
通过request对象获取 : request.getServletContext();
-
通过HttpServlet获取 : this.getServletContext();
-
功能
-
获取MIME类型:
-
域对象 : 共享数据
-
获取文件的真实(服务器)路径
概念 : 代表整个web应用,可以和程序的容器(服务器)来通信
获取
-
通过request对象获取 : request.getServletContext();
-
通过HttpServlet获取 : this.getServletContext();
功能
-
获取MIME类型:
-
域对象 : 共享数据
-
获取文件的真实(服务器)路径
2.5.1 获取MIME类型
-
获取MIME类型
-
MIME类型 : 在互联网通信过程中定义的一种文件数据类型
-
格式 大类型/小类型 text/html image/jpeg
-
获取 : getMimeType(String file)
获取MIME类型
-
MIME类型 : 在互联网通信过程中定义的一种文件数据类型
-
格式 大类型/小类型 text/html image/jpeg
-
-
获取 : getMimeType(String file)
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取
ServletContext servletContext = request.getServletContext();
//定义文件名称
String filename = "a.jpg";
//获取MIME类型
String mimeType = servletContext.getMimeType(filename);
System.out.println(mimeType); //image/jpeg
}
2.5.2 域对象 : 共享数据(慎用)
域对象 : 共享数据(慎用)
-
ServletContext对象范围 : 所有用户所有请求的数据
servletContext.setAttribute("messageKey", "messagevalue");
Object messageKey = servletContext.getAttribute("messageKey");
servletContext.removeAttribute("messageKey");
@RestController
public class TestController {
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("messageKey", "messagevalue");
}
@GetMapping("/redirect")
public void test2(HttpServletRequest request, HttpServletResponse response){
ServletContext servletContext = request.getServletContext();
Object messageKey = servletContext.getAttribute("messageKey");
System.out.println(messageKey);
}
}
2.5.3 获取文件的真实(服务器)路径
-
获取文件的真实(服务器)路径
-
servletContext.getRealPath(String path);
获取文件的真实(服务器)路径
-
servletContext.getRealPath(String path);
@GetMapping("/test")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取
ServletContext servletContext = request.getServletContext();
//获取真实路径(tomcat)
String realPath = servletContext.getRealPath("src\main\resources\application.properties");
System.out.println(realPath);
}
2.6 文件下载案例
-
文件下载需求
-
页面显示超链接
-
点击超链接后弹出下载提示框
-
完成图片文件下载
-
分析
-
超链接指向的资源如果能够被浏览器解析,则在浏览器中显示,如果不能解析,则弹出下载提示框.不满足需求.
-
任何资源都必须弹出下载提示框
-
使用响应头设置资源的打开方式 :
-
content-disposition : attachment;filename = xxx
-
步骤
-
定义页面 , 编辑超链接href属性,指向Servlet,传递资源名称filename
-
定义Servlet
-
获取文件名称
-
使用字节输入流加载文件进内存
-
指定reponse的响应头 : content-disposition:attach;filename=xxx
-
将数据写出到response输出流
文件下载需求
-
页面显示超链接
-
点击超链接后弹出下载提示框
-
完成图片文件下载
分析
-
超链接指向的资源如果能够被浏览器解析,则在浏览器中显示,如果不能解析,则弹出下载提示框.不满足需求.
-
任何资源都必须弹出下载提示框
-
使用响应头设置资源的打开方式 :
-
content-disposition : attachment;filename = xxx
-
步骤
-
定义页面 , 编辑超链接href属性,指向Servlet,传递资源名称filename
-
定义Servlet
-
获取文件名称
-
使用字节输入流加载文件进内存
-
指定reponse的响应头 : content-disposition:attach;filename=xxx
-
将数据写出到response输出流
-
@GetMapping("/downServlet")
public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {
//获取参数
String fileName = request.getParameter("fileName");
//获取服务器真实路径,使用字节输入流加载文件至内存
ServletContext servletContext = request.getServletContext();
String realPath = servletContext.getRealPath("src\main\resources\img\"+fileName);
FileInputStream fileInputStream = new FileInputStream(realPath);
//设置响应头,文件以附件形式下载和MIME类型
response.setHeader("content-type",servletContext.getMimeType(fileName));
response.setHeader("content-disposition", "attachment;filename="+fileName);
//将输入流写到输出流
ServletOutputStream servletOutputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len=fileInputStream.read(buffer)) != -1){
servletOutputStream.write(buffer,0,len);
}
}
中文文件名问题
-
工具类
public class DownUtils {
public static String getFileName(String agent,String filename) throws UnsupportedEncodingException {
if(agent.contains("MSIE")){
//IE
filename = URLEncoder.encode(filename, "utf-8");
filename = filename.replace("+", " ");
}else if(agent.contains("Firefox")){
//火狐
base64Encoder base64Encoder = new base64Encoder();
filename = "?utf-8?B?" +base64Encoder.encode(filename.getBytes("utf-8"))+"?=";
}else {
//其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
}
步骤
-
获取user-agent请求头
-
使用工具类,根据不同浏览器对文件名进行编码
@GetMapping("/downServlet")
public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {
//获取参数
String fileName = request.getParameter("fileName");
//获取服务器真实路径,使用字节输入流加载文件至内存
ServletContext servletContext = request.getServletContext();
String realPath = servletContext.getRealPath("src\main\resources\img\"+fileName);
FileInputStream fileInputStream = new FileInputStream(realPath);
//设置响应头,文件以附件形式下载和MIME类型
response.setHeader("content-type",servletContext.getMimeType(fileName));
//解决中文文件名问题
//获取user-agent请求头
String agent = request.getHeader("user-agent");
//根据不同浏览器对文件名进行编码
fileName = DownUtils.getFileName(agent, fileName);
response.setHeader("content-disposition", "attachment;filename="+fileName);
//将输入流写到输出流
ServletOutputStream servletOutputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while((len=fileInputStream.read(buffer)) != -1){
servletOutputStream.write(buffer,0,len);
}
}
3.会话技术 :cookie
-
会话 : 一次会话中包含多次请求和响应
-
一次会话 : 浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止(浏览器关闭,或服务器关闭等等)
-
功能 : 在一次会话的范围内的多次请求间 ,共享数据.
-
方式 :
-
客户端会话技术 : cookie
-
服务器端会话技术 : Session
会话 : 一次会话中包含多次请求和响应
-
一次会话 : 浏览器第一次给服务器资源发送请求,会话建立,直到有一方断开为止(浏览器关闭,或服务器关闭等等)
-
功能 : 在一次会话的范围内的多次请求间 ,共享数据.
-
方式 :
-
客户端会话技术 : cookie
-
服务器端会话技术 : Session
-
3.1 概念
-
概念 : 客户端会话技术 , 将数据保存到客户端.
-
使用步骤
-
创建cookie对象,绑定数据
-
new cookie(String name,String value);
-
发送cookie对象
-
response.addcookie(cookie cookie);
-
获取cookie,拿到数据
-
cookie[] request.getcookie();
概念 : 客户端会话技术 , 将数据保存到客户端.
-
使用步骤
-
创建cookie对象,绑定数据
-
new cookie(String name,String value);
-
-
发送cookie对象
-
response.addcookie(cookie cookie);
-
-
获取cookie,拿到数据
-
cookie[] request.getcookie();
-
-
@RestController
public class TestController {
@GetMapping("/cookieTest")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建cookie对象
cookie cookie = new cookie("cookieKey", "cookievalue");
//向客户端浏览器发送cookie
response.addcookie(cookie);
}
@GetMapping("/getcookie")
public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {
//获取cookie
cookie[] cookies = request.getcookies();
//获取数据,遍历cookies
if(cookies != null){
for (cookie cookie : cookies) {
String cookieKey = cookie.getValue();
System.out.println(cookieKey);
}
}
}
}
3.2 一次发送多个cookie+
-
一次发送多个cookie
@GetMapping("/cookieTest")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建cookie对象
cookie cookie = new cookie("cookieKey", "cookievalue");
cookie cookie1 = new cookie("cookieKey2", "cookievalue2");
//向客户端浏览器发送cookie
response.addcookie(cookie);
response.addcookie(cookie1);
}
3.3 cookie的存活时间
一次发送多个cookie
-
默认情况下,当浏览器关闭后,cookie数据被销毁
-
持久化存储 :
-
setMaxAge(int seconds)
-
正数 : 将cookie数据写到硬盘的文件中.持久化存储.cookie存活时间.(浏览器关闭之后开始计时)
-
负数 : 默认值
-
零 : 删除cookie信息
-
-
-
cookie的键名不能为中文
-
在tomcat8之前 cookie中不能直接存储中文数据.
-
需要将中文(特殊字符)数据转码 --- 一般采用URL编码()
-
-
cookie的共享问题
-
假设在一个tomcat服务器中,部署了多个web应用,那么在这些web项目中cookie能不能共享?
-
默认情况下cookie不能共享
-
cookie.setPaht(String path) : 设置cookie的获取范围.默认情况下,设置当前的虚拟目录
-
如果要当前服务器所有项目共享,则可以将path设置为 "/"
-
-
-
@GetMapping("/cookieTest")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建cookie对象
cookie cookie = new cookie("cookieKey", "cookie值");
//设置共享范围 服务器范围
cookie.setPath("/");
//向客户端浏览器发送cookie
response.addcookie(cookie);
}
-
不同的tomcat服务器见cookie共享问题?
-
cookie.setDomain(String path) : 如果设置一级域名相同,那么多个服务器之前cookie是可以共享数据的
-
cookie.setDomain(".baidu.com"),那么tieba.baidu.com 和 news.baidu.com中cookie时可以共享的
-
多用于分布式
-
-
特点 :
-
cookie存储数据在客户端浏览器 (安全性相对较低)
-
浏览器对于单个cookie的大小也有限制(4kb)以及对同一域名下的总cookie数量也有限制(20个)
-
-
作用 :
-
在cookie一般用于存储少量的不太敏感的数据
-
在不登录的情况下,完成服务器对客户端的身份识别
-
-
需求
-
访问一个Servlet,如果是第一次访问,则提示:您好,欢迎您首次访问.
-
如果不是第一次访问.则提示 : 欢迎回来,您上次访问时间为 : 显示时间字符串.
-
-
分析 :
-
可以采用cookie来完成
-
服务器中的Servlet判断是否有一个名为lastTime的cookie
-
有 : 不是第一次访问
-
响应数据 : 欢迎回来 , 您上次访问时间为 : 2018年6月10日11:50:20
-
写回cookie : lastTime = 2018年6月12日11:50:20
-
-
没有
-
响应数据 : 您好,欢迎您首次访问
-
写回cookie : lastTime = 2018年6月12日11:50:20
-
-
-
@RestController
public class TestController {
public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static Date now = new Date();
@GetMapping("/cookieLastTime")
public String testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Boolean flag = false;
//1.获取所有cookie
cookie[] cookies = request.getcookies();
//遍历cookie数组
if (cookies != null || cookies.length != 0){
for (cookie cookie : cookies) {
String cookieName = cookie.getName();
if("lastTime".equals(cookieName)){ //有lastTime cookie
flag = true;
//set
String format = sdf.format(now);
System.out.println("编码前:"+format);
//URL编码
format = URLEncoder.encode(format, "utf-8");
cookie.setValue(format);
cookie.setMaxAge(60*60*24*30); // 一个月
response.addcookie(cookie);
//get
String lastTimevalue = cookie.getValue();
//解码
System.out.println("解码前:"+lastTimevalue);
//URL解码
lastTimevalue = URLDecoder.decode(lastTimevalue, "utf-8");
System.out.println("解码后:"+lastTimevalue);
return "您上次访问的时间为"+lastTimevalue;
}
}
}
if(cookies == null || cookies.length == 0 || flag ==false){
//没有,第一次访问
String format = URLEncoder.encode(sdf.format(now), "utf-8");
cookie cookie = new cookie("lastTime", format);
cookie.setMaxAge(60*60*24*30);
response.addcookie(cookie);
return "您好,欢迎您您首次访问";
}
return null;
}
}
4.会话技术 : Session
-
概念 : 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中.HttpSession
-
快速入门 :
-
获取HttpSession对象
-
使用HttpSession对象
-
HttpSession对象 :
-
Object getAttribute(String name)
-
void setAttribute(String name,Object value)
-
void removeAttribute(String name)
概念 : 服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器端的对象中.HttpSession
快速入门 :
-
获取HttpSession对象
-
使用HttpSession对象
-
HttpSession对象 :
-
Object getAttribute(String name)
-
void setAttribute(String name,Object value)
-
void removeAttribute(String name)
-
@RestController
public class TestController {
@GetMapping("/sessionSet")
public void testController(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取Session对象
HttpSession session = request.getSession();
//set
session.setAttribute("sessionKey","sessionValue");
}
@GetMapping("/sessionGet")
public void test2(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession();
//get
Object sessionValue = session.getAttribute("sessionKey");
System.out.println(sessionValue);
}
}
4.1 Session原理
-
服务器如何确保在一次会话范围你,多次获取的Session对象是同一个?
-
Session是依赖于cookie的!
-
当客户端关闭后,服务器不关闭,两次获取Session是否为一个?
-
默认情况下,不是.因为上一次会话已经结束了
-
如果需要相同,可以创建cookie,键位JSESSIONID,设置最大存活时间,让cookie持久化保存.
-
cookie c = new cookie("JSESSIONID",session.getId());
c.setMaxAge(60*60);
response.addcookie(c);
4.3 Session的统一性Ω
-
当服务器关闭后,Session不唯一
-
虽然Session对象不是同一个,但是要确保数据不丢失
-
Session的钝化 :
-
在服务器正常关闭之前,将session对象序列化到硬盘上
-
-
Session的活化 :
-
在服务器启动之后,将Session文件转化为内存中的session对象即可
-
-
-
-
Session什么时候被销毁
-
服务器关闭
-
session对象调用invalidate();
-
session默认失效时间 30min(页面打开无任何操作)
-
-
session用于存储一次会话的多次请求的数据,存在服务器端
-
session可以存储任意类型数据,任意大小的数据



