EasyExcel_通过模板导出(多sheet、列表、图片)

news2024/11/23 8:40:01

文章目录

  • 前言
  • 一、EasyExcel是什么?
  • 二、模板样式调整
  • 三、使用步骤
    • 1.引入jar包
    • 2.方法示例
      • 2.1 Controller:
      • 2.2 Service:
      • 2.3 ServiceImpl:
      • 2.4 合并策略:
      • 2.5 对应DTO
  • 总结


前言

产品今天提了个需求,大概是这样的,来,请看大屏幕。。。额。。。搞错了,重来!来,请看需求
设计到多sheet、列表、图片的模板导出,先看成品

首页

报告封面

详情页


一、EasyExcel是什么?

EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。
他能让你在不用考虑性能、内存的等因素的情况下,快速完成Excel的读、写等功能。
详细介绍见官网:EasyExcel官网

二、模板样式调整

模板首页
模板-报告封面
在这里插入图片描述

三、使用步骤

1.引入jar包

	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>easyexcel</artifactId>
		<version>3.1.1</version>
	</dependency>

2.方法示例

2.1 Controller:

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
/**
 1. <p>
 2. 可靠性测试委托单 前端控制器
 3. </p>
 4.  5. @author zs
 6. @since 2024-06-21
 */
@RestController
@Api(tags = "可靠性测试委托单")
@Validated
@Slf4j
@RequestMapping("/reliabitestEntrust")
public class ReliabitestEntrustController {
	@Resource
    private IReliabitestEntrustService entrustService;


	@ApiOperation(value = "可靠性测试委托单-下载报告")
    @GetMapping("/downEntrustReport")
    public void downEntrustReport(HttpServletResponse response, @RequestParam("id") @NotNull(message = "id不能为空") Long id) {
        try {
            ByteArrayOutputStream oos = new ByteArrayOutputStream();
            String fileName = entrustService.downEntrustReport(oos, id);
            response.setHeader("Content-Disposition", "attachment;filename*=" + URLEncoder.encode(fileName, "UTF-8"));
            oos.writeTo(response.getOutputStream());
            oos.flush();
            oos.close();
        } catch (Exception e) {
            log.error("可靠性测试委托单-下载报告出错了:{}", e);
            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            try {
                ResponseBean resp = ResponseBean.buildFail(CodeEnums.FAIL.getCode(), e.getMessage());
                response.getWriter().println(JSONObject.toJSONString(resp));
            } catch (Exception e1) {
                log.error("可靠性测试委托单-下载报告,出错了:{}", e1);
            }
        }
    }
}

2.2 Service:

/**
 * <p>
 * 可靠性测试委托单 服务类
 * </p>
 *
 * @author zs
 * @since 2024-06-21
 */
public interface IReliabitestEntrustService extends IService<ReliabitestEntrust> { 
    /**
     * 功能: 下载委托单报告
     * 调用时机: 点击下载报告按钮
     * 注意事项: 参数必传
     *
     * @return
     * @author zs
     * @date 2024/6/27
     */
    String downEntrustReport(OutputStream outputStream, Long id) throws Exception;


}

