【保姆级】Java后端查询数据库结果导出xlsx文件+打印xlsx表格

news2024/11/18 10:53:33

目录

    • 前言
    • 一、需求一:数据库查询的数据导出成Excel表格
      • 1.1 Vue前端实现导出按钮+点击事件
      • 1.2 后端根据数据库查询结果生成xlsx文件
    • 二、需求二:对生成的xlsx文件调用打印机打印
      • 2.1 Vue前端实现按钮+事件
      • 2.2 后端实现打印

前言

最近在弄一个需求,需求如下:
需求一:Vue前端点击导出按钮,就可以将从数据库查出的数据导出成xlsx,即Excel表格形式
需求二点击打印按钮,要将生成的xlsx文件启动进程,调用打印接口,实现打印,这是为了生成客户订单表,可以让机器直接打印

PS:想吐槽网上很多都复制粘贴的技术文章,找半天一点卵用都没用,这里记录一下自己解决方案,若转发请注明出处,原创不易,有问题可评论区留言

需求一效果预览
在这里插入图片描述
需求二预览
在这里插入图片描述

一、需求一:数据库查询的数据导出成Excel表格

1.1 Vue前端实现导出按钮+点击事件

<el-button type="success" round icon="el-icon-download" @click="exportByEasyPoi">导出</el-button>

对应按钮点击触发的exportByEasyPoi方法,这里我用的是EasyPoi操作Excel,也挺多公司用的
注:前端是Vue2

<script>
import userApi from '@/api/userManage'
export default {
	methods: {
		exportByEasyPoi() {
      		userApi.exportByEasyPoi().then(response => {
        		this.$message.success('导出成功')
      		})
    	}
	}
}
</script>

这里我调用了src/api/userManage.js,这是自己创建的js脚本,调用后端接口的

import request from '@/utils/request'

export default {
	exportByEasyPoi() {
    return request({
      url: `/user/exportep`,
      method: 'get',
      timeout: '10000'
    })
  }
}

需求一前端就这么多了,接下来就是后端

1.2 后端根据数据库查询结果生成xlsx文件

首先导入EasyPoi相关依赖

<!--easypoi-->
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-spring-boot-starter</artifactId>
    <version>4.3.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-base</artifactId>
    <version>4.3.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-web</artifactId>
    <version>4.3.0</version>
</dependency>
<dependency>
    <groupId>cn.afterturn</groupId>
    <artifactId>easypoi-annotation</artifactId>
    <version>4.3.0</version>
</dependency>
<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.20</version>
</dependency>

下面先给出后端核心逻辑代码,后面会具体讲解,这里就不加篇幅,直接把逻辑代码写在Controller层,原本应该写在Service层,即xxxServiceImpl实现类中,这里为了方便,直接这么写下。

@Autowired
private IUserService userService;

@GetMapping("/exportep")
    public Result<?> exportByEasyPoi(HttpServletResponse response) throws IOException {
    	// mybatisplus实现的list(),拿到用户信息列表
        List<User> users = userService.list();
        List<ExcelUserVo> excelUserVos = BeanCopyUtils.copyBeanList(users, ExcelUserVo.class);
        // easypoi导出
        ExportParams params = new ExportParams();
        params.setTitle("测试");
        // 表格左下角的sheet名称
        params.setSheetName("用户信息");
        Workbook workbook = ExcelExportUtil.exportExcel(params, ExcelUserVo.class, excelUserVos);
        // 判断文件路径是否存在,并将信息写入文件
        try{
            // 文件夹是否存在,若没有对应文件夹直接根据路径生成文件会报错
            File folder = new File(Constants.XLSX_DIR);
            if (!folder.exists() && !folder.isDirectory()) {
                folder.mkdirs();
            }
            // 文件是否存在
            File file = new File(Constants.XLSX_DIR + "\\" + Constants.XLSX_NAME);
            if (!file.exists()){
                file.createNewFile();
            }
            // 输出流写入
            FileOutputStream outputStream = new FileOutputStream(Constants.XLSX_DIR + "\\" + Constants.XLSX_NAME);
            workbook.write(outputStream);
            // 关闭写,不然用户点击生成的文件会显示只读
            outputStream.close();
            workbook.close();
        }catch (IOException e){
            e.printStackTrace();
        }
        return Result.success("导出成功");
    }

