02【Http、Request】

news2024/11/27 19:38:50

文章目录

  • 02【Http、Request】
  • 一、HTTP协议
    • 1.1 HTTP协议概述
      • 1.1.1 HTTP协议的概念
      • 1.1.2 HTTP协议的特点:
    • 2.1 HTTP请求的组成
      • 2.1.1 请求行
      • 2.1.2 请求头
      • 2.1.3 请求体
  • 二、HttpServletRequest对象
    • 2.1 HttpServletRequest对象简介
    • 2.2 HttpServletRequest的使用
      • 2.2.1 请求行相关的方法
      • 2.2.2 请求头相关的方法
        • 1)请求头相关方法的使用
        • 2)防盗链案例
      • 2.2.3 请求参数相关方法
    • 2.3 BeanUtils的使用
      • 2.3.1 什么是BeanUtils
      • 2.3.2 BeanUtils的使用
    • 2.4 参数的乱码问题
  • 三、请求域有关的方法
    • 3.1 作用域介绍
    • 3.2 作用域的使用
      • 3.2.1 作用域相关的方法
      • 3.2.2 作用域操作
    • 3.3 RequestDispatcher分发器
  • 四、转发与重定向
    • 4.1 转发
      • 4.1.1 转发的概念
      • 4.1.2 转发相关的方法
      • 4.1.3 转发的特点
    • 4.2 重定向
      • 4.2.1 重定向的概念
      • 4.2.2 重定向的方法
      • 4.2.3 重定向的特点
    • 4.3 重定向和转发的区别
      • 4.3.1 测试重定向请求域数据丢失
      • 4.3.2 转发和重定向后面的代码是否会执行
  • 五、案例: 实现登录功能
    • 5.1 案例步骤
    • 5.2 案例流程图
    • 5.3 实现步骤
      • 5.3.1 准备登录页面:
      • 5.3.2 失败页面:
      • 5.3.3 创建User表
      • 5.3.4 导入相关jar包
      • 5.3.5 创建实体类User
      • 5.3.6 配置文件druid.properties:
      • 5.3.7 工具类DataSourceUtils:
      • 5.3.8 数据层代码
      • 5.3.9 业务层代码
      • 5.3.10 控制器层代码:
      • 5.3.11 SuccessServlet

02【Http、Request】

一、HTTP协议

1.1 HTTP协议概述

1.1.1 HTTP协议的概念

在BS架构中,浏览器通过HTTP协议访问服务器。它是一种应用层协议,运行在TCP传输层协议之上。HTTP作用是指定数据传输格式,全称:Hyper Text Transfer Protocol 超文本传输协议

Tips:HTTP协议的默认端口为80

HTTP是通信双方(客户端、服务器)都需要遵守的协议标准;

当浏览器需要发送数据(请求)到服务器时,浏览器首先会将请求的数据封装成一个合格的HTTP请求报文,然后将其发送给服务器;该报文包含客户端用户所携带的一些普通数据,如用户名、密码等,也包含HTTP请求报文中所固有的一些数据,如请求方式、连接状态等

服务器接收到HTTP请求报文后,将会按照HTTP请求报文的格式进行解析,来提取浏览器发送过来的关键数据,进行业务逻辑处理,当服务器需要响应数据到客户端时,首先会将我们的响应数据封装成一个合格的HTTP响应报文该报文包含本次响应的一些业务数据,如响应的一个html页面、一个Java对象的值、响应的图片等,也包含HTTP响应报文中所固有的一些数据,如响应状态码、本次响应的数据类型;

在这里插入图片描述

1.1.2 HTTP协议的特点:

  • 1)HTTP协议组成:由请求报文和响应报文组成
  • 2)是一种无状态协议,不记录用户访问状态。同一个用户在同一个浏览器上发送的多次请求,服务器并不能通过HTTP协议来判断是否是同一个用户。
  • 3)因为HTTP协议不记录用户的状态信息,所以它的传输效率相对比较高。

2.1 HTTP请求的组成

一个完整的HTTP请求封装了浏览器发送给服务器的数据和信息,我们学习HTTP请求就是学习HTTP协议中到底封装了什么数据发送给服务器;

一个完整的HTTP请求包含请求行、请求头、请求体;

编写测试代码

  • LoginServlet:
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;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo01")
public class Demo01Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("ok");
    }
}
  • demo01.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h2>GET方式提交</h2>
<form action="/login" method="get">
    用户名:
    <input type="text" name="username"><br/>
    密  码:
    <input type="password" name="pwd"><br/>
    <input type="submit" value="登录">
</form>
<hr>
<h2>POST方式提交</h2>
<form action="/login" method="post">
    用户名:
    <input type="text" name="username"><br/>
    密码:
    <input type="password" name="password"><br/>
    <input type="submit" value="登录">
</form>
</body>
</html>

打开F12,抓包查看请求详情:

在这里插入图片描述

2.1.1 请求行

一个完整的请求行包括请求的方式、请求的地址、协议和版本

  • POST:请求的方式
  • /login: 请求的地址
  • HTTP/1.1 协议和版本

  • GET和POST请求的区别:
POST方式GET方式
地址栏参数不会在地址栏上显示出来参数会显示出来,以查询字符串的方式发送数据
大小理论上没有大小限制,使用流的方式来发送数据。受浏览器限制,通常是1K
安全性POST数据在请求体中发送,安全性要高一些数据在请求行中发送,安全性要低一些
缓存不使用缓存如果静态资源在浏览器端已经访问过,下次可能会使用缓存,如果使用缓存状态码是304

如果是GET方式请求的服务器,那么数据将会携带在地址栏,并且GET方式的请求没有请求体:

在这里插入图片描述

Tips:如果在浏览器上直接输入地址访问的服务器,则使用的是GET方式

2.1.2 请求头

请求头描述示例
Accept描述客户端希望接收的响应body 数据类型Accept: text/plain, text/html
Accept-Encoding浏览器支持的web服务器返回内容压缩编码类型。Accept-Encoding: compress, gzip
Connection表示是否需要持久连接。Connection: close
Cookie本次请求携带的Cookie值Cookie: user=xiaohui; sex=man;
Content-Length请求的内容长度Content-Length: 348
Content-Type请求的MIME信息(请求的内容的类型)Content-Type: application/x-www-form-urlencoded
Host请求的服务器的域名和端口号Host: localhost:8080
Referer获取从哪个页面跳转到当前页面来的
得到上一个访问的页面
Referer: http://localhost:8080/demo01.html
User-Agent请求的用户信息User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)

查看请求头:

在这里插入图片描述

Tips:不是每次请求都会显示所有的请求头

2.1.3 请求体

请求体就是本次请求携带的数据(用户自己的数据);

  • GET方法发送数据的时候没有请求体,数据是在地址栏发送,没有请求内容的长度。

  • POST方法发送数据在请求体中发送,有请求内容的长度。

    在这里插入图片描述

    内容类型表示,以键值对的方式发送表单的数据,如:name=xiaohui

关于GET和POST请求的Content-type:

  • Query String Parameters:当发起一次GET请求时,参数会以url string的形式进行传递。即?后的字符串则为其请求参数,并以&作为分隔符。
  • Form Data:当发起一次POST请求时,若未指定content-type,则默认content-type为application/x-www-form-urlencoded。即参数会以Form Data的形式进行传递,不会显式出现在请求url中。
  • Request Payload:当发起一次POST请求时,若content-type为application/json,则参数会以Request Payload的形式进行传递(显然的,数据格式为JSON),不会显式出现在请求url中。

二、HttpServletRequest对象

2.1 HttpServletRequest对象简介

HttpServletRequest是ServletRequest接口的子接口,代表一个请求对象,用来封装所有从浏览器发送给服务器的数据

我们之前介绍HTTP报文时说到,HTTP报文分为请求报文和响应报文,请求报文中包含有请求行、请求头、请求体等数据,HttpServletRequest则是对HTTP请求报文的封装,通过HttpServletRequest对象,可以获取请求报文中的数据,也可以使用该对象设置一些HTTP请求的数据

2.2 HttpServletRequest的使用

2.2.1 请求行相关的方法

  • String getMethod():得到请求的方式(GET或POST等)
  • String getRequestURI():得到请求的URI /demo1 只是地址的一部分,Uniform Resource Identifer 统一资源标识符
  • StringBuffer getRequestURL():得到请求的URL http://localhost:8080/demo1 Uniform Resource Locator 统一资源定位符
  • String getProtocol():得到请求行中的协议和版本 HTTP/1.1
  • String getContextPath():得到当前项目的访问地址 /02_Request
  • String getRemoteAddr():得到客户端的IP地址 127.0.0.1
  • String getServletPath():得到当前Servlet的访问地址 /demo1

【案例】

创建一个Servlet,用于获取请求行中相关信息的方法,并且输出到网页上。

创建项目,并部署到Tomcat中:

在这里插入图片描述

访问:http://localhost:8080/02_request/demo01

  • 效果:

在这里插入图片描述

  • 案例代码:
package com.dfbz.request;

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.io.PrintWriter;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo01")
public class Demo01Servlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //调用doGet方法
        this.doGet(req,resp);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置响应的类型
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.print("得到请求的方式:" + request.getMethod() + "<hr>");
        out.print("得到请求的URI:" + request.getRequestURI() + "<hr>");
        out.print("得到请求的URL:" + request.getRequestURL() + "<hr>");
        out.print("得到请求的协议和版本:" + request.getProtocol() + "<hr>");
        out.print("得到当前项目的访问地址:" + request.getContextPath() + "<hr>");
        out.print("得到客户端的IP地址:" + request.getRemoteAddr() + "<hr>");
        out.print("得到当前Servlet的访问地址:" + request.getServletPath() + "<hr>");
    }
}

2.2.2 请求头相关的方法

1)请求头相关方法的使用

请求头中是由各种键值对组成,通过键得到值,相关方法如下:

请求方法功能描述
String getHeader(String headName)通过键的名字得到相应的值,返回字符串类型的值
Enumeration<String> getHeaderNames()得到所有的请求头中的键名字,返回枚举类型。 枚举类型类似于迭代器,可以理解为是一个集合
java.util.Enumeration接口中方法说明
boolean hasMoreElements()判断枚举中是否还有下一个元素,如果有返回true
E nextElement()得到某个元素,并且下移一行

