Java Web入门学习笔记
JavaWeb的基础知识学习
# IDEA整合tomcat
# 2020.2版本的IDEA(专业版)创建Web项目
新版的IDEA创建Java Web项目和老版本有一点不同,在此特别记录一下
- 新建一个正常的Java项目,点击next

- 创建好之后右键点击项目名称,选择 “添加框架支持”

- 勾选 “Web Application”,然后点击确定

- 创建好之后的文件结构

# 整合tomcat
- 点击“运行”,在子菜单里选择“编辑配置”

- 点击左上角 + 号,并选择Tomcat Server中的“本地”

- 点击“配置”,并选择你的Tomcat的安装目录

- 其余默认即可,配置好之后的结果

- 在index.jsp中,如果配置成功则右上角应该出现Tomcat这个配置(红线所划部分)

- 点击一下运行按钮,如果会在浏览器中自动弹出index.jsp,则说明配置成功

# Servlet
# Servlet:server applet
- 概念:运行在服务器的小程序
- 本质上Servlet就是一个接口,定义了Java类被浏览器访问到(Tomcat识别)的规则
- 如果我们自定义了一个类,实现了Servlet接口,复写方法,那么这个类我们就称它为Servlet类
# 快速入门
创建JavaEE项目
定义一个类,实现servlet接口
public class ServletDemo01 implements Servlet{ //复写Servlet接口中的所有抽象方法 }
1
2
3实现接口中的抽象方法
配置servlet
<!--web.xml--> <web-app ···> <!--配置servlet--> <servlet> <servlet-name>demo1</servlet-name> <servlet-class>web.ServletDemo01</servlet-class> </servlet> <servlet-mapping> <servlet-name>demo1</servlet-name> <url-pattern>/demo1</url-pattern> </servlet-mapping> </web-app>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 执行原理
- 当服务器接受到客户端浏览器的请求之后,会解析请求的URL路径,获取到访问的servlet的资源路径。
- 查找web.xml文件,是否有对应的
<url-pattern>
标签体内容。 - 如果有,则找到对应的
<servlet-class>
全类名。 - tomcat会将字节码文件加载进内存,并且创建其对象。
- 调用其方法。
# servlet中的生命周期方法
- init方法:在servlet类被创建的时候执行,且只会执行一次。
- service方法:每一次servlet被访问时执行,会执行多次。
- destroy方法:在servlet被销毁时执行(服务器正常关闭时),只会执行一次。
生命周期:
- 被创建:执行init方法,只执行一次。
- 提供服务:执行service方法,执行多次。
- 被销毁:执行destroy方法,执行一次。
可以通过配置web.xml来指定servlet的创建时机
<!--web.xml-->
···
<servlet>
···
<load-on-startup>{value}</load-on-startup>
<!--当value的值为负数的时候,第一次访问时被创建-->
<!--当value的值为正数或O的时候,服务器启动的时候被创建-->
···
</servlet>
···
2
3
4
5
6
7
8
9
10
11
12
servlet中的init方法只执行一次,说明一个servlet在内存中只存在一个对象,也就是说servlet是单例的。多个用户同时访问的时候,可能存在线程安全的问题。
**解决方案:**尽量不要在servlet中定义成员变量。即使定义了成员变量,也不要对其修改值。
另外两个方法简单介绍:
- getServletConfig方法:获取ServletConfig对象(servlet的配置对象)。
- getServletInfo方法:获取Servlet的一些信息,如版本、作者等等。
# servlet3.0
servlet3.0支持注解配置,不需要对web.xml进行繁琐的配置工作。
步骤:
- 创建JavaEE项目,选择servlet版本3.0以上,可以不创建web.xml。
- 定义一个类,实现servlet接口。
- 复现方法。
- 在类上添加@webServlet注解,进行配置。
···
@WebServlet(urlPatterns = "/demo3")
//也可以这样
@WebServlet("/demo3")
public class ···
···
2
3
4
5
6
7
8
# 体系结构
对于servlet接口来说,JavaEE内置了两个抽象类来作为servlet接口的下实现类:GenericServlet 和 HttpServlet。
# GenericServlet
该抽象类将servlet接口中的其他方法做了默认空实现,只将service方法做了抽象处理。将来定义servlet类的时候,可以继承GenericServlet类,实现service方法。
public class ServletDemo extends GenericServlet {
//只需要覆盖重写service方法
}
2
3
# HttpServlet
该类继承自GenericServlet类,将service方法覆盖重写,获取GET / POST请求。在继承HttpServlet类的时候,需要复写doGet / doPost方法。
public class ServletDemo extends HttpServlet {
//覆盖重写doGet和doPost方法
}
2
3
# request和response
# 原理
- tomcat服务器会根据请求url中的资源路径创建对应的servlet对象。
- tomcat服务器会创建request和response对象,分别封装请求和相应消息。
- tomcat将request和response两个对象传递给service方法,并且调用service方法。
- 我们可以通过request对象获取请求消息数据,通过response对象设置相应消息数据。
- 服务器在给浏览器做出响应之前,会从response对象中拿出设置好的响应消息数据。
# request对象获取请求消息
# 获取请求行数据
对于一个请求行 GET /WebServlet/demo?name=zhangsan HTTP/1.1:
//获取请求方式:GET
String getMethod()
//获取虚拟目录:/WebServlet
String getContextPath()
//获取Servlet路径:/demo
String getServletPath()
//获取get方式请求参数:name=zhangsan
String getQueryString()
//获取请求URI
String getRequestURI() // /WebServlet/demo
StringBuffer getRequestURL() // http://localhost/WebServlet/demo
//获取协议及版本:HTTP/1.1
String getProtocol()
//获取客户机的ID地址:
String getRemoteAddr()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 获取请求头数据
//通过请求头的名称获取请求头的值
String getHeader(String name)
//获取所有请求头名称
Enumeration<String> getHeaderNames()
2
3
4
5
package web.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.util.Enumeration;
@WebServlet(urlPatterns = "/demo5")
public class ServletDemo05 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
System.out.println(req.getHeader(name));
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 获取请求体数据
只有POST请求方式才有请求体,其中封装了POST请求的请求参数。
//获取流对象
BufferedReader getReader() //获取字符输入流,只能操作字符数据
ServletInputStream getInputStream //获取字节输入流,可以操作所有数据
2
3
package web.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.BufferedReader;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet(urlPatterns = "/demo5")
public class ServletDemo05 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
BufferedReader reader = req.getReader();
String line = null;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 其他常用方法
# 获取请求参数(通用)
//根据参数名称获取参数值
String getParameter(String name)
//根据参数名称获取参数值的数组
String[] getParameterValues(String name)
//获取所有请求的参数名称
Enumeration<String> getParameterNames()
//获取所有参数的map集合
Map<String,string[]> getParameterMap()
2
3
4
5
6
7
8
9
10
11
//解决中文乱码问题
//在获取参数前,设置request的编码方式为utf-8
···
req.setCharacterEncoding("utf-8");
···
2
3
4
5
# 请求转发
请求转发:一种在服务器内部的资源跳转方式。
步骤:
- 通过request对象获取请求转发器对象。
- 使用该对象来进行转发。
···
req.getRequestDispatcher("/demo").forward(req, resp);
···
2
3
//ServletDemo06
@WebServlet("/demo6")
public class ServletDemo06 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo6被访问了");
req.getRequestDispatcher("/demo7").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
//ServletDemo07
@WebServlet("/demo7")
public class ServletDemo07 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo7被访问了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
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
访问demo6,得到如下结果
特点:
- 浏览器URL路径不会发生变化。
- 只能转发到当前服务器内部的资源中。
- 浏览器只会向服务器发送一次请求。
# 共享数据
- 域对象:一个有作用范围的对象,可以在范围内共享数据。
- request域:代表一次请求的范围,一般用于请求转发的多个资源中去共享数据(请求转发是一次请求)。
方法:
//存储数据
void setAttribute(String name, Object obj)
//通过键获取值
Object getAttribute(String name)
//通过键来移除键值对
void removeAttribute(String name)
2
3
4
5
6
7
8
//demo6
@WebServlet("/demo6")
public class ServletDemo06 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//存储数据到request域当中
req.setAttribute("name", "ZhangSan");
//请求转发到demo7
req.getRequestDispatcher("/demo7").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
//demo7
@WebServlet("/demo7")
public class ServletDemo07 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("demo7被访问了");
//从request域中获取对象
Object name = req.getAttribute("name");
System.out.println(name);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
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
访问demo6
注意:共享数据必须在请求转发之前设置,否则会造成获取的数据的值为 null 。
# 获取ServletContext
关于ServletContext对象这里不展开讲,后面会专门进行介绍。
ServletContext getServletContext()
# response对象
功能:设置响应消息
//设置响应行
setStatus(int sc)
//设置响应头
setHeader(String name, String value)
//设置响应体
/*
1.获取输出流(字符输出流、字节输出流)
2.使用输出流,将数据输出到客户端浏览器
*/
PrintWriter getWriter() //获取字符输出流
ServletOutputStream getOutputStream() //获取字节输出流
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 案例一:完成重定向
- 设置状态码为302
- 设置头部消息 location
@WebServlet("/Re1")
public class ResponseDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置状态码为302
resp.setStatus(302);
//设置头部消息
resp.setHeader("location", "/Re2");
/*
还有另一种比较简单的重定向方法
resp.sendRedirect("/Re2");
*/
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
------------------------------------------------------------
@WebServlet("/Re2")
public class ResponseDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("重定向完成");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
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
重定向的特点(与转发的特点对比学习):
- URL会发生变化
- 重定向可以访问其他服务器的资源
- 重定向是两次请求,不能使用request对象来共享数据
# 案例二:获取字符输出流
@WebServlet("/Re2")
public class ResponseDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置编码是为了解决中文乱码
resp.setHeader("content-type", "text/html;charset=utf-8");
// resp.setContentType("text/html;charset=utf-8");
//获取字符输出流
PrintWriter printWriter = resp.getWriter();
//输出数据
printWriter.write("<h1>Hello Response</h1>");
printWriter.write("<h1>你好,世界</h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 案例三:获取字节输出流(制作简易验证码)
@WebServlet("/Re3")
public class ResponseDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int height = 50;
int width = 100;
// 1.创建图片对象
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 美化图片
Graphics graphics = bufferedImage.getGraphics(); //获取画笔对象
graphics.setColor(Color.PINK); //设置颜色
graphics.fillRect(0, 0, width, height); //填充背景色
graphics.setColor(Color.BLUE);
graphics.drawRect(0, 0, width - 1, height - 1); //绘制边框
//获取随机字符
String allCharacter = "QWERTYUIOPASDFGHJKLZXCVBNM1234567890";
Random random = new Random();
for (int i = 0; i < 4; i++) {
int nextInt = random.nextInt(allCharacter.length());
char c = allCharacter.charAt(nextInt);
graphics.drawString(c + "", (width / 5 * i) + 15, 30);
}
//绘制干扰线
for (int i = 0; i < 8; i++) {
int randomX1 = random.nextInt(width);
int randomX2 = random.nextInt(width);
int randomY1 = random.nextInt(height);
int randomY2 = random.nextInt(height);
graphics.setColor(Color.GREEN);
graphics.drawLine(randomX1, randomY1, randomX2, randomY2);
}
// 3.输出图片
ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
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
虽然十分丑陋,但是总体上还是达成了一定的效果
实现点击图片切换验证码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>code</title>
<script>
window.onload = function () {
// 1.获取图片对象
let img = document.getElementById("code");
// 2.为图片绑定单击事件
img.onclick = function () {
let date = new Date().getTime()
img.src = "/Re3?"+date
}
}
</script>
</head>
<body>
<img src="/Re3" alt="code" id="code">
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# ServletContext对象
在学习request对象中提到了获取ServletContext对象的方法,接下来就开始正式学习这个对象。
**概念:**这个代表整个Web应用,可以和程序的容器(服务器)来通信
功能:
- 获取MIME类型
- 域对象:共享数据
- 获取文件的服务器路径
获取该对象:
//通过request对象获取
request.getServletContext()
//通过HttpServlet获取
this.getServletContext()
2
3
4
5
@WebServlet("/Context1")
public class ContextDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通过request对象获取
ServletContext servletContext = req.getServletContext();
//通过HttpServlet获取
ServletContext servletContext1 = this.getServletContext();
//判断两者是否相等
System.out.println(servletContext);
System.out.println(servletContext1);
System.out.println(servletContext == servletContext1);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# 获取MIME类型
MIME类型是互联网通信过程中定义的一种文件数据类型,这里不展开讲了,参考百度百科:MIME(多用途互联网邮件扩展类型)
格式:大类型/小类型 比如 text/html image/jpeg
ServletContext context = this.getServletContext();
String mimeType = context.getMimeType(String);
2
@WebServlet("/Context2")
public class ContextDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext(); //获取ServletContext对象
String filename = "a.jpg";
String mimeType = servletContext.getMimeType(filename); //获取文件的MIME类型
System.out.println(mimeType);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 域对象:共享数据
域对象可以用来共享数据(request对象就是一个域对象)
//存储数据
void setAttribute(String name, Object obj)
//通过键获取值
Object getAttribute(String name)
//通过键来移除键值对
void removeAttribute(String name)
2
3
4
5
6
7
8
ServletContext对象范围:所用用户所有请求的数据
@WebServlet("/Context3")
public class ContextDemo03 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取ServletContext对象
ServletContext servletContext = this.getServletContext();
// 设置共享数据
servletContext.setAttribute("msg", "hello");
}
}
@WebServlet("/Context4")
public class ContextDemo04 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
ServletContext servletContext = this.getServletContext();
// 获取并打印数据
Object msg = servletContext.getAttribute("msg");
System.out.println(msg);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
先访问 /Context3 再访问 /Context4 得到如下结果
我们并没有在两个setvlet中设置请求转发,但是数据依然可以被共享。request域对象范围是一次请求,而SetvletContext域对象范围是整个web应用。
# 案例:文件下载
# 案例分析
# 案例需求
- 页面提示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件下载
# 案例分析
- 超链接指向的资源如果可以被浏览器解析,则会在浏览器中展示,如果不能解析,则会弹出下载提示框。
- 任何资源都必须弹出下载提示框
- 设置响应头
Content-disposition:attachment;filename=xxx
只有设置了该响应头之后,任何文件都会以下载的形式打开
# 实现步骤
- 定义页面,编辑超链接href属性,指向servlet,并传递参数filename
- 定义servlet
- 获取文件名称
- 使用字节输入流加载文件进内存
- 设置response响应头
- 将数据写出到response输出流
# 案例实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/Down1?filename=pic.png">点击下载图片</a>
</body>
</html>
2
3
4
5
6
7
8
9
10
@WebServlet("/Down1")
public class downloadDemo1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取参数
String filename = req.getParameter("filename");
// 设置响应头
ServletContext servletContext1 = this.getServletContext();
String mimeType = servletContext1.getMimeType(filename);
resp.setContentType(mimeType);
resp.setHeader("Content-disposition", "attachment;filename=" + filename);
// 获取文件真实路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename);
// 使用字节流关联
FileInputStream fileInputStream = new FileInputStream(realPath);
//讲输入流的数据写出到输出流
ServletOutputStream outputStream = resp.getOutputStream();
byte[] bytes = new byte[1024 * 8]; //缓冲区
int len = 0;
while ((len = fileInputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
fileInputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
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
# 会话技术
# 客户端会话:Cookie
概念:一种客户端会话技术,将数据保存到客户端浏览器。
# Cookie快速入门
- 创建Cookie对象,绑定数据
- 发送Cookie对象
- 获取Cookie,拿到数据
// 创建Cookie对象
Cookie cookie = new Cookie(String name, String value)
// 发送Cookie对象
response.addCookie(Cookie cookie)
// 获取Cookie
Cookie[] request.getCookies()
2
3
4
5
6
7
8
@WebServlet("/Cookie1")
public class CookieDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建Cookie对象
Cookie cookie = new Cookie("username", "Horizon");
// 发送Cookie
resp.addCookie(cookie);
// 获取Cookie
Cookie[] cookies = req.getCookies();
if (cookies != null) {
for (Cookie tempCookie : cookies) {
String name = tempCookie.getName();
String value = tempCookie.getValue();
System.out.println(name + ":" + value);
}
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
前三个为IDEA自带的一些Cookie。
同样,在浏览器中也可以看到已经设置好的cookie
# Cookie原理分析
浏览器收到这样的响应头之后会自动设置Cookie
# Cookie细节处理
# 一次发送多个Cookie
可以创建多个Cookie对象,使用response调用多次addCookie方法发送即可。
(代码演示略)
# Cookie的存活时间
默认情况下,当浏览器关闭后,Cookie数据被销毁,如果想要持久化储存,可以使用Cookie对象的一个方法
setMaxAge(int seconds)
/*
seconds的取值:
1.正数:将Cookie数据写到硬盘的文件中,持久化储存。另外还代表Cookie的存活时间。
2.负数:默认值。
3.零:删除Cookie信息。
*/
2
3
4
5
6
7
# Cookie的获取范围
假设在一个tomcat服务器中部署了多个web项目,默认情况下在不同的项目中间cookie不能共享,使用Cookie对象中的一个方法可以设置cookie的获取范围。
//设置cookie的获取范围,默认情况下会去设置当前的虚拟目录。
setPath(String path)
//需要共享,可将path设为 “/”
setPath("/")
2
3
4
对于不同的tomcat服务器,cookie也是可以被共享的。
setDomain(String path)
//如果设置一级域名相同,那么多个服务器之间的cookie可以共享
2
比如设置setDomain(".baidu.com"),那么tieba.baidu.com和news.baidu.com中的cookie就可以共享
# Cookie的特点
- Cookie存储数据在客户端浏览器,安全系数不高。
- 浏览器对于单个cookie的大小有限制,以及对同一个域名下的总cookie数量也有限制。
Cookie一般用于存储少量的不敏感数据。
# 服务器端会话:Session
概念:服务器端会话技术,在一次会话的多次请求间共享数据,将数据保存在服务器的对象中。
# Session快速入门
HttpSession是一个域对象,可以用来共享数据。
// 1.获取HttpSession对象
HttpSession session = request.getSession();
// 2.使用HttpSession对象
Object getAttribute(String name)
void setAttribute(String name, object value)
void removeAttribute(String name)
2
3
4
5
6
Session技术依赖于cookie,通过cookie中的SESSIONID来作为Session的标识
@WebServlet("/Session1")
public class SessionDemo01 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
session.setAttribute("username", "Horizon");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
同时又因为Session对象是域对象,可以共享数据,所以在另一个servlet中可以获取到设置的Session
@WebServlet("/Session2")
public class SessionDemo02 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Object username = session.getAttribute("username");
System.out.println(username);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
只要不关闭浏览器并且在Session不失效的情况下,同一个用户在项目不同servlet中的任意请求获取到的都是同一个Session对象
通过以下方法可以设置session的存活时间
session.setMaxInactiveInterval(int seconds); //设置session的存活时间
session.invalidate(); //强制销毁session
2
# JSP
JSP(Java Server Pages):Java服务器端页面。可以理解为一个特殊的页面,其中既可以定义HTML标签,又可以定义Java代码。(类似于PHP+HTML的混合页面)
原理:JSP本质上就是一个servlet
# JSP的脚本
JSP的脚本:JSP定义Java代码的方式。
- <% 代码 %>:定义的Java代码在service方法中;service中可以定义什么,该脚本中就可以定义什么。
- <%! 代码 %>:定义的Java代码在JSP转换后的Java类的成员位置。
- <%= 代码 %>:定义的Java代码会输出到页面上;输出语句中可以定义什么,该脚本中就可以定义什么。
# JSP内置对象
在JSP页面中需要获取和创建,可以直接使用的对象称为JSP的内置对象。
JSP一共有9个内置对象:
对象名 | 真实类型 | 作用 |
---|---|---|
request | HttpServletRequest | 一次请求访问的多个资源(转发)共享数据 |
response | HttpServletResponse | 响应对象 |
out | JspWriter | 输出对象,把数据输出到页面上 |
pageContext | PageContext | 当前页面共享数据,还可以来获取其他8个内置对象 |
session | HttpSession | 一次会话的多个请求间共享数据 |
application | ServletContext | 多个用户间共享数据 |
config | ServletConfig | servlet的配置对象 |
exception | Throwable | 异常处理对象 |
page | Object | 当前页面(servlet)的对象 |
out.write() 和 response.getWriter() 的区别:out.wirte()定义在JSP页面的哪个位置,就会在实际页面的哪个位置输出;而response.getWriter()总是会先进行输出,无论其定义在哪个位置,都会在浏览器页面中最先输出。
# 指令
- 作用:用于配置JSP页面,导入资源文件。
- 格式:
<%@ 指令名称 属性名1=属性值1 属性名2=属性值2 ... %>
- 分类:
page:配置JSP页面
inlcude:页面包含,导入资源文件
taglib:导入资源