Servlet实现常用功能及其他方法

getParameter

获取body或url中指定的key/value值

String classId=req.getParameter("classId");

getQueryString

获取请求的所有查询参数key,values1

String queryString=req.getQueryString();

from表单提交

前端通过from表单提交用户名和密码

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="Demo4" method="post"><input type="text" name="username"><input type="password" name="password"><input type="submit" name="提交"></form>
</body>
</html>

后端通过req.getParameter获取用户名和密码

package Demo;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("/Demo4")
public class Demo4 extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf8");String username=req.getParameter("username");String password=req.getParameter("password");if(username.equals("user")&&password.equals("123")){resp.getWriter().write("登录成功!");}else{resp.getWriter().write("用户名或者密码错误!");}}
}

构造json格式

body中的json格式

使用jackson库解析json格式

版本随便一个都可以

拷贝复制

记得刷新

读取从客户端传来的json数据

class Student{public int classId;public int studentId;
}
//        使用jackSon库处理JSON格式ObjectMapper objectMapper=new ObjectMapper();
//        从请求获取body并且解析
//        使用readValue来把json字符串转成java对象
//        第一个对象是String或者InputStream
//        第二个参数是转换的结果对应的java类对象//把JSON字符串转成java对象Student s=objectMapper.readValue(req.getInputStream(),Student.class);resp.getWriter().write("classId="+s.classId+" studentId="+s.studentId);

服务器把json写入到客户端

        //传json时,要用这个类型resp.setContentType("application/json;charset=utf8");//要拿到写数据库操作的类BlogDao blogDao=new BlogDao();String jsonString=objectMapper.writeValueAsString(blogs);//响应resp.getWriter().write(jsonString);

客户端如何解析json格式?

后端设置了application/json格式,并且返回json格式,那么ajax会自动把body中的json格式转换成js对象

function getBlogs(){//构造ajax$.ajax({type:'get',url:'blog',success: function(body){let container=document.querySelector('.container-right');//后端返回的是json数据//如果Content-Type是application/json,jquery ajax会把body转成js对象for(let blog of body){//构造最外层的divlet blogDiv=document.createElement('div');blogDiv.className='blog';//创建博客标题let titleDiv=document.createElement('div');titleDiv.className='title';//把后端传来的json,被jackson解析成blog对象,对象内的标题属性赋值titleDiv.innerHTML=blog.title;//把titleDiv添加在blogDiv内blogDiv.appendChild(titleDiv);

页面自动刷新

设置头部信息Refresh属性 values为秒

package Demo;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("/Demo5")
public class Demo5 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf8");resp.setHeader("Refresh","1");resp.getWriter().write("设置页面1秒后自动刷新");}
}

跳转页面

        //跳转页面resp.setStatus(302);//设置状态码 302resp.setHeader("Location","Demo1.html");

N秒后自动跳转页面

        //2秒后,跳转页面resp.getWriter().write("2秒后我将跳转页面");resp.setHeader("refresh", "2;Demo1.html");

自动下载

response.setHeader("content-disposition", "attachment;filename=3.jpg");

对话墙

基本逻辑

前端构造post方法,把数据构造成json格式,发送给后端,后端解析json格式,存储到数据库。

当页面刷新时,前端构造get方法,把数据构造成json格式,发送给后端,后端从数据库读取数据,再构造成json格式,发送给前端。

ajax会自动把body中的json格式解析成js对象,之后前端把数据显示到页面上。

