關聯表多數據的批量insert (批量導入,測試19W條數據用時46秒)

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

一、業務需求 :作多個批量導入 ,根據業務不同,每條數據導入前作各種驗證,

? ? ? ? ? ? ? ? ? ? ? ? ? 導入后提示驗證失敗的所有數據和原因。

?

二、思路: 1. 批量導入用 jdbc 直連數據庫 addBatch方法實現 ,不走 Mybatis ,

? ? ? ?2. 數據驗證用 SQL 語句實現,不走 Mybatis ,

? ? ? ? ? ??? 3.?創建臨時表記錄合格數據并導入正式數據庫表

? ? ? ? ? ? ? ? ? ?4. 創建臨時表記錄驗證失敗的數據,并最終返回

? ? ?5. 由于業務需求批量導入時是要導入到 2 張主外鍵關聯表 ,

? ? ? ?? ? ? ?所以一次性獲取多個序列值以實現 2 表主外鍵的一致性。

6. ?用 sessionID 區分表名和序列名,實現并發導入時數據無污染 。

?

三、代碼:

?

?

 /*** 跳轉用戶導入頁面* @param request* @param session* @return String */@RequestMapping("userInfoImport")public  String userInfoImport(HttpServletRequest request,HttpSession session){return "op/usermgr/userInfoImport";}@RequestMapping("userInfoExcelImport")public  String userInfoExcelImport(HttpServletRequest request,HttpSession session,@RequestParam("excelPath")MultipartFile excelPath){Long start = System.currentTimeMillis();String backUrl = "../usermgr/initQuery.do";String[] excelTop = new String[]{"msisdn","custname","phoneType","creditamount","payType"}; // 表頭String tableName = session.getId().substring(0,8);// 定義-修改數據臨時表 String updateListTemp ="CREATE TABLE updateListTemp"+tableName+"("+"id integer NOT NULL,"+"msisdn varchar2(12) NOT NULL,"+"custname varchar2(50) NOT NULL,"+"phoneType varchar2(50) NOT NULL,"+"creditamount varchar2(10) NOT NULL,"+"payType varchar2(50) NOT NULL)"+" tablespace ISMP pctfree 60 initrans 1 maxtrans 255 storage (initial 64K) ";String updateTemp_seq ="CREATE SEQUENCE updateTemp_seq"+tableName+""+" INCREMENT BY 1" // 每次加1+" START WITH 1 "  // 從1開始計數+" NOMAXvalue "    // 不設置最大值+" NOCYCLE " 	    // 一直累加,不循環+" CACHE 10 "; 	    // 緩存10個// 定義-新增數據臨時表 String insertListTemp ="CREATE TABLE insertListTemp"+tableName+"("+"id integer NOT NULL,"+"msisdn varchar2(12) NOT NULL,"+"custname varchar2(50) NOT NULL,"+"phoneType varchar2(50) NOT NULL,"+"creditamount varchar2(10) NOT NULL,"+"payType varchar2(50) NOT NULL)"+" tablespace ISMP pctfree 60 initrans 1 maxtrans 255 storage (initial 64K) ";String insertTemp_seq ="CREATE SEQUENCE insertTemp_seq"+tableName+""+" INCREMENT BY 1" // 每次加1+" START WITH 1 "  // 從1開始計數+" NOMAXvalue "   // 不設置最大值+" NOCYCLE "	     // 一直累加,不循環+" CACHE 10 "; try {if(excelPath == null){OprResult.SetOprResult(request, "導入用戶異常","導入用戶失敗,請選擇要導入的內容 !", backUrl,OprResult.FAILURE);return "/op/oprResult";}// 解析得到的用戶表集合List<List<Object>> usrlist = ImportExcelUtil.getExcelList(excelPath.getInputStream(),excelTop);if(usrlist == null){OprResult.SetOprResult(request, "導入用戶異常", "導入用戶信息,數據表格不能有空值 !", backUrl,OprResult.FAILURE);return "/op/oprResult";}// 驗證電話、寬帶賬號List<String> failMsisdnList = new ArrayList<String>();List<String> msiddn = new ArrayList<String>();for(int y =0; y<usrlist.size(); y++){if(String.valueOf(usrlist.get(y).get(2).toString()).equals("電話號碼")){ // 驗證電話號碼if(!ValidateUtils.isMobile(usrlist.get(y).get(0).toString())){failMsisdnList.add(usrlist.get(y).get(0).toString());usrlist.remove(usrlist.get(y));y--;}}else{if(ValidateDhmp.validateUserMsisdn(usrlist.get(y).get(0).toString())){ // 驗證寬帶賬號failMsisdnList.add(usrlist.get(y).get(0).toString());usrlist.remove(usrlist.get(y));y--;}}}int failsize = failMsisdnList.size();// 去重for(int y =0; y<usrlist.size(); y++){if(y<1){msiddn.add(usrlist.get(y).get(0).toString());}else{if(msiddn.contains(usrlist.get(y).get(0).toString())){usrlist.remove(usrlist.get(y));y--;}else{msiddn.add(usrlist.get(y).get(0).toString());}}}// 創建臨時表和序列 -正確數據表、問題數據表BatchInsert.goSql(updateListTemp); BatchInsert.goSql(updateTemp_seq); BatchInsert.goSql(insertListTemp); BatchInsert.goSql(insertTemp_seq); // 導入sql:String insertSql ="insert into insertListTemp"+tableName+" values(updateTemp_seq"+tableName+".nextval,?,?,?,?,?)";BatchInsert.exeBatch(insertSql , usrlist); // 批量導入到新增數據表// 插入問題數據(用戶已存在)-sqlinsertSql ="insert into updateListTemp"+tableName+" select updateTemp_seq"+tableName+".nextval,"+"temp.msisdn,temp.custname,temp.phoneType,temp.creditamount,temp.payType"+" from insertListTemp"+tableName+" temp where temp.msisdn in (select msisdn from usr_end_user )";BatchInsert.goSql(insertSql); // 刪除問題數據(用戶已存在)-sqlString deleteErrorSql ="delete from insertListTemp"+tableName+" where msisdn in (select msisdn from usr_end_user )";BatchInsert.goSql(deleteErrorSql);// 只修改數據String[] col = new String[] {"id","msisdn","custname","phoneType","creditamount","payType"};List<List<Object>> failList = BatchInsert.selectToList("select * from updateListTemp"+tableName,col);failsize += failList.size();StringBuffer failbuffer = new StringBuffer();failbuffer.append("<br><br>一、請注意保留以下信息,此提示只顯示一次  !");failbuffer.append("<br><br>二、失敗數據,");if(failList != null && failList.size() > 0){failbuffer.append("<br><br> 賬號:"); for(List<Object> fail :failList){failbuffer.append(fail.get(1)+", "); }failbuffer.append("<br><br>原因:用戶已經存在,請直接編輯。"); }for(List<Object> fail : failList){fail.remove(0);}usrlist.removeAll(failList); // 求差 if(failMsisdnList != null && failMsisdnList.size() > 0){failbuffer.append("<br><br> 賬號:");for(String msisdn :failMsisdnList){ // 電話、寬帶賬號格式不對failbuffer.append(msisdn+", "); }failbuffer.append("<br><br>原因:電話號碼或寬帶賬號格式不對。"); }String squence ="select USR_CUSTOMER_SEQ.nextval cust_id from (select 1 from all_objects where rownum <= "+usrlist.size()+")";List<String> squenceList = BatchInsert.selectSql(squence);// 拼裝customListList<List<Object>> customList  = new ArrayList<List<Object>>(); Long maxCode = (long) 0; String maxCustCode = "";for(int i=0; i< usrlist.size(); i++){List<Object> custom = new ArrayList<Object>();custom.add(squenceList.get(i)); // usr_customer表的序列值custom.add(usrlist.get(i).get(1)); // custnamecustomList.add(custom);if(i<2){maxCustCode = usermgrService.findMaxCustCode();if(maxCustCode!= null && !"".equals(maxCustCode)){maxCode = Long.parseLong(maxCustCode)+1;custom.add(String.valueOf(maxCode));}else{custom.add(String.valueOf("10000000")); // setCustCode}}else{maxCode += 1;custom.add(String.valueOf(maxCode)); // setCustCode}}// 客戶表insert Sql:String customerSql ="insert into usr_customer(cust_id,cust_name,cust_code)values(?,?,?)";BatchInsert.exeBatch(customerSql , customList); // 插入客戶表// 用戶表insert Sql:String userSql ="insert into usr_end_user(user_id,cust_id,msisdn,creditamount,phone_type,user_payment_type,"+"user_stat,user_prvc_code,user_trade_type,is_black,is_active,language,user_level,is_test_user,"+"consume_limit,limit_tips,dayfee,monthfee,is_realname)"+" values(usr_end_user_seq.nextVal, ?,?,?,?,? ,?,?,?,?,? ,?,?,?,?,? ,?,?,?) ";// 拼裝userListList<List<Object>> userList  = new ArrayList<List<Object>>(); for(int i=0;i<usrlist.size();i++){List<Object> user = new ArrayList<Object>();user.add(squenceList.get(i)); //cust_iduser.add(usrlist.get(i).get(0));//msisdnuser.add(String.valueOf(usrlist.get(i).get(3))); //creditamountif("電話號碼".equals(String.valueOf(usrlist.get(i).get(2)))){user.add("1"); //phone_type}else if("寬帶號碼".equals(String.valueOf(usrlist.get(i).get(2)))){user.add("3"); //phone_type}if("后付費用戶".equals(String.valueOf(usrlist.get(i).get(4)))){user.add("1"); //user_payment_type}else  if("預付費用戶".equals(String.valueOf(usrlist.get(i).get(4)))){user.add("2"); //user_payment_type}user.add("1"); //user_statuser.add("08"); //user_prvc_codeuser.add("0"); //user_trade_type-賬戶行業類型:默認為家庭user.add(0); //is_blackuser.add(0); //is_activeuser.add("01"); //LANGUAGEuser.add("01"); //USER_LEVELuser.add(0); //IS_TEST_USERuser.add("'3|0|0|0|0|0|0|0|0'");//consumeLimituser.add("'0|0|0'");//LIMIT_TIPSuser.add("0"); //DAYFEEuser.add("0"); //MONTHFEEuser.add("1"); //IS_REALNAMEuserList.add(user);}BatchInsert.exeBatch(userSql ,userList); // 正式插入用戶表/*try{//日志log(session, UsermgrServiceImpl.class,"exeBatch", "批量新增用戶");log(session, UsermgrServiceImpl.class,"exeBatch", "批量新增客戶");}catch (Exception e){e.printStackTrace();}*/// 刪除臨時表String dropSql ="drop table updateListTemp"+tableName;String dropSql2 ="drop sequence updateTemp_seq"+tableName;String dropSql3 ="drop table insertListTemp"+tableName;String dropSql4 ="drop sequence insertTemp_seq"+tableName;BatchInsert.goSql(dropSql);BatchInsert.goSql(dropSql2);BatchInsert.goSql(dropSql3);BatchInsert.goSql(dropSql4);Long end = System.currentTimeMillis();System.out.println();System.out.println("導入用戶信息表"+userList.size()+"條數據,總用時==============================:"+ (end-start)/1000+"秒 。");System.out.println();if(failsize > 0){OprResult.SetOprResult(request, "提示信息", "部分用戶信息導入失敗,如下:"+failbuffer, backUrl, OprResult.FAILURE);}else{OprResult.SetOprResult(request, "提示信息", "用戶信息導入成功", backUrl, OprResult.SUCCESS);}} catch (EncryptedDocumentException e) {e.printStackTrace();OprResult.SetOprResult(request, "導入用戶異常","導入用戶信息失敗,請刷新頁面后重試 !", backUrl,OprResult.FAILURE);} catch (InvalidFormatException e) {e.printStackTrace();OprResult.SetOprResult(request, "導入用戶異常","導入用戶信息失敗,請刷新頁面后重試 !", backUrl,OprResult.FAILURE);} catch (IOException e) {e.printStackTrace();OprResult.SetOprResult(request, "導入用戶異常","導入用戶信息失敗,請刷新頁面后重試 !", backUrl,OprResult.FAILURE);} catch (Exception e) {e.printStackTrace();OprResult.SetOprResult(request, "導入用戶異常","導入用戶信息失敗,請刷新頁面后重試 !", backUrl,OprResult.FAILURE);}return "/op/oprResult";}

?

?

?

?

?

?

	/*** 判斷是不是合法手機號碼* @param mobile* @return*/public static boolean isMobile(String mobile) {Pattern pattern = Pattern.compile("^((13[0-9])|(15[0-9])|(18[0-9]))\\d{8}$");return pattern.matcher(mobile).matches();}

?

?

?

?

?

批量導入、表格解析工具類:

?

package com.mc.common.util;import java.sql.Connection;import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;import com.zznode.ismp.mc.common.MspException;/*** 批量導入工具類* @author JiangYu*/
public class BatchInsert {//    private static String url="jdbc:oracle:thin:@127.0.0.1:9521:orcl";    private static String url = MspConfiguration.getInstance().getParaValue("DBUrl");  // oracle數據庫用戶名     private static String user = MspConfiguration.getInstance().getParaValue("DBUser");    // oracle數據庫密碼     private static String password = MspConfiguration.getInstance().getParaValue("DBPassword");    public static Connection conn;    public static PreparedStatement ps;    public static ResultSet rs;    public static Statement st ;  public static Connection getConnection(){ //連接數據庫的方法        try {    Class.forName("oracle.jdbc.driver.OracleDriver"); //初始化驅動包         conn = DriverManager.getConnection(url, user, password);    } catch (Exception e) {    e.printStackTrace();    }  return conn;}    public static void main(String[] args) {   getConnection();    if(conn==null){    System.out.println("與oracle數據庫連接失敗!");    }else{    System.out.println("與oracle數據庫連接成功!");   }    } /*** 批量運行sql* @param con* @param sql* @param list*/public static void exeBatch(String sql,List<List<Object>> list) throws Exception{try {StringBuffer sqlbuffer = new StringBuffer();sqlbuffer.append(sql);Connection con = getConnection();con.setAutoCommit(false);// 關閉事務自動提交final int batchSize = 1000; // 每滿1000條數據運行一次int count = 0;Long startTime = System.currentTimeMillis();PreparedStatement pst = (PreparedStatement) con.prepareStatement(String.valueOf(sql));if(list != null && list.size() > 0){for (int i = 0; i < list.size(); i++) {for(int x =0;x<list.get(i).size();x++){pst.setObject(x+1,list.get(i).get(x));}pst.addBatch();// 把一個SQL命令加入命令列表if(++count % batchSize == 0 ){pst.executeBatch();count = 0;}}}pst.executeBatch();con.commit();pst.close();con.close();Long endTime = System.currentTimeMillis();System.out.println("單純inserrt用時:" + (endTime - startTime));} catch (Exception e) {e.printStackTrace();throw new MspException("網絡不暢,請刷新頁面后重試 !");}} // 解析數據表public static List<List<Object>> selectToList(String sql,String[] col){Connection conn = null;//定義為空值Statement stmt = null;ResultSet rs = null;conn = getConnection();List<Object> list = null;List<List<Object>> resultList = new ArrayList<List<Object>>(); try {stmt = conn.createStatement();//創建一個Statement語句對象rs = stmt.executeQuery(sql);//執行sql語句while(rs.next()){list = new ArrayList<Object>();for(int i=0; i< col.length; i++){list.add(rs.getObject(col[i]));}resultList.add(list);}} catch (SQLException e) {e.printStackTrace();}finally{try {conn.close();stmt.cancel();rs.close();}catch (SQLException e) {e.printStackTrace();}}return resultList;}// 執行增、刪、改sqlpublic static void goSql(String sql){Connection conn = null;//定義為空值Statement stmt = null;conn = getConnection();try {    stmt = conn.createStatement();    } catch (SQLException e) {    e.printStackTrace();    }    //4、執行語句    try {    stmt.executeUpdate(sql);    } catch (SQLException e) {    e.printStackTrace();    }    //5、關閉操作    try {    stmt.close();    conn.close();    } catch (SQLException e) {    e.printStackTrace();    }}// 單純查詢 public static List<String> selectSql(String sql){Connection conn = null;//定義為空值Statement stmt = null;ResultSet rs = null;conn = getConnection();List<String> list = new ArrayList<String>();try {stmt = conn.createStatement();//創建一個Statement語句對象rs = stmt.executeQuery(sql);//執行sql語句while(rs.next()){list.add(rs.getString("cust_id"));}} catch (SQLException e) {e.printStackTrace();}finally{try {conn.close();stmt.cancel();rs.close();}catch (SQLException e) {e.printStackTrace();}}return list;}}

?

?

?

?

?

說明:此句是為了一次性獲取 多個序列值,方便 2 表關聯:

String squence ="select USR_CUSTOMER_SEQ.nextval cust_id from (select 1 from all_objects where rownum <= "+usrlist.size()+")";

?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/451123.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/451123.shtml
英文地址,請注明出處:http://en.pswp.cn/news/451123.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java已死?九百萬程序員說不

Java沒死&#xff0c;事實上它擁有足夠的能量讓你的應用跑起來。那些對Java吹毛求疵人頻繁地聚焦在一些小眾問題上&#xff0c;總是和其他技術或者語言做些不公平的對比&#xff0c;這些語言并沒有像Java一樣得到廣泛應用及長遠的歷史。 現在的小孩都能學Java&#xff0c;它在…

Linux SSH遠程管理故障如何排查?

SSH遠程管理故障排查方案&#xff1a;1、檢測兩個機器是否暢通兩個機器之間是否暢通&#xff0c;查看物理鏈路是否有問題(網線網卡、IP是否正確)第1步&#xff1a;物理鏈路是否暢通&#xff0c;比喻為“高速公路是否暢通”ping 排查客戶端到服務端的線路問題&#xff0c;ping是…

CSS中position的absolute和relative用法

static: HTML元素的默認定位方式absolute: 將對象從文檔流中拖出&#xff0c;使用left&#xff0c;right&#xff0c;top&#xff0c;bottom等屬性進行絕對定位。而其層疊通過z-index屬性定義。絕對定位的元素的位置相對于最近的已定位父元素&#xff0c;如果元素沒有已定位的父…

Spring HttpMessageNotReadableException異常

&#xff08;一&#xff09;現象 我們在進行服務間的rpc調用時&#xff0c;可能會遇到org.springframework.http.converter.HttpMessageNotReadableException異常。 其具體報錯如下&#xff1a; {"timestamp": 1456043810789,"status": 400,"error…

解決 -- java 調用webservice 服務端收到參數為null

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我的客戶端和服務端都寫的很簡單&#xff0c;只是調用服務的時候&#xff0c; 服務端得不到參數&#xff0c;后來發現只改一個地方就可…

fastJson性能測試

測試裝備&#xff1a; mac pro 6核12線程 測試代碼&#xff1a; &#xff08;1&#xff09;序列化對象&#xff1a; import lombok.Data;Data public class User {int id;String name;int age;String address; } &#xff08;2&#xff09;序列化邏輯&#xff1a; import…

避免流量高峰期CDN問題的10個方法

在視頻流媒體中&#xff0c;因平臺火爆而出現問題是件好事。至少&#xff0c;這比根本沒有觀眾要好。\\也許你正在使用世界級的CDN&#xff0c;但是&#xff0c;在大型賽事期間&#xff0c;當CDN的服務器和對等點流量變得飽和的時候&#xff0c;一些用戶還是無法享受到流暢的體…

Android應用進入爆發期 手機游戲仍是市場重心

近日&#xff0c;91無線發布了《91無線移動應用發展趨勢報告&#xff08;Android版&#xff09;》。報告顯示&#xff0c;2012年&#xff0c;無論Android移動應用用戶下載還是開發者研發均呈爆發態勢&#xff0c;手機游戲仍是市場重心所在。同時&#xff0c;Android移動應用下載…

MQTT Client軟件-MQTTBox

最近發現了一個連接mqtt broker的軟件&#xff1a;MQTTBox。GitHub地址&#xff1a;https://github.com/workswithweb/MQTTBox 官網網站的介紹為&#xff1a;使用MQTTBox增強你的物聯網流程 MQTT客戶端特性 支持TCP、TLS、Web Sockets和安全的Web Sockets連接MQTT服務器支持各種…

fastJson toJSONString注意點

fastJosn是阿里爸爸推出一款高性能序列化工具&#xff0c;號稱最快的json序列化工具。不過好像也就那樣&#xff0c;在量比較大的時候優勢才會明顯。單次序列化時間還是會達到幾十毫秒的級別。 Fastjson is a Java library that can be used to convert Java Objects into the…

WebService中文件傳輸

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 WebService處理傳遞普通的信息&#xff0c;還可以傳輸文件&#xff0c;下面介紹WebService是怎么完成文件傳輸的。 1、 首先編寫服務器端…

Django框架-Form組件

一、DjangoForm組件介紹 我們之前在html頁面中利用form表單向后端提交數據時&#xff0c;都會寫一些獲取用戶輸入的標簽并且用form標簽把它們包起來。 與此同時我們在好多場景下都需要對用戶的輸入做校驗&#xff0c;比如驗證用戶是否輸入&#xff0c;輸入的長度和格式等是否正…

中國經濟轉型知易行難

摘要&#xff1a;一個亞洲國家正在崛起&#xff0c;出口機器勢不可擋&#xff0c;財富快速增長&#xff0c;覺得美國已是過去&#xff0c;自己的時代已經到來。這是2012年的中國&#xff1f;沒錯———但也是上世紀80年代的日本。 美國《芝加哥論壇報》網站5月20日文章&#xf…

進程和線程的剖析

進程和線程的區別&#xff1f;什么時候用進程&#xff1f;什么時候用線程&#xff1f; 答&#xff1a;首先得知道什么是進程什么是線程&#xff1f; 我的理解是進程是指在系統中正在運行的一個應用程序&#xff1b;程序一旦運行就是進程&#xff0c;或者更專業化來說&#xff1…

解決 java.net.ConnectException: Connection refused: connect 異常

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 一、 我的情況很簡單&#xff1a; 只是因為我調用服務端接口方法包名沒有寫對&#xff0c;應該如下面代碼中這樣寫&#xff1a; call.…

主席樹的各類模板(區間第k大數【動,靜】,區間不同數的個數,區間=k的個數)...

取板粗 好東西來的 1.&#xff08;HDOJ2665&#xff09;http://acm.hdu.edu.cn/showproblem.php?pid2665 &#xff08;POJ2104&#xff09;http://poj.org/problem?id2104 &#xff08;POJ2761&#xff09;http://poj.org/problem?id2761 題意&#xff1a;求區間第K大&…

java類內部的變量

類內部的變量分為兩部分&#xff1a; 一.類的成員變量 在類內部&#xff0c;變量定義部分&#xff0c;定義的變量。 二.局部變量 在類內方法體中定義的變量和方法中涉及的變量。 成員變量和局部變量的區別&#xff1a; &#xff08;1&#xff09;成員變量在整個類中都有效…

騰訊搜搜退出PC搜索領域:百度搜狗迎來雙龍競爭

摘要&#xff1a;據北京商報報道&#xff0c;上周末&#xff0c;騰訊對公司組織架構進行了大規模調整。業內普遍認為&#xff0c;搜搜并入騰訊無線后&#xff0c;這個獨立搜索平臺將被合并&#xff0c;失去獨立性&#xff0c;也將令搜搜官網域名soso.com走向“沒落”。據北京商…

facade-pattern外觀模式

外觀模式&#xff1a; 外觀模式是面向對象編程中的重要設計模式。外觀類用來掩蓋復雜的內部邏輯&#xff0c;為用戶提供簡潔統一的服務接口。外觀類的主要功能如下&#xff1a; 1.通過提供簡明的對外API接口&#xff0c;來提高程序的可閱讀性和間接性。 2.提供通用的特定功能…

Web Service 客戶端,調用服務方法

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 只是最簡單的調用web service 服務&#xff0c;至于要傳什么參數全看到業務了。 以下是最簡單的調用方式 &#xff1a; package hdmp…