【案例】

编写一个Servlet得到所有的请求头信息,并输出所有的请求值信息。

访问:http://localhost:8080/02_request/demo02

  • 效果:

在这里插入图片描述

  • 代码:
package com.dfbz.request;

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.io.PrintWriter;
import java.util.Enumeration;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo02")
public class Demo02Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置响应类型
        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();
        out.print("得到host的值:" + request.getHeader("host") + "<hr>");
        //得到所有的键(名字)
        Enumeration<String> headerNames = request.getHeaderNames();

        while(headerNames.hasMoreElements()) {  //判断是否还有下一个元素
            String name = headerNames.nextElement();  //得到每个元素

            out.print("请求头名字:" + name + "==> 请求头值:" + request.getHeader(name) + "<hr>");
        }
    }
}

2)防盗链案例

【案例】

当我们去访问某个页面的时候,首先会跳转到一个广告页面,看了广告以后才可以访问资源。

原理:通过得到请求头Referer,获取当前页面的从哪里来的。

  1. 如果为null,表示没有上一个页面。
  2. 如果不为null,并且是从广告页面过来的,则可以继续访问。
  3. 否则,表示没有访问广告,跳转到广告页面。
  • 页面:adv.html 是广告页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这是广告页面哦!</h1>
<a href="demo03">去资源页面</a>
</body>
</html>
  • Demo03Servlet:
package com.dfbz.request;

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.io.PrintWriter;

/**
 * @author lscl
 * @version 1.0
 * @intro: 这是web资源,必须先访问广告才可以访问
 */
@WebServlet("/demo03")
public class Demo03Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置响应的类型和编码
        response.setContentType("text/html;charset=utf-8");

        // 获取项目的访问路径
        String contextPath = request.getContextPath();

        // 获取上一个页面访问地址
        String referer = request.getHeader("referer");

        // 如果为空,表示直接访问当前的Servlet,没有上一个页面
        if (referer == null) {
            // 说明还没有看过广告,重定向到广告页面去
            response.sendRedirect("http://localhost:8080" + contextPath + "/adv.html");
        }
        // 有上一个页面,但不是广告页面,盗链
        else if (referer != null && !referer.contains("http://localhost:8080" + contextPath + "/adv.html")) {
            //重定向到广告页面去
            response.sendRedirect("http://localhost:8080" + contextPath + "/adv.html");
        }
        // 如果有上一个页面,而且是广告页面,可以访问资源
        else {
            response.sendRedirect("/index.html");
        }
    }
}
  • 资源页面:index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<h1>web资源....</h1>

</body>
</html>
  • 其它的页面:other.html盗链页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="demo03">进入网站首页</a>
</body>
</html>

2.2.3 请求参数相关方法

方法名描述
String getParameter(String name)通过参数的名字得到参数值
String[] getParameterValues(String name)得到所有同名的参数值,一般用复选框。 返回一个字符串数组
Enumeration<String> getParameterNames()得到所有的参数名字,返回枚举类型
Map<String,String[]> getParameterMap()得到所有参数名和值,封装成Map对象 键就是参数名字,值就是参数的值

【案例】

准备一个表单,将数据提交到后端的servlet,在servlet中获取前端提交的参数;

  • 效果:

在这里插入图片描述

  • 准备register.htm页面:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>用户注册</h2>
<form action="demo04" method="post">
    用户名: <input type="text" name="name"><hr/>
    <!-- 提交的是value值 -->
    性别: <input type="radio" name="gender" value="0" checked="checked"/><input type="radio" name="gender" value="1"/><hr/>
    城市:
    <select name="city">
        <option value="ZhaoQing">肇庆</option>
        <option value="YangJiang">阳江</option>
        <option value="HuiZhou">惠州</option>
    </select>
    <hr/>
    爱好:
    <input type="checkbox" name="hobby" value="chang"/><input type="checkbox" name="hobby" value="tiao"/><input type="checkbox" name="hobby" value="rap"/>rap
    <input type="checkbox" name="hobby" value="lanqiu"/>篮球
    <hr/>
    <input type="submit" value="注册"/>
</form>
</body>
</html>
  • 准备一个servlet来接收前端提交的参数:Demo04Servlet
package com.dfbz.request;

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.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo04")
public class Demo04Servlet extends HttpServlet {
    // 处理Post方法
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 解决汉字乱码问题
        request.setCharacterEncoding("utf-8");  			// tomcat默认采用ISO-8859-1做编码
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //得到某个参数值
        out.print("得到用户名:" + request.getParameter("name") + "<hr>");

        //得到一组同名的值
        String[] hobbies = request.getParameterValues("hobby");
        out.print("爱好是:" + Arrays.toString(hobbies) + "<hr>");

        //得到所有参数的名字
        Enumeration<String> names = request.getParameterNames();
        while (names.hasMoreElements()) {
            //其中的一个名字
            String name = names.nextElement();
            out.print("参数名:" + name + ",  参数值:" + request.getParameter(name) + "<hr>");
            System.out.println("参数名:" + name + ",  参数值:" + request.getParameter(name) + "<hr>");
        }