2.3 ServiceImpl:

 /**
     * 功能: 下载委托单报告
     * 调用时机: 点击下载报告按钮
     * 注意事项: 参数必传
     *
     * @return
     * @author zs
     * @date 2024/6/27
     */
    @Override
    public String downEntrustReport(OutputStream outputStream, Long id) throws Exception {
        // Step 1: 获取委托单主表、详情、问题点与改善、委托单配置
        CompletableFuture<ReliabitestEntrust> entrustFuture = CompletableFuture.supplyAsync(() -> this.getById(id));
        CompletableFuture<List<ReliabitestEntrustDetail>> detailFuture = CompletableFuture.supplyAsync(() -> entrustDetailService.queryByEntrustId(id));
        CompletableFuture<List<ReliabitestEntrustQuestion>> questionFuture = CompletableFuture.supplyAsync(() -> entrustQuestionService.queryByEntrustId(id));
        // 获取config配置
        ResponseBean<List<GetConfigListByTypeResp>> response = basicsClient.getConfigsByType(47);
        CheckException.checkThrowException(() -> !response.isSuccess() || CollectionUtil.isEmpty(response.getData()), "委托单配置为空,请检查配置!!!");
        List<GetConfigListByTypeResp> configList = response.getData();

        // 试验项目 code+名称
        Map<String, String> codeAndNameMap = configList.stream().collect(Collectors.toMap(e -> e.getCode(), a -> a.getName(), (k1, k2) -> k1));

        // 子集
        List<GetConfigListByTypeResp> childrenList = configList.stream().map(GetConfigListByTypeResp::getChildrenList)
                .flatMap(List::stream).collect(Collectors.toList());
        Map<String, String> childMap = childrenList.stream().collect(Collectors.toMap(e -> e.getCode(), a -> a.getName(), (k1, k2) -> k1));

        // Step 2: 组装模板数据
        ReliabitestEntrust entrust = entrustFuture.get();

        // 主信息
        DownEntrustReportDTO dto = new DownEntrustReportDTO();
        if (ObjectUtil.isNotNull(entrust)) {
            assembleData(detailFuture, questionFuture, codeAndNameMap, childMap, entrust, dto);
        }

        // Step 3: 获取下载报告的模板
        String tempFileName = tempPath + "可靠性测试委托单_报告模板.xlsx";

        // Step 4: 模板数据写入
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        ExcelWriter build = EasyExcel.write(outputStream).withTemplate(tempFileName).build();
        WriteSheet writeSheet0 = EasyExcel.writerSheet(0).build();
        build.fill(dto, writeSheet0);

        WriteSheet writeSheet1 = EasyExcel.writerSheet(1).registerWriteHandler(new CustomMergeStrategy()).build();
        build.fill(dto, fillConfig, writeSheet1);
        build.fill(new FillWrapper("projects", dto.getProjects()), fillConfig, writeSheet1);

        WriteSheet writeSheet2 = EasyExcel.writerSheet(2).registerWriteHandler(new CustomMergeStrategy()).build();
        build.fill(dto, fillConfig, writeSheet2);
        build.fill(new FillWrapper("questions", dto.getQuestions()), fillConfig, writeSheet2);
        build.fill(new FillWrapper("details", dto.getDetails()), fillConfig, writeSheet2);
        build.fill(new FillWrapper("infos", dto.getInfos()), fillConfig, writeSheet2);

        build.finish();

        String fileName = String.format("%s_%s.xlsx", dto.getReportCode(), System.currentTimeMillis()).replaceAll(" ", "-");
        log.info("报告委托单名称组成格式:样品ID 样品名称/规则-样品类别-测试报告(固定值)-创建日期(日期格式:yyyyMMdd),{}", dto.getEntrustName());
        return fileName;
    }
	
	/**
     * 功能: 组装模板数据
     * 调用时机:
     *
     * @author zs
     * @date 2024/6/30
     */
	private void assembleData(CompletableFuture<List<ReliabitestEntrustDetail>> detailFuture,
                              CompletableFuture<List<ReliabitestEntrustQuestion>> questionFuture,
                              Map<String, String> codeAndNameMap, Map<String, String> childMap,
                              ReliabitestEntrust entrust, DownEntrustReportDTO dto) throws Exception {
        String sampleIdAndName = String.format("%s %s", entrust.getSampleId(), entrust.getSampleName());

        // 报告委托单名称组成格式:样品ID 样品名称/规则-样品类别-测试报告(固定值)-创建日期(日期格式:yyyyMMdd)
        String sampleTypeStr = "";
        for (EntrustSampleTypeEnums value : EntrustSampleTypeEnums.values()) {
            if (value.getCode().equals(entrust.getSampleType())) {
                sampleTypeStr = value.getMsg();
                break;
            }
        }
        String formatTime = DateTimeFormatter.ofPattern("yyyyMMdd").format(entrust.getCreateTime().toLocalDate());
        String entrustName = String.format("%s %s-%s-测试报告-%s", entrust.getSampleId(), entrust.getSampleName(), sampleTypeStr, formatTime);
        dto.setSampleIdAndName(sampleIdAndName);
        dto.setEntrustName(entrust.getEntrustCode());
        dto.setSampleGiveDate(entrust.getSampleGiveDate().toLocalDate().toString());
        dto.setTotalSampleNum(entrust.getTotalSampleNum());
        dto.setTestSamplingStr(entrust.getTestSampling() == 1 ? "抽样" : "送样");
        dto.setTestBy(entrust.getTestBy());
        dto.setTestHumidity(entrust.getTestHumidity());
        dto.setTestTemperature(entrust.getTestTemperature());
        dto.setAuditBy(entrust.getAuditBy());
        dto.setTestBasis(entrust.getTestBasis());
        dto.setApplyBy(entrust.getApplyBy());
        dto.setReportCode(entrustName);
        dto.setActualStartDate(entrust.getActualStartDate().toLocalDate().toString());
        dto.setActualFinishDate(entrust.getActualFinishDate().toLocalDate().toString());
        dto.setTestSampleInsp(entrust.getTestSampleInsp());
        dto.setTestTotalResultStr(EntrustTestResultEnums.findByCode(entrust.getTestTotalResult()));
        dto.setTestResultRemark(entrust.getTestResultRemark());

        // 试验项目及判定、试验明细、试验信息展示
        List<ReliabitestEntrustDetail> details = detailFuture.get();
        if (CollectionUtil.isNotEmpty(details)) {
            List<DownEntrustReportDTO.TestProject> testProjects = new ArrayList<>();
            List<DownEntrustReportDTO.TestDetail> testDetails = new ArrayList<>();
            List<DownEntrustReportDTO.TestInfo> testInfos = new ArrayList<>();
            for (int i = 0; i < details.size(); i++) {
                int index = i + 1;
                ReliabitestEntrustDetail entrustDetail = details.get(i);

                // 试验结果转换
                String testResult = EntrustTestResultEnums.findByCode(entrustDetail.getTestResult());

                // 试验项目转换
                String testProject = ObjectUtil.isNotNull(codeAndNameMap.get(entrustDetail.getTestProject())) ?
                        codeAndNameMap.get(entrustDetail.getTestProject()) : "";

                // 试验条件参数
                String testCondition = ObjectUtil.isNotNull(childMap.get(entrustDetail.getTestCondition())) ?
                        childMap.get(entrustDetail.getTestCondition()) : "";

                // 试验项目及判定
                DownEntrustReportDTO.TestProject project = new DownEntrustReportDTO.TestProject();
                project.setIndex(Long.valueOf(index));
                project.setTestProject(testProject);      // 试验项目
                StringBuffer sb = new StringBuffer();
                for (int i1 = 1; i1 <= entrustDetail.getSampleNum().intValue(); i1++) {
                    sb.append(entrustDetail.getSampleGroup()).append("-").append(i1);
                    if (i1 < entrustDetail.getSampleNum().intValue()) {
                        sb.append("、");
                    }
                }
                project.setGroupTestSequence(sb.toString());
                project.setTestResultStr(testResult);
                project.setTestResultDesc(entrustDetail.getTestResultDesc());
                testProjects.add(project);

                // 试验明细
                DownEntrustReportDTO.TestDetail detail = new DownEntrustReportDTO.TestDetail();
                detail.setIndex(Long.valueOf(index));
                detail.setTestProject(testProject);      // 试验项目
                detail.setTestCondition(testCondition);  // 试验参数(条件)
                detail.setJudgeStandardStr(entrustDetail.getJudgeStandard());
                detail.setTestMethod(entrustDetail.getTestMethod());
                detail.setTestResultStr(testResult);
                detail.setTestResultDesc(entrustDetail.getTestResultDesc());
                testDetails.add(detail);

                // 试验信息展示
                DownEntrustReportDTO.TestInfo info = new DownEntrustReportDTO.TestInfo();
                info.setIndex(Long.valueOf(index));
                info.setTestProject(testProject);      // 试验项目

                // 测试前图片
                if (StringUtils.isNotBlank(entrustDetail.getBeforeTest())) {
                    byte[] beforePicByte = getImage(entrustDetail.getBeforeTest());
                    WriteCellData<Void> voidWriteCellData = imageCells(beforePicByte, 0, 2);
                    info.setBeforePic(voidWriteCellData);
                }

                // 测试中图片地址
                if (StringUtils.isNotBlank(entrustDetail.getDuringTest())) {
                    byte[] duringPicByte = getImage(entrustDetail.getDuringTest());
                    WriteCellData<Void> voidWriteCellData = imageCells(duringPicByte, 0, 2);
                    info.setDuringPic(voidWriteCellData);
                }
                // 测试后图片地址
                if (StringUtils.isNotBlank(entrustDetail.getAfterTest())) {
                    byte[] afterPicByte = getImage(entrustDetail.getAfterTest());
                    WriteCellData<Void> voidWriteCellData = imageCells(afterPicByte, 0, 2);
                    info.setAfterPic(voidWriteCellData);
                }
                testInfos.add(info);
            }
            dto.setProjects(testProjects);
            dto.setDetails(testDetails);
            dto.setInfos(testInfos);
        }

        // 问题点与改善
        List<ReliabitestEntrustQuestion> questions = questionFuture.get();
        if (CollectionUtil.isNotEmpty(questions)) {
            List<DownEntrustReportDTO.TestQuestion> testQuestions = new ArrayList<>();
            for (int i = 0; i < questions.size(); i++) {
                ReliabitestEntrustQuestion entrustQuestion = questions.get(i);
                DownEntrustReportDTO.TestQuestion question = new DownEntrustReportDTO.TestQuestion();
                question.setProposeTime(entrustQuestion.getProposeTime().toLocalDate().toString());
                question.setQuestionDesc(entrustQuestion.getQuestionDesc());
                question.setQuestionTypeStr(EntrustQuestionTypeEnums.findByCode(entrustQuestion.getQuestionType()));
                question.setQuestionRemark(entrustQuestion.getQuestionRemark());
                testQuestions.add(question);
            }
            dto.setQuestions(testQuestions);
        }
    }
	
	 /**
     * 功能: 设置单元格格式
     * 调用时机:
     * 使用方法:
     * 注意事项: 
     *
     * @Param bytes 图片字节
     * @Param lastRowIndex 行偏移量
     * @Param lastColumnIndex 列偏移
     * @author zs
     * @date 2024/6/30
     */
    public static WriteCellData<Void> imageCells(byte[] bytes, Integer lastRowIndex, Integer lastColumnIndex) throws IOException {
        WriteCellData<Void> writeCellData = new WriteCellData<>();
        // 可以放入多个图片,目前只放一张
        List<ImageData> imageDataList = new ArrayList<>();
        writeCellData.setImageDataList(imageDataList);
        ImageData imageData = new ImageData();
        imageDataList.add(imageData);
        // 设置图片
        imageData.setImage(bytes);
        // 上右下左需要留空,通过这种方式调整图片大小,单位为像素
        imageData.setTop(5);
        imageData.setRight(5);
        imageData.setBottom(5);
        imageData.setLeft(5);

        //以下四个属性分别为设置单元格偏移量,因为图片可能占据多个单元格(合并单元格)
        // 这里以左上角单元格为起始,所以FirstRowIndex和FirstColumnIndex默认为0
        // 向右增加一格则设置LastColumnIndex为1,
        // 向下增加一格设置LastRowIndex属性为1,
        imageData.setRelativeFirstRowIndex(0);
        imageData.setRelativeFirstColumnIndex(0);
        imageData.setRelativeLastRowIndex(lastRowIndex);
        imageData.setRelativeLastColumnIndex(lastColumnIndex);
        return writeCellData;
    }
	
	/**
     * 功能: url链接转byte
     * 调用时机: 图片URL需要转换时
     * 注意事项: 参数必传
     *
     * @author zs
     * @date 2024/6/28
     */
    private byte[] getImage(String url) {
        try {
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection();

            // 设置超时以提高响应性和避免无限等待
            conn.setConnectTimeout(5000); // 连接超时5秒
            conn.setReadTimeout(5000);    // 读取超时5秒

            // 设置为只输入模式
            conn.setRequestMethod("GET");
            conn.setDoInput(true);
            conn.connect();

            // try (Resource r = acquireResource())语法会在try块结束时(无论是否正常结束还是因为异常结束)自动调用资源的close()方法
            try (InputStream is = conn.getInputStream()) {
                return IoUtils.toByteArray(is);
            }
        } catch (IOException e) {
            throw new RuntimeException(String.format("URL转byte报错:%s", e));
        }
    }

