二维码初体验 com.google.zxing 实现续 - web api封装

文章目录

  • 一、概述
  • 二、最终效果
  • 三、源码结构
  • 四、完整代码

一、概述

在 二维码初体验 com.google.zxing 实现 我们实现了二维码的生成,但是大部分情况下,二维码的相关功能是作为API接口来提供服务的。

我们下面便演示在springboot、Knife4j下封装api接口来实现二维码生成功能。

二、最终效果

在这里插入图片描述

三、源码结构

在这里插入图片描述

四、完整代码

如何使用下面的备份文件恢复成原始的项目代码,请移步查阅:神奇代码恢复工具
dog.jpg 在这里插入图片描述

//goto pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.fly</groupId>
	<artifactId>qrcode-web</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
		<relativePath />
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!-- Compile -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
		</dependency>
		<dependency>
			<groupId>com.github.xiaoymin</groupId>
			<artifactId>knife4j-spring-boot-starter</artifactId>
			<version>2.0.8</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>com.google.zxing</groupId>
			<artifactId>core</artifactId>
			<version>3.4.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

		<!-- 异步日志,需要加入disruptor依赖 -->
		<dependency>
			<groupId>com.lmax</groupId>
			<artifactId>disruptor</artifactId>
			<version>3.4.2</version>
		</dependency>
	</dependencies>
	<build>
		<finalName>${project.artifactId}-${project.version}</finalName>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-surefire-plugin</artifactId>
				<configuration>
					<useSystemClassLoader>false</useSystemClassLoader>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
//goto src\main\java\com\fly\core\config\Knife4jConfig.java
package com.fly.core.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;

import io.swagger.annotations.ApiOperation;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

/**
 * knife4j
 *
 * @author jack
 */
@EnableKnife4j
@Configuration
@EnableSwagger2WebMvc
@Import(BeanValidatorPluginsConfiguration.class)
public class Knife4jConfig
{
    @Value("${knife4j.enable: true}")
    private boolean enable;
    
    @Bean
    Docket defaultApi()
    {
        return new Docket(DocumentationType.SWAGGER_2).enable(enable).apiInfo(apiInfo()).groupName("0.1版").select().apis(RequestHandlerSelectors.basePackage("com.fly.qrcode.api"))
            .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) // 同时满足apis多个条件
            .paths(PathSelectors.any())
            .build();
    }
    
    private ApiInfo apiInfo()
    {
        return new ApiInfoBuilder().title("数据接口API").description("接口文档").termsOfServiceUrl("http://00fly.online/").version("1.0.0").build();
    }
}
//goto src\main\java\com\fly\core\utils\SpringContextUtils.java
package com.fly.core.utils;

import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.servlet.ServletContext;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import lombok.extern.slf4j.Slf4j;

/**
 * Spring Context 工具类
 * 
 * @author 00fly
 *
 */
@Slf4j
@Component
public class SpringContextUtils implements ApplicationContextAware
{
    private static ApplicationContext applicationContext;
    
    /**
     * web服务器基准URL
     */
    private static String SERVER_BASE_URL = null;
    
    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException
    {
        log.info("###### execute setApplicationContext ######");
        SpringContextUtils.applicationContext = applicationContext;
    }
    
    public static ApplicationContext getApplicationContext()
    {
        return applicationContext;
    }
    
    public static <T> T getBean(Class<T> clazz)
    {
        Assert.notNull(applicationContext, "applicationContext is null");
        return applicationContext.getBean(clazz);
    }
    
    /**
     * execute @PostConstruct May be SpringContextUtils not inited, throw NullPointerException
     * 
     * @return
     */
    public static String getActiveProfile()
    {
        Assert.notNull(applicationContext, "applicationContext is null");
        String[] profiles = applicationContext.getEnvironment().getActiveProfiles();
        return StringUtils.join(profiles, ",");
    }
    
    /**
     * can use in @PostConstruct
     * 
     * @param context
     * @return
     */
    public static String getActiveProfile(ApplicationContext context)
    {
        Assert.notNull(context, "context is null");
        String[] profiles = context.getEnvironment().getActiveProfiles();
        return StringUtils.join(profiles, ",");
    }
    
