Java 成功实现通过网址URL截图保存

news2025/2/14 5:14:25

Java 实现通过网址URL截图

    • 1.DjNativeSwing方式 (不好用)
    • 2.phantomjs方式 (截图还是有瑕疵)
    • 3.selenium方式 (满意,成功实现)
      • maven 引入
      • 下载相关浏览器chrome
      • 下载相关浏览器chromedriver驱动
      • 后端代码

1.DjNativeSwing方式 (不好用)

实操 DjNativeSwing 方式 的现象
1.截图效果(非百度网页):有图片,排版正常,但是部分样式丢失(输入框的文字掉下去了)
2.main 方法使用的里面没问题 ,但是springboot项目去启动以后,该方式触发报错
需要在启动类,关闭无头模式
3.本地项目成功实现以后
部署linux系统后,我这一块还是出现了 与“awt .headless”相关的错误
(1)Can’t connect to ll window server using ‘0.g’ as the value of the DISPLAY variable.
要我去配置
JAVA OPTS=-Djava.awt.headless=true
可我本地程序需要关闭才能用,怎么linux上面又让我开启
想了想是不是,打包上我改成本地要开启,结果发布上linux还是不行
耗费太长时间,想了想,截出来的图是有瑕疵问题,索性直接放弃了该方式

参考文章
(1)https://codeleading.com/article/3074321735/
(2)https://blog.51cto.com/binghe001/5243790
(3)https://www.cnblogs.com/lsy-blogs/p/7700564.html
(4)https://blog.csdn.net/ljj9oo9/article/details/8771670

<dependency>
   <groupId>com.hynnet</groupId>
   <artifactId>DJNativeSwing</artifactId>
   <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>com.hynnet</groupId>
    <artifactId>DJNativeSwing-SWT</artifactId>
    <version>1.0.0</version>
</dependency>
        <!--win64-->
        <dependency>
            <groupId>org.eclipse.swt</groupId>
            <artifactId>org.eclipse.swt.win32.win32.x86_64</artifactId>
            <version>4.3</version>
        </dependency>
        <!--linux-->
<!--        <dependency>-->
<!--            <groupId>org.eclipse.swt</groupId>-->
<!--            <artifactId>org.eclipse.swt.gtk.linux.x86_64</artifactId>-->
<!--            <version>4.3</version>-->
<!--            <scope>provided</scope>-->
<!--        </dependency>-->
import chrriis.dj.nativeswing.swtimpl.NativeComponent;
import chrriis.dj.nativeswing.swtimpl.NativeInterface;
import chrriis.dj.nativeswing.swtimpl.components.JWebBrowser;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserAdapter;
import chrriis.dj.nativeswing.swtimpl.components.WebBrowserEvent;
import com.linewell.gov.hoox.utils.log.LogUtil;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;

/**
 * Created with CosmosRay
 * 条件:需要给启动类,关闭无头模式,
 * 缺陷:部分网址,截图样式部分还是有问题
 * @author CosmosRay
 * @date 2019/5/22
 * Function:
 */
public class DjNativeSwingUtil extends JPanel {
    // 行分隔符
    final static public String LS = System.getProperty("line.separator", "\n");
    // 文件分割符
    final static public String FS = System.getProperty("file.separator", "\\");
    // 以javascript脚本获得网页全屏后大小
    private static final long serialVersionUID = 1L;
    private static final StringBuffer jsDimension;

    static {
        jsDimension = new StringBuffer();
        jsDimension.append("var width = 0;").append(LS);
        jsDimension.append("var height = 0;").append(LS);
        jsDimension.append("if(document.documentElement) {").append(LS);
        jsDimension.append("  width = Math.max(width, document.documentElement.scrollWidth);").append(LS);
        jsDimension.append("  height = Math.max(height, document.documentElement.scrollHeight);").append(LS);
        jsDimension.append("}").append(LS);
        jsDimension.append("if(self.innerWidth) {").append(LS);
        jsDimension.append("  width = Math.max(width, self.innerWidth);").append(LS);
        jsDimension.append("  height = Math.max(height, self.innerHeight);").append(LS);
        jsDimension.append("}").append(LS);
        jsDimension.append("if(document.body.scrollWidth) {").append(LS);
        jsDimension.append("  width = Math.max(width, document.body.scrollWidth);").append(LS);
        jsDimension.append("  height = Math.max(height, document.body.scrollHeight);").append(LS);
        jsDimension.append("}").append(LS);
        jsDimension.append("return width + ':' + height;");
    }