2.4 合并策略:

package com.smallrig.sku.handler.excel;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;

import java.util.List;

/**
 * CustomMergeStrategy class.
 *
 * @author zs
 * @program: nakadai
 * @description: 合并单元格(获取前一行样式应用于当前行)
 * @date 2024/6/30
 */
public class CustomMergeStrategy extends AbstractMergeStrategy {
    
    @Override
    protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) {
        if (relativeRowIndex == null || relativeRowIndex == 0) {
            return;
        }
        int rowIndex = cell.getRowIndex();
        int colIndex = cell.getColumnIndex();
        sheet = cell.getSheet();
        Row preRow = sheet.getRow(rowIndex - 1);
        //获取上一行的该格
        Cell preCell = preRow.getCell(colIndex);
        List<CellRangeAddress> list = sheet.getMergedRegions();
        CellStyle cs = cell.getCellStyle();
        cell.setCellStyle(cs);
        for (int i = 0, len = list.size(); i < len; i++) {
            CellRangeAddress cellRangeAddress = list.get(i);
            if (cellRangeAddress.containsRow(preCell.getRowIndex()) && cellRangeAddress.containsColumn(preCell.getColumnIndex())) {
                int lastColIndex = cellRangeAddress.getLastColumn();
                int firstColIndex = cellRangeAddress.getFirstColumn();
                CellRangeAddress cra = new CellRangeAddress(cell.getRowIndex(), cell.getRowIndex(), firstColIndex, lastColIndex);
                sheet.addMergedRegion(cra);
                RegionUtil.setBorderBottom(BorderStyle.THIN, cra, sheet);
                RegionUtil.setBorderLeft(BorderStyle.THIN, cra, sheet);
                RegionUtil.setBorderRight(BorderStyle.THIN, cra, sheet);
                RegionUtil.setBorderTop(BorderStyle.THIN, cra, sheet);
                return;
            }
        }
    }
    
}