    /**
     * get web服务基准地址,一般为 http://${ip}:${port}/${contentPath}
     * 
     * @return
     * @throws UnknownHostException
     * @see [类、类#方法、类#成员]
     */
    public static String getServerBaseURL()
        throws UnknownHostException
    {
        if (SERVER_BASE_URL == null)
        {
            ServletContext servletContext = getBean(ServletContext.class);
            Assert.notNull(servletContext, "servletContext is null");
            String ip = InetAddress.getLocalHost().getHostAddress();
            SERVER_BASE_URL = "http://" + ip + ":" + getProperty("server.port") + servletContext.getContextPath();
        }
        return SERVER_BASE_URL;
    }
    
    /**
     * getProperty
     * 
     * @param key eg:server.port
     * @return
     * @see [类、类#方法、类#成员]
     */
    public static String getProperty(String key)
    {
        return applicationContext.getEnvironment().getProperty(key, "");
    }
}
//goto src\main\java\com\fly\qrcode\api\ApiController.java
package com.fly.qrcode.api;

import java.awt.image.BufferedImage;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;

import com.fly.qrcode.qr.QRCodeUtil;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;

/**
 * 
 * QR
 * 
 * @author 00fly
 * @version [版本号, 2021年4月14日]
 * @see [相关类/方法]
 * @since [产品/模块版本]
 */
@Controller
@Api(tags = "二维码API接口")
public class ApiController
{
    @ApiOperation("生成二维码")
    @ApiImplicitParam(name = "content", value = "二维码文本", required = true, example = "乡愁是一棵没有年轮的树,永不老去")
    @PostMapping(value = "/create", produces = MediaType.IMAGE_JPEG_VALUE)
    public void index(String content, HttpServletResponse response)
        throws Exception
    {
        if (StringUtils.isNotBlank(content))
        {
            Resource resource = new ClassPathResource("qrCode/dog.jpg");
            URL imgURL = resource.getURL();
            BufferedImage image = QRCodeUtil.createImage(content, imgURL, true);
            
            // 输出图象到页面
            ImageIO.write(image, "JPEG", response.getOutputStream());
        }
    }
}
//goto src\main\java\com\fly\qrcode\qr\BufferedImageLuminanceSource.java
package com.fly.qrcode.qr;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

import com.google.zxing.LuminanceSource;

public class BufferedImageLuminanceSource extends LuminanceSource
{
    private BufferedImage image;
    
    private int left;
    
    private int top;
    
    public BufferedImageLuminanceSource(BufferedImage image)
    {
        this(image, 0, 0, image.getWidth(), image.getHeight());
    }
    
    public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height)
    {
        super(width, height);
        
        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        if (left + width > sourceWidth || top + height > sourceHeight)
        {
            throw new IllegalArgumentException("Crop rectangle does not fit within image data.");
        }
        
        for (int y = top; y < top + height; y++)
        {
            for (int x = left; x < left + width; x++)
            {
                if ((image.getRGB(x, y) & 0xFF000000) == 0)
                {
                    image.setRGB(x, y, 0xFFFFFFFF);
                }
            }
        }
        
        this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);
        this.image.getGraphics().drawImage(image, 0, 0, null);
        this.left = left;
        this.top = top;
    }
    
    @Override
    public byte[] getRow(int y, byte[] row)
    {
        if (y < 0 || y >= getHeight())
        {
            throw new IllegalArgumentException("Requested row is outside the image: " + y);
        }
        int width = getWidth();
        if (row == null || row.length < width)
        {
            row = new byte[width];
        }
        image.getRaster().getDataElements(left, top + y, width, 1, row);
        return row;
    }
    
    @Override
    public byte[] getMatrix()
    {
        int width = getWidth();
        int height = getHeight();
        int area = width * height;
        byte[] matrix = new byte[area];
        image.getRaster().getDataElements(left, top, width, height, matrix);
        return matrix;
    }
    
    @Override
    public boolean isCropSupported()
    {
        return true;
    }
    
    @Override
    public LuminanceSource crop(int left, int top, int width, int height)
    {
        return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);
    }
    
    @Override
    public boolean isRotateSupported()
    {
        return true;
    }
    
    @Override
    public LuminanceSource rotateCounterClockwise()
    {
        int sourceWidth = image.getWidth();
        int sourceHeight = image.getHeight();
        AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0, 0.0, sourceWidth);
        BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D g = rotatedImage.createGraphics();
        g.drawImage(image, transform, null);
        g.dispose();
        int width = getWidth();
        return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);
    }
}
//goto src\main\java\com\fly\qrcode\qr\QRCodeUtil.java
package com.fly.qrcode.qr;

