F4de's blog F4de's blog
首页
WP整理
技术文章
学习笔记
其它随笔
关于|友链

F4de

Syclover | Web
首页
WP整理
技术文章
学习笔记
其它随笔
关于|友链
  • Java

    • JAVA学习笔记
    • Java学习笔记-第二部分
    • Java-Web入门学习笔记
      • IDEA整合tomcat
        • 2020.2版本的IDEA(专业版)创建Web项目
        • 整合tomcat
      • Servlet
        • Servlet:server applet
        • 快速入门
        • servlet3.0
        • 体系结构
        • request和response
        • ServletContext对象
        • 案例:文件下载
      • 会话技术
        • 客户端会话:Cookie
        • 服务器端会话:Session
      • JSP
        • JSP的脚本
        • JSP内置对象
        • 指令
    • Java8-Stream
  • 学习笔记
  • Java
F4de
2020-10-02

Java Web入门学习笔记

JavaWeb的基础知识学习

# IDEA整合tomcat

# 2020.2版本的IDEA(专业版)创建Web项目

新版的IDEA创建Java Web项目和老版本有一点不同,在此特别记录一下

  1. 新建一个正常的Java项目,点击next
image-20200815170748931
  1. 创建好之后右键点击项目名称,选择 “添加框架支持”
image-20200815170954287
  1. 勾选 “Web Application”,然后点击确定
image-20200815171224223
  1. 创建好之后的文件结构
image-20200815174834540

# 整合tomcat

  1. 点击“运行”,在子菜单里选择“编辑配置”
image-20200815171526714
  1. 点击左上角 + 号,并选择Tomcat Server中的“本地”
image-20200815171644798
  1. 点击“配置”,并选择你的Tomcat的安装目录
image-20200815171816303
  1. 其余默认即可,配置好之后的结果
image-20200815171913180
  1. 在index.jsp中,如果配置成功则右上角应该出现Tomcat这个配置(红线所划部分)
image-20200815172043845
  1. 点击一下运行按钮,如果会在浏览器中自动弹出index.jsp,则说明配置成功
image-20200815172322055

# Servlet

# Servlet:server applet

  • 概念:运行在服务器的小程序
  • 本质上Servlet就是一个接口,定义了Java类被浏览器访问到(Tomcat识别)的规则
  • 如果我们自定义了一个类,实现了Servlet接口,复写方法,那么这个类我们就称它为Servlet类

# 快速入门

  1. 创建JavaEE项目

  2. 定义一个类,实现servlet接口

    public class ServletDemo01 implements Servlet{
        //复写Servlet接口中的所有抽象方法
    }
    
    1
    2
    3
  3. 实现接口中的抽象方法

  4. 配置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

# 执行原理

  1. 当服务器接受到客户端浏览器的请求之后,会解析请求的URL路径,获取到访问的servlet的资源路径。
  2. 查找web.xml文件,是否有对应的<url-pattern>标签体内容。
  3. 如果有,则找到对应的<servlet-class>全类名。
  4. tomcat会将字节码文件加载进内存,并且创建其对象。
  5. 调用其方法。

# servlet中的生命周期方法

  • init方法:在servlet类被创建的时候执行,且只会执行一次。
  • service方法:每一次servlet被访问时执行,会执行多次。
  • destroy方法:在servlet被销毁时执行(服务器正常关闭时),只会执行一次。

生命周期:

  1. 被创建:执行init方法,只执行一次。
  2. 提供服务:执行service方法,执行多次。
  3. 被销毁:执行destroy方法,执行一次。

可以通过配置web.xml来指定servlet的创建时机

<!--web.xml-->

···
<servlet>
    ···
    <load-on-startup>{value}</load-on-startup>
    <!--当value的值为负数的时候,第一次访问时被创建-->
    <!--当value的值为正数或O的时候,服务器启动的时候被创建-->
    ···
</servlet>

···
1
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进行繁琐的配置工作。

步骤:

  1. 创建JavaEE项目,选择servlet版本3.0以上,可以不创建web.xml。
  2. 定义一个类,实现servlet接口。
  3. 复现方法。
  4. 在类上添加@webServlet注解,进行配置。
···
    
@WebServlet(urlPatterns = "/demo3")
//也可以这样
@WebServlet("/demo3")
public class ···
    
···
1
2
3
4
5
6
7
8

# 体系结构

对于servlet接口来说,JavaEE内置了两个抽象类来作为servlet接口的下实现类:GenericServlet 和 HttpServlet。

# GenericServlet

该抽象类将servlet接口中的其他方法做了默认空实现,只将service方法做了抽象处理。将来定义servlet类的时候,可以继承GenericServlet类,实现service方法。

