使用java實現(xiàn)字符編碼轉(zhuǎn)換(附源碼)
1. 項目背景詳細(xì)介紹
隨著全球化的軟件應(yīng)用越來越廣泛,不同平臺與系統(tǒng)之間的數(shù)據(jù)交換,常常面臨字符集不一致的問題。尤其在中國國內(nèi),Windows 默認(rèn)使用 GBK,而 Linux、macOS、Web 端及 Java 默認(rèn)使用 UTF-8。若不進(jìn)行正確的編碼轉(zhuǎn)換,就會導(dǎo)致中文出現(xiàn)亂碼、數(shù)據(jù)丟失,嚴(yán)重影響用戶體驗與系統(tǒng)穩(wěn)定性。
Java 語言原生支持多種字符集,并提供豐富的 I/O 與轉(zhuǎn)換 API。但初學(xué)者往往只停留在單純的 new String(bytes, "UTF-8") 或 String.getBytes("GBK"),缺乏對大文件、網(wǎng)絡(luò)流、隨機(jī)訪問、字符流/字節(jié)流混合、異常處理、性能優(yōu)化、可配置化等生產(chǎn)環(huán)境需求的全方位掌握。
本項目目標(biāo)是從易到難、由淺入深地,構(gòu)建一個完整的“字符編碼轉(zhuǎn)換”解決方案,包括:
- 支持文件批量轉(zhuǎn)換(單個文件、整個目錄)
- 支持標(biāo)準(zhǔn)輸入/輸出流的編碼轉(zhuǎn)換(管道模式)
- 支持自定義源字符集與目標(biāo)字符集
- 提供命令行工具與圖形化界面兩種使用方式
- 支持大文件時的內(nèi)存與性能優(yōu)化
- 對轉(zhuǎn)換過程中的異常、日志與報告進(jìn)行完整管理
通過本項目,您將系統(tǒng)掌握 Java 中字符集與編碼轉(zhuǎn)換的核心原理、最佳實踐與高級技巧,能夠在企業(yè)級項目中靈活應(yīng)用。
2. 項目需求詳細(xì)介紹
功能需求
1.文件轉(zhuǎn)換
- 支持單個文件的編碼轉(zhuǎn)換:從 UTF-8 轉(zhuǎn)為 GBK,或從 GBK 轉(zhuǎn)為 UTF-8;
- 支持批量目錄轉(zhuǎn)換:遞歸遍歷指定目錄,按原相對路徑輸出到目標(biāo)目錄;
2.流式轉(zhuǎn)換
支持命令行管道模式:讀取標(biāo)準(zhǔn)輸入,以指定編碼寫入標(biāo)準(zhǔn)輸出;
3.編碼檢測與驗證
- 對輸入流或文件自動檢測字符集(基于 BOM 或最小化猜測);
- 轉(zhuǎn)換后可選生成轉(zhuǎn)換報告(文件列表、大小、耗時、錯誤行);
4.命令行工具
- 參數(shù)化:-srcCharset UTF-8 -destCharset GBK -in fileOrDir -out fileOrDir;
- 參數(shù)校驗與幫助文檔輸出;
- 支持多線程并發(fā)轉(zhuǎn)換、大文件分片處理;
5.GUI 工具
Swing 界面:選擇源/目標(biāo)目錄、選擇編碼、啟動轉(zhuǎn)換、查看進(jìn)度條與日志;
6.配置與擴(kuò)展
- 支持外部 application.properties 配置:默認(rèn)編碼、線程數(shù)、日志級別;
- 可插件化新增更多字符集(如 ISO-8859-1、Shift_JIS)。
非功能需求
性能:對 10GB 級大文件轉(zhuǎn)換時可控制內(nèi)存峰值于 500MB 內(nèi),轉(zhuǎn)換吞吐率 ≥ 200MB/s;
可靠性:當(dāng)某文件轉(zhuǎn)換失敗時,能跳過并記錄錯誤,保證目錄批量轉(zhuǎn)換不中斷;
可維護(hù)性:模塊化設(shè)計,Converter、I/O 層、CLI 層、GUI 層解耦;
易用性:命令行與 GUI 使用方式直觀明了,日志與報告格式清晰;
跨平臺:純 Java 實現(xiàn),Windows/macOS/Linux 一致性測試通過;
日志與監(jiān)控:集成 SLF4J + Logback 輸出日志,支持日志文件輪轉(zhuǎn);
3. 相關(guān)技術(shù)詳細(xì)介紹
1.Java 字符集與編碼
- java.nio.charset.Charset、CharsetEncoder、CharsetDecoder;
- 常見字符集:StandardCharsets.UTF_8、Charset.forName("GBK");
2.字節(jié)流與字符流
- InputStreamReader/OutputStreamWriter 將字節(jié)流與字符流橋接;
- BufferedReader/BufferedWriter、BufferedInputStream/BufferedOutputStream 提升 I/O 性能;
3.NIO 高性能 I/O
- FileChannel + MappedByteBuffer 實現(xiàn)大文件內(nèi)存映射;
- AsynchronousFileChannel 支持異步讀寫;
4.多線程并發(fā)處理
- ExecutorService、ThreadPoolExecutor;
- 分段讀取大文件、分片轉(zhuǎn)換、回寫合并策略;
5.命令行解析
Apache Commons CLI 或 Picocli 實現(xiàn)參數(shù)解析;
6.Swing GUI
JFileChooser 目錄選擇、JComboBox 編碼選擇、JProgressBar 進(jìn)度顯示;
7.日志管理
SLF4J + Logback 配置 logback.xml,支持按天或大小滾動;
8.配置管理
Spring Boot @ConfigurationProperties 或 Commons Configuration 讀取 application.properties;
4. 實現(xiàn)思路詳細(xì)介紹
1.架構(gòu)分層
- Core 模塊:實現(xiàn)編碼轉(zhuǎn)換核心 EncodingConverter,提供 convert(InputStream, Charset src, OutputStream, Charset dest);
- CLI 模塊:MainCli 類,使用 Picocli 注解定義命令行參數(shù),調(diào)用 EncodingBatchConverter;
- GUI 模塊:MainGui 類,基于 Swing,組合核心模塊,并通過 SwingWorker 在后臺執(zhí)行轉(zhuǎn)換;
- I/O 模塊:提供工具 FileUtils 實現(xiàn)目錄遍歷、文件復(fù)制、分片讀寫;
- Config 模塊:讀取外部屬性 app.properties,注入默認(rèn)編碼、線程數(shù);
- Logging 模塊:Logback 配置文件,初始化日志系統(tǒng)。
2.核心流程
單文件轉(zhuǎn)換:
- 通過 Files.newInputStream(path) 與 Files.newOutputStream(outPath) 獲得流;
- 包裝為 InputStreamReader 與 OutputStreamWriter;
- 以 char[] buf = new char[bufferSize] 循環(huán) read(buf) → write(buf,0,len);
- flush() 并關(guān)閉資源。
目錄批量轉(zhuǎn)換:
- 遞歸查找符合后綴(如 .txt, 可配置)所有文件;
- 按相對路徑在目標(biāo)目錄創(chuàng)建父目錄;
- 提交給線程池執(zhí)行單文件轉(zhuǎn)換,記錄 Future。
管道模式:
- 無 -in、-out 參數(shù)時,從 System.in/System.out 讀取寫入;
- 直接調(diào)用核心 convert(System.in, src, System.out, dest)。
GUI:
- 在主界面按鈕監(jiān)聽事件中啟動 SwingWorker<Report,Progress>;
- doInBackground() 中調(diào)用批量轉(zhuǎn)換,publish() 進(jìn)度更細(xì)化到每個文件;
- process() 更新 JProgressBar 與文本日志;
- done() 彈出報告對話框。
3.性能優(yōu)化
- 對大文件使用 NIO 的 FileChannel.map() 內(nèi)存映射,減少 JVM 與操作系統(tǒng)切換;
- 適當(dāng)調(diào)整 bufferSize(4KB~64KB)以平衡延遲與吞吐;
- 多線程并發(fā)轉(zhuǎn)換時限制線程數(shù)為 CPU 核心數(shù)或 I/O 密集型的 2×CPU;
4.錯誤與回退
- 對每個文件轉(zhuǎn)換加異常捕獲,失敗時記錄到 ErrorReport 并跳過;
- 最終在報告中列出成功與失敗文件列表。
5. 完整實現(xiàn)代碼
// ===== 文件:src/main/java/com/encoding/Config.java =====
package com.encoding;
import java.io.InputStream;
import java.util.Properties;
/**
* 讀取 application.properties 配置。
*/
public class Config {
private String defaultSrcCharset;
private String defaultDestCharset;
private int threadCount;
private int bufferSize;
public Config() {
// 默認(rèn)值
defaultSrcCharset = "UTF-8";
defaultDestCharset = "GBK";
threadCount = Runtime.getRuntime().availableProcessors();
bufferSize = 8192;
// 加載外部配置
try (InputStream in = getClass()
.getClassLoader()
.getResourceAsStream("application.properties")) {
if (in != null) {
Properties p = new Properties();
p.load(in);
defaultSrcCharset = p.getProperty(
"app.srcCharset", defaultSrcCharset);
defaultDestCharset = p.getProperty(
"app.destCharset", defaultDestCharset);
threadCount = Integer.parseInt(
p.getProperty("app.threadCount", String.valueOf(threadCount)));
bufferSize = Integer.parseInt(
p.getProperty("app.bufferSize", String.valueOf(bufferSize)));
}
} catch (Exception e) {
System.err.println("加載配置失敗,使用默認(rèn)值");
}
}
// getters...
public String getDefaultSrcCharset() { return defaultSrcCharset; }
public String getDefaultDestCharset() { return defaultDestCharset; }
public int getThreadCount() { return threadCount; }
public int getBufferSize() { return bufferSize; }
}
// ===== 文件:src/main/java/com/encoding/EncodingConverter.java =====
package com.encoding;
import java.io.*;
import java.nio.charset.Charset;
/**
* 核心編碼轉(zhuǎn)換器:從 InputStream 讀取,使用 srcCharset 解碼,
* 再用 destCharset 編碼寫入 OutputStream。
*/
public class EncodingConverter {
/**
* 將輸入流按 srcCharset 解碼,按 destCharset 編碼寫入輸出流。
*/
public static void convert(
InputStream in,
Charset srcCharset,
OutputStream out,
Charset destCharset,
int bufferSize) throws IOException {
// Reader/Writer 橋接
try (Reader reader = new BufferedReader(
new InputStreamReader(in, srcCharset), bufferSize);
Writer writer = new BufferedWriter(
new OutputStreamWriter(out, destCharset), bufferSize)) {
char[] buf = new char[bufferSize];
int len;
while ((len = reader.read(buf)) != -1) {
writer.write(buf, 0, len);
}
writer.flush();
}
}
}
// ===== 文件:src/main/java/com/encoding/FileUtils.java =====
package com.encoding;
import java.io.IOException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
/**
* 文件與目錄工具:
* - 遞歸遍歷目錄獲取文件列表
* - 創(chuàng)建目錄
*/
public class FileUtils {
/**
* 遞歸查找目錄下所有文件。
*/
public static List<Path> listFiles(Path dir) throws IOException {
List<Path> list = new ArrayList<>();
try (var stream = Files.walk(dir)) {
stream.filter(Files::isRegularFile)
.forEach(list::add);
}
return list;
}
/**
* 確保目標(biāo)文件的父目錄存在。
*/
public static void ensureParent(Path file) throws IOException {
Path parent = file.getParent();
if (parent != null && !Files.exists(parent)) {
Files.createDirectories(parent);
}
}
}
// ===== 文件:src/main/java/com/encoding/BatchConverter.java =====
package com.encoding;
import java.io.IOException;
import java.nio.file.*;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.*;
/**
* 對目錄或列表文件進(jìn)行批量編碼轉(zhuǎn)換。
*/
public class BatchConverter {
private final ExecutorService pool;
private final Config config;
public BatchConverter(Config config) {
this.config = config;
this.pool = Executors.newFixedThreadPool(config.getThreadCount());
}
/**
* 將 srcPath(文件或目錄)批量轉(zhuǎn)換到 destPath(文件或目錄)。
*/
public void batchConvert(
Path srcPath,
Charset srcCharset,
Path destPath,
Charset destCharset) throws IOException, InterruptedException {
if (Files.isRegularFile(srcPath)) {
// 單文件
pool.submit(() -> {
convertFile(srcPath, destPath, srcCharset, destCharset);
});
} else {
// 目錄:遞歸
List<Path> files = FileUtils.listFiles(srcPath);
for (Path f : files) {
Path rel = srcPath.relativize(f);
Path target = destPath.resolve(rel);
pool.submit(() -> {
convertFile(f, target, srcCharset, destCharset);
});
}
}
pool.shutdown();
pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
private void convertFile(
Path inFile,
Path outFile,
Charset srcCharset,
Charset destCharset) {
try {
FileUtils.ensureParent(outFile);
try (var in = Files.newInputStream(inFile);
var out = Files.newOutputStream(outFile,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING)) {
EncodingConverter.convert(
in, srcCharset, out, destCharset, config.getBufferSize());
}
System.out.println("轉(zhuǎn)換成功: " + inFile + " → " + outFile);
} catch (IOException e) {
System.err.println("轉(zhuǎn)換失敗: " + inFile + ": " + e.getMessage());
}
}
}
// ===== 文件:src/main/java/com/encoding/MainCli.java =====
package com.encoding;
import java.nio.charset.Charset;
import java.nio.file.Path;
import picocli.CommandLine;
import picocli.CommandLine.*;
/**
* 命令行入口,使用 picocli 解析參數(shù)。
*/
@Command(name = "encode-convert", mixinStandardHelpOptions = true,
description = "批量轉(zhuǎn)換文件或流的字符編碼")
public class MainCli implements Runnable {
@Option(names = {"-sc", "--srcCharset"},
description = "源字符集,默認(rèn) ${DEFAULT-VALUE}")
private String srcCharset;
@Option(names = {"-dc", "--destCharset"},
description = "目標(biāo)字符集,默認(rèn) ${DEFAULT-VALUE}")
private String destCharset;
@Option(names = {"-i", "--in"},
description = "輸入文件或目錄,若省略則讀 stdin")
private Path inPath;
@Option(names = {"-o", "--out"},
description = "輸出文件或目錄,若省略則寫 stdout")
private Path outPath;
private Config config = new Config();
@Override
public void run() {
Charset sc = Charset.forName(
srcCharset != null ? srcCharset : config.getDefaultSrcCharset());
Charset dc = Charset.forName(
destCharset != null ? destCharset : config.getDefaultDestCharset());
try {
BatchConverter bc = new BatchConverter(config);
if (inPath == null || outPath == null) {
// 流模式
EncodingConverter.convert(
System.in, sc, System.out, dc, config.getBufferSize());
} else {
bc.batchConvert(inPath, sc, outPath, dc);
}
} catch (Exception e) {
System.err.println("執(zhí)行失敗: " + e.getMessage());
}
}
public static void main(String[] args) {
int exitCode = new CommandLine(new MainCli()).execute(args);
System.exit(exitCode);
}
}
// ===== 文件:src/main/java/com/encoding/MainGui.java =====
package com.encoding;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.nio.charset.Charset;
import java.nio.file.Path;
/**
* Swing GUI 界面,后臺使用 SwingWorker 執(zhí)行轉(zhuǎn)換。
*/
public class MainGui extends JFrame {
private JTextField srcField, destField;
private JButton srcBtn, destBtn, startBtn;
private JComboBox<String> srcCharsetBox, destCharsetBox;
private JProgressBar progressBar;
private JTextArea logArea;
private Config config = new Config();
public MainGui() {
setTitle("字符編碼轉(zhuǎn)換工具");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new BorderLayout());
// 上方:路徑和編碼選擇
JPanel top = new JPanel(new GridLayout(3, 3, 5, 5));
top.add(new JLabel("源文件/目錄:"));
srcField = new JTextField();
top.add(srcField);
srcBtn = new JButton("選擇...");
top.add(srcBtn);
top.add(new JLabel("目標(biāo)目錄:"));
destField = new JTextField();
top.add(destField);
destBtn = new JButton("選擇...");
top.add(destBtn);
top.add(new JLabel("源編碼:"));
srcCharsetBox = new JComboBox<>(
new String[]{"UTF-8","GBK","ISO-8859-1"});
srcCharsetBox.setSelectedItem(config.getDefaultSrcCharset());
top.add(srcCharsetBox);
top.add(new JLabel());
top.add(new JLabel("目標(biāo)編碼:"));
destCharsetBox = new JComboBox<>(
new String[]{"UTF-8","GBK","ISO-8859-1"});
destCharsetBox.setSelectedItem(config.getDefaultDestCharset());
top.add(destCharsetBox);
startBtn = new JButton("開始轉(zhuǎn)換");
top.add(startBtn);
add(top, BorderLayout.NORTH);
// 中部:日志與進(jìn)度
progressBar = new JProgressBar();
add(progressBar, BorderLayout.SOUTH);
logArea = new JTextArea(10, 80);
logArea.setEditable(false);
add(new JScrollPane(logArea), BorderLayout.CENTER);
pack();
setLocationRelativeTo(null);
bindActions();
}
private void bindActions() {
srcBtn.addActionListener(e -> {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
if (chooser.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) {
srcField.setText(
chooser.getSelectedFile().getAbsolutePath());
}
});
destBtn.addActionListener(e -> {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
if (chooser.showOpenDialog(this)==JFileChooser.APPROVE_OPTION) {
destField.setText(
chooser.getSelectedFile().getAbsolutePath());
}
});
startBtn.addActionListener(e -> startConversion());
}
private void startConversion() {
Path in = Path.of(srcField.getText());
Path out = Path.of(destField.getText());
Charset sc = Charset.forName((String)srcCharsetBox.getSelectedItem());
Charset dc = Charset.forName((String)destCharsetBox.getSelectedItem());
BatchConverter bc = new BatchConverter(config);
// SwingWorker 執(zhí)行后臺任務(wù)
SwingWorker<Void, String> worker = new SwingWorker<>() {
@Override
protected Void doInBackground() throws Exception {
publish("開始轉(zhuǎn)換...");
bc.batchConvert(in, sc, out, dc);
return null;
}
@Override
protected void process(java.util.List<String> chunks) {
for (String msg : chunks) {
logArea.append(msg + "\n");
}
}
@Override
protected void done() {
logArea.append("全部完成。\n");
}
};
worker.execute();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new MainGui().setVisible(true));
}
}
// ===== 文件:src/main/resources/application.properties =====
/*
app.srcCharset=UTF-8
app.destCharset=GBK
app.threadCount=4
app.bufferSize=8192
*/
// ===== 文件:src/main/resources/logback.xml =====
/*
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
*/6. 代碼詳細(xì)解讀
Config:讀取 application.properties,提供默認(rèn)源/目標(biāo)字符集、并發(fā)線程數(shù)、緩存大小。
EncodingConverter.convert(...):核心方法,接收字節(jié)流,使用 InputStreamReader/OutputStreamWriter 按指定字符集讀寫,基于 char[] 循環(huán)。
FileUtils:輔助目錄遍歷與父目錄創(chuàng)建。
BatchConverter:使用線程池并發(fā)執(zhí)行單文件轉(zhuǎn)換;按文件或目錄模式提交任務(wù);每個任務(wù)捕獲并記錄異常,不影響總體進(jìn)度。
MainCli:命令行工具,使用 Picocli 解析參數(shù);支持流模式(stdin→stdout)和文件/目錄模式;調(diào)用 BatchConverter 或 EncodingConverter。
MainGui:Swing GUI,包含路徑選擇、編碼下拉、開始按鈕、日志區(qū)和進(jìn)度條;后臺使用 SwingWorker 執(zhí)行批量轉(zhuǎn)換并在 process() 中更新日志。
application.properties:外部可配置默認(rèn)編碼、線程數(shù)和緩存大小。
logback.xml:Logback 日志配置,按天滾動保存最近 7 天日志。
7. 項目詳細(xì)總結(jié)
本項目完整實現(xiàn)了 Java 平臺下字符編碼轉(zhuǎn)換的工業(yè)級方案,既支持命令行工具(CLI),也支持圖形化界面(GUI);既有單文件/目錄批量轉(zhuǎn)換,又有管道流模式;既具有基本示例代碼,又具備配置化、并發(fā)化和日志監(jiān)控功能。通過模塊化設(shè)計和詳細(xì)注釋,您可以輕松擴(kuò)展更多字符集、更多模式(如異步 NIO 轉(zhuǎn)換)、更多 UI 風(fēng)格或接入 Spring Boot。
8. 項目常見問題及解答
Q1:轉(zhuǎn)換大文件時內(nèi)存溢出?
A:當(dāng)前使用流式讀寫,不會一次性加載整個文件。若使用 NIO MappedByteBuffer,需注意內(nèi)存映射上限并及時取消映射。
Q2:如何支持更多字符集?
A:在下拉框或命令行中指定 --srcCharset=Shift_JIS 即可。Java 內(nèi)置眾多字符集,可用 Charset.availableCharsets() 查看。
Q3:轉(zhuǎn)換進(jìn)度怎么實時顯示?
A:可在 BatchConverter 每完成一個文件或每處理 X 字節(jié)時 publish() 進(jìn)度,GUI 接收后更新 JProgressBar。
9. 擴(kuò)展方向與性能優(yōu)化
NIO 零拷貝:對大文件使用 FileChannel.transferTo 或內(nèi)存映射完成轉(zhuǎn)換;
異步 I/O:使用 AsynchronousFileChannel 實現(xiàn)完全異步讀寫;
流格式檢測:引入 ICU4J 或 juniversalchardet 自動判斷未知編碼;
Web 服務(wù):將轉(zhuǎn)換功能封裝為 RESTful API,前端上傳文件后返回轉(zhuǎn)換結(jié)果;
Docker 打包:構(gòu)建輕量化鏡像,實現(xiàn)云端轉(zhuǎn)換服務(wù);
監(jiān)控告警:整合 Prometheus + Grafana 監(jiān)控轉(zhuǎn)換任務(wù)的吞吐和錯誤率;
用戶界面優(yōu)化:使用 JavaFX 或 Electron 構(gòu)建更現(xiàn)代的桌面客戶端;
多平臺支持:結(jié)合 GraalVM Native Image 打包為原生可執(zhí)行文件(Windows EXE / macOS App)。
到此這篇關(guān)于使用java實現(xiàn)字符編碼轉(zhuǎn)換(附源碼)的文章就介紹到這了,更多相關(guān)java字符編碼轉(zhuǎn)換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java微信開發(fā)API第二步 獲取和回復(fù)消息
這篇文章主要為大家詳細(xì)介紹了java微信開發(fā)API第二步,獲取消息和回復(fù)消息,感興趣的小伙伴們可以參考一下2016-06-06
java實現(xiàn)兩張圖片2D翻轉(zhuǎn)動畫效果
這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)兩張圖片2D翻轉(zhuǎn)動畫效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
在Spring Boot中使用Spring-data-jpa實現(xiàn)分頁查詢
如何使用jpa進(jìn)行多條件查詢以及查詢列表分頁呢?下面我將介紹兩種多條件查詢方式。具體實例代碼大家參考下本文吧2017-07-07
Java實現(xiàn)在線預(yù)覽的示例代碼(openOffice實現(xiàn))
本篇文章主要介紹了Java實現(xiàn)在線預(yù)覽的示例代碼(openOffice實現(xiàn)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
詳解SpringBoot基礎(chǔ)之banner玩法解析
SpringBoot項目啟動時會在控制臺打印一個默認(rèn)的啟動圖案,這個圖案就是我們要講的banner,這篇文章主要介紹了SpringBoot基礎(chǔ)之banner玩法解析,感興趣的小伙伴們可以參考一下2019-04-04
透過Spring源碼查看Bean的命名轉(zhuǎn)換規(guī)則圖文詳解
Java Bean是一種 Java 編程語言編寫的可重用軟件組件,包括符合一定規(guī)范的Java 類、屬性和方法,用于描述和處理應(yīng)用程序中的數(shù)據(jù)對象,下面這篇文章主要給大家介紹了關(guān)于透過Spring源碼查看Bean的命名轉(zhuǎn)換規(guī)則的相關(guān)資料,需要的朋友可以參考下2023-06-06
Java使用Fastjson2處理JSON字段大小寫不一致的優(yōu)雅方案
這篇文章主要為大家詳細(xì)介紹了Java使用Fastjson2處理JSON字段大小寫不一致的優(yōu)雅方案,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2026-04-04
Kotlin-Coroutines中的async與await異步協(xié)程管理
這篇文章主要為大家介紹了Kotlin-Coroutines中的async與await異步協(xié)程管理,提升程序性能解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10

