欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java多種方式實(shí)現(xiàn)Excel轉(zhuǎn)Pdf的保姆級(jí)教程

 更新時(shí)間:2025年08月21日 09:40:47   作者:暗武逢天  
在企業(yè)級(jí)系統(tǒng)使用或日常使用中,我們經(jīng)常使用excel表格數(shù)據(jù)進(jìn)行瀏覽數(shù)據(jù),但有時(shí)候我們會(huì)想要將excel轉(zhuǎn)換成pdf進(jìn)行預(yù)覽使用,本篇博文以java進(jìn)行編寫多種實(shí)現(xiàn)方式實(shí)現(xiàn)多sheet頁(yè)excel轉(zhuǎn)換一個(gè)pdf的需求,需要的朋友可以參考下

需求介紹

在企業(yè)級(jí)系統(tǒng)使用或日常使用中,我們經(jīng)常使用excel表格數(shù)據(jù)進(jìn)行瀏覽數(shù)據(jù),但有時(shí)候我們會(huì)想要將excel轉(zhuǎn)換成pdf進(jìn)行預(yù)覽使用,這時(shí)就需要進(jìn)行程序編寫實(shí)現(xiàn)這個(gè)需求,本篇博文以java進(jìn)行編寫多種實(shí)現(xiàn)方式實(shí)現(xiàn)多sheet頁(yè)excel轉(zhuǎn)換一個(gè)pdf的需求

itextpdf實(shí)現(xiàn)

引入maven依賴

引入所需依賴,下面五個(gè)是主要依賴

        <dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itextpdf</artifactId>
			<version>5.5.13</version>
		</dependency>
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itext-asian</artifactId>
			<version>5.2.0</version>
		</dependency>

具體哪幾個(gè)博主忘了,如果上面依賴導(dǎo)入后寫代碼還有缺失的,可以直接把下面完整的都copy下

        <dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
		</dependency>
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>1.10</version>
		</dependency>
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.4</version>
		</dependency>
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>4.1.0</version>
		</dependency>
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itextpdf</artifactId>
			<version>5.5.13</version>
		</dependency>
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>itext-asian</artifactId>
			<version>5.2.0</version>
		</dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.27</version>
        </dependency>
        
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
            <scope>provided</scope>
        </dependency>

代碼實(shí)現(xiàn)

由于在使用時(shí),有時(shí)候excel里會(huì)插入圖片,所以我們?cè)谵D(zhuǎn)換時(shí)候需要考慮到圖片的業(yè)務(wù)

先對(duì)圖片類型進(jìn)行建模處理

import java.io.Serializable;

/**
 * 圖片信息
 */
public class PicturesInfo implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 最小行
     */
    private int minRow;

    /**
     * 最大行
     */
    private int maxRow;

    /**
     * 最小列
     */
    private int minCol;

    /**
     * 最大列
     */
    private int maxCol;

    /**
     * 擴(kuò)展
     */
    private String ext;

    /**
     * 圖片數(shù)據(jù)
     */
    private byte[] pictureData;

    public int getMinRow() {
        return minRow;
    }

    public PicturesInfo setMinRow(int minRow) {
        this.minRow = minRow;
        return this;
    }

    public int getMaxRow() {
        return maxRow;
    }

    public PicturesInfo setMaxRow(int maxRow) {
        this.maxRow = maxRow;
        return this;
    }

    public int getMinCol() {
        return minCol;
    }

    public PicturesInfo setMinCol(int minCol) {
        this.minCol = minCol;
        return this;
    }

    public int getMaxCol() {
        return maxCol;
    }

    public PicturesInfo setMaxCol(int maxCol) {
        this.maxCol = maxCol;
        return this;
    }

    public String getExt() {
        return ext;
    }

    public PicturesInfo setExt(String ext) {
        this.ext = ext;
        return this;
    }

    public byte[] getPictureData() {
        return pictureData;
    }

    public PicturesInfo setPictureData(byte[] pictureData) {
        this.pictureData = pictureData;
        return this;
    }
}

書寫轉(zhuǎn)換工具類

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.List;

/**
 * Excel轉(zhuǎn)PDF
 * @author 廖航
 * @date 2024-08-29 10:52
 */
//@UtilityClass
//@Slf4j
public class ExcelToPdfUtil {

    /**
     * 日志輸出
     */
//    private static final log log = log.getlog(ExcelToPdfUtil.class);

    /**
     * 單元格隊(duì)列
     */
    static Set<String> cellSet = new HashSet<>();

    /**
     * Excel轉(zhuǎn)PDF
     *
     * @param excelPath Excel文件路徑
     * @param pdfPath PDF文件路徑
     * @param excelSuffix Excel文件后綴
     */
    public static void excelToPdf(String excelPath, String pdfPath, String excelSuffix) {
        try (InputStream in = Files.newInputStream(Paths.get(excelPath));
             OutputStream out = Files.newOutputStream(Paths.get(pdfPath))) {
            ExcelToPdfUtil.excelToPdf(in, out, excelSuffix);
        } catch (Exception e) {

        }
    }