前端页面

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>对话墙</title><style>* {padding: 0;margin: 0;box-sizing: border-box;}.container {width: 800px;margin: 10px auto;}.container h2 {text-align: center;margin: 30px 0px;}.row {height: 50px;display: flex;justify-content: center;margin-top: 5px;line-height: 50px;}.row span {height: 50px;width: 100px;line-height: 50px;}.row input {height: 50px;width: 300px;line-height: 50px;}.row button {width: 400px;height: 50px;color: white;background-color: orange;border: none;border-radius: 10px;}.row button:active {background-color: grey;}</style>
</head>
<body><!-- 这是一个顶层容器, 放其他元素 --><div class="container"><h2>表白墙</h2><div class="row"><span>谁</span><input type="text" id="from"></div><div class="row"><span>对谁</span><input type="text" id="to"></div><div class="row"><span>说什么</span><input type="text" id="message"></div><div class="row"><button>提交</button></div></div><script src="https://code.jquery.com/jquery-3.7.1.min.js"></script><script>let container = document.querySelector('.container');let fromInput = document.querySelector('#from');let toInput = document.querySelector('#to');let messageInput = document.querySelector('#message');let button = document.querySelector('button');button.onclick = function() {// 1. 把用户输入的内容获取到. let from = fromInput.value;let to = toInput.value;let message = messageInput.value;if (from == '' || to == '' || message == '') {return;}// 2. 构造一个 div, 把这个 div 插入到 .container 的末尾let newDiv = document.createElement('div');newDiv.className = 'row';newDiv.innerHTML = from + " 对 " + to + " 说: " + message;// 3. 把 div 挂在 container 里面container.appendChild(newDiv);// 4. 把之前的输入框内容进行清空fromInput.value = '';toInput.value = '';messageInput.value = '';// 5. [新的步骤] 需要把刚才输入框里取到的数据, 构造成 POST 请求, 交给后端服务器!// JSON格式let messageJson={//kv值 k是我们现在定义的,v是在上面我们自己定义的from:from,to:to,message:message}$.ajax({type:"post",url:"message",contentType:'application/json;charset=utf8',// ajax构造请求发送JSONdata:JSON.stringify(messageJson),//当服务器返回数据时,执行success:function (){alert("提交成功!");},error:function (){alert("提交失败");}})}//这个函数再页面加载时候调用,通过这个函数从服务器获取当前的消息列表//摈弃显示到页面上function load(){$.ajax({type: 'get',url: 'message',contentType:'application/json;charset=utf8',//当服务器返回数据时,才会执行success: function(body){//服务器传来的时JSON格式,但ajax根据Content-Type为//application/json,ajax会帮我们自动类型转换成js数组let container=document.querySelector('.container');//服务器传来的数据都在body里//遍历bodyfor(let message of body){let newDiv=document.createElement('div');newDiv.className='row';newDiv.innerHTML=message.from +" 对 "+message.to+ " 说 "+message.message;//把newDiv加在container的里面container.appendChild(newDiv);}}})}//函数页面写在这代表页面加载/刷新时执行load函数load();</script>
</body>
</html>

后端页面

package org.example;import com.fasterxml.jackson.databind.ObjectMapper;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.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;//对应前端的格式
//名字和全都key时一致的
class Message{public String from;public String to;public String message;@Overridepublic String toString() {return "org.example.Message{" +"from='" + from + '\'' +", to='" + to + '\'' +", message='" + message + '\'' +'}';}
}@WebServlet("/message")
public class MessageServlet extends HttpServlet {//因为get、post都会用到这个对象,所以共享出来private ObjectMapper objectMapper=new ObjectMapper();//private List<org.example.Message> messageList=new ArrayList<>();@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//报文格式resp.setContentType("application/json;charset=utf8");List<Message> messageList=load();//把messageList对象转成JSON格式String respString=objectMapper.writeValueAsString(messageList);resp.getWriter().write(respString);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("application/json;charset=utf8");//第一个参数从拿哪读,转成什么类型Message message=objectMapper.readValue(req.getInputStream(),Message.class);save(message);System.out.println("message"+message);//把这些数据存储起来//messageList.add(message);//System.out.println("messaage="+message);//返回保存成功响应resp.getWriter().write("{\"ok\":1}");}// 把当前的消息存到数据库中private void save(Message message) {Connection connection = null;PreparedStatement statement = null;try {// 1. 和数据库建立连接connection = DBUtil.getConnection();// 2. 构造 SQL 语句String sql = "insert into message values(?, ?, ?)";//写入sqlstatement = connection.prepareStatement(sql);//填入问号statement.setString(1, message.from);statement.setString(2, message.to);statement.setString(3, message.message);// 3. 执行 SQL 语句int ret = statement.executeUpdate();if (ret != 1) {System.out.println("插入失败!");} else {System.out.println("插入成功!");}} catch (SQLException e) {e.printStackTrace();} finally {// 4. 关闭连接.DBUtil.close(connection, statement, null);}}// 从数据库查询到记录private List<Message> load() {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;List<Message> messageList = new ArrayList<>();try {// 1. 建立连接connection = DBUtil.getConnection();// 2. 构造 SQLString sql = "select * from message";//写入sqlstatement = connection.prepareStatement(sql);// 3. 执行 SQLresultSet = statement.executeQuery();// 4. 遍历结果集while (resultSet.next()) {Message message = new Message();message.from = resultSet.getString("from");message.to = resultSet.getString("to");message.message = resultSet.getString("message");messageList.add(message);}} catch (SQLException throwables) {throwables.printStackTrace();} finally {// 5. 释放资源DBUtil.close(connection, statement, resultSet);}return messageList;}
}

建立连接

完成与数据库建立连接

package org.example;import com.mysql.cj.jdbc.MysqlDataSource;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;// 期望通过这个类来完成数据库建立连接的过程.
// 建立连接需要使用 DataSource . 并且一个程序有一个 DataSource 实例即可. 此处就使用单例模式来实现.
public class DBUtil {private static DataSource dataSource = null;private static DataSource getDataSource() {if (dataSource == null) {dataSource = new MysqlDataSource();((MysqlDataSource)dataSource).setURL("jdbc:mysql://127.0.0.1:3306/MessageWall?characterEncoding=utf8&useSSL=false");((MysqlDataSource)dataSource).setUser("root");((MysqlDataSource)dataSource).setPassword("monan1946");}return dataSource;}public static Connection getConnection() throws SQLException {return getDataSource().getConnection();}public static void close(Connection connection, PreparedStatement statement, ResultSet resultSet) {// 此处还是推荐大家写成分开的 try catch.// 保证及时一个地方 close 异常了, 不会影响到其他的 close 的执行.if (resultSet != null) {try {resultSet.close();} catch (SQLException e) {e.printStackTrace();}}if (statement != null) {try {statement.close();} catch (SQLException e) {e.printStackTrace();}}if (connection != null) {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}

抓包过程

当页面提交数据时,触发post请求,会把数据提交到服务器,服务器会把数据存储起来。

当刷新页面时,会触发get请求,服务器会把数据回传给页面,页面会把数据继续显示到页面上,所以数据会依据存在

为什么刷新页面时会自动触发get请求呢?

在HTTP协议中,GET请求是用来获取服务器上的资源的。当你在浏览器中输入一个URL并按下回车键或者点击刷新按钮时,浏览器会向服务器发送一个GET请求,请求服务器返回该URL对应的资源。

客户端发起的请求,会自动触发服务器的对应的do方法

服务器返回响应,就会触发客户端的代码,也就是success的回调函数

模拟用户登录

基本逻辑

前端传递用户名和密码

当用户名与密码正确时,后端创建session(cookie),把用户名写进去,并且创建计数器。之后在另一个页面,获取session中的用户名,再把计数器也取出,计数器++,并且两个打印,计数器更新后,再把更新后的计数器写入session

前端

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>登录页</title>
</head>
<body><!-- action是路径 method是方法 --><form action="login" method="post"><input type="text" name="username"><input type="password" name="password"><input type="submit" name="提交"></form>
</body>
</html>

后端

loginServlet

package login;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 javax.servlet.http.HttpSession;
import java.io.IOException;@WebServlet("/login")
//处理登录请求
public class loginServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf8");String username=req.getParameter("username");String password=req.getParameter("password");//数据为空时if(username==null || username.equals("")|| password==null || password.equals("")){//返回到登录页面//resp.sendRedirect("login.html");resp.getWriter().write("用户名或密码错误,请重新登录!");return;}if(username.equals("user")&&password.equals("123")){//创建一个session会话 把用户信息填写到session中//如果会话存在直接获取,根据cookie中的sessionid来查//如果不存在就创建新的//第一次登录时,cookie没有sessionid,就会创建新的会话对象//同时这个getsession还会生成一个sessionid,把这个sessionid作为Set-Cookie中的字段返回//给浏览器保存//一个sessionid对应一个sessionHttpSession sessio=req.getSession(true);sessio.setAttribute("username","user");//设置计数器 用来表示用户访问页面次数Integer visitCount= (Integer) sessio.getAttribute("visitCount");//如果visitCount为空时,就设置0if(visitCount==null){//第二个参数是Object 所以会自动装箱成Integersessio.setAttribute("visitCount",0);}else{//如果已经存在,就不设置为0}resp.sendRedirect("index");}else{resp.getWriter().write("用户名或密码错误,请重新登录!");return;}}
}

indexServlet

package login;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 javax.servlet.http.HttpSession;
import java.io.IOException;@WebServlet("/index")
public class indexServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf8");//false不创建会话,有则有,没有则要求用户重新登录HttpSession session=req.getSession(false);//用户未登录,跳转登录界面,重新登录//当浏览器直接访问这个页面时 并没有先进入login.html页面 就会出现session==null的情况if(session==null){resp.sendRedirect("login.html");return;}//这里就是登录成功//获取会话中的数据//因为getAttribute返回的是Object 所以要强转//获取session中传来的usernameString username= (String) session.getAttribute("username");//session第二个参数是Object,虽然写的是0,但是会自动装箱成Integer,取的时候也是Integer//获取session中传来的计数器Integer visitCount= (Integer) session.getAttribute("visitCount");visitCount=visitCount+1;//加数后,再写回去session.setAttribute("visitCount",visitCount);resp.getWriter().write("当前用户: "+username+"访问次数:"+visitCount);}
}

第一次请求

首次登录,都会触发get方法

第二次请求 

输入用户名密码登录

响应

JSESSIONID就是key(servlet自动生成的key名字) 后面是一传很长的十六进制数字,就是value

value就是服务器生成的sessionid

可以看到已经保存在浏览器内了

HttpSession sessio=req.getSession(true);

就是这个代码,实现创建会话,生成sessionid并且把sessionid通过Set-Cookie返回给浏览器

因为上面重定向了,所以浏览器get了index的页面

这是报文里就有了cookie

响应

这时就会读取请求中的cookie中的username,并且显示出来

上传文件

前端

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><!-- enctype="multipart/form-data"指定了表单数据的编码方式,这样文件上传操作才能正确地执行。 --><form action="upload" method="post" enctype="multipart/form-data"><input type="file" name="MyFile"><input type="submit" value="上传"></form>
</body>
</html>

后端

package upload;import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;@MultipartConfig//servlet上传文件时默认关闭的,写上这个注解,打开
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setContentType("text/html;charset=utf8");
//        name要对应前端的name//获取文件Part part=req.getPart("MyFile");//        文件真实名字resp.getWriter().write(part.getSubmittedFileName()+"<br>");//文件大小System.out.println(part.getSize()+"<br>");//文件类型resp.getWriter().write(part.getContentType()+"<br>");//将文件写入磁盘part.write("D:/4k阿狸.jpg");resp.getWriter().write("upload ok");}
}

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

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

