亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot整合EasyExcel實現(xiàn)文件導(dǎo)入導(dǎo)出

 更新時間:2021年05月03日 09:11:43   作者:JackHorse  
這篇文章主要介紹了SpringBoot整合EasyExcel實現(xiàn)文件導(dǎo)入導(dǎo)出的方法,幫助大家更好的理解和學(xué)習(xí)使用SpringBoot,感興趣的朋友可以了解下

準備工作

注意:點擊查看官網(wǎng)Demo

1. 引入pom依賴

        <!--easyExcel-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
        </dependency>

2. 實現(xiàn)功能

  • 結(jié)合Vue前端,實現(xiàn)瀏覽器頁面直接導(dǎo)出日志文件
  • 實現(xiàn)文件的導(dǎo)入

Excel文件下載

3. 日志實體類

實體類里有自定義轉(zhuǎn)換器:用于Java類型數(shù)據(jù)和Excel類型數(shù)據(jù)的轉(zhuǎn)換,非常使用。結(jié)合注解,可以非常方便的進行Excel文件導(dǎo)出。

/**
 * <p>
 * 操作日志信息
 * </p>
 *
 * @author horse
 * @since 2020-09-08
 * 注意: 實體類中如果使用@Accessory(chain=true),那么導(dǎo)入的數(shù)據(jù)無法填充到實例中,導(dǎo)出數(shù)據(jù)不受影響
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("tb_operational_log")
@ApiModel(value = "OperationalLog對象", description = "操作日志信息")
public class OperationalLog implements Serializable {

    private static final long serialVersionUID = 1L;

    @ExcelProperty({"操作日志", "日志ID"})
    @ApiModelProperty(value = "日志ID")
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;

    @ExcelProperty({"操作日志", "操作類型"})
    @ApiModelProperty(value = "操作類型")
    private String operType;

    @ExcelProperty({"操作日志", "操作描述"})
    @ApiModelProperty(value = "操作描述")
    private String operDesc;

    @ExcelProperty({"操作日志", "操作員ID"})
    @ApiModelProperty(value = "操作員ID")
    private String operUserId;

    @ExcelProperty({"操作日志", "操作員名稱"})
    @ApiModelProperty(value = "操作員名稱")
    private String operUserName;

    @ExcelProperty({"操作日志", "操作方法"})
    @ApiModelProperty(value = "操作方法")
    private String operMethod;

    @ExcelProperty({"操作日志", "請求方法"})
    @ApiModelProperty(value = "請求方法")
    private String operRequWay;

    @ExcelProperty(value = {"操作日志", "請求耗時:單位-ms"}, converter = CustomRequestTimeConverter.class)
    @ApiModelProperty(value = "請求耗時:單位-ms")
    private Long operRequTime;

    @ExcelProperty({"操作日志", "請求參數(shù)"})
    @ApiModelProperty(value = "請求參數(shù)")
    private String operRequParams;

    @ExcelProperty({"操作日志", "請求Body"})
    @ApiModelProperty(value = "請求Body")
    private String operRequBody;

    @ExcelProperty({"操作日志", "請求IP"})
    @ApiModelProperty(value = "請求IP")
    private String operRequIp;

    @ExcelProperty({"操作日志", "請求URL"})
    @ApiModelProperty(value = "請求URL")
    private String operRequUrl;

    @ExcelProperty(value = {"操作日志", "日志標識"}, converter = CustomLogFlagConverter.class)
    @ApiModelProperty(value = "日志標識: 1-admin,0-portal")
    private Boolean logFlag;

    @ExcelProperty({"操作日志", "操作狀態(tài)"})
    @ApiModelProperty(value = "操作狀態(tài):1-成功,0-失敗")
    @TableField(value = "is_success")
    private Boolean success;

    @ExcelIgnore
    @ApiModelProperty(value = "邏輯刪除 1-未刪除, 0-刪除")
    @TableField(value = "is_deleted")
    @TableLogic(value = "1", delval = "0")
    private Boolean deleted;

    @ExcelProperty(value = {"操作日志", "創(chuàng)建時間"}, converter = CustomTimeFormatConverter.class)
    @ApiModelProperty(value = "創(chuàng)建時間")
    private Date gmtCreate;
}

4. 接口和具體實現(xiàn)

4.1 接口

    @OperatingLog(operType = BlogConstants.EXPORT, operDesc = "導(dǎo)出操作日志,寫出到響應(yīng)流中")
    @ApiOperation(value = "導(dǎo)出操作日志", hidden = true)
    @PostMapping("/oper/export")
    public void operLogExport(@RequestBody List<String> logIds, HttpServletResponse response) {
        operationalLogService.operLogExport(logIds, response);
    }

4.2 具體實現(xiàn)

  • 自定義導(dǎo)出策略HorizontalCellStyleStrategy
  • 自定義導(dǎo)出攔截器CellWriteHandler,更加精確的自定義導(dǎo)出策略
    /**
     * 導(dǎo)出操作日志(可以考慮分頁導(dǎo)出)
     *
     * @param logIds
     * @param response
     */
    @Override
    public void operLogExport(List<String> logIds, HttpServletResponse response) {
        OutputStream outputStream = null;
        try {
            List<OperationalLog> operationalLogs;
            LambdaQueryWrapper<OperationalLog> queryWrapper = new LambdaQueryWrapper<OperationalLog>()
                    .orderByDesc(OperationalLog::getGmtCreate);
            // 如果logIds不為null,按照id查詢信息,否則查詢?nèi)?
            if (!CollectionUtils.isEmpty(logIds)) {
                operationalLogs = this.listByIds(logIds);
            } else {
                operationalLogs = this.list(queryWrapper);
            }
            outputStream = response.getOutputStream();

            // 獲取單元格樣式
            HorizontalCellStyleStrategy strategy = MyCellStyleStrategy.getHorizontalCellStyleStrategy();

            // 寫入響應(yīng)輸出流數(shù)據(jù)
            EasyExcel.write(outputStream, OperationalLog.class).excelType(ExcelTypeEnum.XLSX).sheet("操作信息日志")
                    // .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 自適應(yīng)列寬(不是很適應(yīng),效果并不佳)
                    .registerWriteHandler(strategy) // 注冊上面設(shè)置的格式策略
                    .registerWriteHandler(new CustomCellWriteHandler()) // 設(shè)置自定義格式策略
                    .doWrite(operationalLogs);
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e));
            throw new BlogException(ResultCodeEnum.EXCEL_DATA_EXPORT_ERROR);
        } finally {
            IoUtil.close(outputStream);
        }
    }