    /**
     * Excel轉(zhuǎn)PDF并寫入輸出流
     *
     * @param inStream    Excel輸入流
     * @param outStream   PDF輸出流
     * @param excelSuffix Excel類型 .xls 和 .xlsx
     * @throws Exception 異常信息
     */
    public static void excelToPdf(InputStream inStream, OutputStream outStream, String excelSuffix) throws Exception {


        // 輸入流轉(zhuǎn)workbook,獲取sheet  讀取Excel文件
        Workbook workbook = getPoiWorkbookByFileStream(inStream, excelSuffix);
        //設(shè)置pdf紙張大小 PageSize.A4 A4橫向
//        Document document = new Document(PageSize.B0);
        Document document = new Document(PageSize.A2.rotate());
//        綁定PDF寫入器到輸出流
        PdfWriter.getInstance(document, outStream);
        // 設(shè)置頁(yè)面四周邊距
        document.setMargins(50, 50, 30, 30);
        document.open(); // 準(zhǔn)備開始寫入內(nèi)容
        //設(shè)置基本字體
        BaseFont baseFont = BaseFont.createFont("C:\\Windows\\Fonts\\simsun.ttc,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        for (int j = 0; j < workbook.getNumberOfSheets(); j++) {
            if(j != 0) {
                document.newPage(); // 新的Sheet開始新的一頁(yè)
            }
            //獲取sheet
            Sheet sheet = workbook.getSheetAt(j);

            // 獲取列寬度占比
            float[] widths = getColWidth(sheet);
            PdfPTable table = new PdfPTable(widths);
            // 設(shè)置表格寬度為頁(yè)面內(nèi)容區(qū)域的百分比
            table.setWidthPercentage(100);

            int colCount = widths.length;
            // 遍歷行
            for (int rowIndex = sheet.getFirstRowNum(); rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (Objects.isNull(row)) {
                    // 插入空對(duì)象
                    for (int i = 0; i < colCount; i++) {
                        table.addCell(createPdfPCell(null, 0, 11f, null));
                    }
                } else {
                    // 遍歷單元格
                    for (int columnIndex = 0; (columnIndex < row.getLastCellNum() || columnIndex < colCount) && columnIndex > -1; columnIndex++) {
                        PdfPCell pCell = excelCellToPdfCell(sheet, row.getCell(columnIndex), baseFont);
                        // 是否合并單元格
                        if (isMergedRegion(sheet, rowIndex, columnIndex)) {
                            int[] span = getMergedSpan(sheet, rowIndex, columnIndex);
                            //忽略合并過(guò)的單元格
                            boolean mergedCell = span[0] == 1 && span[1] == 1;
                            if (mergedCell) {
                                continue;
                            }
                            pCell.setRowspan(span[0]);
                            pCell.setColspan(span[1]);
                        }

                        table.addCell(pCell);
                    }
                }
            }

            document.add(table);
        }
        document.close();

    }


    protected static CellRangeAddress getColspanRowspanByExcel(int rowIndex, int colIndex,Sheet sheet) {
        CellRangeAddress result = null;
        int num = sheet.getNumMergedRegions();
        for (int i = 0; i < num; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            if (range.getFirstColumn() == colIndex && range.getFirstRow() == rowIndex) {
                result = range;
            }
        }
        return result;
    }

    // 獲取Workbook對(duì)象
    public static Workbook getPoiWorkbookByFileStream(InputStream inputStream, String excelSuffix) throws IOException {
        if (excelSuffix.endsWith(".xlsx")) {
            return new XSSFWorkbook(inputStream);
        } else {
            return new HSSFWorkbook(inputStream);
        }
    }

    /**
     * 單元格轉(zhuǎn)換,poi cell 轉(zhuǎn)換為 itext cell
     *
     * @param sheet     poi sheet頁(yè)
     * @param excelCell poi 單元格
     * @param baseFont  基礎(chǔ)字體
     * @return PDF單元格
     */
    private static PdfPCell excelCellToPdfCell(Sheet sheet, Cell excelCell, BaseFont baseFont) throws Exception {
        if (Objects.isNull(excelCell)) {
            return createPdfPCell(null, 0, 11f, null);
        }
        int rowIndex = excelCell.getRowIndex();
        int columnIndex = excelCell.getColumnIndex();
        // 圖片信息
        List<PicturesInfo> infos = getAllPictureInfos(sheet, rowIndex, rowIndex, columnIndex, columnIndex, false);
        PdfPCell pCell;
        if (infos != null && !infos.isEmpty()) {
            Image image = Image.getInstance(infos.get(0).getPictureData());
            // 調(diào)整圖片大小
            image.scaleAbsolute(527, 215);
            pCell = new PdfPCell(image);
        } else {
            Font excelFont = getExcelFont(sheet, excelCell);
            //設(shè)置單元格字體
            com.itextpdf.text.Font pdFont = new com.itextpdf.text.Font(baseFont, excelFont.getFontHeightInPoints(), excelFont.getBold() ? 1 : 0, BaseColor.BLACK);
            Integer border = hasBorder(excelCell) ? null : 0;
            String excelCellValue = getExcelCellValue(excelCell);
            pCell = createPdfPCell(excelCellValue, border, excelCell.getRow().getHeightInPoints(), pdFont);
        }
        // 水平居中
        pCell.setHorizontalAlignment(getHorAlign(excelCell.getCellStyle().getAlignment().getCode()));
        // 垂直對(duì)齊
        pCell.setVerticalAlignment(getVerAlign(excelCell.getCellStyle().getVerticalAlignment().getCode()));
        return pCell;
    }


    /**
     * 創(chuàng)建itext pdf 單元格
     *
     * @param content       單元格內(nèi)容
     * @param border        邊框
     * @param minimumHeight 高度
     * @param pdFont        字體
     * @return pdf cell
     */
    private static PdfPCell createPdfPCell(String content, Integer border, Float minimumHeight, com.itextpdf.text.Font pdFont) {
        String contentValue = content == null ? "" : content;
        com.itextpdf.text.Font pdFontNew = pdFont == null ? new com.itextpdf.text.Font() : pdFont;
        PdfPCell pCell = new PdfPCell(new Phrase(contentValue, pdFontNew));
        if (Objects.nonNull(border)) {
            pCell.setBorder(border);
        }
        if (Objects.nonNull(minimumHeight)) {
            //設(shè)置單元格的最小高度
            pCell.setMinimumHeight(minimumHeight);

        }

        return pCell;
    }

    /**
     * excel垂直對(duì)齊方式映射到pdf對(duì)齊方式
     *
     * @param align 對(duì)齊
     * @return 結(jié)果
     */
    private static int getVerAlign(int align) {
        switch (align) {
            case 2:
                return com.itextpdf.text.Element.ALIGN_BOTTOM;
            case 3:
                return com.itextpdf.text.Element.ALIGN_TOP;
            default:
                return com.itextpdf.text.Element.ALIGN_MIDDLE;
        }
    }