相关文章

DataX配置案例@Source:MySQL,Sink:HDFS [SQLMode] 及空值如何存储

HFDS Writer并未提供nullFormat参数&#xff1a;也就是用户并不能自定义null值写到HFDS文件中的存储格式。默认情况下&#xff0c;HFDS Writer会将null值存储为空字符串&#xff08;&#xff09;&#xff0c;而Hive默认的null值存储格式为\N。所以后期将DataX同步的文件导入Hiv…

Windows本地搭建开源的stable-diffusion-webui用于AIGC文生图

开源的stable-diffusion-webui来自于https://github.com/AUTOMATIC1111/stable-diffusion-webui 在windows搭建似乎比较方便些,需要python3.8;比如CUDA模式下,显卡驱动比较好安装(若使用cuda需要更新显卡驱动在https://www.nvidia.com/download/index.aspx?lang=en-us )…

docker swarm 详细安装配置步骤

在 Linux 环境下安装和配置 Docker Swarm 的详细步骤。假设您已经安装了 Docker&#xff0c;并且使用的 Docker 版本 > 1.12&#xff0c;因为从这个版本开始&#xff0c;Swarm 模式已集成到 Docker 引擎中。这里以 Ubuntu 为例&#xff0c;但基本步骤适用于其他 Linux 发行版…