public class ServletDemo extends GenericServlet {
    //只需要覆盖重写service方法
}
1
2
3

# HttpServlet

该类继承自GenericServlet类,将service方法覆盖重写,获取GET / POST请求。在继承HttpServlet类的时候,需要复写doGet / doPost方法。

public class ServletDemo extends HttpServlet {
    //覆盖重写doGet和doPost方法
}
1
2
3

# request和response

# 原理

  1. tomcat服务器会根据请求url中的资源路径创建对应的servlet对象。
  2. tomcat服务器会创建request和response对象,分别封装请求和相应消息。
  3. tomcat将request和response两个对象传递给service方法,并且调用service方法。
  4. 我们可以通过request对象获取请求消息数据,通过response对象设置相应消息数据。
  5. 服务器在给浏览器做出响应之前,会从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()
1
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()
1
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));
        }
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

image-20200817124802933

# 获取请求体数据

只有POST请求方式才有请求体,其中封装了POST请求的请求参数。

//获取流对象
BufferedReader getReader()   //获取字符输入流,只能操作字符数据
ServletInputStream getInputStream   //获取字节输入流,可以操作所有数据
1
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);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

image-20200817154138673

# 其他常用方法

# 获取请求参数(通用)
//根据参数名称获取参数值
String getParameter(String name)

//根据参数名称获取参数值的数组
String[] getParameterValues(String name)
    
//获取所有请求的参数名称
Enumeration<String> getParameterNames()
    
//获取所有参数的map集合
Map<String,string[]> getParameterMap()
1
2
3
4
5
6
7
8
9
10
11
//解决中文乱码问题
//在获取参数前,设置request的编码方式为utf-8
···
req.setCharacterEncoding("utf-8");
···
1
2
3
4
5
# 请求转发

请求转发:一种在服务器内部的资源跳转方式。

image-20200818204016649

步骤:

  1. 通过request对象获取请求转发器对象。
  2. 使用该对象来进行转发。
···
req.getRequestDispatcher("/demo").forward(req, resp);
···
1
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);
    }
}
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

访问demo6,得到如下结果

image-20200818203604814

特点:

  1. 浏览器URL路径不会发生变化。
  2. 只能转发到当前服务器内部的资源中。
  3. 浏览器只会向服务器发送一次请求。
# 共享数据
  • 域对象:一个有作用范围的对象,可以在范围内共享数据。
  • request域:代表一次请求的范围,一般用于请求转发的多个资源中去共享数据(请求转发是一次请求)。

方法:

//存储数据
void setAttribute(String name, Object obj)

//通过键获取值
Object getAttribute(String name)
    
//通过键来移除键值对
void removeAttribute(String name)
1
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);
    }
}
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

访问demo6

image-20200818212854280

注意:共享数据必须在请求转发之前设置,否则会造成获取的数据的值为 null 。

# 获取ServletContext

关于ServletContext对象这里不展开讲,后面会专门进行介绍。

ServletContext getServletContext()
1

# response对象

功能:设置响应消息

//设置响应行
setStatus(int sc)

//设置响应头
setHeader(String name, String value)
    
//设置响应体
/*

 1.获取输出流(字符输出流、字节输出流)
 2.使用输出流,将数据输出到客户端浏览器
 
 */
 
 PrintWriter getWriter()  //获取字符输出流
 ServletOutputStream getOutputStream()  //获取字节输出流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 案例一:完成重定向
  1. 设置状态码为302
  2. 设置头部消息 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);
    }
}
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

重定向的特点(与转发的特点对比学习):

  • 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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

image-20200823163401434

# 案例三:获取字节输出流(制作简易验证码)
@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);
    }
}
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

虽然十分丑陋,但是总体上还是达成了一定的效果

image-20200824170503806

image-20200824170523950

实现点击图片切换验证码

<!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>
1
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应用,可以和程序的容器(服务器)来通信

功能:

  1. 获取MIME类型
  2. 域对象:共享数据
  3. 获取文件的服务器路径

获取该对象:

//通过request对象获取
request.getServletContext()

//通过HttpServlet获取
this.getServletContext()
1
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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

image-20200824201318689

# 获取MIME类型

MIME类型是互联网通信过程中定义的一种文件数据类型,这里不展开讲了,参考百度百科:MIME(多用途互联网邮件扩展类型)

格式:大类型/小类型 比如 text/html image/jpeg

ServletContext context = this.getServletContext();
String mimeType = context.getMimeType(String);
1
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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

image-20200824203000279

# 域对象:共享数据