    public DjNativeSwingUtil( String url, String token, String fileName, int maxWidth,  int maxHeight) {
        super(new BorderLayout());
        //面板
        LogUtil.info("DjNativeSwingUtil-面板进入");
        JPanel webBrowserPanel = new JPanel(new BorderLayout());
        final JWebBrowser webBrowser = new JWebBrowser(null);
        webBrowser.setBarsVisible(false);
        //设置cooker
        webBrowser.setCookie(url, "token=" + token);
        webBrowser.navigate(url);
        webBrowserPanel.add(webBrowser, BorderLayout.CENTER);
        add(webBrowserPanel, BorderLayout.CENTER);

        JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 4, 4));

        webBrowser.addWebBrowserListener(new WebBrowserAdapter() {
                                             // 监听加载进度
                                             @Override
                                             public void loadingProgressChanged(WebBrowserEvent e) {
                                                 // 当加载完毕时
                                                 if (e.getWebBrowser().getLoadingProgress() == 100) {
                                                     /*睡眠3秒钟,等待页面请求完毕再截取图片信息
                                                      * 如果不延时,则图片等可能没有时间下载显示
                                                      * 具体的秒数需要根据网速等调整
                                                      * */
                                                     try {
                                                         Thread.sleep(3000);
                                                     } catch (InterruptedException e1) {
                                                         e1.printStackTrace();
                                                     }
                                                     String result = (String) webBrowser.executeJavascriptWithResult(jsDimension.toString());
                                                     int index = result == null ? -1 : result.indexOf(":");
                                                     NativeComponent nativeComponent = webBrowser.getNativeComponent();
                                                     Dimension originalSize = nativeComponent.getSize();
                                                     Dimension imageSize = new Dimension(Integer.parseInt(result.substring(0, index)), Integer.parseInt(result
                                                             .substring(index + 1)));
//                                                     imageSize.width = Math.max(originalSize.width, imageSize.width + 50);
//                                                     imageSize.height = Math.max(originalSize.height, imageSize.height + 50);
                                                     imageSize.width = maxWidth;
                                                     imageSize.height = maxHeight;

                                                     nativeComponent.setSize(imageSize);
                                                     BufferedImage image = new BufferedImage(imageSize.width,
                                                             imageSize.height, BufferedImage.TYPE_INT_RGB);
                                                     nativeComponent.paintComponent(image);
                                                     nativeComponent.setSize(originalSize);
                                                     try {
                                                         // 输出图像
                                                         System.out.println(fileName);
                                                         ImageIO.write(image, "png", new File(fileName));
                                                     } catch (IOException ex) {
                                                         ex.printStackTrace();
                                                     }
                                                     // 退出操作 (会把整个springboot项目都杀掉)
                                                     //System.exit(0);
                                                 }
                                             }
                                         }
        );
        add(panel, BorderLayout.SOUTH);
    }

    public static void main(String[] args) {
        NativeInterface.open();
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                // SWT组件转Swing组件,不初始化父窗体将无法启动webBrowser
                javax.swing.JFrame frame = new javax.swing.JFrame("以DJ组件保存指定网页截图");
                // 加载google,最大保存为640x480的截图
                //实际项目中传入URL参数,根据不同参数截取不同网页快照,保存地址也可以在构造器中多设置一个参数,保存到指定目录
                frame.getContentPane().add(new DjNativeSwingUtil(
                        "https://www.baidu.com",
                        null,
                        "D:\\" + System.currentTimeMillis() + ".png",
                        1800, 1300
                ), BorderLayout.CENTER);
                frame.setSize(2200, 1800);

                // 仅初始化,但不显示
                frame.invalidate();
                frame.pack();
                //隐藏并释放内存,并不一定结束整个应用程序
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                //将窗口隐藏(但窗口的相关资源仍然存在)
                frame.setVisible(false);
            }
        });
        NativeInterface.runEventPump();
    }
}

2.phantomjs方式 (截图还是有瑕疵)

实操 phantomjs 方式 的现象
截图效果(非百度网页):有图片,排版稍微有点问题,样式正常,但是有些文字居然少了一截
虽然不用搞什么“无头”模式子类的了,但是我看到本地截图效果还是选择放弃使用这种方式