2.5 对应DTO

package com.smallrig.sku.dto;

import com.alibaba.excel.metadata.data.WriteCellData;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.math.BigDecimal;
import java.util.List;

/**
 * DownloadEntrustReportDTO class.
 *
 * @author zs
 * @program: nakadai
 * @description: 下载委托单报告
 * @date 2024/6/27
 */
@Data
@ApiModel(value = "下载委托单报告")
public class DownEntrustReportDTO {

    @ApiModelProperty(value = "样品ID和样品名称/规格组合")
    private String sampleIdAndName;

    @ApiModelProperty("委托单名称")
    private String entrustName;

    @ApiModelProperty("送样日期")
    private String sampleGiveDate;

    @ApiModelProperty("总样品数量")
    private Long totalSampleNum;

    @ApiModelProperty("取样: 1 抽样 2 送样")
    private String testSamplingStr;

    @ApiModelProperty("试验单位")
    private String testCompany = "质量服务部";

    @ApiModelProperty("测试工程师")
    private String testBy;

    @ApiModelProperty("测试环境湿度%RH")
    private BigDecimal testHumidity;

    @ApiModelProperty("测试环境温度℃")
    private BigDecimal testTemperature;

    @ApiModelProperty("审核人")
    private String auditBy;

    @ApiModelProperty("试验依据")
    private String testBasis;