    /**
     * excel水平對(duì)齊方式映射到pdf水平對(duì)齊方式
     *
     * @param align 對(duì)齊
     * @return 結(jié)果
     */
    private static int getHorAlign(int align) {
        switch (align) {
            case 1:
                return com.itextpdf.text.Element.ALIGN_LEFT;
            case 3:
                return com.itextpdf.text.Element.ALIGN_RIGHT;
            default:
                return com.itextpdf.text.Element.ALIGN_CENTER;
        }
    }

    /*============================================== POI獲取圖片及文本內(nèi)容工具方法 ==============================================*/

    /**
     * 獲取字體
     *
     * @param sheet excel 轉(zhuǎn)換的sheet頁(yè)
     * @param cell  單元格
     * @return 字體
     */
    private static Font getExcelFont(Sheet sheet, Cell cell) {
        // xls
        if (sheet instanceof HSSFSheet) {
            Workbook workbook = sheet.getWorkbook();
            return ((HSSFCell) cell).getCellStyle().getFont(workbook);
        }
        // xlsx
        return ((XSSFCell) cell).getCellStyle().getFont();
    }

    /**
     * 判斷excel單元格是否有邊框
     *
     * @param excelCell 單元格
     * @return 結(jié)果
     */
    private static boolean hasBorder(Cell excelCell) {
        CellStyle style = excelCell.getCellStyle();

        BorderStyle top = style.getBorderTop();
        BorderStyle bottom = style.getBorderBottom();
        BorderStyle left = style.getBorderLeft();
        BorderStyle right = style.getBorderRight();

        return top != BorderStyle.NONE ||
                bottom != BorderStyle.NONE ||
                left != BorderStyle.NONE ||
                right != BorderStyle.NONE;
    }

