Java生成Echarts表圖的2種實現(xiàn)方案
前言
最近被生成報告糾結了一個禮拜,生成word并不難,可以通過模版來實現(xiàn),目前用得比較多的技術有,poi,freemarker等等工具,只需要自己寫一個模版通過占位符的形式來替換里面的變量。這里生成word就不過多去介紹(后期出一篇文章)但是里面的圖表就沒有那么好去實現(xiàn),要考慮到通過后臺獲取數(shù)據來生成圖表。經過了一個禮拜的查閱資料找到了兩種在后端實現(xiàn)方式,本篇以生成柱狀圖為例:
一、Jfreechart
簡介
JFreeChart是JAVA平臺上的一個開放的圖表繪制類庫。它完全使用JAVA語言編寫,是為applications, applets, servlets 以及JSP等使用所設計。JFreeChart可生成餅圖(pie charts)、柱狀圖(bar charts)、散點圖(scatter plots)、時序圖(time series)、甘特圖(Gantt charts)等等多種圖表,并且可以產生PNG和JPEG格式的輸出,還可以與PDF和EXCEL關聯(lián)。
導入依賴
<dependency> <groupId>jfreechart</groupId> <artifactId>jfreechart</artifactId> <version>1.0.0</version> </dependency>
簡單demo
/** * 功能描述: 創(chuàng)建JFreeChart對象并設置樣式 * * @param categoryDataset 類別數(shù)據集 * @return org.jfree.chart.JFreeChart * @author Jack_Liberty * @date 2021-04-01 11:16 */ public static JFreeChart createChart(CategoryDataset categoryDataset) { JFreeChart jfreechart = ChartFactory.createBarChart("Test", "", "", categoryDataset, PlotOrientation.VERTICAL, false, false, false); Font labelFont = new Font(Font.SANS_SERIF, Font.TRUETYPE_FONT, 15); // Font labelFont1 = new Font(Font.SANS_SERIF, Font.TRUETYPE_FONT, 24); // jfreechart.setTextAntiAlias(false); jfreechart.setBackgroundPaint(Color.white); // 獲得圖表區(qū)域對象 CategoryPlot plot = jfreechart.getCategoryPlot(); // 設置橫虛線可見 plot.setRangeGridlinesVisible(true); // 虛線色彩 plot.setRangeGridlinePaint(Color.gray); // 數(shù)據軸精度 NumberAxis vn = (NumberAxis) plot.getRangeAxis(); DecimalFormat df = new DecimalFormat("#0.0"); // 數(shù)據軸數(shù)據標簽的顯示格式 vn.setNumberFormatOverride(df); // x軸設置 CategoryAxis domainAxis = plot.getDomainAxis(); // 軸標題 domainAxis.setLabelFont(labelFont); // 軸數(shù)值 domainAxis.setTickLabelFont(labelFont); // X軸標題過長可設置傾斜度 domainAxis.setCategoryLabelPositions(CategoryLabelPositions.createUpRotationLabelPositions(Math.PI / 3.0)); // 橫軸上的 Label domainAxis.setMaximumCategoryLabelWidthRatio(6.00f); // 是否完整顯示 // 設置距離圖片左端距離 domainAxis.setLowerMargin(0.0); // 設置距離圖片右端距離 domainAxis.setUpperMargin(0.0); // 設置 columnKey 是否間隔顯示 plot.setDomainAxis(domainAxis); // 設置柱圖背景色(注意,系統(tǒng)取色的時候要使用16位的模式來查看顏色編碼,這樣比較準確) plot.setBackgroundPaint(new Color(255, 255, 255, 255)); // y軸設置 ValueAxis rangeAxis = plot.getRangeAxis(); rangeAxis.setLabelFont(labelFont); rangeAxis.setTickLabelFont(labelFont); // 設置最高的一個 Item 與圖片頂端的距離 rangeAxis.setUpperMargin(0.15); // 設置最低的一個 Item 與圖片底端的距離 rangeAxis.setLowerMargin(0.15); plot.setRangeAxis(rangeAxis); // 解決中文亂碼問題(關鍵) TextTitle textTitle = jfreechart.getTitle(); textTitle.setFont(new Font("黑體", Font.PLAIN, 20)); domainAxis.setTickLabelFont(new Font("sans-serif", Font.PLAIN, 15)); domainAxis.setLabelFont(new Font("宋體", Font.PLAIN, 15)); vn.setTickLabelFont(new Font("sans-serif", Font.PLAIN, 15)); vn.setLabelFont(new Font("黑體", Font.PLAIN, 15)); // 使用自定義的渲染器 CustomRenderer renderer = new CustomRenderer(); ArrayList<Double> data = new ArrayList<Double>(); data.add(99D); data.add(87D); data.add(89D); data.add(45D); data.add(78D); data.add(92D); data.add(98D); data.add(80D); renderer.setScores(data); // 設置柱子寬度 renderer.setMaximumBarWidth(0.1); // 設置柱子高度 renderer.setMinimumBarLength(0.1); // 設置柱子邊框顏色 renderer.setBaseOutlinePaint(Color.BLACK); // 設置柱子邊框可見 renderer.setDrawBarOutline(true); // 設置每個地區(qū)所包含的平行柱的之間距離 renderer.setItemMargin(1); jfreechart.getRenderingHints().put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); // 顯示每個柱的數(shù)值,并修改該數(shù)值的字體屬性 // renderer.setIncludeBaseInRange(true); renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator()); renderer.setBaseItemLabelsVisible(true); plot.setRenderer(renderer); // 設置柱的透明度 plot.setForegroundAlpha(1.0f); // 背景色 透明度 plot.setBackgroundAlpha(0.5f); return jfreechart; }
/** * 功能描述: 創(chuàng)建CategoryDataset對象 * * @return org.jfree.data.category.CategoryDataset * @author Jack_Liberty * @date 2021-04-01 16:20 */ public static CategoryDataset createDataset() { double[][] data = new double[][]{{1,9,0,15,9,3,4}}; String[] rowKeys = {"1"}; String[] columnKeys = {"Test1","Test2","Test3","Test4","Test5","Test6","Test7"}; return DatasetUtilities.createCategoryDataset(rowKeys, columnKeys, data); }
啟動測試
public static void main(String[] args) throws Exception { // 創(chuàng)建CategoryDataset對象 CategoryDataset dataset = createDataset(); // 根據Dataset 生成JFreeChart對象,并設置相應的樣式 JFreeChart freeChart = createChart(dataset); FileOutputStream out = null; try { out = new FileOutputStream("F:\\chart110605.png"); ChartUtilities.writeChartAsPNG(out, freeChart, 800, 450);// 輸出圖表 System.out.println("圖片運行成功"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { out.close(); } catch (final Exception ex) { ex.printStackTrace(); } } }
生成圖片展示
第一種方式到此為止,下面上第二種
二、Echarts插件
簡介
Echarts在熟悉了解前端的一定不會感到陌生,ECharts是一款基于JavaScript的數(shù)據可視化圖表庫,提供直觀,生動,可交互,可個性化定制的數(shù)據可視化圖表。ECharts最初由百度團隊開源,并于2018年初捐贈給Apache基金會,成為ASF孵化級項目。
Echarts官網鏈接: https://echarts.apache.org/zh/index.html
Echarts插件安裝包鏈接:https://pan.baidu.com/s/1EHk4ALdk-QAedp99c_tcmQ?pwd=aytd
提取碼: aytd
解壓后里面包含phantomjs-2.1.1-windows和echarts-convert.js,進入\echarts\phantomjs-2.1.1-windows\bin目錄下通過cmd命令啟動phantomjs D:\toos\echarts\saintlee-echartsconvert-master\echartsconvert\echarts-convert.js -s -p 6666
導入依賴
<dependency> <groupId>com.github.abel533</groupId> <artifactId>Echarts</artifactId> <version>3.0.0.6</version> </dependency>
直接上代碼
這里是echarts-pojo模塊(數(shù)據模型)
/** * <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 14:11 **/ @Data public class BarParam { private Object[] barName; private Object[] barValue; private String legendName; }
/** * <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 14:11 **/ @Data public class BarData { private String title; //標題 private BarParam barParamList; private Boolean isHorizontal; //是否水平放置 //省略get/set方法,使用lombok插件@Data }
對GsonOption.java做一層封裝,繼承GsonOption 類
* <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 14:13 **/ @Data public class EnhancedOption extends GsonOption { private String filepath; private static boolean VIEW =false; private static String EXPORT_PATH =""; /** * 輸出到控制臺 */ public void print() { GsonUtil.print(this); } /** * 輸出到控制臺 */ public void printPretty() { GsonUtil.printPretty(this); } /** * 在瀏覽器中查看 */ public void view() { if (!VIEW) { return; } if (this.filepath != null) { try { OptionUtil.browse(this.filepath); } catch (Exception e) { this.filepath = OptionUtil.browse(this); } } else { this.filepath = OptionUtil.browse(this); } } /** * 導出到指定文件名 * * @param fileName * @return 返回html路徑 */ public String exportToHtml(String fileName) { return exportToHtml(EXPORT_PATH, fileName); } }
請求工具類
/** * <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 14:02 **/ @Slf4j public class HttpUtil { /** * 發(fā)送post請求 * @param url * @param params * @param charset * @return * @throws ClientProtocolException * @throws IOException */ public static String post(String url, Map<String, String> params, String charset) throws ClientProtocolException, IOException { log.info("httpPostRequest url : " + url + " paramMap : " + params); String responseEntity = ""; // 創(chuàng)建CloseableHttpClient對象 CloseableHttpClient client = HttpClients.createDefault(); // 創(chuàng)建post方式請求對象 HttpPost httpPost = new HttpPost(url); // 生成請求參數(shù) List<NameValuePair> nameValuePairs = new ArrayList<>(); if (params != null) { for (Map.Entry<String, String> entry : params.entrySet()) { nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue())); } } // 將參數(shù)添加到post請求中 httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, charset)); // 發(fā)送請求,獲取結果(同步阻塞) CloseableHttpResponse response = client.execute(httpPost); // 獲取響應實體 HttpEntity entity = response.getEntity(); if (entity != null) { // 按指定編碼轉換結果實體為String類型 responseEntity = EntityUtils.toString(entity, charset); } // 釋放資源 EntityUtils.consume(entity); response.close(); //System.out.println("responseEntity = " + responseEntity); return responseEntity; } public static String postUrl(String url, Map<String, Object> params, String charset) { String responseEntity = ""; // 創(chuàng)建CloseableHttpClient對象 CloseableHttpClient client = HttpClients.createDefault(); // 創(chuàng)建post方式請求對象 HttpPost httpPost = new HttpPost(url); // 將參數(shù)添加到post請求中 httpPost.setEntity(new StringEntity(JSONObject.toJSONString(params), charset)); // 發(fā)送請求,獲取結果(同步阻塞) CloseableHttpResponse response = null; try { response = client.execute(httpPost); // 獲取響應實體 HttpEntity entity = response.getEntity(); if (entity != null) { // 按指定編碼轉換結果實體為String類型 responseEntity = EntityUtils.toString(entity, charset); } // 釋放資源 EntityUtils.consume(entity); } catch (Exception e) { e.printStackTrace(); } finally { try { response.close(); } catch (IOException e) { e.printStackTrace(); } } return responseEntity; } /** * post請求(用于請求json格式的參數(shù)) * @param url * @param params * @return */ public static String doPost(String url, String params) throws Exception { log.info("httpPostRequest url : " + url + " paramMap : " + params); CloseableHttpClient httpclient = HttpClients.createDefault(); HttpPost httpPost = new HttpPost(url);// 創(chuàng)建httpPost httpPost.setHeader("Accept", "application/json"); httpPost.setHeader("Content-Type", "application/json"); String charSet = "UTF-8"; StringEntity entity = new StringEntity(params, charSet); //logger.info("entity = " + entity); httpPost.setEntity(entity); CloseableHttpResponse response = null; try { response = httpclient.execute(httpPost); //logger.info("response = " + response); StatusLine status = response.getStatusLine(); int state = status.getStatusCode(); if (state == HttpStatus.SC_OK) { HttpEntity responseEntity = response.getEntity(); String jsonString = EntityUtils.toString(responseEntity); log.info("post請求響應結果:{}", jsonString); return jsonString; } else{ log.error("請求返回:"+state+"("+url+")"); } } finally { if (response != null) { try { response.close(); } catch (IOException e) { log.error(e.getMessage()); } } try { httpclient.close(); } catch (IOException e) { log.error(e.getMessage()); } } return null; } /** * http發(fā)送POST請求 * * @author J.M.C * @since 2019年1月16日 * @param url 長連接URL * @param paramsJson 請求參數(shù)body * @return result 字符串 */ public static String doPostJson(String url, JSONObject paramsJson) { log.info("httpPostRequest url : " + url + " paramMap : " + paramsJson); if(StringUtils.isBlank(url)){ log.error("httpPostRequest url is null"); return null; } String result = ""; try { // 創(chuàng)建httpClient實例 CloseableHttpClient httpClient = HttpClients.createDefault(); // 創(chuàng)建httpPost遠程連接實例 HttpPost httpPost = new HttpPost(url); // 配置請求參數(shù)實例 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000)// 設置連接主機服務超時時間 .setConnectionRequestTimeout(10000)// 設置連接請求超時時間 .setSocketTimeout(30000)// 設置讀取數(shù)據連接超時時間 .build(); // 為httpPost實例設置配置 httpPost.setConfig(requestConfig); // 設置請求頭 httpPost.addHeader("content-type", "application/json;charset=utf-8"); // 封裝post請求參數(shù) httpPost.setEntity(new StringEntity(paramsJson.toJSONString(), Charset.forName("UTF-8"))); // httpClient對象執(zhí)行post請求,并返回響應參數(shù)對象 // HttpResponse httpResponse = httpClient.execute(httpPost); CloseableHttpResponse httpResponse = httpClient.execute(httpPost); // 從響應對象中獲取響應內容 result = EntityUtils.toString(httpResponse.getEntity()); //logger.info("result = {}" , result); } catch (UnsupportedEncodingException e) { log.error("URLUtil.httpPostRequest encounters an UnsupportedEncodingException : {}",e); } catch (IOException e) { log.error("URLUtil.httpPostRequest encounters an IOException : {}",e); } log.info("URLUtil.httpPostRequest -----result----: " + result); return result; } } **文件工具類**
/** * <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 15:31 **/ public class FileUtil { public static File generateImage(String base64, String path) throws IOException { BASE64Decoder decoder = new BASE64Decoder(); File file = new File(path); String fileName = file.getName(); System.out.println("file = " + file); //創(chuàng)建臨時文件 //File tempFile = File.createTempFile(fileName, ".png"); //FileOutputStream fos = new FileOutputStream(tempFile);*/ try (OutputStream out = new FileOutputStream(path)){ // 解密 byte[] b = decoder.decodeBuffer(base64); for (int i = 0; i < b.length; ++i) { if (b[i] < 0) { b[i] += 256; } } out.write(b); out.flush(); return file; } /* finally { //關閉臨時文件 fos.flush(); fos.close(); try { Thread.sleep(10000); tempFile.deleteOnExit();//程序退出時刪除臨時文件 } catch (InterruptedException e) { e.printStackTrace(); } } */ } public static void deleteFile(File file) { //File file = new File(); String fileName = file.getName(); // 如果文件路徑所對應的文件存在,并且是一個文件,則直接刪除 if (file.exists() && file.isFile()) { if (file.delete()) { System.out.println("刪除單個文件" + fileName + "成功!"); } else { System.out.println("刪除單個文件" + fileName + "失?。?); } } else { System.out.println("刪除單個文件失?。? + fileName + "不存在!"); } } }
EchartsUtil.java:將option轉化為圖片編碼base64
/** * <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 14:07 **/ public class EchartsUtil { // private static String url = "http://localhost:6666"; private static final String SUCCESS_CODE = "1"; public static String generateEchartsBase64(String option, String url) throws ClientProtocolException, IOException { String base64 = ""; if (option == null) { return base64; } option = option.replaceAll("\\s+", "").replaceAll("\"", "'"); // 將option字符串作為參數(shù)發(fā)送給echartsConvert服務器 Map<String, String> params = new HashMap<>(); params.put("opt", option); String response = HttpUtil.post(url, params, "utf-8"); // 解析echartsConvert響應 JSONObject responseJson = JSONObject.parseObject(response); String code = responseJson.getString("code"); // 如果echartsConvert正常返回 if (SUCCESS_CODE.equals(code)) { base64 = responseJson.getString("data"); } // 未正常返回 else { String string = responseJson.getString("msg"); throw new RuntimeException(string); } return base64; } }
生成柱狀圖
/** * 生成單柱狀圖 * @param //isHorizontal 是否水平放置 * @param //color 柱狀圖顏色,可以不設置,默認為紅色 * @param //title 柱狀圖標題 * @param //xdatas 橫軸數(shù)據 * @param //ydatas 縱軸數(shù)據 * @return */ public static GsonOption createBar(BarData barData){ String title = barData.getTitle(); boolean isHorizontal = barData.getIsHorizontal(); Object[] xdatas = barData.getBarParamList().getBarName(); Object[] ydatas = barData.getBarParamList().getBarValue(); String legendName = barData.getBarParamList().getLegendName(); Bar bar = new Bar(); //圖類別(柱狀圖) //title EnhancedOption option = new EnhancedOption(); option.title(title); //標題 option.title().textStyle().fontSize(15).color("#000000").fontWeight("bolder"); //工具欄 toolbox option.toolbox().show(true).feature(Tool.mark, //輔助線 Tool.dataView, //數(shù)據視圖 new MagicType(Magic.line, Magic.bar), //線圖,柱狀圖切換 Tool.restore, //還原 Tool.saveAsImage //保存圖片 ); option.toolbox().show(true).feature(); //tooltip option.tooltip().show(true).formatter("{a}<br/> : {c}"); //顯示工具提示,設置提示格式 //legend Legend legend = new Legend(); TextStyle textStyle = new TextStyle(); textStyle.color("red"); textStyle.fontSize(10); textStyle.fontWeight("bolder"); legend.setData(Collections.singletonList(legendName)); legend.setTextStyle(textStyle); // legend.setBorderWidth(100); option.setLegend(legend); //圖例 //axisLabel AxisLabel axisLabel = new AxisLabel(); TextStyle textStyle1 = new TextStyle(); textStyle1.fontSize(10); textStyle1.fontWeight("bolder"); axisLabel.show(true); axisLabel.textStyle(textStyle1); axisLabel.setRotate(40); axisLabel.setInterval(0); //axisLine AxisLine axisLine = new AxisLine(); LineStyle lineStyle = new LineStyle(); lineStyle.color("#000000"); lineStyle.width(4); axisLine.lineStyle(lineStyle); //xAxis CategoryAxis category = new CategoryAxis();// 軸分類 category.data(xdatas);// 軸數(shù)據類別 category.axisLabel(axisLabel); // x軸文字樣式 category.axisLine(axisLine); //x軸樣式 //yAxis ValueAxis valueAxis = new ValueAxis(); valueAxis.setName("次數(shù)"); valueAxis.axisLabel().show(true).textStyle().fontSize(15).fontWeight("bolder"); //y軸文字樣式 valueAxis.axisLine().lineStyle().color("#315070").width(4); //y軸樣式 //series bar.name(legendName); Normal normal = new Normal(); normal.setShow(true); if(barData.getIsHorizontal() == false){ normal.position(Position.inside); }else { normal.position(Position.top); } normal.color("green"); normal.textStyle().color("red").fontSize(15).fontWeight("bolder"); bar.setBarWidth("70"); //柱條寬度 // bar.setBarMaxWidth(100); //柱條最大寬度 //bar.setBarMinHeight(10); //柱條最小高度 bar.label().normal(normal); //循環(huán)數(shù)據 for(int i = 0;i < xdatas.length;i++){ int data = (int) ydatas[i]; String color = "rgb(251,153,2)"; //類目對應的柱狀圖 Map<String, Object> map = new HashMap<>(2); map.put("value", data); map.put("itemStyle", new ItemStyle().normal(new Normal().color(color))); bar.data(map); } if(isHorizontal){ //橫軸為類別,縱軸為值 option.xAxis(category); //x軸 option.yAxis(valueAxis); //y軸 }else { //橫軸為值,縱軸為類別 option.xAxis(valueAxis); //x軸 option.yAxis(category); //y軸 } option.series(bar); return option; }
啟動測試
/** * <h3>demo</h3> * <p></p> * * @author : dkl * @date : 2023-05-12 14:09 **/ @Slf4j public class EchartBar { private static String requestUrl= "http://127.0.0.1:6666"; private static String imgUrl= "F:/"; public static void main(String[] args) { BarData barData = new BarData(); barData.setTitle("Test"); barData.setIsHorizontal(true); BarParam barParam = new BarParam(); String[] columnKeys = {"Test1","Test2","Test3","Test4","Test5","Test6","Test7"}; barParam.setBarName(columnKeys); Object[] data ={1,9,0,15,9,3,4}; barParam.setBarValue(data); barData.setBarParamList(barParam); GsonOption option = createBar(barData); String optionStr = JSONObject.toJSONString(option); log.error(optionStr); if(optionStr == null || "".equals(optionStr)){ return; } try { String base64 = EchartsUtil.generateEchartsBase64(optionStr, requestUrl); log.info("base64:" + base64); long nowStr = Calendar.getInstance().getTimeInMillis(); //圖片名 String imageName = JDate.getDuanshijian(new JDate(),"yyyy-MM-dd_HH_mm_ss") +".png"; log.info("bar圖片:" + imageName); File oldfile = FileUtil.generateImage(base64, imgUrl+imageName); } catch (Exception e) { e.printStackTrace(); } }
生成圖片展示
兩種方案到這就都實現(xiàn)了,來講一下這兩種的優(yōu)缺點吧
- JFreeChart 方便快捷,不需要自己去安裝啟動什么服務,而Echarts插件需要安裝啟動一個服務
- JFreeChart 生成的圖片清晰度感覺不是很清晰,Echarts的X軸字符太多導致展示不齊全
以上是個人覺得,不詆毀。
總結
到此這篇關于Java生成Echarts表圖的2種實現(xiàn)方案的文章就介紹到這了,更多相關Java生成Echarts表圖內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法
這篇文章主要給大家介紹了關于MybatisPlusException:Failed?to?process,Error?SQL異常報錯的解決辦法,文中通過實例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2023-03-03SpringBoot實現(xiàn)JPA多數(shù)據源配置小結
本文主要介紹了SpringBoot實現(xiàn)JPA多數(shù)據源配置小結,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2025-01-01Spring BeanFactory和FactoryBean區(qū)別解析
這篇文章主要介紹了Spring BeanFactory和FactoryBean區(qū)別解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03Mybatis的TypeHandler加解密數(shù)據實現(xiàn)
在我們數(shù)據庫中有些時候會保存一些用戶的敏感信息,所以就需要對這些數(shù)據進行加密,那么本文就介紹了Mybatis的TypeHandler加解密數(shù)據實現(xiàn),感興趣的可以了解一下2021-06-06eclipse/IDEA配置javafx項目步驟(圖文教程)
這篇文章主要介紹了eclipse/IDEA配置javafx項目步驟(圖文教程),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03springboot高并發(fā)下提高吞吐量的實現(xiàn)
這篇文章主要介紹了springboot高并發(fā)下提高吞吐量的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11