PlantomJs是一个基于javascript的webkit内核无头浏览器 也就是没有显示界面的浏览器,你可以在基于 webkit 浏览器做的事情,它都能做到。PlantomJs提供了如 CSS 选择器、DOM操作、JSON、HTML5、Canvas、SVG 等。
PhantomJS 的用处很广泛,如网络监控、网页截屏、页面访问自动化、无需浏览器的 Web 测试等,这里只用到网页截屏。
PlantomJs可以通过官网下载http://phantomjs.org/download.html,
也可以通过(只有windows版本):https://pan.baidu.com/s/1EVX1RPX7gY0rGvEI6OHcwg 密码:brb4 下载;解压后可以看到

参考链接
(1)Java实现网页截屏功能(基于phantomJs)https://www.cnblogs.com/han108/p/9216583.html#:~:text=var%20page%20%3D%20require%20%28%27webpage%27%29.create%20%28%29%2C%20system%20%3D,%28output%29%3B%20phantom.exit%20%28%29%3B%20%7D%2C%20200%29%3B%20%7D%20%7D%29%3B%20%7D
(2)完美解决java截图网页并保存到数据库中预览
https://blog.csdn.net/qq_43665446/article/details/129312799?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3-129312799-blog-37992055.235%5Ev38%5Epc_relevant_anti_vip&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-3-129312799-blog-37992055.235%5Ev38%5Epc_relevant_anti_vip&utm_relevant_index=4
(3)phantom添加cookie
https://www.ngui.cc/el/2578032.html?action=onClick
(4)使用phantomjs对网页截图
https://blog.csdn.net/FreemanZhao/article/details/77498749
(5)selenium+phantomjs截长图踩坑
https://blog.csdn.net/u014307117/article/details/108187245

下载好后的“D:\phantomjs-2.1.1-windows”文件夹里面的 “examples”文件夹里面有个rasterize.js文件,用下面这个内容替代掉即可

rasterize.js
如果要加cookie,要特别注意"domain"这个值是必传且不能随便乱传,和你要截图的地址相关,不然会报错的

var page = require('webpage').create(),
    system = require('system'),
    address, output, size;

//可以带cookie
//var flag = phantom.addCookie({
//        "domain": ".baidu.com" ,
//        "expires": "Fri, 01 Jan 2038 00:00:00 GMT",
//        "expiry": 2145916800,
//        "httponly": false,
//        "name": "token",
//        "path": "/",
//        "secure": false,
//        "value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiJud19kemdkIiwiRXhwaXJlIjoiMjAyMy0wOC0xMCAxNDoyMzo0NyJ9.InsFJkcXI6C57r-1Oqb7PMn-OcP9k0W5lf1K896EasY"
//});

if (system.args.length < 3 || system.args.length > 5) {
    phantom.exit(1);
} else {
    address = system.args[1];//传入url地址
    output = system.args[2];//输出图片的地址
    page.viewportSize = { width: 800, height: 1800 };//自定义定义宽高
    if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
        size = system.args[3].split('*');
        page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
                                           : { format: system.args[3], orientation: 'portrait', margin: '1cm' };
    } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
        size = system.args[3].split('*');
        if (size.length === 2) {
            pageWidth = parseInt(size[0], 10);
            pageHeight = parseInt(size[1], 10);
            page.viewportSize = { width: pageWidth, height: pageHeight };
            page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };
        } else {
            console.log("size:", system.args[3]);
            pageWidth = parseInt(system.args[3], 10);
            pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
            console.log ("pageHeight:",pageHeight);
            page.viewportSize = { width: pageWidth, height: pageHeight };
        }
    }
    if (system.args.length > 4) {
        page.zoomFactor = system.args[4];
    }
    page.open(address, function (status) {
        if (status !== 'success') {
            console.log('Unable to load the address!');
            phantom.exit(1);
        } else {
            window.setTimeout(function () {
                page.render(output);
                phantom.exit();
            }, 3000);
        }
    });
}

address = system.args[1];//传入url地址
output = system.args[2];//输出图片的地址
page.viewportSize = { width: 2000, height: 1300 };//自定义定义宽高

后端代码

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Scanner;

/**
 * @Description:根据网页地址转换成图片
 * @Author: admin
 *  条件:需要插件及js脚本
 *  缺陷:部分网址,截图样式部分还是有问题
 * @CreateDate: 2018年6月22日
 */
