java如何執(zhí)行bat腳本,并監(jiān)控執(zhí)行結(jié)果
java執(zhí)行bat腳本,并監(jiān)控執(zhí)行結(jié)果
親測(cè)可用!
直接上工具類(lèi)的代碼:
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class NoteUtil {
/**
* 執(zhí)行bat腳本文件,彈出cmd黑窗
* @param command 執(zhí)行腳本文件命令
* @param navigatePath 腳本文件所在文件夾地址
*/
public static void runExecution(List<String> command, File navigatePath) {
System.out.println(command);
ProcessBuilder executeProcess=new ProcessBuilder(command);
executeProcess.directory(navigatePath);
try {
Process resultExecution = executeProcess.start();
}catch (Exception e){
}
}
/**
* 執(zhí)行bat腳本,讀取cmd輸出內(nèi)容
* 注意:按行執(zhí)行的,所以需要注意腳本編寫(xiě)的時(shí)候一條命令需要寫(xiě)進(jìn)一行中,而且還要注意執(zhí)行命令時(shí)所在的文件夾地址,如果是需要在特定文件夾下執(zhí)行的命令,則需要每行命令開(kāi)始時(shí)跳轉(zhuǎn)到該目錄
* @param batPath 執(zhí)行的腳本文件絕對(duì)路徑
*/
public static Map<String, String> runExecution2(String batPath) {
StringBuffer sb1 = new StringBuffer();
StringBuffer sb2 = new StringBuffer();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(batPath), "UTF-8"));//讀取腳本
String line;
List<String> batList = new ArrayList();
while ((line = br.readLine()) != null) {
if (!line.equals("")) {
batList.add(line);
}
}
for (String command : batList) {
Process pro = Runtime.getRuntime().exec("cmd /c " + command);
BufferedReader br1 = new BufferedReader(new InputStreamReader(pro.getInputStream(), "GBK"));
BufferedReader br2 = new BufferedReader(new InputStreamReader(pro.getErrorStream(), "GBK"));
System.out.println("Input Stream:");
while ((line = br1.readLine()) != null) {
System.out.println(line);
sb1.append(line).append(System.getProperty("line.separator"));
}
System.out.println("Error Stream:");
while ((line = br2.readLine()) != null) {
System.out.println(line);
sb2.append(line).append(System.getProperty("line.separator"));
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
Map map = new HashMap();
map.put("getInputStreamString", sb1.toString());
map.put("getErrorStreamString", sb2.toString());
return map;
}
}
public static void main(String[] args) {
//cmd彈窗
File jsFile=new File("D:\\application\\bat文件所在的目錄");
String cmdPrompt="cmd";
String type="/c";
String start = "start";
String bat="run.bat";
List<String> updateCommand=new ArrayList<String>();
updateCommand.add(cmdPrompt);
updateCommand.add(type);
updateCommand.add(start);
updateCommand.add(bat);
runExecution(updateCommand,jsFile);
//不需要彈窗,獲得命令執(zhí)行后的輸入流,打印執(zhí)行結(jié)果
System.out.println(runExecution2("D:\\application\\腳本文件絕對(duì)路徑.bat"));
}
}
在測(cè)試的發(fā)現(xiàn),如果彈窗來(lái)執(zhí)行bat腳本,那么java代碼中獲取到的輸入流中是空的
bat腳本使用 && 對(duì)兩條語(yǔ)句進(jìn)行拼接,語(yǔ)句拼接的時(shí)候注意注釋?zhuān)悦饽_本都拼接到注釋后面去了導(dǎo)致執(zhí)行不到
java執(zhí)行bat、exe等cmd命令
方式一
建議使用hutool-all.jar,它對(duì)Runtime.getRuntime()做了完美的封裝
String cmdStr =
new StringBuffer("cmd /c osgTo3DTiles.exe -C OsgTo3DtilesConfig.json").toString();
Process exec = RuntimeUtil.exec(null,new File(CLOUDDISK_TOOLBOX),cmdStr);
String result = RuntimeUtil.getResult(exec, io.netty.util.CharsetUtil.UTF_8);
String errorResult = RuntimeUtil.getErrorResult(exec, io.netty.util.CharsetUtil.UTF_8);完整的調(diào)用案例:
public HttpResponse<String> objto3dtiles(ObjTo3dtilesVo objto3dtilesVo) {
//檢測(cè)工具是否存在
if (!FileUtil.exist(CLOUDDISK_TOOLBOX + "/osgTo3DTiles.exe")) {
return new HttpResponse<>("工具不存在,檢查路徑");
}
//配置文件是否存在
if (!FileUtil.exist(CLOUDDISK_TOOLBOX + "/OsgTo3DtilesConfig.json")) {
return new HttpResponse<>("工具配置文件不存在,檢查路徑");
}
//讀取配置文件 OsgTo3DtilesConfig.json
JSONObject config = JSONObject.parseObject(FileUtil.readString(CLOUDDISK_TOOLBOX + "/OsgTo3DtilesConfig.json", CharsetUtil.UTF_8));
if (config.replace("osgRootDir", config.getString("osgRootDir"), objto3dtilesVo.getSourceFile()) &&
config.replace("tileRootDir", config.getString("tileRootDir"), objto3dtilesVo.getTartgetFile())) {
FileUtil.writeUtf8String(config.toJSONString(), CLOUDDISK_TOOLBOX + "/OsgTo3DtilesConfig.json");
String cmdStr =
new StringBuffer("cmd /c osgTo3DTiles.exe -C OsgTo3DtilesConfig.json").toString();
ToolBoxTask toolBoxTask = new ToolBoxTask();
toolBoxTask.setCreator(objto3dtilesVo.getCreator());
toolBoxTask.setCreatorId(objto3dtilesVo.getCreatorId());
toolBoxTask.setStatus(2);
toolBoxTask.setType(1);
toolBoxTask.setTaskName("osgTo3DTiles_" + System.currentTimeMillis());
ToolBoxTask save = toolBoxDao.save(toolBoxTask);
new Thread(()->{
Process exec = RuntimeUtil.exec(null,new File(CLOUDDISK_TOOLBOX),cmdStr);
String result = RuntimeUtil.getResult(exec, io.netty.util.CharsetUtil.UTF_8);
String errorResult = RuntimeUtil.getErrorResult(exec, io.netty.util.CharsetUtil.UTF_8);
save.setResult(result);
save.setRemark(errorResult);
save.setStatus(10);
toolBoxDao.save(save);
}).start();
return new HttpResponse<>("osbj轉(zhuǎn)3dtiles程序開(kāi)始執(zhí)行");
} else {
return new HttpResponse<>("工具配置設(shè)置失敗,請(qǐng)檢查配置文件");
}
}方式二
下面是原生寫(xiě)法,除非需要盡量減小外部依賴(lài)比如很明確不能用hutools工具,否則建議拋棄下面寫(xiě)法,就用上面的就好
- controller層
/**
* Copyright ? 2021. All rights reserved.
*
* @描述: 監(jiān)控服務(wù)
* @Prject: DataHub
* @Package: com.domain.module.ops.message.controller
* @ClassName: MonitorController
* @date: 2022年6月21日
* @version: V1.0
*/
package com.domain.module.ops.monitor.controller;
import com.domain.common.aop.Log;
import com.domain.common.response.HttpResponse;
import com.domain.common.response.HttpResponsePageList;
import com.domain.framework.controller.BaseController;
import com.domain.framework.service.BaseService;
import com.domain.module.ops.monitor.entity.MonitorEntity;
import com.domain.module.ops.monitor.service.MonitorService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @ClassName: MonitorController
* * @描述: 監(jiān)控服務(wù)
* * @author: Eric
* * @date: 2022年6月21日
*/
@Log(value = "", name = "監(jiān)控服務(wù)")
@RestController
@RequestMapping(value = "/ops/monitor")
public class MonitorController extends BaseController<MonitorEntity> {
@Resource
public MonitorService monitorService;
@Override
public BaseService<MonitorEntity> getBaseService() {
return monitorService;
}
@Log(value = "獲取服務(wù)啟動(dòng)狀態(tài)", name = "")
@RequestMapping(value = "/list", method = RequestMethod.GET)
public HttpResponsePageList<MonitorEntity> list() {
return monitorService.getServerList();
}
@Log(value = "獲取服務(wù)啟動(dòng)日志", name = "")
@RequestMapping(value = "/getLog", method = RequestMethod.GET)
public HttpResponse<String> list(String serverName,String port) {
return monitorService.getLog(serverName,port);
}
@Log(value = "啟動(dòng)服務(wù)", name = "")
@RequestMapping(value = "/startServer", method = RequestMethod.GET)
public HttpResponse<String> startServer(String serverName,String port) {
return monitorService.startServer(serverName,port);
}
@Log(value = "關(guān)閉服務(wù)", name = "")
@RequestMapping(value = "/stopServer", method = RequestMethod.GET)
public HttpResponse<String> stopServer(String serverName,String port) {
return monitorService.stopServer(serverName,port);
}
@Log(value = "地圖服務(wù)訪問(wèn)情況統(tǒng)計(jì)", name = "")
@RequestMapping(value = "/statisticServiceType", method = RequestMethod.GET)
public HttpResponse<String> statisticServiceType() {
return monitorService.statisticServiceType();
}
}
- service層
/**
* Copyright ? 2021. All rights reserved.
*
* @描述: 消息中心
* @Prject: DataHub
* @Package: com.domain.module.ops.message.service
* @ClassName: OpinionServiceImpl
* @author: Eric
* @date: 2022年6月6日
* @version: V1.0
*/
package com.domain.module.ops.monitor.service;
import com.alibaba.fastjson.JSONObject;
import com.domain.common.response.HttpResponse;
import com.domain.common.response.HttpResponsePageList;
import com.domain.common.response.PageList;
import com.domain.framework.dao.BaseDao;
import com.domain.framework.service.BaseServiceImpl;
import com.domain.module.ops.monitor.dao.MonitorDao;
import com.domain.module.ops.monitor.entity.MonitorEntity;
import com.domain.module.res.registerresources.service.RegisterResourcesService;
import com.domain.module.store.file.dao.FileDao;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.Charset;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @ClassName: MonitorServiceImpl
* @描述: 監(jiān)控服務(wù)
* @author: Eric
* @date: 2022年5月16日
*/
@Service
public class MonitorServiceImpl extends BaseServiceImpl<MonitorEntity> implements MonitorService {
@Resource
public MonitorDao monitorDao;
@Value("${nginx.logsUrl}")
public String NGINX_LOG_URL;
@Resource
public RegisterResourcesService registerResourcesService;
@Autowired
FileDao fileDao;
@Resource
org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate template;
private static String readFile(File file) {
List<String> list = new ArrayList<>();
try {
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "gbk");
BufferedReader bw = new BufferedReader(isr);
String line = null;
while ((line = bw.readLine()) != null) {
list.add(line);
}
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
StringBuffer text = new StringBuffer();
for (int i = 0; i < list.size(); i++) {
String[] st = list.get(i).split("\t");
for (int j = 0; j < st.length; j++) {
text.append(st[j]);
}
}
return text.toString();
}
@Override
public BaseDao<MonitorEntity> getBaseDao() {
return monitorDao;
}
@Override
public HttpResponsePageList<MonitorEntity> getServerList() {
String baseUrlStr = NGINX_LOG_URL + "bat_logs";
try {
File[] serverList = new File(baseUrlStr).listFiles();
if (serverList != null || serverList.length > 0) {
Stream<File> fileStream = Stream.of(serverList);
List<MonitorEntity> MonitorList = fileStream.map(n -> {
String nameStr = n.getName();
boolean contains = nameStr.contains("-");
String sName = "";
String sPort = "";
Boolean sStatus = false;
StringBuffer cmdStr = new StringBuffer();
if (contains) {
String[] splitName = nameStr.split("-");
sName = splitName[0];
sPort = splitName[1].replace(".log", "");
cmdStr.append("cmd /c netstat -aon|findstr ").append(sPort);
} else {
sName = nameStr.replace(".log", "");
cmdStr.append("tasklist /fi \"imagename eq " + sName + ".exe\"");
}
String result = startBatShell(cmdStr.toString());
sStatus = (result == null || result.equals("") || result.contains("信息")) ? false : true;
String fileContext = readFile(n);
return new MonitorEntity(sName, sPort, sStatus, fileContext);
}).collect(Collectors.toList());
return new HttpResponsePageList<MonitorEntity>(new PageList<>(MonitorList));
}
} catch (Exception e) {
e.printStackTrace();
}
return new HttpResponsePageList<MonitorEntity>();
}
@Override
public HttpResponse<String> getLog(String serverName, String port) {
String baseUrlStr = NGINX_LOG_URL.split("/DMS/")[0] + "/DMS/";
switch (serverName) {
case "nginx":
baseUrlStr += "online_datahub/logs/";
String index = "access-" + LocalDate.now().toString(); //access-2022-06-23
File nginxLog = new File(baseUrlStr + index + ".log");
if (nginxLog.exists()) {
String readFile = readFile(nginxLog);
serverName = readFile;
}
break;
case "mapserver":
baseUrlStr += "service_engine/mapserver/log/app.log";
serverName = readLog(baseUrlStr);
break;
case "rasterserver":
baseUrlStr += "service_engine/rasterserver/log/app.log";
serverName = readLog(baseUrlStr);
break;
case "elasticsearch":
baseUrlStr += "system_plugins/elasticsearch/logs/elasticsearch.log";
serverName = readLog(baseUrlStr);
break;
case "server_controller":
baseUrlStr += "server_controller/logs/";
String scIndex = "catalina." + LocalDate.now().toString();
File scLog = new File(baseUrlStr + scIndex + ".log");
if (scLog.exists()) {
String readFile = readFile(scLog);
serverName = readFile;
}
break;
default:
String path = (port == null || "".equals(port)) ? NGINX_LOG_URL + "bat_logs/" + serverName + ".log" : NGINX_LOG_URL + "bat_logs/" + serverName + "-" + port + ".log";
File batLog = new File(path);
if (batLog.exists()) {
String readFile = readFile(batLog);
serverName = readFile;
}
break;
}
return new HttpResponse<>(serverName);
}
@Override
public HttpResponse<String> stopServer(String serverName, String port) {
String os = System.getProperty("os.name").toLowerCase();
String cmdStr = "";
if (os.contains("windows")) {
if (port.equals("") || null == port) {
cmdStr = "taskkill /f /t /im " + serverName + ".exe";
} else {
String getPidStr = "netstat -ano|findstr " + port;
String startBatShell = startBatShell(getPidStr);
if (startBatShell.length() > 0) {
BufferedReader br = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(startBatShell.getBytes(Charset.forName("utf8"))), Charset.forName("utf8")));
String readLine = null;
try {
readLine = br.readLine();
if (readLine != null && readLine.contains("LISTENING")) {
String pidStr = readLine.split("LISTENING")[1].trim();
cmdStr = "taskkill /pid " + pidStr + " /f";
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
startBatShell(cmdStr);
}
return new HttpResponse<>(serverName + "已停止");
}
@Override
public HttpResponse<String> startServer(String serverName, String port) {
String baseUrlStr = NGINX_LOG_URL.split("/DMS/")[0] + "/DMS/";
switch (serverName) {
case "mapserver":
case "rasterserver":
baseUrlStr += "service_engine/" + serverName + "/";
startBatShell("cmd /c start cd " + baseUrlStr + " && start /d \"" + baseUrlStr + "\" " + serverName + ".exe");
break;
case "online_datahub":
baseUrlStr += "online_datahub/";
startBatShell("cmd /c start " + baseUrlStr + "server.bat");
break;
case "server_controller":
baseUrlStr += "server_controller/bin/startup.bat";
startBatShell("cmd /c start " + baseUrlStr);
break;
case "server_manager":
baseUrlStr += "service_engine/server-manager/";
startBatShell("cmd /c start " + baseUrlStr + "server.bat");
break;
}
return new HttpResponse<>(serverName + "已啟動(dòng)");
}
@Override
public HttpResponse<String> statisticServiceType() {
IndexCoordinates index = IndexCoordinates.of("filebeat-log*");
NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
builder.withQuery(QueryBuilders.boolQuery());
builder.withFields("message", "@timestamp");
NativeSearchQuery searchQuery = builder.build();
SearchHits<JSONObject> scroll = template.search(searchQuery, JSONObject.class, index);
Iterator<SearchHit<JSONObject>> iterator = scroll.iterator();
Long rasterTotal = 0L;
Long mapTotal = 0L;
Long rasterDate = 0L;
Long mapDate = 0L;
String tempMapDate = "";
String tempRasterDate = "";
ArrayList<Map> mapList = new ArrayList<>();
ArrayList<Map> rasterList = new ArrayList<>();
ArrayList<Map> shareList = new ArrayList<>();
while (iterator.hasNext()) {
JSONObject content = iterator.next().getContent();
String message = content.getString("message");
String date = content.getString("@timestamp").split("T")[0];
if (message.contains("/mapserver/")) {
mapTotal++;
if (date.equals(tempMapDate) || tempMapDate.equals("")) {
tempMapDate = date;
mapDate++;
} else {
Map<String, Object> map = new HashMap<>();
map.put("mapDate", tempMapDate);
map.put("mapValue", mapDate);
mapList.add(map);
mapDate = 0L;
tempMapDate = date;
}
} else if (message.contains("/rasterserver/")) {
rasterTotal++;
if (date.equals(tempRasterDate) || tempRasterDate.equals("")) {
tempRasterDate = date;
rasterDate++;
} else {
Map<String, Object> map = new HashMap<>();
map.put("rasterDate", tempRasterDate);
map.put("rasterValue", rasterDate);
rasterList.add(map);
rasterDate = 0L;
tempRasterDate = date;
}
}
}
Map<String, Object> map = new HashMap<>();
map.put("mapDate", tempMapDate);
map.put("mapValue", mapDate);
mapList.add(map);
map = new HashMap<>();
map.put("rasterDate", tempRasterDate);
map.put("rasterValue", rasterDate);
rasterList.add(map);
Map<String, Object> res = new HashMap<>();
res.put("mapTotal", mapTotal);
res.put("rasterTotal", rasterTotal);
res.put("mapDateCount", mapList);
res.put("rasterDateCount", rasterList);
List<Object[]> objects = fileDao.countFileType();
res.put("storeFile", objects);
List<Map<String, Object>> downloadList = registerResourcesService.resourceDownLoadCount();
res.put("download", downloadList);
Map<String, Object> shareType = registerResourcesService.registerCount();
res.put("shareType", shareType);
return new HttpResponse<>(JSONObject.toJSONString(res));
}
private String readLog(String baseUrlStr) {
String log = "";
File file = new File(baseUrlStr);
if (file.exists()) {
log = readFile(file);
}
return log;
}
String startBatShell(String cmd) {
try {
Process psServe = Runtime.getRuntime().exec(cmd);
psServe.waitFor();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(psServe.getInputStream(), "gbk"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line + "\n");
}
return sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
注意一:執(zhí)行exe時(shí)不能直接start,得先cd進(jìn)去,比如
cmd /c start cd E:/Work/File//路網(wǎng)計(jì)算程序 && start /d "E:/Work/File/路網(wǎng)計(jì)算程序" RdFLSim.exe
注意/d命令后面有引號(hào)將xxx.exe分開(kāi)了
注意二:如果執(zhí)行exe后面還需要帶參數(shù),則注意一中的寫(xiě)法無(wú)效,可以使用下面方式執(zhí)行,指定環(huán)境里面執(zhí)行exe
* Runtime.exec(String command, String[] envp, File dir) //在指定環(huán)境和工作目錄的獨(dú)立進(jìn)程中執(zhí)行指定的命令和變量
//說(shuō)明:參數(shù)1是需要執(zhí)行的cmd命令,不需要先cd到相關(guān)目錄了,
// 參數(shù)2是 環(huán)境變量
// 參數(shù)3是執(zhí)行exe的工作目錄,
Runtime.getRuntime().exec("cmd /c start osgTo3DTiles.exe -C OsgTo3DtilesConfig.json", null,
new File("E:/Work/2022/clouddisk/toolbox/osgTo3Dtiles"));方式三
需要輸入?yún)?shù)的cmd命令,比如中間需要輸入數(shù)據(jù)庫(kù)密碼
public static String ExecuteCmd(String cmdsql,String directorypath,Map<String, String> envMap) throws Exception {
ProcessBuilder builder = new ProcessBuilder();
if (isWindows) {
//cmdsql = " pg_dump -h localhost -p 5432 -U postgres -d platform -t shapefile_d644d48_1553046876115 -f F:/1234/testshp/bbb/tb_news60.sql"
builder.command("cmd.exe", "/c",cmdsql);
} else {
builder.command("sh", "-c", cmdsql);
}
//directorypath = "D:/Program Files/PostgreSQL/14/bin/"
builder.directory(new File(directorypath));
Map<String, String> env = builder.environment();
//env.putAll(envMap);
env.put("PGPASSWORD", "qQq314159@26");
Process process = null;
try {
process = builder.start();
} catch (IOException e) {
e.printStackTrace();
}
StreamGobbler streamGobbler =
new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
switch (exitCode){
case 0:
return "ok";
case 1:
return "error";
}
return "ok";
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java 配置log4j日志文件路徑 (附-獲取當(dāng)前類(lèi)路徑的多種操作)
這篇文章主要介紹了Java 配置log4j日志文件路徑 (附-獲取當(dāng)前類(lèi)路徑的多種操作),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
Oracle+Mybatis的foreach insert批量插入報(bào)錯(cuò)的快速解決辦法
本文給大家介紹Oracle+Mybatis的foreach insert批量插入報(bào)錯(cuò)的快速解決辦法,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友參考下吧2016-08-08
Spring Boot分段處理List集合多線程批量插入數(shù)據(jù)的解決方案
大數(shù)據(jù)量的List集合,需要把List集合中的數(shù)據(jù)批量插入數(shù)據(jù)庫(kù)中,本文給大家介紹Spring Boot分段處理List集合多線程批量插入數(shù)據(jù)的解決方案,感興趣的朋友跟隨小編一起看看吧2024-04-04
Java Swing組件布局管理器之FlowLayout(流式布局)入門(mén)教程
這篇文章主要介紹了Java Swing組件布局管理器之FlowLayout(流式布局),結(jié)合實(shí)例形式分析了Swing組件布局管理器FlowLayout流式布局的常用方法及相關(guān)使用技巧,需要的朋友可以參考下2017-11-11
Java中ArrayList和LinkedList有什么區(qū)別舉例詳解
這篇文章主要介紹了Java中ArrayList和LinkedList區(qū)別的相關(guān)資料,包括數(shù)據(jù)結(jié)構(gòu)特性、核心操作性能、內(nèi)存與GC影響、擴(kuò)容機(jī)制、線程安全與并發(fā)方案,以及工程實(shí)踐場(chǎng)景,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02
Spring Boot 通過(guò) Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換的代碼詳解
這篇文章主要介紹了Spring Boot 通過(guò) Mvc 擴(kuò)展方便進(jìn)行貨幣單位轉(zhuǎn)換,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
SpringCloud?集成Sentinel的實(shí)戰(zhàn)教程
這篇文章主要介紹了SpringCloud?集成Sentinel的詳細(xì)過(guò)程,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-08-08
Java連接SQL?Server數(shù)據(jù)庫(kù)的超詳細(xì)教程
在Java應(yīng)用程序中我們經(jīng)常需要與數(shù)據(jù)庫(kù)進(jìn)行交互,一種常見(jiàn)的數(shù)據(jù)庫(kù)是Microsoft?SQL?Server,下面這篇文章主要給大家介紹了關(guān)于Java連接SQL?Server數(shù)據(jù)庫(kù)的超詳細(xì)教程,需要的朋友可以參考下2024-01-01
Mybatisplus更新某個(gè)字段為null問(wèn)題
Mybatisplus更新某個(gè)字段為null時(shí),可以使用@TableField(updateStrategy=FieldStrategy.IGNORED)注解,該注解提供了字段映射、忽略非表字段、自動(dòng)填充策略、字段條件處理等功能2025-02-02

