自定义复杂图片水印
我的社交能力还不如5岁儿童和狗。
文章目录
- 前言
- 一、主要工具类
- 总结
前言
之前写过一些简单的图片压缩和图片加水印:JAVA实现图片质量压缩和加水印
本次主要是针对图片加水印进行一个升级,图片水印自定义,自适应大小。
来,先看几张不同分辨率的图片加过水印的效果
分辨率:1702 x 1276

分辨率:4000 x 3000

分辨率:1080 x 1440

其实大家看右下角,csdn自动给我图片加的水印就能发现,4000*3000的图片几乎都看不到右下角的水印,说明他这个水印不是自适应的。但是我左下角加的,三张图片都是这么大,根据图片自动变化大小。
提示:以下是本篇文章正文内容,下面案例可供参考
一、主要工具类
其中主要是进行了坐标点的计算,通过拼接计算来确定各个水印的坐标点,从而进行绘制。
其中进行了一部分封装
/*** 添加图片文字水印(此方法不在考虑文字过长需要换行等情况)** @param targetImg 原图片路径,需要是本地路径,如是网络url需要单独更改* @param x 水印x轴坐标* @param y 水印y轴坐标* @param fontSize 水印文字大小 英镑,会根据图片分辨率自动放大和缩小,只需要指定标准350像素的文字标准值即可* @param c 水印文字颜色 例如:Color.WHITE* @param fontName 水印文字字体 例如:宋体,微软雅黑* @param fontStyle 水印文字字体风格,例如:Font.PLAIN正常字体/BOLD加粗/ITALIC斜体.* @param alpha 水印文字透明度,例如: 1.0F,范围 0-1F* @param text 水印文字*/public static void pressText(String targetImg, int x, int y, int fontSize, Color c, String fontName, int fontStyle, float alpha, String text) {try {// 读取原图片BufferedImage src = ImageIO.read(new File(targetImg));// 获取原图的宽和高int width = src.getWidth(null);int height = src.getHeight(null);// 动态设置字体大小fontSize = width < height ? width / 350 * fontSize : height / 350 * fontSize;// 创建空图片,指定宽高BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 准备绘制图片Graphics2D g = image.createGraphics();// 将原图绘制到此空图片上,左上角为坐标起点,(0,0),宽和高为原图大小g.drawImage(src, 0, 0, width, height, null);// 设置水印字体颜色.g.setColor(c);// 设置水印字体,Font.PLAIN正常字体/BOLD加粗/ITALIC斜体.g.setFont(new Font(fontName, fontStyle, fontSize));// 透明度g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));/* 消除java.awt.Font字体的锯齿 */g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);// 添加文字水印g.drawString(text, x, y);// 输出图像g.dispose();File f = new File(targetImg);// 将加过水印的图片保存到指定文件ImageIO.write(image, targetImg.substring(targetImg.lastIndexOf(".") + 1), f);} catch (Exception e) {log.error("水印添加失败:{}", e.getMessage());}}
中间还有一部分的坐标点计算,感觉写的有点乱了,没有梳理好,仅供参考。
下面是整个工具类的代码:
package com.example.demo.util;import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.Week;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONObject;
import lombok.extern.slf4j.Slf4j;import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Date;/*** @author GMaya* @create 2023/2/22 9:44* @Description 类描述: 图片相关的工具类*/
@Slf4j
public class ImageUtils {/*** 图片加水印** @param json 相关设置* @param targetImg 要加水印的图片路径* @param staticUrl 静态地址*/public static void pressTexts(JSONObject json, String targetImg, String staticUrl) {try {long l = System.currentTimeMillis();// 读取原图片,获取宽度和高度 TODO 使用BufferedImage中没有exif信息,导致有exif的图片宽和高会读取错误,需要进行修正。目前本地图片修正暂时没有处理。线上图片来源为阿里oss,在链接后拼接自动修正参数即可:?x-oss-process=image/auto-orient,1
// String uuu = "https://xxx-dev.oss-cn-shanghai.aliyuncs.com/upload/123123/aa/20230223/b811b496cff29f02f0fa5a994c66867e.jpg";
// String uuu = "https://xxx-dev.oss-cn-shanghai.aliyuncs.com/upload/123123/aa/20230223/b811b496cff29f02f0fa5a994c66867e.jpg?x-oss-process=image/auto-orient,1";
// URL url = new URL(uuu);
// BufferedImage src = ImgUtil.read(url);BufferedImage src = ImgUtil.read(targetImg);int width = src.getWidth(null);int height = src.getHeight(null);log.info("原图宽:{},高:{}",width,height);// 动态设置字体大小 , 以350像素9的基数大小设置int fontSize = width < height ? width / 350 * 9 : height / 350 * 9;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g = image.createGraphics();// 将原图绘制g.drawImage(src, 0, 0, width, height, null);// 设置水印字体颜色.g.setColor(Color.WHITE);// 设置水印字体,Font.PLAIN正常字体/BOLD加粗/ITALIC斜体.g.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));// 透明度
// g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.9f));// 消除java.awt.Font字体的锯齿g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);// 比例int rat = width < height ? width / 350 : height / 350;BufferedImage readAddress = ImgUtil.read(staticUrl + "address.png");BufferedImage readUserName = ImgUtil.read(staticUrl + "userName.png");BufferedImage readCompanyName = ImgUtil.read(staticUrl + "companyName.png");BufferedImage readFloor = ImgUtil.read(staticUrl + "floor.png");int imageWidth = rat * 6;int imageHeight = rat * 7;// 计算各个坐标点int xx1 = 0; // 姓名图标int yy1 = 0; // 姓名图标int xx2 = 0; // 姓名int yy2 = 0; // 姓名int xx3 = 0; // 公司图标int yy3 = 0; // 公司图标int xx4 = 0; // 公司int yy4 = 0; // 公司int xx5 = 0; // 地址图标int yy5 = 0; // 地址图标int xx6 = 0; // 地址int yy6 = 0; // 地址int xx7 = 0; // 左侧竖线int yy7 = 0; // 左侧竖线int xx8 = 0; // 拍照标签int yy8 = 0; // 拍照标签int xx9 = 0; // logo图标int yy9 = 0; // logo图标int xx10 = 32; // 年月日坐标int yy10 = 0; // 年月日坐标int xx11 = 32; // 时分秒坐标int yy11 = 0; // 时分秒坐标int w12 = 0; // 底板宽 底板坐标点无需计算,但是底板的宽高需要计算int h12 = 0; // 底板高int sd = 0; // 标准差// 公共坐标计算点 xx为图标,xxx为文字int xx = 0;int yy = 0;int xxx = 0;int yyy = 0;// 提前计算出各个坐标点for (int i = 0; i < 7; i++) {if (i == 0) {// 用户名称String userNameIsShow = json.getStr("userNameIsShow");if ("0".equals(userNameIsShow)) {// x轴默认距离左边16*比例xx1 = 10 * rat;yy1 = height - (10 * rat) - imageHeight;xx = xx1;yy = yy1;xx2 = 10 * rat + imageWidth + (4 * rat);yy2 = height - (10 * rat);xxx = xx2;yyy = yy2;}continue;}if (i == 1) {// 公司名称String companyNameIsShow = json.getStr("companyNameIsShow");if ("0".equals(companyNameIsShow)) {// 如果公司展示,则需要判断上一个用户字段是否展示,如果展示和不展示,x,y轴坐标将不一样if (xx == 0) {xx3 = 10 * rat;yy3 = height - (10 * rat) - imageHeight;xx = xx3;yy = yy3;xx4 = 10 * rat + imageWidth + (4 * rat);yy4 = height - (10 * rat);xxx = xx4;yyy = yy4;} else {xx3 = xx;yy3 = yy - (5 * rat) - imageHeight;yy = yy3;xx4 = xxx;yy4 = yyy - (5 * rat) - fontSize;yyy = yy4;}}continue;}if (i == 2) {// 全部默认0是,1否String addressIsShow = json.getStr("addressIsShow");if ("0".equals(addressIsShow)) {// 此处定义最高位置的地址即可,换行的在真正生成时进行处理String address = json.getStr("address");int maxLength = 13;// 计算出地址的占用行数int i2 = address.length() / maxLength + (address.length() % maxLength == 0 ? 0 : 1);if (xx == 0) {// 公司和姓名都不展示xx5 = 10 * rat;yy5 = height - 12 - (fontSize * i2);xx6 = 10 * rat + imageWidth + 10;yy6 = height - (12 * (i2 + 1)) - (fontSize * (i2 + 1));xxx = xx6;yyy = yy6;continue;} else {xx5 = xx;yy5 = yy - 12 - (fontSize * i2);yy = yy5;xx6 = xxx;yy6 = yyy - (12 * (i2 + 1)) - (fontSize * (i2 + 1));yyy = yy6;}}}if (i == 5) {// 时间控制String timeIsShow = json.getStr("timeIsShow");if ("0".equals(timeIsShow)) {xx10 = xx;xx11 = xx;if (xx == 0) {yy10 = height - (10 * rat);yy11 = yy10 - fontSize - 8 * rat;}else{yy10 = yyy - (8 * rat);yy11 = yy10 - fontSize - 8 * rat;}yyy = yy11;yy = yy11;}continue;}if (i == 6) {// 计算地图蒙版,需要在所有坐标计算后,在计算地图大小// 缩放比例int i1 = width < height ? width / 350 : height / 350;w12 = readFloor.getWidth() * i1 / 3 * 2 ;String timeIsShow = json.getStr("timeIsShow");if ("0".equals(timeIsShow)) {h12 = height - yyy + (i1 * 18);continue;}String addressIsShow = json.getStr("addressIsShow");String companyNameIsShow = json.getStr("companyNameIsShow");String userNameIsShow = json.getStr("userNameIsShow");if("0".equals(addressIsShow) || "0".equals(companyNameIsShow) ||"0".equals(userNameIsShow)){h12 = height - yyy - 6 + 30;}System.out.println(h12);continue;}}for (int i = 0; i < 6; i++) {if (i == 1) {// 优先绘制底板String addressIsShow = json.getStr("addressIsShow");String companyNameIsShow = json.getStr("companyNameIsShow");String userNameIsShow = json.getStr("userNameIsShow");String timeIsShow = json.getStr("timeIsShow");if (!"0".equals(addressIsShow) && !"0".equals(companyNameIsShow) && !"0".equals(userNameIsShow) &&!"0".equals(timeIsShow)) {// 如果所有的都关闭,则无需添加底板和水印,直接跳出循环,结束水印绘制。break;}g.drawImage(readFloor, 6 * rat, height - h12, w12, h12 - 6 * rat, null);continue;}if (i == 2) {// 全部默认0是,1否String userNameIsShow = json.getStr("userNameIsShow");if ("0".equals(userNameIsShow)) {String userName = json.getStr("userName");g.drawImage(readUserName, xx1, yy1,imageWidth,imageHeight, null);g.drawString(userName, xx2, yy2);}continue;}if (i == 3) {// 全部默认0是,1否String companyNameIsShow = json.getStr("companyNameIsShow");if ("0".equals(companyNameIsShow)) {String companyName = json.getStr("companyName");g.drawImage(readCompanyName, xx3, yy3,imageWidth,imageHeight, null);g.drawString(companyName, xx4, yy4);}continue;}if (i == 4) {// 全部默认0是,1否String addressIsShow = json.getStr("addressIsShow");if ("0".equals(addressIsShow)) {String address = json.getStr("address");int maxLength = 13;// 计算出地址的占用行数int i2 = address.length() / maxLength + (address.length() % maxLength == 0 ? 0 : 1);int len = 0;for (int j = i2 - 1; j >= 0; j--) {int mlen = maxLength * (j + 1);len = j * maxLength;if (mlen < address.length()) {g.drawString(address.substring(len, mlen), xx6, yy6 + (fontSize * (j + 1)));} else {g.drawString(address.substring(len), xx6, yy6 + (fontSize * (j + 1)));}}// 图标g.drawImage(readAddress, xx5, yy5,imageWidth,imageHeight, null);}continue;}}// 输出图像g.dispose();File f = new File(targetImg);ImageIO.write(image, targetImg.substring(targetImg.lastIndexOf(".") + 1), f);// 如果年月日展示,则进行坐标计算String timeIsShow = json.getStr("timeIsShow");if ("0".equals(timeIsShow)) {String s = DateUtil.formatDate(new Date());Week week = DateUtil.dayOfWeekEnum(new Date());// 文字水印为:2023-02-22 星期三pressText(targetImg, xx10, yy10, 12, Color.WHITE, "微软雅黑", Font.PLAIN, 0.9F, s + " " + week.toChinese());String time = DateUtil.format(new Date(), "HH:mm:ss");pressText(targetImg, xx11, yy11, 18, Color.WHITE, "微软雅黑", Font.BOLD, 0.9F, time);}//花费毫秒数long ll = System.currentTimeMillis();log.info("图片加水印耗时:{}{}", ll - l, "ms");} catch (Exception e) {e.printStackTrace();}}/*** 添加图片文字水印(此方法不在考虑文字过长需要换行等情况)** @param targetImg 原图片路径,需要是本地路径,如是网络url需要单独更改* @param x 水印x轴坐标* @param y 水印y轴坐标* @param fontSize 水印文字大小 英镑,会根据图片分辨率自动放大和缩小,只需要指定标准350像素的文字标准值即可* @param c 水印文字颜色 例如:Color.WHITE* @param fontName 水印文字字体 例如:宋体,微软雅黑* @param fontStyle 水印文字字体风格,例如:Font.PLAIN正常字体/BOLD加粗/ITALIC斜体.* @param alpha 水印文字透明度,例如: 1.0F,范围 0-1F* @param text 水印文字*/public static void pressText(String targetImg, int x, int y, int fontSize, Color c, String fontName, int fontStyle, float alpha, String text) {try {// 读取原图片BufferedImage src = ImageIO.read(new File(targetImg));// 获取原图的宽和高int width = src.getWidth(null);int height = src.getHeight(null);// 动态设置字体大小fontSize = width < height ? width / 350 * fontSize : height / 350 * fontSize;// 创建空图片,指定宽高BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);// 准备绘制图片Graphics2D g = image.createGraphics();// 将原图绘制到此空图片上,左上角为坐标起点,(0,0),宽和高为原图大小g.drawImage(src, 0, 0, width, height, null);// 设置水印字体颜色.g.setColor(c);// 设置水印字体,Font.PLAIN正常字体/BOLD加粗/ITALIC斜体.g.setFont(new Font(fontName, fontStyle, fontSize));// 透明度g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));/* 消除java.awt.Font字体的锯齿 */g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,RenderingHints.VALUE_FRACTIONALMETRICS_ON);// 添加文字水印g.drawString(text, x, y);// 输出图像g.dispose();File f = new File(targetImg);// 将加过水印的图片保存到指定文件ImageIO.write(image, targetImg.substring(targetImg.lastIndexOf(".") + 1), f);} catch (Exception e) {log.error("水印添加失败:{}", e.getMessage());}}/*** 计算文字长度,一个中文按两个长度,英文按一个长度计算** @param text 文字* @return*/public static int getLength(String text) {int length = 0;for (int i = 0; i < text.length(); i++) {if (new String(text.charAt(i) + "").getBytes().length > 1) {length += 2;} else {length += 1;}}return length / 2;}/*** 导出zip压缩包** @param srcPath 要压缩的文件夹路径* @param response 输出流*/public static void downloadZip(String srcPath, HttpServletResponse response) {// 将此目录打包成zipFile file = ZipUtil.zip(srcPath);OutputStream toClient = null;try {// 以流的形式下载文件。BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));byte[] buffer = new byte[fis.available()];fis.read(buffer);fis.close();// 清空responseresponse.reset();toClient = new BufferedOutputStream(response.getOutputStream());response.setCharacterEncoding("UTF-8");response.setContentType("application/zip");response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());toClient.write(buffer);toClient.flush();} catch (Exception e) {log.error("下载zip压缩包过程发生异常:", e);} finally {if (toClient != null) {try {toClient.close();} catch (IOException e) {log.error("zip包下载关流失败:", e);}}//删除改临时zip包(此zip包任何时候都不需要保留,因为源文件随时可以再次进行压缩生成zip包)file.delete();}}}
总结
其中,通过ImageIO.read读取的图片,是没有exif信息的,这样就会导致有exif的图片,读取后宽和高可能不准确,最终生成的图片就是未旋转的,看起来就是颠倒的。如果有谁有办法处理本地图片exif问题,可以回复下。
让我学习学习。
如果使用的是阿里云oss地址,在后面拼接参数即可:
例如:
String uuu = "https://xxx-dev.oss-cn-shanghai.aliyuncs.com/upload/123123/aa/20230223/b811b496cff29f02f0fa5a994c66867e.jpg";
String uuu = "https://xxx-dev.oss-cn-shanghai.aliyuncs.com/upload/123123/aa/20230223/b811b496cff29f02f0fa5a994c66867e.jpg?x-oss-process=image/auto-orient,1";
在oss地址后面拼接?x-oss-process=image/auto-orient,1 即可。阿里云oss自适应传送门
相关文章:
自定义复杂图片水印
我的社交能力还不如5岁儿童和狗。 文章目录前言一、主要工具类总结前言 之前写过一些简单的图片压缩和图片加水印:JAVA实现图片质量压缩和加水印 本次主要是针对图片加水印进行一个升级,图片水印自定义,自适应大小。 来,先看几…...
文章读后感——《人间清醒,内容为王》
观后感 人间清醒,内容为王 - 技术er究竟该如何写博客?1024上海嘉年华之敖丙演讲观后感。 致敬愿意带领后生的前辈——哈哥 哈哥,《人间清醒,内容为王》这篇,我的鱼获, 是里面传递出来写技术博客的思维与想法…...
51单片机入门 - 驱动多位数码管
我使用的是普中51单片机开发板A2套件(2022),驱动数码管可能需要参考电路原理图。开发环境的搭建教程在本专栏的 51单片机开发环境搭建 - VS Code 从编写到烧录 有过介绍。 关于我的软硬件环境信息: Windows 10STC89C52RCSDCC &am…...
Java进击框架:Spring(一)
Java进击框架:Spring(一)前言创建Spring项目Spring IoC容器和Beans介绍Bean的概述Spring IoC配置元数据实例化Bean依赖注入循环依赖详细配置生命周期回调Bean定义继承基于注解的容器配置Component和进一步的原型注解自动检测类和注册Bean定义…...
Java笔记(18)
目录 什么是mvc? 什么是SpringMVC Spring MVC的特点: 原理: 什么是Thymeleaf? thymeleaf依赖包:...
【免费教程】地下水环境监测技术规范HJ/T164-2020解读使用教程
地下水环境监测技术规范依据《中华人民共和国环境保护法》第十一条“国务院环境保护行政主管部门建立监测制度、制订监测规范”和《中华人民共和国水污染防治法》的要求,积极开展地下水环境监测,掌握地下水环境质量,保护地下水水质࿰…...
Html 代码学习
场景:在页面中插入音频 代码 常见属性: src 音频的路径 controls 显示播放的控件 autoplay 自动播放 loop 循环播放 场景:在页面中插入视频 代码 常见属性: src 路径 controls 显示播放的控件 autoplay 自动播放 要配合muted 例如 autoplay muted loop 循环播放 链接 /…...
如何通过IP找到地址?
在我们印象中,我们都知道可以通过 IP 地址找到某个人。但当我们细想一下,我们会发现其实 IP 地址与地理位置并不是直接相关的。那我们到底是如何通过 IP 地址找到地址的呢?答案是:通过自治系统(Autonomous System&…...
业务单据堆积如山?如何提升会计做账效率?
某集团以“创建现代能源体系、提高人民生活品质”为使命,形成了贯通下游分销、中游贸易储运、上游生产的清洁能源产业链和涵盖健康、文化、旅游、置业的生命健康产品链。目前,某集团在全国21个省,为超过2681万个家庭用户、21万家企业提供能源…...
华为OD机试题,用 Java 解【VLAN 资源池】问题
最近更新的博客 华为OD机试 - 猴子爬山 | 机试题算法思路 【2023】华为OD机试 - 分糖果(Java) | 机试题算法思路 【2023】华为OD机试 - 非严格递增连续数字序列 | 机试题算法思路 【2023】华为OD机试 - 消消乐游戏(Java) | 机试题算法思路 【2023】华为OD机试 - 组成最大数…...
面试加分项:JVM 锁优化和逃逸分析详解
1 锁优化JVM 在加锁的过程中,会采用自旋、自适应、锁消除、锁粗化等优化手段来提升代码执行效率。1.1 自旋锁和自适应自旋现在大多的处理器都是多核处理器 ,如果在多核心处理器,有让两个或者以上的线程并行执行,我们可以让一个等待…...
C++继承、构造函数和析构函数
构造函数 与 析构函数 构造函数代表一个对象的生成,主要作用是初始化类的成员变量,可以被重载 如果没有显式构造函数,则实例化对象时,系统会自动生成一个无参的构造函数 构造函数的名称与类名相同 析构函数代表的是一个对象的销…...
Python如何实现异步并发之async(1)
前言 本文是该专栏的第14篇,后面会持续分享python的各种干货知识,值得关注。 在python中使用async方式,实现异步并发,而本文笔者提到的代码案例仅支持python3.7及以上版本,这主要在于不同的版本之间都更新了异步的使用方法,这点暂时不详述了。 而所谓的异步,通常就是程…...
震撼!阿里首次开源 Java 10万字题库,Github仅一天星标就超60K
程序员面试 现在是程序员找工作、跳槽最重要的月份。随着行业的发展程序员面试也越来越难,面试中都是7分的能力,再加上3分的技巧; 对于应聘者,重中之重的就是简历,面试前一定要将最拿手和最能吸引面试官的技能在简历…...
十三、RESTful API
RESTful API 什么是RESTful REST一词,是Roy Thomas Fielding在他2000年的博士论文中提出的。 Fielding是一个非常重要的人,他是HTTP协议(1.0版和1.1版)的主要设计者、Apache服务器软件的作者之一、Apache基金会的第一任主席。所…...
路由器防火墙配置(14)
实验目的 通过本实验,理解路由器的防火墙工作原理,掌握路由器的防火墙功能配置方法,主要包括网络地址转换功能和数据包过滤功能的配置。 培养根据具体环境与实际需求进行网络地址转换及数据包过滤的能力。 预备知识网络地址转换 网络地址转…...
灰狼算法优化VMD对时序信号分析python
VMD算法变分模态分解(VMD)算法是一种根据变分方程计算,将信号分析过程转换成求解变分方程的过程,具体分析过程可见前面写的另外一篇博客VMD,这里不多介绍。 VMD算法在进行信号分析时,将一段时序信号分解成不同频段的几个子信号,但其分解效果的好坏由其两个参数影响较大—…...
微服务架构中的多级缓存设计还有人不懂?
今天我们来聊聊缓存这个话题,看看在微服务环境下如何设计有效的多级缓存架构。主要涉及三方面内容: Web 应用的客户端缓存;应用层静态资源缓存;服务层多级缓存。 首先,咱们先讲解微服务架构的多级缓存设计。 微服务…...
【图神经网络 医学/药物/目标/分子/(结构/相互作用)预测】用于药物-目标相互作用预测的元集合(Metapath)异构图神经网络(MHGNN)
May the immensity of the universe, guide us to meet again. 我个人觉得这篇Paper很好。哈哈! 本次学习的Paper于2023年1月15日索引于 Web of Science,是比较新的。 作者:中国天津,南开大学计算机科学学院。 本篇Paper的研究方向(类别/分类):生物化学 & 分子生物学…...
《Java核心技术》笔记——第六章
文章目录CH6.接口、lambda表达式与内部类1.接口基本2.常用接口3.lambda表达式4.内部类5.服务加载器与代理前章: 第三章~第五章的学习笔记CH6.接口、lambda表达式与内部类 1.接口基本 接口基本——interface声明,方法无需指明public(默认都是…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误
HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误,它们的含义、原因和解决方法都有显著区别。以下是详细对比: 1. HTTP 406 (Not Acceptable) 含义: 客户端请求的内容类型与服务器支持的内容类型不匹…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