public class PhantomTools {
    private static String tempPath = "D:/temp/img";// 图片保存目录
    private static String BLANK = " ";
    // 下面内容可以在配置文件中配置
    private static String binPath = "D:\\phantomjs-2.1.1-windows\\bin\\phantomjs.exe";// 插件引入地址
    private static String jsPath = "D:\\phantomjs-2.1.1-windows\\examples\\rasterize.js";// js引入地址

    private static String cookie = "token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWQiOiJud19kemdkIiwiRXhwaXJlIjoiMjAyMy0wOC0xMCAxMzoxMTozMCJ9.IbO0oobfU5GTURuTnc7NyfnbMN-lkXalNEafDPXyzWE";// token

    // 执行cmd命令
    public static String cmd(String imgagePath, String url) {
        return binPath + BLANK + jsPath + BLANK + url + BLANK + imgagePath;
    }
    //关闭命令
    public static void close(Process process, BufferedReader bufferedReader) throws IOException {
        if (bufferedReader != null) {
            bufferedReader.close();
        }
        if (process != null) {
            process.destroy();
            process = null;
        }
    }
    /**
     * @param
     * @param url
     * @throws IOException
     */
    public static void printUrlScreen2jpg(String url) throws IOException{
        String imgagePath = tempPath+"/"+System.currentTimeMillis()+".png";//图片路径
        //Java中使用Runtime和Process类运行外部程序
        Process process = Runtime.getRuntime().exec(cmd(imgagePath,url));
        InputStream inputStream = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String tmp = "";
        while ((tmp = reader.readLine()) != null) {
            close(process,reader);
        }
        System.out.println("success");
    }

    public static void main(String[] args) throws IOException {
        String url = "https://www.baidu.com/";//以百度网站首页为例
        PhantomTools.printUrlScreen2jpg(url);
    }
}

3.selenium方式 (满意,成功实现)

实操 selenium 方式 的现象
截图效果(非百度网页):有图片,排版没问题,样式没问题
经测试决定使用它了

参考链接
(1)Java 实现通过网址URL截取整个网页的长图并保存(遇到的各种坑)
https://blog.csdn.net/Mli_Mi/article/details/116259669
(2)selenium+phantomjs截长图踩坑
https://blog.csdn.net/u014307117/article/details/108187245
(3)如何在linux系统执行java项目+selenium
https://blog.csdn.net/weixin_42736075/article/details/113444305?spm=1001.2014.3001.5506

maven 引入

1.请注意自己的项目里面是不是存在其他的“com.google.guava”版本,如果有请排除(全部排除),不然会出现所谓的
“com.google.common.util.concurrent.SimpleTimeLimiter.create(Ljava/util/concurrent/ExecutorService;)Lcom/google/common/util/concurrent/SimpleTimeLimiter;”
2.以下我选择的依赖版本是和后面的“浏览器版本”及“驱动版本”息息相关,
高版本亦或者低版本都可能会出现运行失败的现象

<!--自动化测试工具,需要去其他网址下第三方包-->
<dependency>
  <groupId>org.seleniumhq.selenium</groupId>
  <artifactId>selenium-java</artifactId>
  <version>3.141.59</version>
   <exclusions>
    <exclusion>
     <artifactId>guava</artifactId>
     <groupId>com.google.guava</groupId>
    </exclusion>
   </exclusions>
  </dependency>
  <dependency>
  <groupId>com.google.guava</groupId>
   <artifactId>guava</artifactId>
    <version>23.0</version>
    </dependency>
   <dependency>
   <groupId>com.google.code.gson</groupId>
     <artifactId>gson</artifactId>
    <version>2.8.2</version>
  </dependency>

下载相关浏览器chrome

我这边下载的是98.0.4758.102版本的浏览器(最新版本不容易配置)

(windows)https://www.chromedownloads.net/chrome64win/
在这里插入图片描述

(linux)https://www.chromedownloads.net/chrome64linux/
在这里插入图片描述

下载相关浏览器chromedriver驱动

我这边下载的也是98.0.4758.102版本
https://registry.npmmirror.com/binary.html?path=chromedriver/98.0.4758.102/
在这里插入图片描述

liunx服务器上面的安装相应的浏览器的执行命令