Zookeeper和Kafka的部署

目录 一、Zookeeper的基本概念 1. Zookeeper定义 2. Zookeeper工作机制 3. Zookeeper特点 4. Zookeeper数据结构 5. Zookeeper应用场景 5.1 统一命名服务 5.2 统一配置管理 5.3 统一集群管理 5.4 服务器动态上下线 5.5 软负载均衡 6. Zookeeper 选举机制 6.1 第一…

【opencv】示例-text_skewness_correction.cpp 校正文本图像的倾斜度

// 此教程展示了如何矫正文本的偏斜。 // 程序接受一个偏斜的源图像作为输入&#xff0c;并显示非偏斜的文本。#include <opencv2/core.hpp> // 包含OpenCV核心功能的头文件 #include <opencv2/imgcodecs.hpp> // 包含OpenCV图像编解码功能的头文件 #include <o…

每日练习——leetcode402. 移掉 K 位数字和17. 电话号码的字母组合

目录 402. 移掉 K 位数字 题目描述 解题思路 代码实现 17. 电话号码的字母组合 题目描述 解题思路 代码实现 402. 移掉 K 位数字 题目描述 给你一个以字符串表示的非负整数 num 和一个整数 k &#xff0c;移除这个数中的 k 位数字&#xff0c;使得剩下的数字最小。请…