    @ApiModelProperty("申请人")
    private String applyBy;

    // 报告编号格式:委托单名称+"报告(固定值)"+当前日期(日期格式:yyyyMMdd)
    @ApiModelProperty(value = "报告编号")
    private String reportCode;

    @ApiModelProperty("开始试验日期")
    private String actualStartDate;

    @ApiModelProperty("结束试验日期")
    private String actualFinishDate;

    @ApiModelProperty("试验前样品检验")
    private String testSampleInsp;

    @ApiModelProperty("总测试结果(EntrustTestResultEnums.class)")
    private String testTotalResultStr;

    @ApiModelProperty("测试结果备注")
    private String testResultRemark;
    
    @ApiModelProperty(value = "试验项目及判定列表")
    private List<TestProject> projects;

    @ApiModelProperty(value = "问题点与改善")
    private List<TestQuestion> questions;
    
    @ApiModelProperty(value = "试验明细")
    private List<TestDetail> details;

    @ApiModelProperty(value = "试验信息展示")
    private List<TestInfo> infos;


    @Data
    @ApiModel(value = "试验项目及判定")
    public static class TestProject {

        @ApiModelProperty(value = "序号")
        private Long index;

        @ApiModelProperty("试验项目")
        private String testProject;

        // 试验顺序格式:分组+"-"+组内试验顺序
        @ApiModelProperty("试验顺序")
        private String groupTestSequence;