        //得到所有的键和值
        Map<String, String[]> map = request.getParameterMap();
        Set<Map.Entry<String, String[]>> entries = map.entrySet();

        //遍历set集合
        for (Map.Entry<String, String[]> entry : entries) {
            out.print(entry.getKey() + "=" + Arrays.toString(entry.getValue()) + "<hr>");
        }
    }
}

2.3 BeanUtils的使用

2.3.1 什么是BeanUtils

BeanUtils是Apache Commons组件的成员之一,主要用于简化JavaBean封装数据的操作。

在这里插入图片描述

BeanUtils是第三方组织写的工具类,要使用它,得先下载对应的工具jar包。

  1. 下载地址:http://commons.apache.org/

  2. 相关的jar包

相关的包说明
commons‐beanutils‐1.9.3.jarBeanUtils工具的核心包
commons‐logging‐1.2.jar用于日志记录功能
commons‐collections‐3.2.2.jar公共的集合增强的包

2.3.2 BeanUtils的使用

BeanUtils常用方法说明
public static void populate(Object bean, Map<String, ? extends Object> properties)作用:将Map中所有的键和值封装到bean的同名的属性中,如果不同的名字会忽略。 参数: bean: 目标对象,要复制到的对象 properties: 源对象,有数据的Map象

web项目jar包所在的目录:

在这里插入图片描述

【案例】

使用BeanUtils将前端提交的参数封装为一个Java对象;

  • 案例效果:

在这里插入图片描述

  • 准备JavaBean
package com.dfbz.entity;

import java.util.Arrays;

public class Student {
    private String name;
    private String gender;
    private String city;
    private String hobby[];

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", city='" + city + '\'' +
                ", hobby=" + Arrays.toString(hobby) +
                '}';
    }

    public Student() {
    }

    public Student(String name, String gender, String city, String[] hobby) {
        this.name = name;
        this.gender = gender;
        this.city = city;
        this.hobby = hobby;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }
}

  • 准备一个新的Servlet来接收表单提交的数据:
package com.dfbz.request;

import com.dfbz.entity.Student;
import org.apache.commons.beanutils.BeanUtils;

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.Map;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo05")
public class Demo05Servlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    //处理Post方法
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //解决汉字乱码问题
        request.setCharacterEncoding("utf-8");

        // 设置响应内容的类型
        response.setContentType("text/html;charset=utf-8");

        Map<String, String[]> map = request.getParameterMap();

        // 创建Student对象
        Student user = new Student();

        //使用BeanUtils工具将表单中所有的数据封装成User对象
        try {
            BeanUtils.populate(user, map);
        } catch (Exception e) {
            e.printStackTrace();
        }
        response.getWriter().println("用户对象:" + user);
    }
}

BeanUtils参数封装图解:

在这里插入图片描述

BeanUtils可以将Map<String,String[]>类型的数据映射到一个Java对象中,其中Map的key为Java对象属性名,Value为该属性的值;当值为String或String[]时都可以将其映射到Java对象的String或String[]上;

我们现在将Student的bobby改为String类型:

package com.dfbz.entity;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class Student {
    private String name;
    private String gender;
    private String city;

    // 改为String类型而不是String[]类型
    private String hobby;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", city='" + city + '\'' +
                ", hobby='" + hobby + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getHobby() {
        return hobby;
    }

    public void setHobby(String hobby) {
        this.hobby = hobby;
    }
}

默认情况下,只会获取第一个参数;

在这里插入图片描述

提交之后的效果:

在这里插入图片描述

2.4 参数的乱码问题

Tomcat中默认对使用POST方法提交的参数使用是ISO-8859-1编码,这是一个欧洲码表,不支持汉字。

  • POST方式乱码解决方案:

    • 1)方法:request.setCharacterEncoding("utf-8"),告诉tomcat,post方法使用utf-8进行解码。

    Tips:上面这句话代码位置,必须放在所有得到参数的代码之前。

    • 2)必须与页面的编码相同, 如果提交的页面是GBK,则这里也要使用GBK。

在Tomcat8以后,GET方法参数是在地址栏发送,那么默认就是UTF-8编码,并且Tomcat解析地址栏中的数据也是以UTF-8解码,所以GET方法汉字没有乱码的问题。

三、请求域有关的方法

3.1 作用域介绍

  • 什么是作用域:用于在不同的Servlet之间共享数据区域,这个区域在服务器的内存中。底层的结构是一个Map对象,由键和值组成,键是String,值是Object,作用域中可以存放任意的类型。

  • Servlet中四个作用域:页面域page、请求域request,会话域session,上下文域ServletContext

  • 请求域的范围:数据只能在同一个请求中共享,请求结束或其它的请求不能访问其中的数据。

在这里插入图片描述

3.2 作用域的使用

3.2.1 作用域相关的方法

request与域有关的方法作用
void setAttribute(“键”,Object数据)向请求域中添加键和值
Object getAttribute(“键”)从请求域中获取一个值,返回Object类型
void removeAttribute(“键”)从请求域中删除一个键值对

3.2.2 作用域操作

【案例】

OneServlet创建一个键和值,转发到另一个TwoServlet,从TwoServlet中取出键和值,并且输出。使用转发可以将一个Servlet中的请求转到另一个Servlet中

  • 案例效果:

在这里插入图片描述

  • OneServlet:
package com.dfbz.request;

import javax.servlet.RequestDispatcher;
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;

@WebServlet("/one")
public class OneServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 往请求域对象里面设置值
        request.setAttribute("user", "Jack");

        // 获取一个转发器,并指定要转发的地址
        RequestDispatcher dispatcher = request.getRequestDispatcher("/two");

        // 进行转发
        dispatcher.forward(request,response);
    }
}
  • TwoServlet:
package com.dfbz.request;

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.io.PrintWriter;

@WebServlet("/two")
public class TwoServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置响应的格式
        response.setContentType("text/html;charset=utf-8");

        // 获取打印字符流流(指向的是客户端)
        PrintWriter out = response.getWriter();

        //从请求域中取出键和值
        String user = (String) request.getAttribute("user");

        // 向客户端打印字符
        out.print("在two中输出user值:" + user + "<br>");
    }
}

3.3 RequestDispatcher分发器

在上述案例中,我们使用RequestDispatcher分发器可以当请求进行转发,让当前请求指向一个地址;使用RequestDispatcher也可以将这个请求的结果包含到此次请求中;

  • forward(ServletRequest request, ServletResponse Response):将请求跳转到分发器指定的地方;
  • include(ServletRequest request, ServletResponse Response):收集分发器指定的请求的响应结果;

【案例】

定义ArticleServlet:

在这里插入图片描述

package com.dfbz.dispatcher;

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.io.PrintWriter;

@WebServlet("/article")
public class ArticleServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        String article = "怒发冲冠,凭栏处、潇潇雨歇。<hr />抬望眼、仰天长啸,壮怀激烈。<hr />三十功名尘与土,八千里路云和月。<hr />莫等闲、白了少年头,空悲切。<hr />靖康耻,犹未雪。<hr />臣子恨,何时灭。<hr />驾长车,踏破贺兰山缺。<hr />壮志饥餐胡虏肉,笑谈渴饮匈奴血。<hr />待从头、收拾旧山河,朝天阙<hr>";

        // 设置响应类型以及编码
        response.setContentType("text/html;charset=utf8");

        // 获取字符打印流
        PrintWriter writer = response.getWriter();

        writer.println(article);

    }
}
  • 定义Demo07Servlet:
package com.dfbz.dispatcher;

import javax.servlet.RequestDispatcher;
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.io.PrintWriter;

@WebServlet("/demo07")
public class Demo07Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置响应类型以及编码
        response.setContentType("text/html;charset=utf-8");

        // 获取字符打印流
        PrintWriter writer = response.getWriter();

        writer.println("文章内容如下: <hr />");

        // 获取分发器,关联/article请求的内容
        RequestDispatcher dispatcher = request.getRequestDispatcher("/article");

        dispatcher.include(request, response);
    }
}

访问:http://localhost:8080/02_request/demo07

在这里插入图片描述

四、转发与重定向

转发与重定向实现的功能是相同的,用于从一个页面跳转到另一个页面。但是从内部细节上有很大的不同;

4.1 转发

4.1.1 转发的概念

  • 概念:由服务器进行的页面跳转,因此也叫服务器内部转发;

客户端访问资源/demo01,服务器发现客户端想要的资源不在/demo01于是自己将请求转发到/demo02,这个过程客户端无感知;客户端只请求了一次;

原理图:

在这里插入图片描述

4.1.2 转发相关的方法

1)首先获取转发器(分发器)request.getRequestDispatcher(“/转发的地址”)

2)使用转发器的forward方法进行转发

4.1.3 转发的特点

1)转发是服务器内部的行为,因此在转发时,客户端请求的地址不会发生变化,即使服务器内部已经跳转了好几次了,但是客户端访问的地址依旧不变;

2)整个转发过程中,客户端从始至终只发送了一次请求;

3)由于在整个转发过程中,客户端只发送了一次请求,因此请求域的数据不会失效;

4)转发是服务器内部的行为,我们因此我们不需要加上项目名;例如:request.getRequestDispatcher(“/demo01”)

4.2 重定向

4.2.1 重定向的概念

  • 概念:客户端根据服务器反馈的信息再次请求服务器;

  • 原理图:

客户端首先访问资源/demo01,服务器发现想要的资源不在demo01这里,于是告诉(sendRedirect)客户端:"你要的资源不在我这里,你去访问/demo02"吧!于是客户端再次访问资源/demo02;在重定向中,客户端已经请求了两次服务器;

在这里插入图片描述

4.2.2 重定向的方法

  • response.sendRedirect(“访问的地址”)

4.2.3 重定向的特点

1)由于客户端重定向是客户端再次请求,因此客户端的地址栏的地址已经发生了变化;

2)客户端请求了两次服务器

3)在整个重定向过程中,客户端发送了两次请求,请求域中的数据丢失;

4)重定向是客户端行为(客户端再次请求),我们需要加上项目名;例如:sendRedirect("request.getContextPath()+/demo01")

Tips:如果需要保留请求域中的数据,使用转发,否则使用重定向。

4.3 重定向和转发的区别