域对象可以用来共享数据(request对象就是一个域对象)

//存储数据
void setAttribute(String name, Object obj)

//通过键获取值
Object getAttribute(String name)
    
//通过键来移除键值对
void removeAttribute(String name)
1
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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

先访问 /Context3 再访问 /Context4 得到如下结果

image-20200824234606136

我们并没有在两个setvlet中设置请求转发,但是数据依然可以被共享。request域对象范围是一次请求,而SetvletContext域对象范围是整个web应用。

# 案例:文件下载

# 案例分析

# 案例需求
  • 页面提示超链接
  • 点击超链接后弹出下载提示框
  • 完成图片文件下载
# 案例分析
  • 超链接指向的资源如果可以被浏览器解析,则会在浏览器中展示,如果不能解析,则会弹出下载提示框。
  • 任何资源都必须弹出下载提示框
  • 设置响应头Content-disposition:attachment;filename=xxx 只有设置了该响应头之后,任何文件都会以下载的形式打开
# 实现步骤
  1. 定义页面,编辑超链接href属性,指向servlet,并传递参数filename
  2. 定义servlet
    1. 获取文件名称
    2. 使用字节输入流加载文件进内存
    3. 设置response响应头
    4. 将数据写出到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>
1
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);
    }
}
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

image-20200825110259395

# 会话技术

# 客户端会话:Cookie

概念:一种客户端会话技术,将数据保存到客户端浏览器。

# Cookie快速入门

  1. 创建Cookie对象,绑定数据
  2. 发送Cookie对象
  3. 获取Cookie,拿到数据
//  创建Cookie对象
Cookie cookie = new Cookie(String name, String value)

//  发送Cookie对象
response.addCookie(Cookie cookie)
    
//  获取Cookie
Cookie[] request.getCookies()
1
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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

image-20200825202327905

前三个为IDEA自带的一些Cookie。

同样,在浏览器中也可以看到已经设置好的cookie

image-20200825202456199

# Cookie原理分析

image-20200825203632301

浏览器收到这样的响应头之后会自动设置Cookie

# Cookie细节处理

# 一次发送多个Cookie

可以创建多个Cookie对象,使用response调用多次addCookie方法发送即可。

(代码演示略)

# Cookie的存活时间

默认情况下,当浏览器关闭后,Cookie数据被销毁,如果想要持久化储存,可以使用Cookie对象的一个方法

setMaxAge(int seconds)
/*
seconds的取值:
1.正数:将Cookie数据写到硬盘的文件中,持久化储存。另外还代表Cookie的存活时间。
2.负数:默认值。
3.零:删除Cookie信息。
*/
1
2
3
4
5
6
7
# Cookie的获取范围

假设在一个tomcat服务器中部署了多个web项目,默认情况下在不同的项目中间cookie不能共享,使用Cookie对象中的一个方法可以设置cookie的获取范围。

//设置cookie的获取范围,默认情况下会去设置当前的虚拟目录。
setPath(String path)
//需要共享,可将path设为 “/”
setPath("/")
1
2
3
4

对于不同的tomcat服务器,cookie也是可以被共享的。

setDomain(String path)
//如果设置一级域名相同,那么多个服务器之间的cookie可以共享
1
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)
1
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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

image-20200829204030308

同时又因为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);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

image-20200829204205598

只要不关闭浏览器并且在Session不失效的情况下,同一个用户在项目不同servlet中的任意请求获取到的都是同一个Session对象

通过以下方法可以设置session的存活时间

session.setMaxInactiveInterval(int seconds);  //设置session的存活时间
session.invalidate();  //强制销毁session
1
2

# JSP

JSP(Java Server Pages):Java服务器端页面。可以理解为一个特殊的页面,其中既可以定义HTML标签,又可以定义Java代码。(类似于PHP+HTML的混合页面)

原理:JSP本质上就是一个servlet

# JSP的脚本

JSP的脚本:JSP定义Java代码的方式。

  1. <% 代码 %>:定义的Java代码在service方法中;service中可以定义什么,该脚本中就可以定义什么。
  2. <%! 代码 %>:定义的Java代码在JSP转换后的Java类的成员位置。
  3. <%= 代码 %>:定义的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:导入资源
#JAVA
Java学习笔记-第二部分
Java8-Stream

← Java学习笔记-第二部分 Java8-Stream→

最近更新
01
Java8-Stream
01-03
02
谈一谈Java动态加载字节码的方式
12-18
03
Fastjson反序列化(2)-TemplatesImpl利用链
12-01
更多文章>
Theme by Vdoing | Copyright © 2019-2021
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式