        @ApiModelProperty("试验结果")
        private String testResultStr;

        @ApiModelProperty("试验结果描述")
        private String testResultDesc;

    }

    @Data
    @ApiModel(value = "问题点与改善")
    public static class TestQuestion {

        @ApiModelProperty("提出时间")
        private String proposeTime;

        @ApiModelProperty("问题描述")
        private String questionDesc;

        @ApiModelProperty("问题类型")
        private String questionTypeStr;

        @ApiModelProperty("问题备注")
        private String questionRemark;
        
    }

    @Data
    @ApiModel(value = "试验明细")
    public static class TestDetail {

        @ApiModelProperty(value = "序号")
        private Long index;

        @ApiModelProperty("试验项目")
        private String testProject;

        @ApiModelProperty("试验参数(条件)")
        private String testCondition;

        @ApiModelProperty("判定标准")
        private String judgeStandardStr;

        @ApiModelProperty("试验方法")
        private String testMethod;

        @ApiModelProperty("试验结果")
        private String testResultStr;

        @ApiModelProperty("试验结果描述")
        private String testResultDesc;
        
    }

    @Data
    @ApiModel(value = "试验信息展示")
    public static class TestInfo {
        
        @ApiModelProperty(value = "序号")
        private Long index;

        @ApiModelProperty("试验项目")
        private String testProject;

        @ApiModelProperty("测试前图片地址")
        private WriteCellData beforePic;

        @ApiModelProperty("测试中图片地址")
        private WriteCellData duringPic;

        @ApiModelProperty("测试后图片地址")
        private WriteCellData afterPic;
        
    }

}


总结

整个方法中有几个重要点:

  1. 合并逻辑,因为模板设计中,图片存在跨行和跨列。
  2. 通过图片链接去获取图片数据并转换和写入
  3. DTO中图片类使用WriteCellData
  4. 多sheet页写入需要对应不同的WriteSheet

原创不易,望一键三连 (^ _ ^)

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

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

相关文章

中秋节月饼销售利用106短信群发平台业绩翻倍案例分析

在中秋节这一传统佳节&#xff0c;月饼作为节日的标志性食品&#xff0c;其销售市场竞争尤为激烈。为了在众多品牌中脱颖而出&#xff0c;不少月饼销售企业开始探索创新的营销方式。其中&#xff0c;利用106短信群发平台进行精准营销&#xff0c;成为众多企业实现业绩翻倍的有效…