    /**
     * 判斷單元格是否是合并單元格
     *
     * @param sheet 表
     * @param row 行
     * @param column 列
     * @return 結(jié)果
     */
    private static boolean isMergedRegion(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (row >= firstRow && row <= lastRow) {
                if (column >= firstColumn && column <= lastColumn) {
                    return true;
                }
            }
        }
        return false;
    }



    /**
     * 計(jì)算合并單元格合并的跨行跨列數(shù)
     *
     * @param sheet 表
     * @param row 行
     * @param column 列
     * @return 結(jié)果
     */
    private static int[] getMergedSpan(Sheet sheet, int row, int column) {
        int sheetMergeCount = sheet.getNumMergedRegions();
        int[] span = {1, 1};
        for (int i = 0; i < sheetMergeCount; i++) {
            CellRangeAddress range = sheet.getMergedRegion(i);
            int firstColumn = range.getFirstColumn();
            int lastColumn = range.getLastColumn();
            int firstRow = range.getFirstRow();
            int lastRow = range.getLastRow();
            if (firstColumn == column && firstRow == row) {
                span[0] = lastRow - firstRow + 1;
                span[1] = lastColumn - firstColumn + 1;
                break;
            }
        }
        return span;
    }

    /**
     * 獲取excel中每列寬度的占比
     *
     * @param sheet 表
     * @return 結(jié)果
     */
    private static float[] getColWidth(Sheet sheet) {
        int rowNum = getMaxColRowNum(sheet);
        Row row = sheet.getRow(rowNum);
        int cellCount = row.getPhysicalNumberOfCells();
        int[] colWidths = new int[cellCount];
        int sum = 0;

        for (int i = row.getFirstCellNum(); i < cellCount; i++) {
            Cell cell = row.getCell(i);
            if (cell != null) {
                colWidths[i] = sheet.getColumnWidth(i);
                sum += sheet.getColumnWidth(i);
            }
        }

        float[] colWidthPer = new float[cellCount];
        for (int i = row.getFirstCellNum(); i < cellCount; i++) {
            colWidthPer[i] = (float) colWidths[i] / sum * 100;
        }
        return colWidthPer;
    }

    /**
     * 獲取excel中列數(shù)最多的行號(hào)
     *
     * @param sheet 表
     * @return 結(jié)果
     */
    private static int getMaxColRowNum(Sheet sheet) {
        int rowNum = 0;
        int maxCol = 0;
        for (int r = sheet.getFirstRowNum(); r < sheet.getPhysicalNumberOfRows(); r++) {
            Row row = sheet.getRow(r);
            if (row != null && maxCol < row.getPhysicalNumberOfCells()) {
                maxCol = row.getPhysicalNumberOfCells();
                rowNum = r;
            }
        }
        return rowNum;
    }

    /**
     * poi 根據(jù)單元格類型獲取單元格內(nèi)容
     *
     * @param excelCell poi單元格
     * @return 單元格內(nèi)容文本
     */
    public static String getExcelCellValue(Cell excelCell) {
//        if (excelCell == null) {
//            return "";
//        }
//        // 判斷數(shù)據(jù)的類型
//        CellType cellType = excelCell.getCellType();
//
//        if (cellType == CellType.STRING) {
//            return excelCell.getStringCellValue();
//        }
//        if (cellType == CellType.BOOLEAN) {
//            return String.valueOf(excelCell.getBooleanCellValue());
//        }
//        if (cellType == CellType.FORMULA) {
//            return excelCell.getCellFormula();
//        }
//        if (cellType == CellType.NUMERIC) {
//            // 處理日期格式、時(shí)間格式
//            if (DateUtil.isCellDateFormatted(excelCell)) {
//                SimpleDateFormat sdf;
//                // 驗(yàn)證short值
//                if (excelCell.getCellStyle().getDataFormat() == 14) {
//                    sdf = new SimpleDateFormat("yyyy/MM/dd");
//                } else if (excelCell.getCellStyle().getDataFormat() == 21) {
//                    sdf = new SimpleDateFormat("HH:mm:ss");
//                } else if (excelCell.getCellStyle().getDataFormat() == 22) {
//                    sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
//                } else {
//                    throw new RuntimeException("日期格式錯(cuò)誤!!!");
//                }
//                Date date = excelCell.getDateCellValue();
//                return sdf.format(date);
//            } else if (excelCell.getCellStyle().getDataFormat() == 0) {
//                //處理數(shù)值格式
//                DataFormatter formatter = new DataFormatter();
//                return formatter.formatCellValue(excelCell);
//            }
//        }
//        if (cellType == CellType.ERROR) {
//            return "非法字符";
//        }
//        return "";
        if (excelCell == null) {
            return "";
        }

        DataFormatter formatter = new DataFormatter();
        return formatter.formatCellValue(excelCell);
    }


    /**
     * 根據(jù)sheet和單元格信息獲取圖片
     *
     * @param sheet        sheet表
     * @param minRow       最小行
     * @param maxRow       最大行
     * @param minCol       最小列
     * @param maxCol       最大列
     * @param onlyInternal 是否內(nèi)部
     * @return 圖片集合
     * @throws Exception 異常
     */
    public static List<PicturesInfo> getAllPictureInfos(Sheet sheet, Integer minRow, Integer maxRow, Integer minCol,
                                                        Integer maxCol, boolean onlyInternal) throws Exception {
        if (sheet instanceof HSSFSheet) {
            return getXLSAllPictureInfos((HSSFSheet) sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
        } else if (sheet instanceof XSSFSheet) {
            return getXLSXAllPictureInfos((XSSFSheet) sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
        } else {
            throw new Exception("未處理類型,沒有為該類型添加:GetAllPicturesInfos()擴(kuò)展方法!");
        }
    }

    /**
     * 獲取XLS圖片信息
     *
     * @param sheet 表
     * @param minRow 最小行
     * @param maxRow 最大行
     * @param minCol 最小列
     * @param maxCol 最大列
     * @param onlyInternal 只在內(nèi)部
     * @return 圖片信息列表
     */
    private static List<PicturesInfo> getXLSAllPictureInfos(HSSFSheet sheet, Integer minRow, Integer maxRow,
                                                            Integer minCol, Integer maxCol, Boolean onlyInternal) {
        List<PicturesInfo> picturesInfoList = new ArrayList<>();
        HSSFShapeContainer shapeContainer = sheet.getDrawingPatriarch();
        if (shapeContainer == null) {
            return picturesInfoList;
        }
        List<HSSFShape> shapeList = shapeContainer.getChildren();
        for (HSSFShape shape : shapeList) {
            if (shape instanceof HSSFPicture && shape.getAnchor() instanceof HSSFClientAnchor) {
                HSSFPicture picture = (HSSFPicture) shape;
                HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();

                if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),
                        anchor.getCol1(), anchor.getCol2(), onlyInternal)) {
//                    String item = StrUtil.format("{},{},{},{}", anchor.getRow1(), anchor.getRow2(), anchor.getCol1(), anchor.getCol2());
                    String item = String.format("%d,%d,%d,%d",
                            anchor.getRow1(),
                            anchor.getRow2(),
                            anchor.getCol1(),
                            anchor.getCol2());
                    if (cellSet.contains(item)) {
                        continue;
                    }
                    cellSet.add(item);
                    HSSFPictureData pictureData = picture.getPictureData();
                    picturesInfoList.add(new PicturesInfo()
                            .setMinRow(anchor.getRow1())
                            .setMaxRow(anchor.getRow2())
                            .setMinCol(anchor.getCol1())
                            .setMaxCol(anchor.getCol2())
                            .setPictureData(pictureData.getData())
                            .setExt(pictureData.getMimeType()));
                }
            }
        }
        return picturesInfoList;
    }

    /**
     * 獲取XLSX圖片信息
     *
     * @param sheet 表
     * @param minRow 最小行
     * @param maxRow 最大行
     * @param minCol 最小列
     * @param maxCol 最大列
     * @param onlyInternal 只在內(nèi)部
     * @return 圖片信息列表
     */
    private static List<PicturesInfo> getXLSXAllPictureInfos(XSSFSheet sheet, Integer minRow, Integer maxRow,
                                                             Integer minCol, Integer maxCol, Boolean onlyInternal) {
        List<PicturesInfo> picturesInfoList = new ArrayList<>();

        List<POIXMLDocumentPart> documentPartList = sheet.getRelations();
        for (POIXMLDocumentPart documentPart : documentPartList) {
            if (documentPart instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) documentPart;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    if (shape instanceof XSSFPicture) {
                        XSSFPicture picture = (XSSFPicture) shape;
                        XSSFClientAnchor anchor = picture.getPreferredSize();

                        if (isInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.getRow1(), anchor.getRow2(),
                                anchor.getCol1(), anchor.getCol2(), onlyInternal)) {
//                            String item = StrUtil.format("{},{},{},{}", anchor.getRow1(), anchor.getRow2(), anchor.getCol1(), anchor.getCol2());
                            String item = String.format("%d,%d,%d,%d",
                                    anchor.getRow1(),
                                    anchor.getRow2(),
                                    anchor.getCol1(),
                                    anchor.getCol2());
                            if (cellSet.contains(item)) {
                                continue;
                            }
                            cellSet.add(item);
                            XSSFPictureData pictureData = picture.getPictureData();
                            picturesInfoList.add(new PicturesInfo()
                                    .setMinRow(anchor.getRow1())
                                    .setMaxRow(anchor.getRow2())
                                    .setMinCol(anchor.getCol1())
                                    .setMaxCol(anchor.getCol2())
                                    .setPictureData(pictureData.getData())
                                    .setExt(pictureData.getMimeType()));
                        }
                    }
                }
            }
        }

        return picturesInfoList;
    }

    /**
     * 是內(nèi)部的或相交的
     *
     * @param rangeMinRow 最小行范圍
     * @param rangeMaxRow 最大行范圍
     * @param rangeMinCol 最小列范圍
     * @param rangeMaxCol 最大列范圍
     * @param pictureMinRow 圖片最小行
     * @param pictureMaxRow 圖片最大行
     * @param pictureMinCol 圖片最小列
     * @param pictureMaxCol 圖片最大列
     * @param onlyInternal 只在內(nèi)部
     * @return 結(jié)果
     */
    private static boolean isInternalOrIntersect(Integer rangeMinRow, Integer rangeMaxRow, Integer rangeMinCol,
                                                 Integer rangeMaxCol, int pictureMinRow, int pictureMaxRow, int pictureMinCol, int pictureMaxCol,
                                                 Boolean onlyInternal) {
        int _rangeMinRow = rangeMinRow == null ? pictureMinRow : rangeMinRow;
        int _rangeMaxRow = rangeMaxRow == null ? pictureMaxRow : rangeMaxRow;
        int _rangeMinCol = rangeMinCol == null ? pictureMinCol : rangeMinCol;
        int _rangeMaxCol = rangeMaxCol == null ? pictureMaxCol : rangeMaxCol;

        if (onlyInternal) {
            return (_rangeMinRow <= pictureMinRow && _rangeMaxRow >= pictureMaxRow && _rangeMinCol <= pictureMinCol
                    && _rangeMaxCol >= pictureMaxCol);
        } else {
            return ((Math.abs(_rangeMaxRow - _rangeMinRow) + Math.abs(pictureMaxRow - pictureMinRow) >= Math
                    .abs(_rangeMaxRow + _rangeMinRow - pictureMaxRow - pictureMinRow))
                    && (Math.abs(_rangeMaxCol - _rangeMinCol) + Math.abs(pictureMaxCol - pictureMinCol) >= Math
                    .abs(_rangeMaxCol + _rangeMinCol - pictureMaxCol - pictureMinCol)));
        }
    }


    public static void main(String[] args) {
        ExcelToPdfUtil.excelToPdf("原excel文件路徑.xlsx",
                "轉(zhuǎn)換后輸出pdf路徑.pdf", ".xlsx");

    }
}