先cmd到你创建的目录下面,把linux版本chrome浏览器安装包移到下面,以上链接下载下来解压以后里面有两个版本的(rpm包和deb包)
rpm包相对来说版本不是最新的,但是比较稳定;
而deb包则相对来说版本比较新,一般某个新软件出来说可能有deb包,但是使用过程中容易引起bugs。
所以只留rpm包即可,放到linux的上面去

执行命令
cd到你放那个包的位置,然后执行安装命令

yum install 98.0.4758.102-google-chrome-stable_current_x86_64.rpm

后面会出现选择,输入“y” 确认安装即可

在这里插入图片描述

对于驱动文件也需要执行一下“可执行、读取”的命令

cd /usr/local/xxxx/ChromeDriver/chromedriver_linux64
chmod a+x chromedriver

再下载字体包,如果部分字体还是有问题,就需要去找字体包了
(我这边都是正常的字体,就没有去找其他的字体包了)

yum install mesa-libOSMesa-devel gnu-free-sans-fonts wqy-zenhei-fonts

后端代码

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.epoint.third.apache.commons.io.FileUtils;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;

import java.io.File;
import java.sql.Timestamp;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * 条件:需要谷歌浏览器版本和驱动版本一张
 */
public class SeleniumTools {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        Timestamp now1 = new Timestamp(startTime);
        System.out.println("now1:" + now1);
        for (int i = 0; i < 1; i++) {
            guge("D:/guge/img"+"/"+System.currentTimeMillis()+".png",
                    "https://mpage.taobao.com/hd/download.html",
                    "123");
        }
        long between = DateUtil.between(new Date(startTime), new Date(), DateUnit.SECOND);
        System.out.println("相差秒"+between);
        System.out.println("相差分钟"+between/60);


    }


    //解决如下: 模拟浏览器滚动滚动条 解决懒加载问题
    public static void guge(String hzdtpwzPath, String url, String nhhzdtoken) {
        LogUtil.info("=====guge=========");
        LogUtil.info(hzdtpwzPath);
        LogUtil.info(url);
        LogUtil.info(nhhzdtoken);
        // 根据系统来添加不同的驱动路径
        String os = System.getProperty("os.name");
        LogUtil.info(os);
        if (StrUtil.containsIgnoreCase(os, "Windows")) {
            //这里设置下载的驱动路径,Windows对应chromedriver.exe Linux对应chromedriver,具体路径看你把驱动放在哪
            System.setProperty("webdriver.chrome.driver", "D:\\chromedriver_win32 (98.0.4758.102)\\chromedriver.exe");
        } else {
            // 只考虑Linux环境,需要下载对应版本的驱动后放置在绝对路径/usr/bin目录下
            System.setProperty("webdriver.chrome.driver", "/usr/local/xxxx/ChromeDriver/chromedriver_linux64/chromedriver");
        }
        ChromeOptions options = new ChromeOptions();
        //ssl证书支持
        options.setCapability("acceptSslCerts", true);
        //截屏支持
        options.setCapability("takesScreenshot", true);
        //css搜索支持
        options.setCapability("cssSelectorsEnabled", true);
        //设置浏览器参数
        // 设置无轨 开发时还是不要加,可以看到浏览器效果
        options.addArguments("--headless");
        options.addArguments("--no-sandbox");
        options.addArguments("--disable-gpu");
        options.addArguments("--disable-dev-shm-usage");
        //设置无头模式,一定要设置headless,否则只能截出电脑屏幕大小的图!!!
        options.setHeadless(true);
        ChromeDriver driver = new ChromeDriver(options);
        //设置超时,避免有些内容加载过慢导致截不到图
        driver.manage().timeouts().pageLoadTimeout(1, TimeUnit.MINUTES);
        driver.manage().timeouts().implicitlyWait(1, TimeUnit.MINUTES);
        driver.manage().timeouts().setScriptTimeout(1, TimeUnit.MINUTES);
        try {
            //设置需要访问的地址
            driver.get(url);
            //先登录,再设置cookies
            Cookie c1 = new Cookie("token", nhhzdtoken);
            driver.manage().addCookie(c1);
            //设置需要访问的地址
            driver.get(url);
            //获取高度和宽度一定要在设置URL之后,不然会导致获取不到页面真实的宽高;
            Long width = (Long) driver.executeScript("return document.documentElement.scrollWidth");
            Long height = (Long) driver.executeScript("return document.documentElement.scrollHeight");
            // 通过执行脚本解决Selenium截图不全问题
            //Long width = (Long) driver.executeScript(
            //        "return Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);");
            //Long height = (Long) driver.executeScript(
            //        "return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);");
            System.out.println("宽带:" + width);
            System.out.println("高度:" + height);
            //这里需要模拟滑动,有些是滑动的时候才加在的
            long temp_height = 0;
            while (true) {
                //每次滚动500个像素,因为懒加载所以每次等待2S 具体时间可以根据具体业务场景去设置
                Thread.sleep(1000);
                driver.executeScript("window.scrollBy(0,500)");
                temp_height += 500;
                if (temp_height >= height) {
                    break;
                }
            }
            //设置窗口宽高,设置后才能截全
            //后面都加了相应固定值,是业务需求
            driver.manage().window().setSize(new Dimension(width.intValue()+1120, height.intValue()+303));
            //设置截图文件保存的路径
            String screenshotPath = hzdtpwzPath;
            File srcFile = driver.getScreenshotAs(OutputType.FILE);
            FileUtils.copyFile(srcFile, new File(screenshotPath));
        } catch (Exception e) {
            throw new RuntimeException("截图失败", e);
        } finally {
            driver.quit();
        }
    }

}

