Three——四、几何体、高光网络材质、锯齿模糊以及GUI库的使用
文章:
- Three——一、初识Three以及基础的前端场景搭建(结尾含源码)
- Three——二、加强对三维空间的认识
- Three——三、动画执行、画布大小、渲染帧率和相机适配体验
- Three——四、几何体、高光网络材质、锯齿模糊以及GUI库的使用
- Three——五、点线模型对象、三角形概念、几何体顶点位置,顶点索引、法线以及对几何体进行旋转缩放和平移
Threejs 常见几何体简介
Three.js 常见的几何体:

常见的几何体:
//BoxGeometry:长方体
const geometry = new THREE.BoxGeometry(100, 100, 100);
// SphereGeometry:球体
const geometry = new THREE.SphereGeometry(50);
// CylinderGeometry:圆柱
const geometry = new THREE.CylinderGeometry(50, 50, 100);
// PlaneGeometry:矩形平面
const geometry = new THREE.PlaneGeometry(100, 50);
// CircleGeometry:圆形平面
const geometry = new THREE.CircleGeometry(50);
这里拿平面做示例:

双面可见
Three.js 的材质默认正面可见,反面不可见,对于矩形平面PlaneGeometry、圆形平面如果你想看到两面,可以设置side: THREE.DoubleSide。
new THREE.MeshBasicMaterial({side: THREE.FrontSide, //默认只有正面可见
});
new THREE.MeshBasicMaterial({side: THREE.DoubleSide, //两面可见
});

高光网络材质
高光网格材质MeshPhongMaterial和基础网格材质MeshBasicMaterial、漫反射网格材质MeshLambertMaterial一样都是网格模型的 Mesh 的材质。
注意:高光网格材质MeshPhongMaterial和漫反射网格材质MeshLambertMaterial一样会受到光照的影响。
MeshPhongMaterial 对光照反射特点
MeshPhongMaterial和MeshLambertMaterial都会收到光照的影响区别在于,对光线反射方式有差异。
MeshPhongMaterial可以实现高光反射效果,而MeshLamberMaterial恰恰相反。所谓的高光,就比如你在一个太阳下方去看一个小汽车,你会在特定的角度及位置看到玻璃表面某个位置特别亮。
镜面反射与漫反射
MeshPhongMaterial可以提供一个镜面的反射效果,可以类比你生活中拿一面镜子,放在太阳光下,调整角度,可以把太阳光反射到其它地方,如果反射光对着眼睛,也就是反射光线和视线平行的时候,会非常刺眼。
MeshLambertMaterial对应的 Mesh 受到光线照射,没有镜面反射的效果,只是一个漫反射,也就是光线向四周反射。

高光亮度属性shininess
通过MeshPhongMaterial的高光亮度shininess属性,可以控制高光反射效果
// 模拟镜面反射,产生一个高光效果
const material = new THREE.MeshPhongMaterial({color: 0x00ffff,shininess: 500, //高光部分的亮度,默认30
});
数字越大,光越亮
对比效果:

下面是使用MeshLambertMaterial材质的效果:

WebGL 渲染器设置(锯齿模糊)
设置渲染器锯齿属性:antialias
const renderer = new THREE.WebGLRenderer({antialias: true,
});
对比:


设置背景的两种方式
scene.background = new THREE.Color(0xaaaaaa);
// or
// renderer.setClearColor(0xffffff, 1); //设置背景颜色
gui.js 库
简介
借助gui.js可以快速创建控制三维场景的UI交互界面
gihtub地址:https://github.com/dataarts/dat.gui
npm地址:https://www.npmjs.com/package/dat.gui
three中自带了gui库
import { GUI } from "three/addons/libs/lil-gui.module.min.js";
创建 GUI 对象
const gui = new GUI();
通过domElement改变 GUI 界面默认的 style 属性
尝试改变他的位置和长度
const gui = new GUI();
gui.domElement.style.right = "0px";
gui.domElement.style.width = "300px";