自定義導(dǎo)出策略簡單如下:

/**
 * @author Mr.Horse
 * @version 1.0
 * @description: 單元格樣式策略
 * @date 2021/4/30 8:43
 */

public class MyCellStyleStrategy {

    /**
     * 設(shè)置單元格樣式(僅用于測試)
     *
     * @return 樣式策略
     */
    public static HorizontalCellStyleStrategy getHorizontalCellStyleStrategy() {
        // 表頭策略
        WriteCellStyle headerCellStyle = new WriteCellStyle();
        // 表頭水平對齊居中
        headerCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 背景色
        headerCellStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
        WriteFont headerFont = new WriteFont();
        headerFont.setFontHeightInPoints((short) 14);
        headerCellStyle.setWriteFont(headerFont);
        // 自動換行
        headerCellStyle.setWrapped(Boolean.FALSE);

        // 內(nèi)容策略
        WriteCellStyle contentCellStyle = new WriteCellStyle();
        // 設(shè)置數(shù)據(jù)允許的數(shù)據(jù)格式,這里49代表所有可以都允許設(shè)置
        contentCellStyle.setDataFormat((short) 49);
        // 設(shè)置背景色: 需要指定 FillPatternType 為FillPatternType.SOLID_FOREGROUND 不然無法顯示背景顏色.頭默認了 FillPatternType所以可以不指定
        contentCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
        contentCellStyle.setFillForegroundColor(IndexedColors.GREY_40_PERCENT.getIndex());
        // 設(shè)置內(nèi)容靠左對齊
        contentCellStyle.setHorizontalAlignment(HorizontalAlignment.LEFT);
        // 設(shè)置字體
        WriteFont contentFont = new WriteFont();
        contentFont.setFontHeightInPoints((short) 12);
        contentCellStyle.setWriteFont(contentFont);
        // 設(shè)置自動換行
        contentCellStyle.setWrapped(Boolean.FALSE);
        // 設(shè)置邊框樣式和顏色
        contentCellStyle.setBorderLeft(MEDIUM);
        contentCellStyle.setBorderTop(MEDIUM);
        contentCellStyle.setBorderRight(MEDIUM);
        contentCellStyle.setBorderBottom(MEDIUM);
        contentCellStyle.setTopBorderColor(IndexedColors.RED.getIndex());
        contentCellStyle.setBottomBorderColor(IndexedColors.GREEN.getIndex());
        contentCellStyle.setLeftBorderColor(IndexedColors.YELLOW.getIndex());
        contentCellStyle.setRightBorderColor(IndexedColors.ORANGE.getIndex());

        // 將格式加入單元格樣式策略
        return new HorizontalCellStyleStrategy(headerCellStyle, contentCellStyle);
    }
}