測(cè)試時(shí)直接創(chuàng)建一個(gè)多sheet頁(yè)的excel表格,并填入一些測(cè)試數(shù)據(jù)進(jìn)行測(cè)試,查看轉(zhuǎn)換后的結(jié)果

在主方法里更改路徑進(jìn)行測(cè)試

等待程序執(zhí)行完后在導(dǎo)出路徑查看轉(zhuǎn)換后的pdf

點(diǎn)擊查看

可以看到轉(zhuǎn)換后的效果還是不錯(cuò)的,表格內(nèi)容寬度自動(dòng)使用pdf頁(yè)面的寬度,每個(gè)sheet頁(yè)都另起新的頁(yè)面,多個(gè)sheet頁(yè)拼接在一個(gè)pdf里,后續(xù)紙張大小參數(shù)等都可以在代碼里進(jìn)行靈活調(diào)整

aspose-cell實(shí)現(xiàn)

簡(jiǎn)介

Aspose.Cells for Java 是一款功能強(qiáng)大的 Java 庫(kù),專門用于操作 Microsoft Excel 文件而無(wú)需依賴 Microsoft Office。提供了豐富的API來(lái)創(chuàng)建、修改、轉(zhuǎn)換和打印Excel文檔。

主要功能包括但不限于:

  • 文件格式支持:全面支持 Excel 的各種格式,如 .xls.xlsx.xlsm.xltx.xltm 等。
  • 數(shù)據(jù)處理:輕松讀取、寫入及修改工作表中的數(shù)據(jù),支持復(fù)雜的數(shù)據(jù)類型與結(jié)構(gòu)。
  • 格式化:靈活設(shè)置單元格、行、列的格式,包括字體、顏色、邊框、背景色等,并支持條件格式化。
  • 圖表與圖形:創(chuàng)建、更新或刪除圖表,添加圖片和其他圖形元素到工作表中。
  • 公式計(jì)算:支持復(fù)雜的公式計(jì)算,確保數(shù)據(jù)準(zhǔn)確性。
  • PDF 轉(zhuǎn)換:高質(zhì)量地將 Excel 文檔轉(zhuǎn)換為 PDF 格式,同時(shí)支持自定義頁(yè)面大小、方向等屬性。
  • 安全性和保護(hù):對(duì) Excel 文件進(jìn)行加密、解密,以及設(shè)置打開或修改密碼。
  • 批量處理:高效處理大量數(shù)據(jù)集,適用于大規(guī)模數(shù)據(jù)操作場(chǎng)景。

特別亮點(diǎn)

  • 無(wú)須安裝 Microsoft Office:由于其獨(dú)立性,開發(fā)者可以在沒有安裝 MS Office 的環(huán)境中使用此庫(kù)執(zhí)行所有相關(guān)任務(wù)。
  • 跨平臺(tái)兼容性:完全基于Java開發(fā),可在任何支持Java的平臺(tái)上運(yùn)行。
  • 性能優(yōu)越:優(yōu)化了內(nèi)存管理和處理速度,即使對(duì)于大型文件也能保持良好的性能表現(xiàn)。

注意該jar包是收費(fèi)的,收費(fèi)版本試用時(shí)候會(huì)有水印和行數(shù)多少限制,一旦達(dá)到一定數(shù)據(jù)量可能會(huì)導(dǎo)致程序報(bào)錯(cuò),可以進(jìn)行破解使用

下載jar包

該jar包在國(guó)內(nèi)鏡像源里是拉取不到的,可以在官網(wǎng)直接下載jar包,后導(dǎo)入到本地使用

aspose官網(wǎng)鏈接

在官網(wǎng)里找到對(duì)應(yīng)版本依賴,如果是國(guó)外鏡像源或者其他源庫(kù)可以嘗試?yán)≡囋?如果沒有也可以直接下載jar包到本地后安裝到本地使用