add()方法
add()方法可以创建一个交互界面,例如滚动条,从而改变 js 对象属性的属性值
.add(控制对象,对象具体属性,其它参数)
其他参数,可以一个或多个,数据类型也可以不同,gui 会自动根据参数形式,自动生成对应的交互界面。
参数 3 和参数 4,分别是一个数字,交互界面是一个鼠标可以拖动的拖动条,可以在一个区间改变属性的值
const obj = {x: 30,
};
gui.add(obj, "x", 0, 100);

gui 改变 js 对象多个属性
const obj = {x: 30,y: 60,z: 300,
};
// gui界面上增加交互界面,改变obj对应属性
gui.add(obj, "x", 0, 100);
gui.add(obj, "y", 0, 50);
gui.add(obj, "z", 0, 60);
通过 gui 改变 threejs 光照强度测试
给光源绑定intensity属性,通过 gui 的拖动条来改变光源属性
// 需要光源和光源位置信息
// const pointLight = new THREE.PointLight(0xffffff, 1.0);
// pointLight.position.set(100, 60, 50);gui.add(pointLight, "intensity", 0, 2.0);
scene.add(pointLight);// 光源辅助观察
// const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
// scene.add(pointLightHelper);
效果:会将下方绑定模型位置同时进行演示
gui 绑定模型位置
mesh.position是 JavaScript 对象,具有 x、y、z 属性,这三个属性分别表示模型的 xyz 坐标,这就是说,gui 改变mesh.position的 x、y、z 属性,就可以可视化改变 mesh 的位置。
function guiFun() {gui.add(mesh.position, "x", 0, 100);gui.add(mesh.position, "y", 0, 50);gui.add(mesh.position, "z", 0, 60);
}
效果演示:

name()
name 属性可以将默认值改成所需文字
gui.add(pointLight, "intensity", 0, 2.0).name("光源");

step()步长
每次拖动的间隔
gui.add(pointLight, "intensity", 0, 2.0).name("光源").step(0.1);
onChange()方法
当 gui 界面某个值的时候,.onChange()方法就会执行,这时候你可以根据需要通过.onChange()执行某些代码。就是可以将老值被新值替换。
let obj = {x: 30,y: 30,z: 30,
};
gui.add(obj, "x", 0, 180).onChange(function (value) {mesh.position.x = value;
});
gui 改变材质颜色
const obj = {color: 0x00ffff,
};
// .addColor()生成颜色值改变的交互界面
gui.addColor(obj, "color").onChange(function (value) {mesh.material.color.set(value);
});

gui 下拉菜单
通过.add()方法创建新的 UI 交互界面,下拉框、单选框
1、 .add()方法参数 3 和 4 数据类型:数字
此方法如上
add(控制对象,对象具体属性,其他参数)
其他参数,可以一个或多个,数据类型也可以不同,gui 会自动根据参数形式,自动生成对应的交互界面。
2、.add()方法参数 3 数据类型:数组
参数 3 如果是一个数组的话,那么他的交互界面是下拉菜单
例如:
const obj = {scale: 0,
};
gui.add(obj, "scale", [-100, 0, 100]).name("x轴坐标").onChange(function (value) {mesh.position.x = value;});