Python杂记--使用asyncio构建HTTP代理服务器

Python杂记--使用asyncio构建HTTP代理服务器 引言基础知识代码实现 引言 本文将介绍 HTTP 代理的基本原理&#xff0c;并带领读者构建一个自己的 HTTP 代理服务器。代码中不会涉及到任何第三方库&#xff0c;全部由 asyncio 实现&#xff0c;性能优秀&#xff0c;安全可靠。 基…

Linux-文件系统理解(磁盘的物理与逻辑结构、什么是inode、OS如何管理磁盘)

一、磁盘 磁盘的物理结构 磁盘的本质是一个机械设备&#xff0c;可以存储大量的二进制信息&#xff0c;是实现数据存储的基础硬件设施&#xff0c;磁盘的盘片类似于光盘&#xff0c;不过盘片的两面都是可读可写可擦除的&#xff0c;每个盘面都有一个磁头&#xff0c;马达可以使…

攻防世界---Web_php_include

1.题目链接 2.补充知识&#xff1a; 3.构造&#xff1a;执行成功 /?pagedata://text/plain,<?php phpinfo()?> 4.构造下面url&#xff0c;得到目录路径 /?pagedata://text/plain,<?php echo $_SERVER[DOCUMENT_ROOT]?> 5构造下面url&#xff0c;读取该路径的…

【网站项目】面向企事业单位的项目申报小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

Node.js、Java、Python、PHP在构建BS系统时的特点比较