C\C++ Sqlite3使用详解

C\C++ Sqlite3使用详解 一、源码下载二、sqlite3接口说明C++2.1 项目创建以及sqlite3使用2.1 连接数据库2.2 sqlite创建表2.2.1 示例代码2.2.2 注意事项2.3 sqlite插入数据2.3.1 示例代码2.3.2 注意事项2.4 sqlite数据删除2.5 sqlite数据查询一、源码下载 下载地址: https://…

思科设备静态路由实验

拓扑及需求 网络拓扑及 IP 编址如图所示&#xff1b;PC1 及 PC2 使用路由器模拟&#xff1b;在 R1、R2、R3 上配置静态路由&#xff0c;保证全网可达&#xff1b;在 R1、R3 上删掉上一步配置的静态路由&#xff0c;改用默认路由&#xff0c;仍然要求全网可达。 各设备具体配置…

UE5.4 - 内容浏览器

目录 一. 简介 二. 打开方式 1.顶部菜单栏打开 2.工具栏创建 3.底部工具栏按钮 三.界面详细介绍 1.导航栏 2.源面板 3.集合 4.筛选器 ​编辑 5.搜索栏 6.资产视图 7.设置按钮 四. 开发者内容 一. 简介 一种你可以用于查看、管理和处理项目中所有资产的工具。 二…

java 变量 基础类型及其转换

为什么需要变量 一个程序就是一个世界 变量是程序的基本组成单位 //不论是使用那种高级程序语言编写程序,变量都是其程序的基本组成单位,比如 //变量有三个基本要素(类型名称值) class Test{public static void main(String[] args) {//定义了一个变量,类型int整型,名称a,值…

哈工大 | 乐聚人形机器人 | 最新演讲

笔者是清华在读研究生&#xff0c;主要关注人形机器人、具身智能。将持续分享行业前沿动态、学者观点整理、论文阅读笔记、知识学习路线等。欢迎交流 最近听了乐聚的最新进展演讲&#xff0c;以下是学习整理。部分图截自直播&#xff0c;若模糊望见谅 基本信息&#xff1a; 【…

光影漫游者:创新球形设计,重新定义移动空间—轻空间

在现代城市中&#xff0c;空间的灵活性和视觉吸引力变得越来越重要。为满足多样化的需求&#xff0c;“光影漫游者”以其独特的球形设计和引人注目的视觉效果&#xff0c;成为了移动空间解决方案的新标杆。无论是商业活动、文化展览&#xff0c;还是沉浸式体验&#xff0c;“光…

文档翻译软件哪个好?这5款文档翻译器还不错

相信大家都有过看着大量外文文档资料而无从下手的经历&#xff0c;曾几何时&#xff0c;我也和大家一样深深困于这种烦恼之中。 好在后来&#xff0c;被我发现了5款趁手的文档翻译器&#xff0c;这才从根本上解决了不少麻烦~今天借此机会也将它们一并整理出来分享给大家&#…

仪器校准周期建议多长时间一次?仪器无校准后果怎么样?

自从国内建立计量以来&#xff0c;仪器计量校准就一直是企业定期进行的一种设备维护工作。定期进行校准已经是企业墨守成规的习惯&#xff0c;但是对于仪器校准周期是多久&#xff0c;具体多久校准一次&#xff0c;大家却不是很清楚&#xff0c;那么仪器校准周期建议多长时间一…

以简单的例子从头开始建spring boot web多模块项目(五)-thymeleaf引擎

继续向里面加&#xff0c;这次是引入thymeleaf渲染引擎。 使用这个引擎的很多&#xff0c;主要是以下几个优点&#xff1a; Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎。Thymeleaf的主要目标是为您的开发工作流程带来优雅的自然模板 -HTML可以在浏览器中正确显…

华普微邀您共聚 2024 elexcon 深圳国际电子展!