区别转发重定向
根目录采用服务器根目录:/02_request/采用客户端根目录:http://localhost:8080/
客户端地址栏不会变化
哪里跳转由服务器进行的跳转由客户端浏览器进行的跳转
请求域不会丢失数据会,因为不是同一次请求

4.3.1 测试重定向请求域数据丢失

  • Demo08Servlet:

往域对象设置值

package com.dfbz.request;

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;

@WebServlet("/demo08")
public class Demo08Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 往请求域对象里面设置值
        request.setAttribute("user", "Jack");

        // 重定向到demo09
        response.sendRedirect("/02_request/demo09");
    }
}
  • Demo09Servlet:

取出域对象的值

package com.dfbz.request;

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;

@WebServlet("/demo09")
public class Demo09Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 取出域对象的值
        String user = (String) request.getAttribute("user");

        // 设置响应的类型和编码
        response.setContentType("text/html;charset=utf8");

        response.getWriter().println("域对象的值: " + user);
    }
}

访问:http://localhost:8080/02_request/dem08

在这里插入图片描述

将重定向改为转发:

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 往请求域对象里面设置值
        request.setAttribute("user", "Jack");

        // 重定向到demo09
//        response.sendRedirect("/02_request/demo09");

        // 转发到demo09(转发采用服务端的根路径)
        request.getRequestDispatcher("/demo09").forward(request,response);
    }
}

重启服务器,访问:http://localhost:8080/02_request/demo08

在这里插入图片描述

4.3.2 转发和重定向后面的代码是否会执行

修改Demo08Servlet代码,分别测试转发和重定向后面的代码是否会执行:

package com.dfbz.request;

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;

@WebServlet("/demo08")
public class Demo08Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 往请求域对象里面设置值
        request.setAttribute("user", "Jack");

        // 重定向到demo09
//        response.sendRedirect("/02_request/demo09");

        // 转发到demo09(转发采用服务端的根路径)
        request.getRequestDispatcher("/demo09").forward(request,response);

        System.out.println("我执行了吗?");
    }
}

Tips:不管是转发还是重定向后面的代码依旧会执行!

五、案例: 实现登录功能

5.1 案例步骤

  1. 用户名和密码正确,将用户成功的信息保存在请求域中,转发到另一个页面,显示用户登录成功

  2. 用户名和密码错误,重定向到另一个html页面,显示登录失败。

  3. 使用表示层,业务层,数据访问层的三层架构实现

  4. 访问数据库Jdbc和连接池Druid

5.2 案例流程图

在这里插入图片描述

1)控制器层

  • 1)需要接受前端传递的参数
  • 2)调用业务逻辑层,做业务处理,数据分析、统计报表、用户行为分析、大数据处理
  • 3)根据业务逻辑层反馈的信息来决定跳转到哪个页面

2)业务逻辑层

  • 1)接受控制器层传递过来的参数
  • 2)调用数据层查询数据库中的结果
  • 3)进行判断、业务处理
  • 4)将结果返回给控制器层

3)数据层

  • 1)将业务逻辑成传递过来的参数变为SQL,查询数据库

5.3 实现步骤

5.3.1 准备登录页面:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body>
<form action="login" method="post">
    <table>
        <tr>
            <td>用户名</td>
            <td><input type="text" name="username"/></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="password"/></td>
        </tr>
        <tr>
           <td colspan="2"><input type="submit" value="登录"/></td>
        </tr>
    </table>
</form>
</body>
</html>

5.3.2 失败页面:

  • failure.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>用户名或密码错误!</h1>
</body>
</html>

5.3.3 创建User表

create table `user`(
    id int primary key auto_increment,
    username varchar(20),
    password varchar(32)
 );

insert into `user`(username, password) values ('admin','123'),('root','456');

select * from `user`;

5.3.4 导入相关jar包

在这里插入图片描述

5.3.5 创建实体类User

package com.dfbz.entity;

public class User {

    private int id;
    private String username;
    private String password;

    public User() {
    }

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", pas=" + password + "]";
    }
}

5.3.6 配置文件druid.properties:

复制到src目录下

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=admin

5.3.7 工具类DataSourceUtils:

package com.dfbz.utils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

public class DataSourceUtils {
    //创建私有静态数据源成员变量
    private static DataSource ds;