import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.URL;
import java.util.Hashtable;

import javax.imageio.ImageIO;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

public class QRCodeUtil
{
    private static final String CHARSET = "utf-8";
    
    /**
     * 二维码尺寸
     */
    private static final int QRCODE_SIZE = 300;
    
    /**
     * LOGO宽度
     */
    private static final int WIDTH = 60;
    
    /**
     * LOGO高度
     */
    private static final int HEIGHT = 60;
    
    /**
     * 给定内容、图标生成二维码图片
     * 
     * @param content 內容
     * @param imgURL 图标
     * @param needCompress 是否压缩尺寸
     * @return
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    public static BufferedImage createImage(String content, URL imgURL, boolean needCompress)
        throws Exception
    {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        if (imgURL == null)
        {
            return image;
        }
        // 插入图片
        insertImage(image, imgURL, needCompress);
        return image;
    }
    
    private static void insertImage(BufferedImage source, URL imgURL, boolean needCompress)
        throws Exception
    {
        if (imgURL == null)
        {
            System.err.println("文件不存在!");
            return;
        }
        Image src = ImageIO.read(imgURL);
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        if (needCompress)
        {
            // 压缩LOGO
            width = Math.min(width, WIDTH);
            height = Math.min(height, HEIGHT);
            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null);
            g.dispose();
            src = image;
        }
        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        int x = (QRCODE_SIZE - width) / 2;
        int y = (QRCODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }
    
    /**
     * 解析二维码图
     * 
     * @param file
     * @return
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    public static String decode(File file)
        throws Exception
    {
        BufferedImage image = ImageIO.read(file);
        if (image == null)
        {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Hashtable<DecodeHintType, String> hints = new Hashtable<>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        Result result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }
    
    /**
     * 解析二维码图
     * 
     * @param path
     * @return
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    public static String decode(String path)
        throws Exception
    {
        return decode(new File(path));
    }
}
//goto src\main\java\com\fly\QrCodeApplication.java
package com.fly;

import java.io.IOException;

import org.apache.commons.lang3.SystemUtils;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.fly.core.utils.SpringContextUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@SpringBootApplication
public class QrCodeApplication implements CommandLineRunner
{
    public static void main(String[] args)
    {
        SpringApplication.run(QrCodeApplication.class, args);
    }
    
    @Override
    public void run(String... args)
        throws IOException
    {
        if (SystemUtils.IS_OS_WINDOWS)
        {
            log.info("★★★★★★★★  now open Browser ★★★★★★★★ ");
            String url = SpringContextUtils.getServerBaseURL();
            Runtime.getRuntime().exec("cmd /c start /min " + url + "/doc.html");
        }
    }
}
//goto src\main\resources\application.yml
server:
  port: 8080
  servlet:
    context-path: /
    session:
      timeout: 1800
spring:
  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
//goto src\main\resources\log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="off">
	<!-- 日志文件目录和压缩文件 -->
	<Properties>
		<Property name="fileName">../logs/hello</Property>
		<Property name="fileGz">../logs/hello/7z</Property>
	</Properties>
	<Appenders>
		<!--这个输出控制台的配置 -->
		<Console name="console" target="SYSTEM_OUT">
			<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
			<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="NEUTRAL" />
			<!--输出日志的格式 -->
			<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} %L %M - %msg%xEx%n" />
		</Console>

		<!--这个会打印出所有的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档 -->
		<RollingRandomAccessFile name="rollingInfoFile" fileName="${fileName}/springboot-info.log" immediateFlush="false"
			filePattern="${fileGz}/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.springboot-info.gz">
			<PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} [%t] %-5level %logger{36} %L %M - %msg%xEx%n" />
			<Policies>
				<TimeBasedTriggeringPolicy interval="6" modulate="true" />
				<SizeBasedTriggeringPolicy size="50 MB" />
			</Policies>
			<Filters>
				<!-- 只记录info级别信息 -->
				<ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL" />
				<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" />
			</Filters>
			<!-- 指定每天的最大压缩包个数,默认7个,超过了会覆盖之前的 -->
			<DefaultRolloverStrategy max="50" />
		</RollingRandomAccessFile>


		<RollingRandomAccessFile name="rollingErrorFile" fileName="${fileName}/springboot-error.log" immediateFlush="false"
			filePattern="${fileGz}/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.springboot-error.gz">
			<PatternLayout pattern="%d{yyyy-MM-dd 'at' HH:mm:ss z} [%t] %-5level %logger{36} %L %M - %msg%xEx%n" />
			<Policies>
				<TimeBasedTriggeringPolicy interval="6" modulate="true" />
				<SizeBasedTriggeringPolicy size="50 MB" />
			</Policies>
			<Filters>
				<!-- 只记录error级别信息 -->
				<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY" />
			</Filters>
			<!-- 指定每天的最大压缩包个数,默认7个,超过了会覆盖之前的 -->
			<DefaultRolloverStrategy max="50" />
		</RollingRandomAccessFile>

	</Appenders>

	<Loggers>
		<!-- 全局配置,默认所有的Logger都继承此配置 -->
		<AsyncRoot level="INFO" additivity="false">
			<AppenderRef ref="console" />
			<AppenderRef ref="rollingInfoFile" />
			<AppenderRef ref="rollingErrorFile" />
		</AsyncRoot>
	</Loggers>
</Configuration>


有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【小沐学Python】Python实现Web服务器(aiohttp)

文章目录 1、简介2、下载和安装3、代码测试3.1 客户端3.2 服务端 4、更多测试4.1 asyncio4.2 aiohttpHTTP服务器4.3 aiohttp爬虫实例4.4 aiohttprequests比较 结语 1、简介 https://github.com/aio-libs/aiohttp https://docs.aiohttp.org/en/stable/index.html Asynchronous …

C/C++图型化编程

一、创建图形化窗口&#xff1a; 1.包含头文件&#xff1a; graphics.h:包含已经被淘汰的函数easyx.h:只包含最新的函数 2.两个函数就可以创建窗口&#xff1a; 打开&#xff1a;initgraph(int x,int y,int style);关闭&#xff1a;closegraph(); 3.窗口坐标的设置&#…

【眼镜】相关知识

眼镜相关 配眼镜可以事先了解的事情&#xff1a; 折射率&#xff1a;先说结论&#xff0c;高度数可以考虑选高折射率&#xff0c;低度数没必要。 折射率&#xff1a;1.50折射率 1.56折射率 1.60折射率 1.67折射率 1.71折射率 1.74折射率. 折射率越高&#xff0c;镜片越薄&a…

全面理解Stable Diffusion采样器

全面理解Stable Diffusion采样器 原文&#xff1a;Stable Diffusion Samplers: A Comprehensive Guide 在 AUTOMATIC1111 的 SD webui 中&#xff0c;有许多采样器&#xff08;sampler&#xff09;&#xff0c;如 Euler a&#xff0c;Heun&#xff0c;DDIM&#xff0c;… 什么是…

应急响应中的溯源方法

在发现有入侵者后&#xff0c;快速由守转攻&#xff0c;进行精准地溯源反制&#xff0c;收集攻击路径和攻击者身份信息&#xff0c;勾勒出完整的攻击者画像。 对内溯源与对内溯源 对内溯源&#xff1a;确认攻击者的行为 &#xff0c;分析日志 数据包等&#xff1b; 对外溯源&…

图像随机裁剪代码实现

原理 在计算机视觉领域&#xff0c;深度学习模型通常需要大量的训练数据才能获得良好的性能。然而&#xff0c;在实际应用中&#xff0c;我们可能面临训练数据不足的问题。为了解决这一问题&#xff0c;可以使用数据增强技术来扩充数据集。随机图像裁剪是其中一种简单而有效的…

系列十四、SpringBoot + JVM参数配置实战调优

一、SpringBoot JVM参数配置实战调优 1.1、概述 前面的系列文章大篇幅的讲述了JVM的内存结构以及各种参数&#xff0c;今天就使用SpringBoot项目实战演示一下&#xff0c;如何进行JVM参数调优&#xff0c;如果没有阅读过前面系列文章的朋友&#xff0c;建议先阅读后再看本篇文…

Windows系统安装 ffmpeg

下载及解压 ffmpeg官方下载地址&#xff1a;https://ffmpeg.org/download.html 下载好后将其解压至你想保存的位置中。 环境变量设置 打开Windows设置&#xff0c;在搜索框输入&#xff1a;系统高级设置。 新建环境变量&#xff0c;并输入bin目录具体位置。 安装检查 按住 w…

人工智能:从基础到前沿

人工智能&#xff1a;从基础到前沿 引言 当我们谈论“人工智能”&#xff08;AI&#xff09;时&#xff0c;我们其实是在谈论一个涵盖了众多学科、技术和应用的广阔领域。从计算机视觉到自然语言处理&#xff0c;从机器人学到深度学习&#xff0c;AI已经成为我们生活中不可或…

电脑上添加不了网络打印机的所有可能的原因,在这里差不多都能找到

在电脑上添加网络打印机通常很容易,但如果Windows无法很好识别或根本找不到它们呢?以下是一些快速解决方案。 无论你是升级到Windows 11还是仍在使用Windows 10,连接无线打印机都应该很容易。Windows应该能够自动连接到与你的电脑位于同一网络上的任何打印机。但有时,Windo…

大数据Doris(四十):聚合模型的局限性和ROLLUP的说明

文章目录 聚合模型的局限性和ROLLUP的说明 一、聚合模型的局限性

linux内存寻址原来那么简单

内存寻址 内存寻址听起来高大上&#xff0c;其实真实处理起来很简单&#xff0c;以常见的80x86架构为例&#xff0c;有三种不同的地址&#xff1a; 逻辑地址线性地址物理地址 内存控制单元(MMU)通过分段单元的硬件电路把一个逻辑地址转化为线性地址&#xff0c;通过分页单元的…

单例模式(C++实现)

RAII运用 只能在栈上创建对象 只能在堆上创建的对象 单例模式 设计模式 懒汉模式 解决线程安全 优化 饿汉模式 饿汉和懒汉的区别

Vue3学习(后端开发)

目录 一、安装Node.js 二、创建Vue3工程 三、用VSCode打开 四、源代码目录src 五、入门案例——手写src 六、测试案例 七、ref和reactive的区别 一、安装Node.js 下载20.10.0 LTS版本 https://nodejs.org/en 使用node命令检验安装是否成功 node 二、创建Vue3工程 在…

C语言--if...else语句【语法讲解】

一.if...else语句的介绍 if…else 语句是编程中常用的一种分支语句&#xff0c;用于根据条件执行不同的操作。 它的基本语法如下&#xff1a; if (条件表达式) {// 当条件表达式为真时执行的代码块 } else {// 当条件表达式为假时执行的代码块 } 当条件表达式为真时&#xff…

互联网上门洗衣洗鞋小程序优势有哪些?

互联网洗鞋店小程序相较于传统洗鞋方式&#xff0c;具有以下优势&#xff1b; 1. 便捷性&#xff1a;用户只需通过手机即可随时随地下单并查询&#xff0c;省去了许多不必要的时间和精力。学生们无需走出宿舍或校园&#xff0c;就能轻松预约洗鞋并取件。 2. 精准定位&#xff1…

前菜---二叉树+堆的小练习

目录 前言&#x1f3dc;️ 1. 二叉树性质总结⛱️ 1.2 性质3⏰ 2. 二叉树性质小练习&#x1f3d5;️ 3. 答案解析&#x1f4a1; 4. 堆概念结构小练习&#x1fa94; 5. 答案解析&#x1f9ff; 6. 前/中/后/层序遍历小练习&#x1f52b; 7. 答案解析&#x1f9fa; 后语…

祝大家圣诞节快乐

同时庆祝 JWFD 20周年

c++代码寻找USB00端口并添加打印机

USB00*端口的背景 插入USB端口的打印机&#xff0c;安装打印机驱动&#xff0c;在控制面板设备与打印机处的打印机对象上右击&#xff0c;可以看到打印机端口。对于不少型号&#xff0c;这个端口是USB001或USB002之类的。 经观察&#xff0c;这些USB00*端口并不是打印机驱动所…

Seata 序列化问题

异常&#xff1a; com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Type id handling not implemented for type java.lang.Object (by serializer of type com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer) (through reference chain: i…