ExcelUserVo.java是自己需要显示在表格中的列,就是我们查询用户表,大部分时候不需要展示所有的属性到前端,挑需要显示的,所以封装成xxxVo,比如密码、创建时间、备注可以不显示在前端,不用打印就不要。

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@ExcelTarget("sys_user")
public class ExcelUserVo implements Serializable {

    @Excel(name = "用户id", width = 10)
//    @ExcelIgnore // 表示忽略, 不在表格生成
    private Integer id;

    @Excel(name = "用户名", width = 20)
    private String username;

    @Excel(name = "邮箱", width = 30)
    private String email;

    @Excel(name = "电话", width = 30)
    private String phone;

    @Excel(name = "状态(1:正常,0:禁用)", width = 10)
    private Integer status;
}

BeanCopyUtils.java是常用工具类,可以实现对象的拷贝,将两个对象中相同属性字段拷贝

import java.util.List;
import java.util.stream.Collectors;

public class BeanCopyUtils {
    private BeanCopyUtils() {
    }

    /** 单个对象*/
    public static <V> V copyBean(Object source, Class<V> clazz) {
        /** 创建目标对象 实现属性拷贝*/
        V result = null;
        try {
            result = clazz.newInstance();
            /** 拷贝*/
            BeanUtils.copyProperties(source, result);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    
    /** 集合*/
    public static <O, V> List<V> copyBeanList(List<O> list, Class<V> clazz) {
        /** 创建目标对象 实现属性拷贝*/
        return list.stream()
                .map(o -> copyBean(o, clazz))
                .collect(Collectors.toList());
    }
}

自定义常量Constants.java,这里主要是定义输出路径

public class Constants {

    // excel表
    public static final String XLSX_DIR = "D:\\study\\excel";

    public static final String XLSX_NAME = "easypoi.xlsx";
    
}

数据库sys_user表结构

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL,
  `password` varchar(100) DEFAULT NULL,
  `email` varchar(50) DEFAULT NULL,
  `phone` varchar(20) DEFAULT NULL,
  `status` int(1) DEFAULT NULL,
  `avatar` varchar(200) DEFAULT NULL,
  `deleted` int(1) DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

二、需求二:对生成的xlsx文件调用打印机打印

2.1 Vue前端实现按钮+事件

<el-button type="warning" round icon="el-icon-printer" @click="printExcel">打印</el-button>
methods: {
	printExcel() {
      userApi.printTable().then(response => {
        this.$message.success('请求打印成功')
      })
	}
}

userManage.js中再写一个调用后端接口的

export default {
	printTable() {
	    return request({
	      url: `/user/print`,
	      method: 'get',
	      timeout: '100000'
	    })
	}
}

2.2 后端实现打印

这里也干脆实现逻辑不写在Service层了,省点字,实际开发中还是要遵循规范哈

@GetMapping("/print")
public Result<?> printInfo(){
    try {
    	String filepath = Constants.XLSX_DIR + "\\" + Constants.XLSX_NAME;
        PrintUtil.print(filepath);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return Result.success();
}

核心打印工具PrintUtil.java,这个java文件稍微有点长

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import javax.print.*;
import javax.print.attribute.DocAttributeSet;
import javax.print.attribute.HashDocAttributeSet;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.standard.OrientationRequested;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class PrintUtil {

    /**
     * 竖屏模式
     */
    public static OrientationRequested PORTRAIT = OrientationRequested.PORTRAIT;

    /**
     * 横屏模式
     */
    public static OrientationRequested LANDSCAPE = OrientationRequested.LANDSCAPE;



    /**
     * 获取全部打印设备信息
     * @return 返回全部能用的打印服务的List
     */
    public static List<PrintService> getDeviceList() {
        // 构建打印请求属性集
        HashPrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
        // 设置打印格式,因为未确定类型,所以选择autosense
        DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
        // 查找所有的可用的打印服务
        PrintService printService[] = PrintServiceLookup.lookupPrintServices(flavor, pras);
        List<PrintService> list = Arrays.asList(printService);
        return list;
    }


    /**
     * 根据文件类型不同调用不同代码去打印
     * @param filePath 文件路径
     */
    public static void print(String filePath) throws Exception {
        PrintService printService = PrintServiceLookup.lookupDefaultPrintService();
        String defaultDeviceName = printService.getName();
        print(filePath, defaultDeviceName);
    }

    /**
     * 额外传入一个 AfterPrint,会在打印完成后调用 afterPrint.run()
     * @param filePath
     * @param afterPrint
     * @throws Exception
     */
    public static void print(String filePath, AfterPrint afterPrint) throws Exception {
        print(filePath);
        afterPrint.run();
    }

    /**
     * 根据文件类型不同调用不同代码去打印
     * @param filePath 文件路径
     * @param deviceName 设备名称,传入哪个设备的名称,就让哪个设备去打印
     */
    public static void print(String filePath, String deviceName) throws Exception{
        List<PrintService> list = getDeviceList();
        PrintService printService = null;
        for (PrintService p : list) {
            if(p.getName().equals(deviceName)) {
                printService = p;
                break;
            }
        }
        if(printService == null) {
            throw new Exception("Device not found");
        }
        String type = filePath.replaceAll(".*\\.","");
        if("jpg".equalsIgnoreCase(type)) {
            normalPrint(new File(filePath), DocFlavor.INPUT_STREAM.JPEG, printService);
            return;
        }
        if("jpeg".equalsIgnoreCase(type)) {
            normalPrint(new File(filePath), DocFlavor.INPUT_STREAM.JPEG, printService);
            return;
        }
        if("gif".equalsIgnoreCase(type)) {
            normalPrint(new File(filePath), DocFlavor.INPUT_STREAM.GIF, printService);
            return;
        }
        if("pdf".equalsIgnoreCase(type)) {
            printPDF(new File(filePath), DocFlavor.INPUT_STREAM.PNG, printService);
            return;
        }
        if("png".equalsIgnoreCase(type)) {
            normalPrint(new File(filePath), DocFlavor.INPUT_STREAM.PNG, printService);
            return;
        }
        if("doc".equalsIgnoreCase(type)) {
            printWord(filePath, deviceName);
            return;
        }
        if("docx".equalsIgnoreCase(type)) {
            printWord(filePath, deviceName);
            return;
        }
        if("xls".equalsIgnoreCase(type)) {
            printExcel(filePath, deviceName);
            return;
        }
        if("xlsx".equalsIgnoreCase(type)) {
            printExcel(filePath, deviceName);
            return;
        }
        if("ppt".equalsIgnoreCase(type)) {
            printPPT(filePath, deviceName);
            return;
        }
        if("pptx".equalsIgnoreCase(type)) {
            printPPT(filePath, deviceName);
            return;
        }

    }

    /**
     * 会在打印完成后调用 afterPrint.run()
     * @param filePath
     * @param deviceName
     * @param afterPrint
     * @throws Exception
     */
    public static void print(String filePath, String deviceName, AfterPrint afterPrint) throws Exception{
        print(filePath, deviceName);
        afterPrint.run();
    }


    /**
     * javase的打印机打印文件,支持jpg,png,gif,pdf等等
     * @param file 要打印的文件
     * @param flavor 打印格式
     */
    private static void normalPrint(File file, DocFlavor flavor) {
        // 定位默认的打印服务
        PrintService service = PrintServiceLookup
                .lookupDefaultPrintService();             // 显示打印对话框
        normalPrint(file, flavor, service);
    }


    private static void normalPrint(File file, DocFlavor flavor, PrintService service) {
        normalPrint(file, flavor, PORTRAIT, service);
    }

    /**
     * javase的打印机打印文件,支持jpg,png,gif等等
     * @param file 要打印的文件
     * @param service 打印机选择
     * @param requested 设定横屏还是竖屏
     * @param flavor 打印格式
     */
    private static void normalPrint(File file, DocFlavor flavor, OrientationRequested requested, PrintService service) {
        // 构建打印请求属性集
        HashPrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
        pras.add(requested);
        if (service != null) {
            try {
                DocPrintJob job = service.createPrintJob(); // 创建打印作业
                FileInputStream fis = new FileInputStream(file); // 构造待打印的文件流
                DocAttributeSet das = new HashDocAttributeSet();
                Doc doc = new SimpleDoc(fis, flavor, das);
                job.print(doc, pras);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 打印pdf的方法,因为java内置的打印pdf的方法有病,所以首先需要把pdf转换成png,然后打印png
     * @param file 要打印的文件
     * @param flavor 要打印的文件
     * @param service 打印设备
     */
    private static void printPDF(File file, DocFlavor flavor, PrintService service) {
        try {
            PDDocument doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for(int i=0;i<pageCount;i++){
                File f = new File(file.getParent() + File.separator + "temp_" + i + ".png");
                BufferedImage image = renderer.renderImageWithDPI(i, 96);
                ImageIO.write(image, "PNG", f);
                normalPrint(f, flavor, LANDSCAPE, service);
                f.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 打印机打印Word
     * @param filepath 打印文件路径
     * @param deviceName 传入哪个设备名称,用哪个设备打印
     */
    private static void printWord(String filepath, String deviceName) {
        if(filepath.isEmpty()){
            return;
        }
        ComThread.InitSTA();
        //使用Jacob创建 ActiveX部件对象:
        ActiveXComponent word=new ActiveXComponent("Word.Application");
        //打开Word文档
        Dispatch doc=null;
        Dispatch.put(word, "Visible", new Variant(false));
        word.setProperty("ActivePrinter", new Variant(deviceName));
        Dispatch docs=word.getProperty("Documents").toDispatch();
        doc=Dispatch.call(docs, "Open", filepath).toDispatch();
        try {
            Dispatch.call(doc, "PrintOut");//打印
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            try {
                if(doc!=null){
                    //关闭文档
                    Dispatch.call(doc, "Close",new Variant(0));
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
            word.invoke("Quit", new Variant[] {});//关闭进程
            //释放资源
            ComThread.Release();
        }
    }

    /**
     * 打印Excel
     * @param filePath 打印文件路径,形如 E:\\temp\\tempfile\\1494607000581.xls
     * @param deviceName 传入哪个设备名称,用哪个设备打印
     */
    private static void printExcel(String filePath, String deviceName){
        if(filePath.isEmpty()){
            return;
        }
        ComThread.InitSTA();

        ActiveXComponent xl=new ActiveXComponent("Excel.Application");
        try {
            Dispatch.put(xl, "Visible", new Variant(true));
            Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
            Dispatch excel=Dispatch.call(workbooks, "Open", filePath).toDispatch();
            Dispatch.callN(excel,"PrintOut",new Object[]{Variant.VT_MISSING, Variant.VT_MISSING, new Integer(1),
                    new Boolean(false), deviceName, new Boolean(true),Variant.VT_MISSING, ""});
            Dispatch.call(excel, "Close", new Variant(false));
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            xl.invoke("Quit",new Variant[0]);
            ComThread.Release();
        }
    }

    /**
     * 打印PPT
     * @param filePath
     * @param deviceName
     */
    private static void printPPT(String filePath, String deviceName) {
        File file = new File(filePath);
        File pdfFile = new File(file.getParentFile().getAbsolutePath() + file.getName() + ".pdf");
        ActiveXComponent app = null;
        Dispatch ppt = null;
        try {
            ComThread.InitSTA();
            app = new ActiveXComponent("PowerPoint.Application");
            Dispatch ppts = app.getProperty("Presentations").toDispatch();

            ppt = Dispatch.call(ppts, "Open", filePath, true, true, false).toDispatch();
            Dispatch.call(ppt, "SaveAs", pdfFile.getAbsolutePath(), 32);

        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {
            if (ppt != null) {
                Dispatch.call(ppt, "Close");
            }
            if (app != null) {
                app.invoke("Quit");
            }
            ComThread.Release();
        }
        try {
            print(pdfFile.getAbsolutePath(), deviceName);
            pdfFile.delete();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 接口,在打印结束后调用
     */
    public interface AfterPrint {
        void run();
    }
}

PrintUtil.java中依赖两个打印需要的非常重要包,jacob和pdfbox,下面给出免费链接,阿里云盘不限速的
链接:Java打印相关依赖包

下载后,需要导入一下,也十分简单,如图
在这里插入图片描述
然后运行后端,点击按钮就会有对应效果了,如果你没有打印机,会弹出生成PDF,有打印机连着,会使用默认打印机,或者通过PrintUtil中方法自定义打印机名称,选择打印机打印

以上就是全部内容,过程有啥问题可以评论区和大家一起交流!

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

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

相关文章

低代码如何推动自动化未来

一项全球研究表明&#xff0c;企业平均每个月有60个小时的工作是手动完成的&#xff0c;也就是每个员工每天花3个小时完成文件归档、数据输入和报告整合&#xff0c;而这些工作都是可以通过自动化的方式完成的。 组织实现数字化转型的关键环节就是自动化。通过自动化&#xff…

温控负荷的需求响应潜力评估及其协同优化管理研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

登录Oracle数据库遇到ORA-01017密码错误的解决办法

文章目录症状分析解决办法欢迎加下方我的微信&#x1f447;&#xff0c;拉你入学习群我们在登录Oracle数据库时可能会遇到ORA-01017错误&#xff0c;这里分析原因并提供解决办法。点击试看博主的专著《MySQL 8.0运维与优化》&#xff08;清华大学出版社&#xff09; 症状 图像…

Linux rpm安装mysql

个人记录 第一步&#xff1a;卸载已安装的mysql rpm -qa | grep -i mysql 查询已安装的mysql1、确认停止mysql服务 2、删除卸载mysql –nodeps&#xff1a;表示强制卸载&#xff0c;如果因为依赖关系导致卸载不成功&#xff0c;加上强制卸载选项–nodeps rpm -ev mysql-com…

C盘爆满?两个超简单的解决办法

我们在使用电脑的过程中&#xff0c;经常容易出现C盘爆红&#xff0c;反而其他盘还有大量可用空间的情况。为什么会这样呢&#xff1f;其实主要就两种原因&#xff1a;一是电脑使用习惯不好&#xff0c;不管什么软件都默认安装在C盘&#xff0c;大文件又喜欢放在桌面&#xff0…

Python(青铜时代)——列表

列表 在Python中&#xff0c;所有 非数字型变量 都支持以下特点&#xff1a; 都是一个序列 sequence, 也可以理解为 容器 取值 [] 遍历 for in 计算长度、最大/最小值、比较、删除 链接 和 重复 * 切片 列表的定义 List (列表) 是Python 中使用 最频繁 的数据类型&#…

6.3 负反馈放大电路的方块图及一般表达式

一、负反馈放大电路的方块图表示法 任何负反馈放大电路都可以用图6.3.1所示的方块图来表示&#xff0c;上面一个方块是负反馈放大电路的基本放大电路&#xff0c;下面一个方块是反馈放大电路的反馈网络。负反馈放大电路的基本放大电路是在断开反馈且考虑了反馈网络的负载效应的…

让您的客户了解您的制造过程“VR云看厂实时数字化展示”

一、工厂云考察&#xff0c;成为市场热点虚拟现实&#xff08;VR&#xff09;全景技术问世已久&#xff0c;但由于应用范围较为狭窄&#xff0c;一直未得到广泛应用。国外客户无法亲自到访&#xff0c;从而导致考察难、产品取样难等问题&#xff0c;特别是对于大型制造企业来说…

剑指 Offer 14-剪绳子

摘要 ​​​​​​剑指 Offer 14- I. 剪绳子 剑指 Offer 14- II. 剪绳子 II 343. 整数拆分 一、动态规划解析 这道题给定一个大于1的正整数n&#xff0c;要求将n 拆分成至少两个正整数的和&#xff0c;并使这些正整数的乘积最大化&#xff0c;返回最大乘积。令x是拆分出的第…

Spark Transformation转换算子和Action行动算子

1、Transformation转换算子 RDD整体上分为Value类型、双Value类型和Key-Value类型 1.1&#xff0c;Value类型 1.1.1&#xff0c;map()映射 object value01_map {def main(args: Array[String]): Unit {//1.创建SparkConf并设置App名称val conf new SparkConf().setAppName(…

c语言入门-5-字符串

c语言入门-5-字符串正文1、字符串怎么用方式一方式二2、字符串的长度深度解析1 字符串的特性2 \0 的含义3 ascii码表下一篇正文 1、字符串怎么用 方式一 // 字符串的标准使用方式&#xff0c;用char类型的数组表示字符串 #include<stdio.h> int main() {char arr[] &…

语音识别技术对比分析

文章目录一、语音识别产品对比二、百度语音识别产品1、套餐及价格&#xff1a;2、官网3、调研结果三、华为语音识别产品四、阿里云语音识别产品1、套餐及价格&#xff1a;2、官网地址3、调研结果五、科大讯飞语音识别产品1、套餐及价格&#xff1a;2、官网3、调研结果六、有道语…

一、Redis入门概述(是什么,能干嘛,去哪下,怎么玩)

一. redis是什么&#xff1f; Redis:REmote Dictionary Server(远程字典服务器)官方解释&#xff1a; Remote Dictionary Server(远程字典服务)是完全开源的&#xff0c;使用ANSIC语言编写遵守BSD协议&#xff0c;是一个高性能的Key-Value数据库提供了丰富的数据结构&#xff…

何谓dB , dB怎么理解?

dB 是什么单位 ?愈低愈好吗?对于声频 ( 声学及电子声学 ) 方面的单位&#xff0c;它是以分贝(decibel &#xff0c;dB ) 来做结果的。斯多里一生专注于科学,1876 发明电话&#xff0c;我们都知道贝尔发明了电话&#xff0c;然而重要的是&#xff0c;他发现我们人类耳朵对声音…

一文带你了解什么是PACS系统源码

▷ 运维级带三维重建和还原的医院PACS系统有源码&#xff0c;有演示&#xff0c;带使用手册和操作说明书。 ▷ PACS系统及影像存取与传输系统( Picture Archiving and Communication System)&#xff0c;为以实现医学影像数字化存储、诊断为核心任务&#xff0c;从医学影像设备…

uniapp小程序接入腾讯地图sdk

新建一个项目。配置uniapp配置文件设置小程序的appid注意&#xff1a;匿名用户可能存在地理定位失效。查uniapp官网官网->apiuni.getLocation(OBJECT) 获取当前的地理位置、速度。属性&#xff1a;success匿名函数返回值&#xff1a;uni.getLocation({type: gcj02,success: …

工作实战之密码防重放攻击

目录 前言 一、登录认证密码加密 二、bcrypt加密密码不一样&#xff0c;匹配原理 1.程序运行现象 2.原理解释 三、密码防重放 总结 前言 密码重放攻击&#xff1a;请求被攻击者获取&#xff0c;并重新发送给认证服务器&#xff0c;从而达到认证通过的目的 一、登录认证密…

系列八、SQL优化

一、插入数据 如果我们需要一次性往数据库表中插入多条记录&#xff0c;可以从以下三个方面进行优化。1.1、优化方案一&#xff08;批量插入数据&#xff09; Insert into tb_test values(1,Tom),(2,Cat),(3,Jerry); 1.2、优化方案二&#xff08;手动控制事务&#xff09; s…

CEC2005:星雀优化算法(Nutcracker optimizer algorithm,NOA)求解CEC2005(提供MATLAB代码)

一、星雀优化算法NOA 星雀优化算法(Nutcracker optimizer algorithm,NOA)由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模拟星雀的两种行为&#xff0c;即&#xff1a;在夏秋季节收集并储存食物&#xff0c;在春冬季节搜索食物的存储位置。 星鸦单独或成对活动&…

C语言循环语句do while和嵌套循环语句讲解

C do…while 循环 不像 for 和 while 循环&#xff0c;它们是在循环头部测试循环条件。在 C 语言中&#xff0c;do…while 循环是在循环的尾部检查它的条件。 do…while 循环与 while 循环类似&#xff0c;但是 do…while 循环会确保至少执行一次循环。 语法 C 语言中 do…w…