    //在静态代码块中创建连接池
    static {
        //创建属性对象
        Properties info = new Properties();
        try (InputStream in = DataSourceUtils.class.getResourceAsStream("/druid.properties")) {
            //从类路径下加载属性文件,得到输入流对象
            info.load(in);
            //通过工厂类创建一个数据源
            ds = DruidDataSourceFactory.createDataSource(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 得到数据源
     * @return
     */
    public static DataSource getDataSource() {
        return ds;
    }

    /**
     * 得到连接对象
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}

5.3.8 数据层代码

数据层负责查询数据库

package com.dfbz.dao;

import com.dfbz.entity.User;
import com.dfbz.utils.DataSourceUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserDao {

    /**
     * 根据用户名查询用户
     *
     * @param username
     * @param password
     * @return
     */
    public User findByUsername(String username,String password) {

        // 获取数据库连接
        try {
            Connection conn = DataSourceUtils.getConnection();

            String sql = "select * from user where username=? and password=?";

            // 获取PreparedStatement对象
            PreparedStatement ps = conn.prepareStatement(sql);

            // 给占位符设置值
            ps.setString(1, username);
            ps.setString(2, password);

            ResultSet rs = ps.executeQuery();

            // 如果有记录
            if (rs.next()) {

                // 封装成一个User对象
                User user = new User(
                        rs.getInt("id"),
                        rs.getString("username"),
                        rs.getString("password")
                );
                return user;
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }

        return null;
    }
}

5.3.9 业务层代码

package com.dfbz.service;

import com.dfbz.dao.UserDao;
import com.dfbz.entity.User;

public class UserService {


    private UserDao userDao=new UserDao();

    /**
     * 调用数据层去数据库查询
     * @param username
     * @param password
     * @return
     */
    public User login(String username,String password) {

        User user=userDao.findByUsername(username,password);

        return user;
    }
}

5.3.10 控制器层代码:

package com.dfbz.controller;

import com.dfbz.entity.User;
import com.dfbz.service.UserService;

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;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    // 处理User业务类
    private UserService userService = new UserService();

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 得到用户名和密码
        String username = request.getParameter("username");   //一定要与表单的名字相同
        String password = request.getParameter("password");

        // 调用业务层登录的方法实现登录
        User user = userService.login(username, password);

        // 如果user不为null,说明数据库有这一条记录(用户名和密码都正确)
        if (user != null){
            request.setAttribute("user", user);

            // 转发到另一个Servlet
            request.getRequestDispatcher("/success").forward(request, response);

        } else{

            // 用户名或密码错误,登录失败,重定向到失败页面
            response.sendRedirect(request.getContextPath() + "/failure.html");
        }
    }
}

5.3.11 SuccessServlet

package com.dfbz.controller;

import com.dfbz.entity.User;

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.io.PrintWriter;

@WebServlet("/success")
public class SuccessServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 从请求域中取出用户对象
        User user = (User) request.getAttribute("user");

        // 设置响应类型和编码
        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();

        out.print("<h1>欢迎您,登录成功" + user.getUsername() + "</h1>");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/153368.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis未授权访问漏洞(三)Redis写入反弹连接定时任务

前言 系列文章 Redis未授权访问漏洞(一)先导篇 Redis未授权访问漏洞(二)Webshell提权篇 Redis写入反弹连接任务 环境准备 攻击机&#xff1a; Centos7 IP:192.168.142.44 靶机&#xff1a;Centos7 IP:192.168.142.66 我们先来回顾一下corntab定时任务的一些基本命令&#xf…

python数据分析及可视化(二十)Power BI的可视化制作以及A股上市公司数据分析

可视化制作 通过图表展示如何用Power BI 制作可视化的图表&#xff0c;来展示可视的数据内容。 柱形图 用水平的柱子来表示不同分类数据的大小&#xff0c;类似于条形图&#xff0c;相当于竖着的条形图。堆积柱形图是不同的序列数据都堆积在一个柱子上&#xff0c;簇状柱形图…

【Spring源码】20. MergedBeanDefinitionPostProcessor修改/合并bean定义

随后进入applyMergedBeanDefinitionPostProcessors()方法applyMergedBeanDefinitionPostProcessors()方法中调用MergedBeanDefinitionPostProcessor后置处理器修改/合并bean定义 进入bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName) 从源码中可以看到&#xff0…

Spring为什么这么火 之 Spring蕴含的设计思想

目录 1、什么是IoC&#xff1f; 2、传统程序开发 3、控制反转式程序开发 4、理解Spring IoC 5、依赖注入【DI】 前言 很多人说&#xff1a;“Java程序员都是Spring程序员”&#xff0c;从这句话就能看出&#xff0c;对于Java程序员来说&#xff0c;Spring是一项必备技能&am…

Mathorcup数学建模竞赛第六届-【妈妈杯】B题:车位分布的优化设计与评价(附一等奖获奖论文、C++和matlab代码)

赛题描述 随着现代社会经济的快速发展,房地产成为国家经济发展中重要的经济增长点之一。而小区内汽车停车位的分布对于小区居民的上下班出行影响很大。请建立数学模型,解决下列问题: 问题1:分析评判小区汽车停车位分布是否合理的几个关键指标,建立评判车位分布合理的数学…

C语言常用字符串函数

专栏&#xff1a;C语言 每日一句&#xff1a;别在乎别人的目光&#xff0c;自己只管一心走路。熬过去&#xff0c;你就能看到柳暗花明&#xff0c;熬过去&#xff0c;你就能看到雨后彩虹&#xff0c;熬过去&#xff0c;你就能看到动人风景。 字符串函数前言一、求字符串长度&am…

UDS - 10.3 ECUReset (11) service

10.3 电子控制单元复位&#xff08;11&#xff09;服务 来自&#xff1a;ISO 14229-1-2020.pdf 10.3.1 服务说明 客户端使用ECUReset服务请求服务器重置。 此服务请求服务器基于ECUReset请求消息中嵌入的resetType参数值的内容有效地执行服务器重置。ECUReset肯定响应消息&am…

剑指 Offer 26树的子结构(相关话题:对称性递归,在线算法)

目录 开篇引言 题目描述 代码实现 题目拓展 拓展解读 一类 100. 相同的树 226. 翻转二叉树 104. 二叉树的最大深度 110. 平衡二叉树 543. 二叉树的直径 617. 合并二叉树 572. 另一个树的子树 965. 单值二叉树 二类 101. 对称二叉树 解题总结 开篇引言 力扣上…

Vue引入并使用Element-UI组件库的两种方式

前言 在开发的时候&#xff0c;虽然我们可以自己写css或者js甚至一些动画特效&#xff0c;但是也有很多开源的组件库帮我们写好了。我们只需要下载并引入即可。 vue和element-ui在开发中是比较般配的&#xff0c;也是我们开发中用的很多的&#xff0c;下面就介绍下如何在eue项…

【力扣/牛客刷题】二叉树篇

作者&#xff1a;✿✿ xxxflower. ✿✿ 博客主页&#xff1a;xxxflower的博客 专栏&#xff1a;【力扣、牛客刷题】篇 语录&#xff1a;⭐每一个不曾起舞的日子&#xff0c;都是对生命的辜负。⭐ 文章目录100. 相同的树572. 另一棵树的子树226. 翻转二叉树平衡二叉树101.对称二…

C++11之后的decltype类型指示符

C11之后的decltype类型指示符一、什么是decltype类型指示符二、typeid运算符三、使用decltype指示符四、decltype和引用五、decltype(auto)六、本章代码汇总一、什么是decltype类型指示符 有时会遇到这种情况&#xff1a;希望从表达式的类型推断出要定义的变量的类型&#xff…

深度对比学习综述

本文综合考察了对比学习近年的发展和进步, 提出一种新的面向对比学习的归类方法, 并基于提出的归类方法, 对现有对比研究成果进行系统综述, 并评述代表性方法的技术特点和区别, 系统对比分析现有对比学习方法在不同基准数据集上的性能表现。 摘要 在深度学习中, 如何利用大量、…

Linux - 目录与文件操作

目录1.操作目录1.1 目录切换1.2 浏览目录1.3 目录创建1.4 目录删除1.5 复制目录1.6 移动或重命名目录2. 操作文件2.1 查找文件2.2 查看文件信息2.3 查看文件内容2.4 创建文件2.5 文件修改-vim2.6 删除文件2.7 复制和重命名文件3. 文件或目录进行压缩或解压3.1 压缩3.2 解压1.操…

链路追踪工具之Zipkin

Zipkin是一个分布式跟踪系统&#xff0c;Zipkin的设计是基于谷歌的Google Dapper论文&#xff0c;它可以帮助收集时间数据&#xff0c;在microservice架构下&#xff0c;通过链路追踪&#xff0c;可以便捷的分析服务调用延迟问题。每个应用程序向Zipkin server端报告数据&#…

【高光谱、多光谱和全色图像融合】

HyperFusion: A Computational Approach for Hyperspectral, Multispectral, and Panchromatic Image Fusion &#xff08;超融合&#xff1a;高光谱、多光谱和全色图像融合的计算方法&#xff09; 高空间分辨率的高光谱图像&#xff08;HSI&#xff09;和多光谱图像&#xff…

链表热门面试题(二)

目录前言一、删除链表的倒数第 N 个结点二、两两交换链表中的节点三、旋转链表四、删除排序链表中的重复元素五、删除排序链表中的重复元素 II六、反转链表II七、删除链表中的节点八、奇偶链表前言 一、删除链表的倒数第 N 个结点 题目&#xff1a; 方法1&#xff1a;找到删除…

【Java多线程】创建多线程方式一

线程的创建和启动 *Java语言的JVM允许程序运行多个线程&#xff0c;它通过java.lang.Thread类来体现。 *Thread类的特性 每个线程都是通过某个特定Thread对象的run()方法来完成操作的&#xff0c;经常 把run()方法的主体称为线程体 通过该Thread对象的start()方法来启动这个…

判断两条线段是否相交

参考链接&#xff1a; 1 2 一、判断线段是否相交需要下面两步&#xff1a; &#xff08;1&#xff09;快速排斥实验 &#xff08;2&#xff09;跨立实验 二、第一步快速排斥实验 对上图两条L1,L2线段来说&#xff0c;L1 x的最大值为d端点x5&#xff0c;L2 x的最小值为a端点x…

RobotFramework环境安装和入门

环境安装1、安装python建议版本3.7&#xff0c;Robot Framework不支持python最新版。 可以通过以下地址下载https://www.python.org/ftp/python/3.7.3/python-3.7.3-amd64.exe安装过程中选择添加到环境变量。2、安装Robot Framework以及所需组件注意各个组件的版本号&#xff0…

LVGL学习笔记15 - 文本框TextArea

目录 1. Parts 2. 样式 2.1 修改背景bg 2.2 修改边界border 2.3 修改文本 2.3.1 lv_textarea_add_char 2.3.2 lv_textarea_add_text 2.3.3 lv_textarea_set_text 2.3.4 设定可输入的字符 2.3.5 删除字符 2.3.6 设定字符串最大长度 2.4 滚动条 2.4.1 滚动方向 2.4.2 …