自定義導(dǎo)出攔截器簡單如下:

/**
 * @author Mr.Horse
 * @version 1.0
 * @description 實現(xiàn)CellWriteHandler接口, 實現(xiàn)對單元格樣式的精確控制
 * @date 2021/4/29 21:11
 */
public class CustomCellWriteHandler implements CellWriteHandler {

    private static Logger logger = LoggerFactory.getLogger(CustomCellWriteHandler.class);

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row,
                                 Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    /**
     * 單元格創(chuàng)建之后(沒有寫入值)
     *
     * @param writeSheetHolder
     * @param writeTableHolder
     * @param cell
     * @param head
     * @param relativeRowIndex
     * @param isHead
     */
    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell,
                                Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                       CellData cellData, Cell cell, Head head, Integer relativeRowIndex,
                                       Boolean isHead) {

    }

    /**
     * 單元格處理后(已寫入值): 設(shè)置第一行第一列的頭超鏈接到EasyExcel的官網(wǎng)(本系統(tǒng)的導(dǎo)出的excel 0,1兩行都是頭,所以只設(shè)置第一行的超鏈接)
     * 這里再進行攔截的單元格樣式設(shè)置的話,前面該樣式將全部失效
     *
     * @param writeSheetHolder
     * @param writeTableHolder
     * @param cellDataList
     * @param cell
     * @param head
     * @param relativeRowIndex
     * @param isHead
     */
    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder,
                                 List<CellData> cellDataList, Cell cell, Head head, Integer relativeRowIndex,
                                 Boolean isHead) {
        // 設(shè)置超鏈接
        if (isHead && cell.getRowIndex() == 0 && cell.getColumnIndex() == 0) {
            logger.info(" ==> 第{}行,第{}列超鏈接設(shè)置完成", cell.getRowIndex(), cell.getColumnIndex());
            CreationHelper helper = writeSheetHolder.getSheet().getWorkbook().getCreationHelper();
            Hyperlink hyperlink = helper.createHyperlink(HyperlinkType.URL);
            hyperlink.setAddress("https://github.com/alibaba/easyexcel");
            cell.setHyperlink(hyperlink);
        }
        // 精確設(shè)置單元格格式
        boolean bool = isHead && cell.getRowIndex() == 1 &&
                (cell.getStringCellValue().equals("請求參數(shù)") || cell.getStringCellValue().equals("請求Body"));
        if (bool) {
            logger.info("第{}行,第{}列單元格樣式設(shè)置完成。", cell.getRowIndex(), cell.getColumnIndex());
            // 獲取工作簿
            Workbook workbook = writeSheetHolder.getSheet().getWorkbook();
            CellStyle cellStyle = workbook.createCellStyle();

            Font cellFont = workbook.createFont();
            cellFont.setBold(Boolean.TRUE);
            cellFont.setFontHeightInPoints((short) 14);
            cellFont.setColor(IndexedColors.SEA_GREEN.getIndex());
            cellStyle.setFont(cellFont);
            cell.setCellStyle(cellStyle);
        }
    }
}