大功搞成了

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

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

相关文章

一文搞懂STP(从原理到配置)

一、STP出现的背景 1. 单点故障 如图9-1所示&#xff0c;PC1和PC2通过LSW1相互通信&#xff0c;如果LSW1出现了故障&#xff0c;那么PC1和PC2将不能相互通信&#xff0c;这种现象我们称之为单点故障。为了解决这个问题&#xff0c;我们提出了冗余的拓扑结构。 图9-1单点故障 …

【数据结构】单链表OJ题(一)

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;数据结构 &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、移除链表元素 &#x1f4a1;方法一&#xff1a; &#x1f4a1;方法二…

安卓如何快速定位native内存泄露。

步骤1&#xff09;cat /proc/pid/status,观察下面俩个指标 RssAnon: 5300 kB //一直增大说明匿名映射的内存增大&#xff0c;malloc本质就是调用匿名映射分 配内存 RssFile: 26884 kB //文件句柄泄露&#…

JMeter 的并发设置教程

JMeter 是一个功能强大的性能测试工具&#xff0c;可以模拟许多用户同时访问应用程序的情况。在使用 JMeter 进行性能测试时&#xff0c;设置并发是非常重要的。本文将介绍如何在 JMeter 中设置并发和查看报告。 设置并发 并发是在线程组下的线程属性中设置的。 线程数&#…

谈一谈在两个商业项目中使用MVI架构后的感悟

作者&#xff1a;leobertlan 前言 当时项目采用MVP分层设计&#xff0c;组员的代码风格差异也较大&#xff0c;代码中类职责赋予与封装风格各成一套&#xff0c;随着业务急速膨胀&#xff0c;代码越发混乱。试图用 MVI架构 单向流 形成 掣肘 带来一致风格。 但这种做法不够以…

一文带你快速掌握如何在Windows系统和Linux系统中安装部署MongoDB

文章目录 前言一、 Windows系统中的安装启动1. 下载安装包2. 解压安装启动3. Shell连接(mongo命令)4. Compass-图形化界面客户端 二、 Linux系统中的安装启动和连接1. 下载安装包2. 解压安装3. 新建并修改配置文件4. 启动MongoDB服务5. 关闭MongoDB服务 总结 前言 为了巩固所学…

Spring Boot对接Oracle数据库

Spring Boot对接Oracle数据库 最近学习了Oracle数据库&#xff0c;那么如何使用Spring Boot和MyBatis Plus对接Oracle数据库呢&#xff1f; 这就有了这篇随记&#xff0c;具体流程如下 1、创建Maven工程 创建一个空的Maven工程&#xff0c;导入如下依赖&#xff1a; <?…

Dubbo1-架构的演变

分布式系统上的相关概念 项目&#xff1a;传统项目、互联网项目 传统项目&#xff1a; 一般为公司内部使用&#xff0c;或者小群体小范围的使用&#xff0c;一般不要求性能&#xff0c;美观&#xff0c;并发等 互联网项目的特点&#xff1a; 1.用户多 2.流量大&#xff0c;并…

第二章:CSS基础进阶-part2:CSS过渡与动画