elexcon2024深圳国际电子展将于2024年8月27日至29日在深圳会展中心&#xff08;福田&#xff09;开幕。汇聚全球优质品牌厂商齐聚现场&#xff0c;打造电子全产业链创新展示、一站式采购及技术交流平台。集中展示集成电路、嵌入式系统、电源管理/功率器件、电子元件与供应链、O…

气膜馆:亲子乐园中的新兴娱乐空间—轻空间

在亲子乐园中&#xff0c;气膜馆作为一种新兴的娱乐空间&#xff0c;凭借其独特的设计和灵活的功能&#xff0c;成为了孩子和家长们的理想去处。这个轻盈而充满趣味的空间&#xff0c;不仅让孩子们尽情玩耍&#xff0c;也为家长提供了舒适的陪伴环境。 全天候的舒适体验 气膜馆…

AOP+ 自定义注解 +SpringElExpress自研缓存组件

AOP 自定义注解 SpringElExpress自研缓存组件 背景前置知识改造代码 背景 思考下这段代码&#xff0c;想想项目中是不是到处存在 先查缓存&#xff0c;缓存里面有&#xff0c;直接返回&#xff1b;缓存没有&#xff0c;查数据库&#xff0c;并更新到缓存 思考&#xff1a;如何…

你遇到过哪些触发NPE的代码场景?

你遇到过哪些触发NPE的代码场景&#xff1f; NPE如何处理NPE 在Java编程实践中&#xff0c;空指针异常&#xff08;NPE&#xff09;是开发过程中常见的障碍&#xff0c;它不仅阻碍了代码的正常运行&#xff0c;还常常成为系统不稳定性的根源。那么如何识别那些潜藏于代码深处的…

6个你应该尝试Lens.org的理由:一个免费的文献可视化和专利网站

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 最近发现的一个免费的文献检索工具Lens.org介绍给大家&#xff0c;相比其他文献检索工具web of science、Scopus等&#xff0c;独到之处在于它对于搜索结果全面的可视化呈现效…

ubuntu右上角没有小键盘图标

这个比较奇怪&#xff0c;一开始好好的&#xff0c;用着用着就不行了。网上解决方案比较多&#xff0c;大多数能解决一部分问题。 1.设置“输入法系统” 2.在终端运行 sudo killall ibus-daemon&#xff08;结束进程&#xff09; bus-daemon -d&#xff08;重启ibus&#xff0…

Go之函数

一、函数基本使用 一&#xff09;函数概述 1、函数定义 对特定的功能进行提取&#xff0c;形成一个代码片段 2、函数的作用 提高代码的复用性&#xff0c;减少代码的冗余&#xff0c;代码的维护性也提高了 3、函数中间的关系 函数与函数是并列关系&#xff0c;所以定义的函数不…

Secure Coding in C and C ++ (四)局部静态构造函数 虚函数

前言 上一章节我们讲解了 关于C静态和指针与引用的部分 我们先来回顾一下相关的内容&#xff1a; 指针说白了就是地址&#xff0c; int a; int * ptr &a这里的整形指针 就是存放的整数变量的地址 静态 static 有两种层面&#xff1a; 第一种层面就是在其他的文件里&…

Ansys Zemax|如何自定义优化操作数

虽然Zemax OpticStudio有300多个内建优化操作数&#xff0c;但是还是会有一些特殊情况是这300多个操作数无法涵盖的。这就要求使用者根据要求计算出某些特定的数值&#xff0c;将这些数值返回到某个操作数&#xff0c;再对此操作数进行优化。 Zemax OpticStudio支持用户编程&a…

【SpringCloud】(一文通)多机部署, 负载均衡-LoadBalance

目 录 一. 负载均衡介绍1.2 什么是负载均衡1.3 负载均衡的⼀些实现 二. Spring Cloud LoadBalancer2.1 快速上手2.1.1 使用 Spring Cloud LoadBalancer 实现负载均衡2.1.2 启动多个product-service实例 2.2 负载均衡策略2.3 LoadBalancer 原理 三. 服务部署(Linux)3.2 服务构建…