4.3 前端請求

前端在基于Vue+Element的基礎(chǔ)上實現(xiàn)了點擊導(dǎo)出按鈕,在瀏覽器頁面進行下載。

// 批量導(dǎo)出
    batchExport() {
      // 遍歷獲取id集合列表
      const logIds = []
      this.multipleSelection.forEach(item => {
        logIds.push(item.id)
      })
       // 請求后端接口
      axios({
        url: this.BASE_API + '/admin/blog/log/oper/export',
        method: 'post',
        data: logIds,
        responseType: 'arraybuffer',
        headers: { 'token': getToken() }
      }).then(response => {
        // type類型可以設(shè)置為文本類型,這里是新版excel類型
        const blob = new Blob([response.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8' })
        const pdfUrl = window.URL.createObjectURL(blob)
        const fileName = 'HorseBlog操作日志' // 下載文件的名字
        // 對于<a>標簽,只有 Firefox 和 Chrome(內(nèi)核)支持 download 屬性
        if ('download' in document.createElement('a')) {
          const link = document.createElement('a')
          link.href = pdfUrl
          link.setAttribute('download', fileName)
          document.body.appendChild(link)
          link.click()
          window.URL.revokeObjectURL(pdfUrl) // 釋放URL 對象
        } else {
          // IE 瀏覽器兼容方法
          window.navigator.msSaveBlob(blob, fileName)
        }
      })
    }

測試結(jié)果:還行,基本實現(xiàn)了頁面下載的功能

Excel文件導(dǎo)入

5. 文件讀取配置

本配置基于泛型的方式編寫,可擴展性較強。

/**
 * @author Mr.Horse
 * @version 1.0
 * @description: EasyExcel文件讀取配置(不能讓spring管理)
 * @date 2021/4/27 13:24
 */

public class MyExcelImportConfig<T> extends AnalysisEventListener<T> {

    private static Logger logger = LoggerFactory.getLogger(MyExcelImportConfig.class);

    /**
     * 每次讀取的最大數(shù)據(jù)條數(shù)
     */
    private static final int MAX_BATCH_COUNT = 10;

    /**
     * 泛型bean屬性
     */
    private T dynamicService;

    /**
     * 可接收任何參數(shù)的泛型List集合
     */
    List<T> list = new ArrayList<>();


    /**
     * 構(gòu)造函數(shù)注入bean(根據(jù)傳入的bean動態(tài)注入)
     *
     * @param dynamicService
     */
    public MyExcelImportConfig(T dynamicService) {
        this.dynamicService = dynamicService;
    }

    /**
     * 解析每條數(shù)據(jù)都進行調(diào)用
     *
     * @param data
     * @param context
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        logger.info(" ==> 解析一條數(shù)據(jù): {}", JacksonUtils.objToString(data));
        list.add(data);
        if (list.size() > MAX_BATCH_COUNT) {
            // 保存數(shù)據(jù)
            saveData();
            // 清空list
            list.clear();
        }
    }

    /**
     * 所有數(shù)據(jù)解析完成后,會來調(diào)用一次
     * 作用: 避免最后集合中小于 MAX_BATCH_COUNT 條的數(shù)據(jù)沒有被保存
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
        logger.info(" ==> 數(shù)據(jù)解析完成 <==");
    }

    /**
     * 保存數(shù)據(jù): 正式應(yīng)該插入數(shù)據(jù)庫,這里用于測試
     */
    private void saveData() {
        logger.info(" ==> 數(shù)據(jù)保存開始: {}", list.size());
        list.forEach(System.out::println);
        logger.info(" ==> 數(shù)據(jù)保存結(jié)束 <==");
    }

    /**
     * 在轉(zhuǎn)換異常 獲取其他異常下會調(diào)用本接口。我們?nèi)绻蹲讲⑹謩訏伋霎惓t停止讀取。如果這里不拋出異常則 繼續(xù)讀取下一行。
     *
     * @param exception
     * @param context
     * @throws Exception
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        logger.error(" ==> 數(shù)據(jù)解析失敗,但是繼續(xù)讀取下一行:{}", exception.getMessage());
        //  如果是某一個單元格的轉(zhuǎn)換異常 能獲取到具體行號
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException convertException = (ExcelDataConvertException) exception;
            logger.error("第{}行,第{}列數(shù)據(jù)解析異常", convertException.getRowIndex(), convertException.getColumnIndex());
        }
    }

}

6. 讀取測試

    @ApiOperation(value = "數(shù)據(jù)導(dǎo)入測試", notes = "操作日志導(dǎo)入測試[OperationalLog]", hidden = true)
    @PostMapping("/import")
    public R excelImport(@RequestParam("file") MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), OperationalLog.class, new MyExcelImportConfig<>(operationalLogService))
                .sheet().doRead();
        return R.ok().message("文件導(dǎo)入成功");
    }

7. 附上自定義屬性轉(zhuǎn)換器

轉(zhuǎn)換器的屬性內(nèi)容轉(zhuǎn)換,需要根據(jù)自己的實際業(yè)務(wù)需求而定,這里僅作為簡單示例

/**
 * @author Mr.Horse
 * @version 1.0
 * @description: 自定義excel轉(zhuǎn)換器: 將操作日志的請求耗時加上單位 "ms"
 * @date 2021/4/27 10:25
 */

public class CustomRequestTimeConverter implements Converter<Long> {

    /**
     * 讀取數(shù)據(jù)時: 屬性對應(yīng)的java數(shù)據(jù)類型
     *
     * @return
     */
    @Override
    public Class<Long> supportJavaTypeKey() {
        return Long.class;
    }

    /**
     * 寫入數(shù)據(jù)時: excel內(nèi)部的數(shù)據(jù)類型,因為請求耗時是long類型,對應(yīng)excel是NUMBER類型,但是加上"ms后對應(yīng)的是STRING類型"
     *
     * @return
     */
    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    /**
     * 讀取回調(diào)
     *
     * @param cellData
     * @param contentProperty
     * @param globalConfiguration
     * @return
     * @throws Exception
     */
    @Override
    public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        // 截取字符串: "ms",轉(zhuǎn)換為long類型
        String value = cellData.getStringValue();
        return Long.valueOf(value.substring(0, value.length() - 2));
    }

    @Override
    public CellData<Long> convertToExcelData(Long value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        // 添加字符串: "ms"
        return new CellData<>(String.valueOf(value).concat("ms"));
    }
}

格式化時間

/**
 * @author Mr.Horse
 * @version 1.0
 * @description: {description}
 * @date 2021/4/27 14:01
 */

public class CustomTimeFormatConverter implements Converter<Date> {

    @Override
    public Class<Date> supportJavaTypeKey() {
        return Date.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public Date convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        String value = cellData.getStringValue();
        return DateUtil.parse(value, DatePattern.NORM_DATETIME_PATTERN);
    }

    @Override
    public CellData<Date> convertToExcelData(Date value, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) throws Exception {
        return new CellData<>(DateUtil.format(value, DatePattern.NORM_DATETIME_PATTERN));
    }
}

EasyExcel簡單使用,到此結(jié)束,打完收功。

以上就是SpringBoot整合EasyExcel實現(xiàn)文件導(dǎo)入導(dǎo)出的詳細內(nèi)容,更多關(guān)于SpringBoot整合EasyExcel的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java 多線程Thread與runnable的區(qū)別

    java 多線程Thread與runnable的區(qū)別

    這篇文章主要介紹了java 多線程Thread與runnable的區(qū)別的相關(guān)資料,java線程有兩種方法繼承thread類與實現(xiàn)runnable接口,下面就提供實例幫助大家理解,需要的朋友可以參考下
    2017-08-08
  • JAVA 16位ID生成工具類含16位不重復(fù)的隨機數(shù)數(shù)字+大小寫

    JAVA 16位ID生成工具類含16位不重復(fù)的隨機數(shù)數(shù)字+大小寫

    這篇文章主要介紹了JAVA 16位ID生成工具類含16位不重復(fù)的隨機數(shù)數(shù)字+大小寫,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-02-02
  • MybatisPlus3.3.0沒有MybatisPlusInterceptor類問題的解決方法

    MybatisPlus3.3.0沒有MybatisPlusInterceptor類問題的解決方法

    項目使用的是mybatis-plus-extension3.3.0依賴,然后在我使用分頁插件的時候,發(fā)現(xiàn)無法導(dǎo)入MybatisPlusInterceptor類所以本文給大家介紹了MybatisPlus3.3.0沒有MybatisPlusInterceptor類問題的解決方法,需要的朋友可以參考下
    2023-12-12
  • Java File類常用方法與文件過濾器詳解

    Java File類常用方法與文件過濾器詳解

    Java File類以抽象的方式代表文件名和目錄路徑名。該類主要用于文件和目錄的創(chuàng)建、文件的查找和文件的刪除等。File對象代表磁盤中實際存在的文件和目錄。本篇文章我們來講解File類的常用方法與文件過濾器
    2022-04-04
  • kotlin和Java的相互調(diào)用示例詳解

    kotlin和Java的相互調(diào)用示例詳解

    Kotlin 的設(shè)計過程中就考慮到了與 Java 的互操作性。在 Kotlin 中可以直接調(diào)用既有的 Java 代碼, 反過來在 Java 中也可以很流暢地使用 Kotlin 代碼,下面這篇文章主要給大家介紹了關(guān)于kotlin和Java的相互調(diào)用的相關(guān)資料,需要的朋友可以參考下。
    2018-02-02
  • 詳解Spring系列之@ComponentScan自動掃描組件

    詳解Spring系列之@ComponentScan自動掃描組件

    這篇文章主要介紹了Spring @ComponentScan自動掃描組件使用,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • SpringCloud feign無法注入接口的問題

    SpringCloud feign無法注入接口的問題

    這篇文章主要介紹了SpringCloud feign無法注入接口的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Java實現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的實例代碼

    Java實現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的實例代碼

    本文主要介紹了Java實現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的實例代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-02-02
  • idea編輯XML文件出現(xiàn):Tag name expected報錯的解決

    idea編輯XML文件出現(xiàn):Tag name expected報錯的解決

    在XML中,一些特殊字符不能直接使用,因為它們被保留用于XML文檔的結(jié)構(gòu)和語法,如果直接使用這些保留字符,會導(dǎo)致解析錯誤,正確的做法是使用實體引用或字符引用,或者使用CDATA標記將這些字符包裹起來
    2025-01-01
  • SpringSecurit鹽值加密的密碼驗證以及強密碼驗證過程

    SpringSecurit鹽值加密的密碼驗證以及強密碼驗證過程

    在密碼加密過程中,鹽值的使用可以增強密碼的安全性,如果忘記存儲鹽值,將無法驗證密碼,強密碼應(yīng)包含數(shù)字、字母和特殊字符,長度應(yīng)在8到30位之間,以提高賬戶安全
    2023-03-03

最新評論