在现代软件开发领域&#xff0c;构建一个稳定、高效的B/S&#xff08;浏览器/服务器&#xff09;系统对于企业的信息化发展至关重要。Node.js、Java、Python和PHP是当下流行的几种后端开发技术&#xff0c;它们各自具有独特的特点和优势。本文将对这几种技术在构建B/S系统时的特…

网络编程【InetAddress , TCP 、UDP 、HTTP 案例】

day38上 网络编程 InetAddress 理解&#xff1a;表示主机类 一个域名 对应 多个IP地址 public static void main(String[] args) throws UnknownHostException {//获取本机的IP地址 // InetAddress localHost InetAddress.getLocalHost(); // System.out.println(localHos…

简单认识Git(dirsearch、githack下载),git泄露(ctfhub)

目录 dirsearch下载地址: githack下载&#xff08;一次不成功可多试几次&#xff09; 一、什么是Git 1.git结构 2.git常用命令及示例 3.Git泄露原理 二、Git泄露 1.Log 2.Stash 3.Index 工具准备&#xff1a;dirsearch、githack dirsearch下载地址: GitHub - mauroso…

如何解决微信小程序无法使用css3过度属性transition

由于微信小程序不支持CSS3过度属性transition,所以我们需要利用微信小程序api进行画面过度的展示 首先是官方示例: wxml: <view animation="{{animationData}}" style="background:red;height:100rpx;width:100rpx"></view> js: Page(…

搭建Hive 3.x环境(CentOS 9 + Hadoop3.x)

零、资源准备 虚拟机相关&#xff1a; VMware workstation 16&#xff1a;虚拟机 > vmware_177981.zipCentOS Stream 9&#xff1a;虚拟机 > CentOS-Stream-9-latest-x86_64-dvd1.iso JDK jdk1.8&#xff1a;JDK > jdk-8u261-linux-x64.tar.gz Hadoop Hadoop 3.3.6&a…

【Java】内存可见性问题是什么?

文章目录 内存模型内存可见性解决方案volatile 内存模型 什么是JAVA 内存模型&#xff1f; Java Memory Model (JAVA 内存模型&#xff09;是描述线程之间如何通过内存(memory)来进行交互。 具体说来&#xff0c; JVM中存在一个主存区&#xff08;Main Memory或Java Heap Mem…

架构师系列-搜索引擎ElasticSearch(七)- 集群管理之分片

集群健康检查 Elasticsearch 的集群监控信息中包含了许多的统计数据&#xff0c;其中最为重要的一项就是集群健康&#xff0c;它在 status字段中展示为 green&#xff08;所有主分片和副本分片都正常&#xff09;、yellow&#xff08;所有数据可用&#xff0c;有些副本分片尚未…

Collection与数据结构 二叉树(三):二叉树精选OJ例题(下)

1.二叉树的分层遍历 OJ链接 上面这道题是分层式的层序遍历,每一层有哪些结点都很明确,我们先想一想普通的层序遍历怎么做 /*** 层序遍历* param root*/public void levelOrder1(Node root){Queue<Node> queue new LinkedList<>();queue.offer(root);while (!qu…

Vue 2实现未登录拦截页面功能

在Vue 2中实现未登录拦截页面功能&#xff0c;通常可以通过路由守卫和全局前置守卫来完成。以下是一个基本的实现步骤和示例代码&#xff0c;帮助你创建一个简单的未登录拦截逻辑。 步骤 1: 安装和配置路由 首先&#xff0c;确保你的Vue项目已经安装并配置了vue-router。如果…

Spring Boot(二)— 自定义Spring Boot Starter

在Spring Boot中&#xff0c;自定义Spring Boot Starter是一个常见且强大的功能&#xff0c;它允许开发者为特定的功能或库创建自己的自动配置&#xff0c;从而简化集成过程。 1 前置知识 Spring Boot的事件为应用的启动和关闭提供了详细的上下文信息&#xff0c;使得开发者能…