3、 .add()方法参数 3 数据类型:对象
参数 3 如果为对象,那么生成的交互界面也会是下拉菜单
例如:
const obj = {scale: 0,
};
// 参数3数据类型:对象(下拉菜单)
gui.add(obj, "scale", {left: -100,center: 0,right: 100,// 左: -100,//可以用中文// 中: 0,// 右: 100}).name("位置选择").onChange(function (value) {mesh.position.x = value;});

4、.add()方法对应属性的数据类型:布尔值
如果.add()改变属性的数据类型如果是布尔值,那么交互界面就是一个单选按钮
例如:
const obj = {bool: false,
};
// 改变的obj属性数据类型是布尔值,交互界面是单选框
gui.add(obj, "bool").name("是否旋转");
gui.add(obj, "bool").onChange(function (value) {// 点击单选框,控制台打印obj.bool变化console.log("obj.bool", value);
});
案例:控制旋转模型
const obj = {bool: false,
};
gui.add(obj, "bool").name("旋转动画");
const render = () => {if (obj.bool) mesh.rotateY(0.01);renderer.render(scene, camera);requestAnimationFrame(render);
};
render();
效果:

gui.js 库(分组)
如果页面出现控制的属性较多时,为了避免混合,可以适当进行分组管理
例如:
const gui = new GUI(); //创建GUI对象
//创建一个对象,对象属性的值可以被GUI库创建的交互界面改变
const obj = {color: 0x00ffff, // 材质颜色specular: 0x111111, // 材质高光颜色
};// 材质颜色color
gui.addColor(obj, "color").onChange(function (value) {material.color.set(value);
});
// 材质高光颜色specular
gui.addColor(obj, "specular").onChange(function (value) {material.specular.set(value);
});// 环境光强度
gui.add(ambient, "intensity", 0, 2);
// 平行光强度
gui.add(directionalLight, "intensity", 0, 2);
// 平行光位置
gui.add(directionalLight.position, "x", -400, 400);
gui.add(directionalLight.position, "y", -400, 400);
gui.add(directionalLight.position, "z", -400, 400);
使用.addFolder()分组
环境光子菜单部分
const gui = new GUI();
let obj = {color: 0x00ffff, // 材质颜色specular: 0xff0000,
};
const matFolder = gui.addFolder("材质");// 材质子菜单部分
matFolder.close();
matFolder.addColor(obj, "color").onChange(function (value) {material.color.set(value);console.log(material.specular.set(value));
});
matFolder.addColor(obj, "specular").onChange(function (value) {material.specular.set(value);
});
环境光子菜单部分
const ambientFolder = gui.addFolder("环境光");
ambientFolder.add(pointLight, "intensity", 0, 2);
平行光
const dirFolder = gui.addFolder("平行光强度");// 光源辅助观察
// const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
// scene.add(pointLightHelper);
// const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);
// directionalLight.position.set(100, 0, 0);// // 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
// directionalLight.target = mesh;
// // 辅助观察
// const dirLightHelper = new THREE.DirectionalLightHelper(
// directionalLight,
// 5,
// 0xff0000
// );
// // 添加辅助标识
// scene.add(dirLightHelper);
// // 添加平行光到场景中
// scene.add(directionalLight);
// 平行光强度
dirFolder.add(directionalLight, "intensity", 0, 2);
// 平行光位置
dirFolder.add(directionalLight.position, "x", -400, 400);
dirFolder.add(directionalLight.position, "y", -400, 400);
dirFolder.add(directionalLight.position, "z", -400, 400);
显示效果如下:

关闭.close()和展开.open()交互界面
用.close()和.open()方法可以设置默认是否折叠还是展开,默认状态为open()
// 菜单名称.close();
dirFolder.close();
matFolder.close();
效果如下:

.addFolder()子菜单嵌套
通过 addFolder 可以再次进行 addFolder 完成子菜单嵌套
const dirFolder2 = dirFolder.addFolder("位置"); //子菜单的子菜单
dirFolder.add(directionalLight, "intensity", 0, 2);
const dirFolder2 = dirFolder.addFolder("位置"); //子菜单的子菜单
dirFolder2.close(); //关闭菜单
// 平行光位置
dirFolder2.add(directionalLight.position, "x", -400, 400);
dirFolder2.add(directionalLight.position, "y", -400, 400);
dirFolder2.add(directionalLight.position, "z", -400, 400);// 平行光位置
dirFolder.add(directionalLight.position, "x", -400, 400);
dirFolder.add(directionalLight.position, "y", -400, 400);
dirFolder.add(directionalLight.position, "z", -400, 400);
dirFolder.close();

至此可以基本的掌握了 three.js 中基本的用法,本专栏只用来学习交流,最后附上示例代码,详情可参考郭老师的电子书:http://www.webgl3d.cn/
<!-- author: Mr.J -->
<!-- date: 2023-04-12 11:43:45 -->
<!-- description: Vue3+JS代码块模板 -->
<template><div class="container" ref="container"></div>
</template><script setup>import * as THREE from "three";// 轨道import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";import { ref, reactive, onMounted } from "vue";import { GUI } from "three/addons/libs/lil-gui.module.min.js";// 三个必备的参数let scene, camera, renderer, controls, mesh, stats, material;import Stats from "three/addons/libs/stats.module.js";// guiconst gui = new GUI();// 旋转控制let obj = {color: 0x00ffff, // 材质颜色specular: 0xff0000,};const matFolder = gui.addFolder("材质");const ambientFolder = gui.addFolder("环境光");const dirFolder = gui.addFolder("平行光强度");onMounted(() => {// 外层需要获取到dom元素以及浏览器宽高,来对画布设置长宽// clientWidth等同于container.value.clientWidthlet container = document.querySelector(".container");const { clientWidth, clientHeight } = container;console.log(clientHeight);init();render();// 首先需要获取场景,这里公共方法放在init函数中function init() {scene = new THREE.Scene();// 给相机设置一个背景scene.background = new THREE.Color(0xaaaaaa);// 透视投影相机PerspectiveCamera// 支持的参数:fov, aspect, near, farcamera = new THREE.PerspectiveCamera(60,clientWidth / clientHeight,0.001,6000);// 相机坐标camera.position.set(300, 300, 300);// 相机观察目标camera.lookAt(scene.position);// 渲染器renderer = new THREE.WebGLRenderer({antialias: true,});// 渲染多大的地方renderer.setSize(clientWidth, clientHeight);container.appendChild(renderer.domElement);stats = new Stats();container.appendChild(stats.domElement);addBox();console.log("查看当前屏幕设备像素比", window.devicePixelRatio);}function addBox() {// 模型部分// 几何体const geometry = new THREE.BoxGeometry(100, 100, 100);// 材质material = new THREE.MeshPhongMaterial({color: 0x00ffff,transparent: true, //开启透明// opacity: 0.5, //设置透明度// side: THREE.DoubleSide, //两面可见shininess: 500,specular: 0xff0000, //高光部分的颜色});mesh = new THREE.Mesh(geometry, material);mesh.position.set(0, 0, 0);scene.add(mesh);guiFun();}function guiFun() {matFolder.close();matFolder.addColor(obj, "color").onChange(function (value) {material.color.set(value);console.log(material.specular.set(value));});matFolder.addColor(obj, "specular").onChange(function (value) {material.specular.set(value);});/* const obj = {scale: 0,};// 参数3数据类型:对象(下拉菜单)gui.add(obj, "scale", {left: -100,center: 0,right: 100,// 左: -100,//可以用中文// 中: 0,// 右: 100}).name("位置选择").onChange(function (value) {mesh.position.x = value;}); *//* const obj = {bool: false,};// 改变的obj属性数据类型是布尔值,交互界面是单选框gui.add(obj, "bool").name("是否旋转").onChange(function (value) {// 点击单选框,控制台打印obj.bool变化console.log("obj.bool", value);}); */}// 相机控件const control = () => {controls = new OrbitControls(camera, renderer.domElement);controls.addEventListener("change", function () {// 浏览器控制台查看相机位置变化// console.log("camera.position", camera.position);});};control();// 光源const linght = () => {const pointLight = new THREE.PointLight(0xffffff, 1.0);pointLight.position.set(100, 60, 50);ambientFolder.add(pointLight, "intensity", 0, 2);scene.add(pointLight);// 光源辅助观察const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);scene.add(pointLightHelper);const directionalLight = new THREE.DirectionalLight(0xffffff, 1.0);directionalLight.position.set(100, 0, 0);// 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0directionalLight.target = mesh;// 辅助观察const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight,5,0xff0000);// 添加辅助标识scene.add(dirLightHelper);// 添加平行光到场景中scene.add(directionalLight);// 平行光强度dirFolder.add(directionalLight, "intensity", 0, 2);const dirFolder2 = dirFolder.addFolder("位置"); //子菜单的子菜单dirFolder2.close(); //关闭菜单// 平行光位置dirFolder2.add(directionalLight.position, "x", -400, 400);dirFolder2.add(directionalLight.position, "y", -400, 400);dirFolder2.add(directionalLight.position, "z", -400, 400);// 平行光位置dirFolder.add(directionalLight.position, "x", -400, 400); bdirFolder.add(directionalLight.position, "y", -400, 400);dirFolder.add(directionalLight.position, "z", -400, 400);dirFolder.close();};linght();// gui.add(obj, "bool").name("旋转动画");function render() {// if (obj.bool) mesh.rotateY(0.01);renderer.render(scene, camera);requestAnimationFrame(render);}window.addEventListener("resize", () => {// 更新摄像头camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);});/* const obj = {bool: false,};gui.add(obj, "bool").name("旋转动画");const render = () => {if (obj.bool) mesh.rotateY(0.01);renderer.render(scene, camera);requestAnimationFrame(render);};render(); */});
</script><style>.container {width: 100%;height: 100vh;position: relative;z-index: 1;}
</style>
相关文章:
Three——四、几何体、高光网络材质、锯齿模糊以及GUI库的使用
文章: Three——一、初识Three以及基础的前端场景搭建(结尾含源码)Three——二、加强对三维空间的认识Three——三、动画执行、画布大小、渲染帧率和相机适配体验Three——四、几何体、高光网络材质、锯齿模糊以及GUI库的使用Three——五、点线模型对象、三角形概念…...
盲目自学网络安全只会成为脚本小子?
前言:我们来看看怎么学才不会成为脚本小子 目录: 一,怎么入门? 1、Web 安全相关概念(2 周)2、熟悉渗透相关工具(3 周)3、渗透实战操作(5 周)4、关注安全圈动…...
文从字顺|程序员须知,如何编写高质量代码
高质量代码是软件开发中至关重要的一部分。高质量的代码不仅可以提高软件的可维护性和可复用性,还可以增强软件的安全性和稳定性。同时,可以降低软件维护成本,提升开发效率,为用户提供更好的使用体验。 写出高质量代码是每个程序…...
PCIe物理层弹性缓存机制(详细)解析-PCIe专题知识(四)
目录 前言一、简介二、详细解析2.1 实例解析2.2 具体实现过程 三、总结四、其他相关链接1、PCI总线及发展历程总结2、PCIe物理层总结-PCIE专题知识(一)3、PCIe数据链路层图文总结-PCIe专题知识(二)4、PCIe物理层链路训练和初始化总…...
分片上传和断点续传的区别?实现思路是什么?
相同: 分片上传和断点续传都是网络传输中常用的重要技术 不同: 分片上传:将一个大文件切分为多个小文件进行上传。这种方式能够加快上传速度,降低服务器压力,特别适用于大型文件的上传。例如,在云存储系统…...
微前端 qiankun@2.10.5 源码分析(二)
微前端 qiankun2.10.5 源码分析(二) 我们继续上一节的内容。 loadApp 方法 找到 src/loader.ts 文件的第 244 行: export async function loadApp<T extends ObjectType>(app: LoadableApp<T>,configuration: FrameworkConfi…...
08异步请求:何种场景下应该使用异步请求?
异步在计算机科学中早就是一个比较常用的词汇,从操作系统的特性( 并发、共享、虚拟、异步)开始,异步就在处理并发操作中起到很大的作用,不仅如此,在软件层面,异步同样也是解决并发请求的一个关键过程,它可以将瞬时激增的请求进行更加灵活的处理,通过异步请求,客户端可…...
【深度学习 | Transformer】Transformers 教程:pipeline一键预测
文章目录 一、前言二、Computer vision2.1 Image classification2.2 Object detection2.3 Image segmentation2.4 Depth estimation 三、NLP3.1 Text classification3.2 Token classification3.3 Question answering3.4 Summarization3.5 Translation3.6 Language modeling3.6.…...
HTMLCSS
1、HTML 1.1 介绍 HTML 是一门语言,所有的网页都是用HTML 这门语言编写出来的,也就是HTML是用来写网页的,像京东,12306等网站有很多网页。 这些都是网页展示出来的效果。而HTML也有专业的解释 HTML(HyperText Markup Language)…...
【安装Nginx】
Linux上安装Nginx 文章目录 Linux上安装NginxUbuntuCentOS查看已安装的软件 Ubuntu 在 Ubuntu 上安装 Nginx 非常简单。只需按照以下步骤操作: 打开终端,更新软件包索引: sudo apt update安装 Nginx: sudo apt install nginx安…...
VSCode作业1:猜数字游戏和简单计数器(包含完整代码)
目录 猜数字游戏 一、使用‘random’函数获取随机数 二、 分情况讨论输入值大小情况 三、HTML代码 四、CSS样式及运行效果 简单计数器(计时器) 一、使用‘setInterval’函数实现计数效果 二、使用’clearInterval‘函数实现暂停计数和重新计数效果 …...
NANK OE骨传导开放式蓝牙耳机发布,极致体验拉满!
近日,中国专业音频品牌NANK南卡发布了全新一代——骨传导开放式蓝牙耳机NANK OE,耳机采用了传统真无线和骨传导的结合方式,带来更加舒适的佩戴体验和音质升级,同时还支持单双耳自由切换,全新的设计收获了市场的喜爱和认…...
看完这篇文章你就彻底懂啦{保姆级讲解}-----(I.MX6U驱动GPIO中断《包括时钟讲解》) 2023.5.9
目录 前言整体文件结构源码分析(保姆级讲解)中断初始化部分初始化GIC控制器初始化中断向量表设置中断向量表偏移 系统时钟初始化部分使能所有的时钟部分led初始化部分beep初始化部分key初始化部分按键中断初始化部分按键中断服务函数部分 while循环部分 …...
MySql -- 事务
目录 1.概念 2.事务的运用场景 3.事务的四大特点 4.执行事务带来的问题 4.1 脏读 4.2 不可重复度 4.3 幻读 5. MySQL中事务的隔离级别 1.概念 事务就是把若干个独立操作打包成一个整体而诞生的一种功能. 2.事务的运用场景 比如:A——>B 转账500 A的余额-500…...
关于大模型对未来影响的一点看法
人们总是高估了未来一到两年的变化,低估了未来十年的变革。 ---比尔盖茨 近来OpenAI的GPT技术可以说在全球都带来了巨大的影响,也让大家看到了什么叫大力出奇迹。chatGPT和GPT4的能力给了大家很大的震撼,其流畅自如、逻辑清晰、出众的能力&am…...
Android - 约束布局 ConstraintLayout
一、概念 解决布局嵌套过多的问题,采用方向约束的方式对控件进行定位。 二、位置约束 2.1 位置 至少要保证水平和垂直方向都至少有一个约束才能确定控件的位置。 layout_constraintLeft_toLeftOf我的左边,与XXX左边对齐。layout_constraintLeft_toRight…...
Addictive Multiplicative in NN
特征交叉是特征工程中的重要环节,在以表格型(或结构化)数据为输入的建模中起到了很关键的作用。 特征交互的作用,一是尽可能挖掘对目标有效的模式、特征,二是具有较好的可解释性,三是能够将对数据的洞见引…...
LeetCode 1206. 实现跳表
不使用任何库函数,设计一个跳表。 跳表是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树,其功能与性能相当,并且跳表的代码长度相较下更短,其设计思想与链表相似。 例如,一个跳表包…...
离散数学_九章:关系(2)
9.2 n元关系及其应用 1、n元关系,关系的域,关系的阶2、数据库和关系 1. 数据库 2. 主键 3. 复合主键 3、n元关系的运算 1. 选择运算 (Select) 2. 投影运算 (Project) 3. 连接运算 (Join) n元关系:两个以上集合的元素间的关系 1、n元关系…...
[ubuntu][原创]通过apt方式去安装libnccl库
ubuntu18.04版本安装流程: wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/cuda-ubuntu1804.pin sudo mv cuda-ubuntu1804.pin /etc/apt/preferences.d/cuda-repository-pin-600 sudo apt-key adv --fetch-keys https://develo…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