點(diǎn)擊后下載

 輸入下面命令進(jìn)行安裝到本地

mvn install:install-file "-Dfile=jar包所在路徑\jar包名.jar" "-DgroupId=com.aspose" "-DartifactId=aspose-cells" "-Dversion=版本號(hào)" "-Dpackaging=jar"

修改對(duì)應(yīng)的jar包路徑和包名后在idea命令行里執(zhí)行安裝jar包

沒有報(bào)錯(cuò)說(shuō)明安裝成功,在pom文件里書寫下對(duì)應(yīng)的依賴刷新下maven即可

刷新下maven即可然后書寫測(cè)試類嘗試轉(zhuǎn)換

執(zhí)行轉(zhuǎn)換 

可以看到導(dǎo)出后的效果還是不錯(cuò)的,但是有水印

crack使用 

這里以aspose-cells-20.7 去除水印及次數(shù)限制破解作為示例

反編譯jar包

使用 jd-gui.exe 反編譯查看jar包,直接搜索 License

1.修改

  public static boolean isLicenseSet() {
    return (a != null);
  }

 改為

  public static boolean isLicenseSet() {
    return true;
  }

2.修改

  public void setLicense(InputStream stream) {
    Document document = null;
    if (stream != null)
      try {
        DocumentBuilder documentBuilder = zad.b();
        document = documentBuilder.parse(stream);
      } catch (Exception exception) {
        throw new CellsException(9, zf.a(new byte[] { 
                -20, 93, -23, 54, -20, -49, -59, 86, -9, -86, 
                49, 44, -59, 71, -52, -86, -90, 6, -90, -25, 
                -86, 1, -1, -92, -91, -126, 7, 113, -66, -95, 
                -121, 16, -122, -126, 7, 104, -40, -70, -10, -37, 
                126, 7, -111, -121, -121 }) + exception.getMessage());
      }  
    a(document);
  }

改成

  public void setLicense(InputStream paramInputStream){
    a = new License();
    zbiw.a();
  }

3.修改

  private static Date k(String paramString) {
    if (paramString == null || paramString.length() < 8)
      return null; 
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat(zf.a(new byte[] { 
            79, 89, 33, -52, 79, -121, -125, 33, 71, -126, 
            105, -121 }));
    try {
      return simpleDateFormat.parse(paramString);
    } catch (ParseException parseException) {
      throw new IllegalArgumentException(zf.a(new byte[] { 
              -21, -113, -77, 13, -115, 27, Byte.MIN_VALUE, 35, 103, -52, 
              -20, -106, 71, 95, 31, -73, -76, -38, 13, 31, 
              -91, -97, -102, 85, -68, -33, -19, -87, -127, -14, 
              78, -23, 6, -25, -94, 1, -97, -95, -57, -121 }));
    } 
  }

改成

  private static Date k(String paramString){
    return new Date(Long.MAX_VALUE);
  }

修改完后使用jdi保存所有的文件為另存

生成 aspose-cells-20.7-crack.jar

修改 class 這里使用 javassist:
新建一個(gè) Spring boot 項(xiàng)目:
pom 文件中引用 javassist

引入破解所需依賴

     <dependency><!--aspose的jar破解工具-->
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.20.0-GA</version>
        </dependency>

指定目錄生成修改后的License.class文件

    public static void crackAspose(String JarPath) throws Exception {
        // 這個(gè)是得到反編譯的池
        ClassPool pool = ClassPool.getDefault();

        // 取得需要反編譯的jar文件,設(shè)定路徑
        pool.insertClassPath(JarPath);

        CtClass cc_License = pool.get("com.aspose.cells.License");

        CtMethod method_isLicenseSet = cc_License.getDeclaredMethod("isLicenseSet");
        method_isLicenseSet.setBody("return true;");

        CtClass cc_License2 = pool.get("com.aspose.cells.License");
        CtMethod method_setLicense = cc_License2.getDeclaredMethod("setLicense");
        method_setLicense.setBody("{    a = new com.aspose.cells.License();\n" +
                "    com.aspose.cells.zbiw.a();}");

        CtMethod method_k = cc_License.getDeclaredMethod("k");
        method_k.setBody("return new java.util.Date(Long.MAX_VALUE);");


        cc_License.writeFile("輸出目錄路徑");
    }

執(zhí)行該方法

在指定目錄下可以看到生成后的編譯文件

復(fù)制一個(gè) aspose-cells-20.7.jar 改名為 aspose-cells-20.7-crack.zip 然后解壓

把剛才生成的 License.class 文件 替換到解壓的源代碼中。

造一個(gè) License xml 文件,這里文件名為 com.aspose.cells.lic_2999.xml, 位置直接放源代碼解壓的根目錄

文件內(nèi)容為:

<License>
  <Data>
    <Products>
      <Product>Aspose.Cells for Java</Product>
    </Products>
    <EditionType>Enterprise</EditionType>
    <SubscriptionExpiry>29991231</SubscriptionExpiry>
    <LicenseExpiry>29991231</LicenseExpiry>
    <SerialNumber>evilrule</SerialNumber>
  </Data>
  <Signature>evilrule</Signature>
</License>

防止文件指紋校驗(yàn),我們需要?jiǎng)h除掉源代碼解壓包中的 META_INF 文件夾。
最后的根目錄:

壓縮源代碼(注意要是 zip 格式)

然后重命名后綴為:jar

測(cè)試 aspose-cells-20.7-crack.jar 使用

封裝一個(gè) License 驗(yàn)證方法:

public static boolean authrolizeLicense() {
    boolean result = false;
    try {
        InputStream is = com.aspose.cells.License.class.getResourceAsStream("/com.aspose.cells.lic_2999.xml");
        License asposeLicense = new License();
        asposeLicense.setLicense(is);
        is.close();
        result = true;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return result;
}

修改 main 方法測(cè)試使用:

    public static void main(String[] args) {



        // 測(cè)試破解后的 aspose-cells-20.7-crack.jar
        boolean auth = authrolizeLicense();
        if (!auth) {
            System.out.println("aspose 許可無(wú)效!");
            return;
        }


        System.out.println("aspose 已就緒!");


        try{
            Workbook wb = new Workbook("F:\\aaa123.xlsx");
            Worksheet ws = wb.getWorksheets().get(0);

            ImageOrPrintOptions imgOptions = new ImageOrPrintOptions();
            imgOptions.setImageFormat(ImageFormat.getPng());
            imgOptions.setCellAutoFit(true);
            imgOptions.setOnePagePerSheet(true);
            SheetRender render = new SheetRender(ws, imgOptions);

            render.toImage(0, "F:\\aaa\\123.png");

        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

這里圖片和excel可以隨便搞一個(gè)嘗試測(cè)試使用

先生成圖片再轉(zhuǎn)pdf

前面的破解工作都做好后就可以嘗試測(cè)試了,aspose可以先將excel轉(zhuǎn)成圖片后再轉(zhuǎn)成pdf

 public static void main(String[] args) {
        // 授權(quán)檢查(假設(shè)你已經(jīng)破解)
        boolean auth = authrolizeLicense();
        if (!auth) {
            System.out.println("aspose 許可無(wú)效!");
            return;
        }

        System.out.println("aspose 已就緒!");

        try {
            Workbook wb = new Workbook("C:\\Users\\d\\Desktop\\excelToPdf\\奧特曼.xlsx");
            ImageOrPrintOptions imgOptions = new ImageOrPrintOptions();
            imgOptions.setImageFormat(ImageFormat.getPng());
            imgOptions.setCellAutoFit(true);
            imgOptions.setOnePagePerSheet(true);

            String outputPdfPath = "C:\\Users\\d\\Desktop\\excelToPdf\\奧特曼Aspose導(dǎo)出圖片版.pdf";

            // 創(chuàng)建一個(gè)無(wú)邊距的文檔
            Document document = new Document(PageSize.A4);  // 使用 A4 紙張尺寸
            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdfPath));

            // 設(shè)置頁(yè)面無(wú)邊距(非常重要)
            document.setMargins(0, 0, 0, 0);  // 左、右、上、下全部為 0
            document.open();

            for (int i = 0; i < wb.getWorksheets().getCount(); i++) {
                Worksheet ws = wb.getWorksheets().get(i);
                SheetRender render = new SheetRender(ws, imgOptions);
                String imageFilePath = "C:\\Users\\d\\Desktop\\excelToPdf\\sheet_" + i + ".png";
                render.toImage(0, imageFilePath);

                Image img = Image.getInstance(imageFilePath);

                // 自動(dòng)縮放圖片以適配頁(yè)面寬度和高度
                img.scaleToFit(document.getPageSize().getWidth(), document.getPageSize().getHeight());

                // 居中顯示(iText 默認(rèn)就是居中的,但我們可以更明確地設(shè)置)
                img.setAlignment(Image.ALIGN_CENTER);

                // 新增一頁(yè)
                document.newPage();

                // 插入圖片到當(dāng)前頁(yè)面
                document.add(img);
            }

            document.close();
            writer.close();

            System.out.println("? PDF 文件已生成: " + outputPdfPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

執(zhí)行測(cè)試

查看生成的效果

可以看到原有的水印都沒了

直接轉(zhuǎn)換

aspose也可以直接進(jìn)行轉(zhuǎn)換

    public static void main(String[] args) throws Exception {
//        // 授權(quán)檢查(假設(shè)你已經(jīng)破解)
//        boolean auth = authrolizeLicense();
//        if (!auth) {
//            System.out.println("aspose 許可無(wú)效!");
//            return;
//        }
//
//        System.out.println("aspose 已就緒!");
//
//        try {
//            Workbook wb = new Workbook("C:\\Users\\d\\Desktop\\excelToPdf\\奧特曼.xlsx");
//            ImageOrPrintOptions imgOptions = new ImageOrPrintOptions();
//            imgOptions.setImageFormat(ImageFormat.getPng());
//            imgOptions.setCellAutoFit(true);
//            imgOptions.setOnePagePerSheet(true);
//
//            String outputPdfPath = "C:\\Users\\d\\Desktop\\excelToPdf\\奧特曼aspose導(dǎo)出圖片版.pdf";
//
//            // 創(chuàng)建一個(gè)無(wú)邊距的文檔
//            Document document = new Document(PageSize.A4);  // 使用 A4 紙張尺寸
//            PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(outputPdfPath));
//
//            // 設(shè)置頁(yè)面無(wú)邊距(非常重要)
//            document.setMargins(0, 0, 0, 0);  // 左、右、上、下全部為 0
//            document.open();
//
//            for (int i = 0; i < wb.getWorksheets().getCount(); i++) {
//                Worksheet ws = wb.getWorksheets().get(i);
//                SheetRender render = new SheetRender(ws, imgOptions);
//                String imageFilePath = "C:\\Users\\d\\Desktop\\excelToPdf\\sheet_" + i + ".png";
//                render.toImage(0, imageFilePath);
//
//                Image img = Image.getInstance(imageFilePath);
//
//                // 自動(dòng)縮放圖片以適配頁(yè)面寬度和高度
//                img.scaleToFit(document.getPageSize().getWidth(), document.getPageSize().getHeight());
//
//                // 居中顯示(iText 默認(rèn)就是居中的,但我們可以更明確地設(shè)置)
//                img.setAlignment(Image.ALIGN_CENTER);
//
//                // 新增一頁(yè)
//                document.newPage();
//
//                // 插入圖片到當(dāng)前頁(yè)面
//                document.add(img);
//            }
//
//            document.close();
//            writer.close();
//
//            System.out.println("? PDF 文件已生成: " + outputPdfPath);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }


        // 加載 Excel 文件
        Workbook workbook = new Workbook("C:\\Users\\d\\Desktop\\excelToPdf\\奧特曼.xlsx");

        // 設(shè)置 PDF 導(dǎo)出選項(xiàng)
        PdfSaveOptions saveOpts = new PdfSaveOptions();

        // 設(shè)置頁(yè)面尺寸為 A2(單位是 像素 或 毫米,這里使用像素)
        // A2 尺寸:4961 x 7016 像素(分辨率為 300 DPI)
        PageSetup pageSetup = workbook.getWorksheets().get(0).getPageSetup();
        pageSetup.setPaperSize(PaperSizeType.PAPER_A_3); // 設(shè)置為 A2 紙張
        pageSetup.setOrientation(PageOrientationType.LANDSCAPE); // 設(shè)置為橫向

        // 如果你想對(duì)所有 sheet 都生效,可以循環(huán)設(shè)置每個(gè) sheet 的頁(yè)面屬性
        for (int i = 0; i < workbook.getWorksheets().getCount(); i++) {
            Worksheet sheet = workbook.getWorksheets().get(i);
            sheet.getPageSetup().setPaperSize(PaperSizeType.PAPER_A_3);
            sheet.getPageSetup().setOrientation(PageOrientationType.LANDSCAPE);
        }

        // 設(shè)置每張工作表輸出為一頁(yè) PDF
        saveOpts.setOnePagePerSheet(true);

        // 導(dǎo)出為 PDF
        String outputPdfPath = "C:\\Users\\d\\Desktop\\excelToPdf\\奧特曼aspose導(dǎo)出.pdf";
        workbook.save(outputPdfPath, saveOpts);

        System.out.println("? 已成功導(dǎo)出 A2 橫向 PDF: " + outputPdfPath);
    }

查看效果

這種方式雖然可直接轉(zhuǎn)換,但是還是會(huì)有水印,所以還是推薦先轉(zhuǎn)圖片后再轉(zhuǎn)pdf的方式

以上就是Java多種方式實(shí)現(xiàn)Excel轉(zhuǎn)Pdf的保姆級(jí)教程的詳細(xì)內(nèi)容,更多關(guān)于Java Excel轉(zhuǎn)Pdf的多種方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • springboot請(qǐng)求找不到路徑異常的問題

    springboot請(qǐng)求找不到路徑異常的問題

    這篇文章主要介紹了springboot請(qǐng)求找不到路徑異常的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • MyBatis中的collection兩種使用方法及效率比較

    MyBatis中的collection兩種使用方法及效率比較

    collection主要是應(yīng)對(duì)表關(guān)系是一對(duì)多的情況,本文主要介紹了MyBatis中的collection兩種使用方法及效率比較,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • java?-jar啟動(dòng)參數(shù)設(shè)置file.encoding編碼,解決中文亂碼的問題

    java?-jar啟動(dòng)參數(shù)設(shè)置file.encoding編碼,解決中文亂碼的問題

    這篇文章主要介紹了java?-jar啟動(dòng)參數(shù)設(shè)置file.encoding編碼,解決中文亂碼的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java源碼解析之HashMap的put、resize方法詳解

    Java源碼解析之HashMap的put、resize方法詳解

    這篇文章主要介紹了Java源碼解析之HashMap的put、resize方法詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很大的幫助,需要的朋友可以參考下
    2021-04-04
  • 深入理解Java8新特性之接口中的默認(rèn)方法和靜態(tài)方法

    深入理解Java8新特性之接口中的默認(rèn)方法和靜態(tài)方法

    從Java8開始,程序允許在接口中包含帶有具體實(shí)現(xiàn)的方法,使用default修飾,這類方法就是默認(rèn)方法。默認(rèn)方法在接口中可以添加多個(gè),并且Java8提供了很多對(duì)應(yīng)的接口默認(rèn)方法,接下來(lái)讓我們一起來(lái)看看吧
    2021-11-11
  • Java  Thread多線程詳解及用法解析

    Java Thread多線程詳解及用法解析

    本文主要介紹Java 多線程詳解及用法,這里整理了詳細(xì)資料及簡(jiǎn)單實(shí)現(xiàn)代碼,有需要的小伙伴可以參考下
    2016-09-09
  • Java Mybatis框架Dao層的實(shí)現(xiàn)與映射文件以及核心配置文件詳解分析

    Java Mybatis框架Dao層的實(shí)現(xiàn)與映射文件以及核心配置文件詳解分析

    MyBatis 是一款優(yōu)秀的持久層框架,它支持自定義 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 免除了幾乎所有的 JDBC 代碼以及設(shè)置參數(shù)和獲取結(jié)果集的工作。MyBatis 可以通過(guò)簡(jiǎn)單的 XML 或注解來(lái)配置和映射原始類型、接口和 Java POJO為數(shù)據(jù)庫(kù)中的記錄
    2021-10-10
  • SpringBoot中的ApplicationListener事件監(jiān)聽器使用詳解

    SpringBoot中的ApplicationListener事件監(jiān)聽器使用詳解

    這篇文章主要介紹了SpringBoot中的ApplicationListener事件監(jiān)聽器使用詳解,ApplicationListener是應(yīng)用程序的事件監(jiān)聽器,繼承自java.util.EventListener標(biāo)準(zhǔn)接口,采用觀察者設(shè)計(jì)模式,需要的朋友可以參考下
    2023-11-11
  • 詳解SpringBoot簡(jiǎn)化配置分析總結(jié)

    詳解SpringBoot簡(jiǎn)化配置分析總結(jié)

    這篇文章主要介紹了詳解SpringBoot簡(jiǎn)化配置分析總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java語(yǔ)言資源國(guó)際化步驟解析

    Java語(yǔ)言資源國(guó)際化步驟解析

    這篇文章主要介紹了Java語(yǔ)言資源國(guó)際化步驟解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10

最新評(píng)論