文章目录 CSS3 过渡动画一、transition属性二、transform属性-2D变换2.1 tanslate &#xff1a; 移动2.2 rotate-旋转2.3 scale-变形2.4 skew-斜切2.5 transform-origin: 变换中心点设置 三、CSS3关键帧动画四、CSS3-3D变换4.1 perspective 定义3D元素距视图距离4.2 transform-…

@Autowired和@Resource注解超详细总结(附代码)

区别 1、来源不同 Autowired 和 Resource 注解来自不同的“父类”&#xff0c;其中Autowired注解是 Spring 定义的注解&#xff0c;而Resource 注解是 Java 定义的注解&#xff0c;它来自于 JSR-250&#xff08;Java 250 规范提案&#xff09;。 2、支持的参数不同 Autowir…

openeuler服务器 ls 和ll 命令报错 command not found...

在openeuler服务器执行 ls 和ll 命令报错 command not found... 大概是系统环境变量导致的问题。 我在安装redis是否没有安装成功后就出现了这样的情况。编辑profile文件没有写正确&#xff0c;导致在命令行下ls 和 ll 等命令不能够识别。 重新设置一下环境变量。 export PAT…

Dynamo_关于参数赋值

写写关于Dynamo参数赋值 为单个对象赋单个参数值 最容易理解&#xff0c;SetParameterByName需要输入三个参数&#xff0c;元素对象&#xff08;数据类型&#xff1a;Element&#xff09;&#xff0c;参数名称&#xff08;数据类型&#xff1a;String&#xff09;&#xff0c;…

Glide 的超时控制相关处理

作者&#xff1a;newki 前言 Glide 相信大家都不陌生&#xff0c;各种源码分析&#xff0c;使用介绍大家应该都是烂熟于心。但是设置 Glide 的超时问题大家遇到过没有。 我遇到了&#xff0c;并且掉坑里了&#xff0c;情况是这样的。 调用接口从网络拉取用户头像&#xff0c…

SSH隧道搭建简单使用

参考&#xff1a; https://www.zsythink.net/archives/2450 https://luckyfuture.top/ssh-tunnel#SSH%E9%9A%A7%E9%81%93 https://zhuanlan.zhihu.com/p/561589204?utm_id0 SSH隧道&#xff08;搭建SSH隧道绕过防火墙&#xff09;&#xff1a; ssh命令除了登陆外还有代理转发…

ASL国产CS5212规格书 DP转VGA 替代RTD2166低成本方案 兼容IT6516设计原理图

CS5212可替代兼容瑞昱RTD2166和联阳T6516&#xff0c;ASL集睿致远这款芯片是一种高性能的DP显示端口到VGA转换器芯片。它结合了DisplayPort输入接口和模拟RGB DAC输出接口&#xff0c;嵌入式单片机基于工业标准8051核心。 CS5212适用于多个细分市场和显示器应用程序&#xff1…

YOLOv8 : TAL与Loss计算

YOLOv8 : TAL与Loss计算 1. YOLOv8 Loss计算 YOLOv8从Anchor-Based换成了Anchor-Free&#xff0c;检测头也换成了Decoupled Head&#xff0c;论文和网络资源中有大量的介绍&#xff0c;本文不做过多的概述。 Decoupled Head具有提高收敛速度的好处&#xff0c;但另一方面讲&am…

华为OD机试真题 Java 实现【城市聚集度】【2023 B卷 200分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…

Linux网络服务之DNS域名解析

重要的DNS域名解析 一、DNS概述1.1 DNS简介1.2 本地hosts文件1.3 DNS架构1.4 查询方式 二、DNS域名解析原理2.1 解析类型2.2 原理详解2.3 举例 三、bind服务端程序3.1 什么是bind&#xff1f;3.2 配置文件详解3.2.1 主配置文件概述及内容主要格式3.2.2 域名文件概述及内容主要格…

leetcode118. 119.杨辉三角

118 题目&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 思路&#xff1a; 可以发现从第三行开始&#xff0c;从第二个元素到倒数第二个元素&#xff0c;每个元素都…

电视盒子什么品牌好?实测20天后分享电视盒子推荐

电视盒子可以让老旧电视机重生&#xff0c;解决卡顿、资源少等问题&#xff0c;只需要联网就能观看海量视频资源。不过对于电视盒子如何选购很多人并不了解&#xff0c;我通过对比十几款主流电视盒子后整理了这份电视盒子推荐清单&#xff0c;跟着我一起看看电视盒子什么品牌好…