บทคัดย่อ: เมื่อเร็ว ๆ นี้มีข้อกำหนดที่จะให้ลูกค้าด้วยอินเทอร์เฟซ API ที่พักผ่อน QA ใช้บุรุษไปรษณีย์สำหรับการทดสอบ แต่อินเทอร์เฟซทดสอบของบุรุษไปรษณีย์นั้นคล้ายคลึงกัน แต่ไม่เหมือนกับการเรียก Java ดังนั้นฉันต้องการเขียนโปรแกรมเพื่อทดสอบอินเทอร์เฟซ RESTFUL API ด้วยตัวเอง เนื่องจากใช้ HTTPS ฉันจึงต้องพิจารณาการประมวลผลของ HTTPS เนื่องจากฉันใช้ Java เพื่อโทรหาอินเทอร์เฟซ RESTFUL เป็นครั้งแรกฉันยังต้องศึกษาดังนั้นฉันจึงปรึกษาข้อมูลบางอย่างโดยธรรมชาติ
การวิเคราะห์: ปัญหานี้แตกต่างจากการโทรระหว่างโมดูล ตัวอย่างเช่นฉันมีสองโมดูลส่วนหน้าและแบ็กเอนด์ Frontend ให้การแสดงผลส่วนหน้าและแบ็กเอนด์ให้การสนับสนุนข้อมูล ฉันใช้ Hession เพื่อลงทะเบียนบริการที่ให้บริการโดย Backend เป็นบริการระยะไกล ในด้านส่วนหน้าบริการระยะไกลนี้สามารถปรับได้โดยตรงกับอินเทอร์เฟซแบ็กเอนด์ แต่นี่ไม่มีปัญหาสำหรับ บริษัท ที่จะใช้เมื่อโครงการของตัวเองมีการเชื่อมโยงกันอย่างมาก อย่างไรก็ตามหากคุณลงทะเบียนบริการระยะไกลดังกล่าวกับลูกค้าดูเหมือนว่าจะไม่ดีและการมีเพศสัมพันธ์สูงเกินไป ดังนั้นฉันจึงพิจารณาใช้วิธีการต่อไปนี้
การแนะนำขั้นพื้นฐาน
สำหรับการโทรของอินเทอร์เฟซ RESTFUL ส่วนหน้าโดยทั่วไปจะใช้การโทร AJAX และ back-end สามารถใช้วิธีการเพิ่มเติม
เวลานี้มีการแนะนำสามประเภท:
1. การใช้งาน httpurlconnection
2. การใช้งาน httpclient
3. สปริงของสปริง
1. httpClient
ทุกคนอาจคุ้นเคยกับ httpClient แต่ไม่คุ้นเคยกับมัน มันคุ้นเคยกับมันเพราะสามารถโทรจากระยะไกลได้เช่นขอ URL จากนั้นรับสถานะการส่งคืนและส่งคืนข้อมูลในการตอบกลับ อย่างไรก็ตามวันนี้ฉันกำลังพูดถึงเรื่องนี้ซับซ้อนขึ้นเล็กน้อยเพราะหัวข้อของวันนี้คือ HTTPS ซึ่งเกี่ยวข้องกับปัญหาของใบรับรองหรือการตรวจสอบผู้ใช้
หลังจากยืนยันว่าการใช้ HTTPClient ฉันค้นหาข้อมูลที่เกี่ยวข้องและพบว่า HTTPClient เวอร์ชันใหม่นั้นแตกต่างจากรุ่นเก่าและเข้ากันได้กับเวอร์ชันเก่า แต่ก็ไม่แนะนำอีกต่อไปว่าจะใช้เวอร์ชันเก่าอีกต่อไป มีวิธีการหรือคลาสมากมายที่ถูกทำเครื่องหมายว่าล้าสมัย วันนี้เราจะใช้เวอร์ชันเก่า 4.2 และเวอร์ชันล่าสุด 4.5.3 เพื่อเขียนรหัสตามลำดับ
เวอร์ชันเก่า 4.2
ต้องการการรับรอง
เลือกการใช้การรับรองความถูกต้องของใบรับรองระหว่างขั้นตอนการเตรียมใบรับรอง
แพ็คเกจ com.darren.test.https.v42; นำเข้า java.io.file; นำเข้า java.io.fileinputstream; นำเข้า java.security.keystore; นำเข้า org.apache.http.conn.ssl.slsocketformatory; {} @Override โมฆะสาธารณะ preperecertificate () พ่นข้อยกเว้น {// รับคีย์คีย์คีย์คีย์สตอร์ TrustStore = keystore.getInstance (keystore.getDefaultType ()); fileInputStream อินพุต = new FileInputStream (ไฟล์ใหม่ ( fileInputStream input = new FileInputStream (ไฟล์ใหม่ ("C: /USERS/ZHDA6001/DOWNLOADS/XXX.KEYSTORE")); // รหัสผ่านของคีย์คีย์ไลบรารี Truststore.load (instream, "รหัสผ่าน" .tochararray ()); // ลงทะเบียนคีย์ไลบรารี this.socketFactory = ใหม่ sslsocketFactory (Truststore); // อย่าตรวจสอบชื่อโดเมน SocketFactory.Sethostnameverifierข้ามการรับรอง
ตัวเลือกในการข้ามการรับรองความถูกต้องในระหว่างขั้นตอนการเตรียมใบรับรองคือ
แพ็คเกจ com.darren.test.https.v42; นำเข้า java.security.cert.certificateException; นำเข้า Java.security.cert.x509certificate; นำเข้า Javax.ssl.sslcontext org.apache.http.conn.ssl.sslsocketfactory; คลาสสาธารณะ httpstrustclient ขยาย httpsclient {public httpstrustclient () {} @Override โมฆะสาธารณะ preperecertificate () sslContext.getInstance ("TLS"); x509trustManager tm = ใหม่ x509trustManager () {@Override โมฆะสาธารณะ checkClientTrusted (x509Certificate [] chain, strytype) โยน certificateException CertificateException {} @Override สาธารณะ x509Certificate [] getacceptedissuers () {return null;}}; // ตั้งค่าเป็นใบรับรองที่เชื่อถือได้ ctx.init (Null, New TrustManager [] {tm}, null); SSLSocketFactory (CTX, SSLSocketFactory.allow_all_hostname_verifier);}}สรุป
ตอนนี้พบว่าทั้งสองคลาสสืบทอดคลาส HTTPSClient เดียวกันและ HTTPSClient สืบทอดคลาส defaulthttpClient จะพบได้ว่ารูปแบบวิธีการเทมเพลตถูกใช้ที่นี่
แพ็คเกจ com.darren.test.https.v42; นำเข้า org.apache.http.conn.ClientConnectionManager; นำเข้า org.apache.http.conn.scheme.scheme; นำเข้า org.apache.http.conn.sl.sslsocket org.apache.http.impl.client.defaulthttpclient; บทคัดย่อคลาสสาธารณะ httpsclient ขยาย defaulthttpclient {ป้องกัน sslsocketfactory socketfactory;/** * เริ่มต้น httpsclient * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * {this.prepRepertificate (); this.regist (); return this;}/*** เตรียมการตรวจสอบใบรับรอง** @throws Exception*/Public Public Void Preperecertificate () โยนข้อยกเว้น;/*** ลงทะเบียนโปรโตคอลและพอร์ต this.getConnectionManager (); schemeregistry sr = ccm.getschemeregistry (); sr.register (โครงการใหม่ ("https", 443, socketfactory));}}ด้านล่างคือคลาสเครื่องมือ
แพ็คเกจ com.darren.test.https.v42; นำเข้า java.util.arraylist; นำเข้า java.util.list; นำเข้า java.util.map; นำเข้า java.util.set; นำเข้า org.apache.http.htttentity; org.apache.http.namevaluepair; นำเข้า org.apache.http.client.entity.urlencodedformentity; นำเข้า org.apache.http.client.methods.httpget; นำเข้า org.apache.http.client.methods.htpost; org.apache.http.client.methods.httprequestbase; นำเข้า org.apache.http.message.basicamevaluepair; นำเข้า org.apache.http.util.entityutils; httpsClient, rl string, map <string, string> paramheader, map <string, string> parambody) พ่นข้อยกเว้น {return dopost (httpsclient, url, paramheader, parambody, default_charset); {string result = null; httppost httppost = new httppost (url); setheader (httppost, paramheader); setbody (httppost, parambody, charset); httpresponse = httpsclient.execute (resentity! = null) {result = entityUtils.toString (ความไม่พอใจ, charset);}} return result;} สตริงคงที่สาธารณะ doget (httpsClient httpsclient, url สตริง, แผนที่, string> paramhead, map <string, string> parambody) default_Charset);} public Static String doget (httpsClient httpsClient, url สตริง, แผนที่ <สตริง, สตริง> paramheader, แผนที่ <สตริง, สตริง> parambody, สตริง charset) โยนข้อยกเว้น {สตริงผลลัพธ์ = null; httpsclient.execute (httpget); if (ตอบสนอง! = null) {httpentity resentity = response.getEntity (); ถ้า (resentity! = null) {result = entityutils.toString (resentity, charset); {// set header if (paramheader! = null) {set <string> keyset = paramheader.keyset (); สำหรับ (คีย์สตริง: keyset) {request.addheader (key, paramheader.get (key));}}}}}}}}}}} (parambody! = null) {list <namevaluePair> list = new ArrayList <namevaluePair> (); ตั้งค่า <string> keyset = parambody.keyset (); สำหรับ (คีย์สตริง: คีย์) {list.add = ใหม่ urlencodedFormentity (รายการ, charset); httppost.setEntity (เอนทิตี);}}}}}จากนั้นมีคลาสทดสอบ:
แพ็คเกจ com.darren.test.https.v42; นำเข้า java.util.hashmap; นำเข้า java.util.map; คลาสสาธารณะ httpsclienttest {โมฆะคงที่สาธารณะหลัก (สตริง [] args) โยนข้อยกเว้น httpStrustClient (). init (); // httpsClient = ใหม่ httpscertifiedClient (). init (); string url = "https://1.2.6.2:8011/xxx/api/gettoken";//string url =" https://1.2.6.2:8011/xxx/api/gethealth "; แผนที่ <string, string> paramheader = ใหม่ hashmap <> (); // paramheader.put ("เนื้อหาประเภท", "แอปพลิเคชัน/json"); paramheader.put ("ยอมรับ", "แอปพลิเคชัน/xml"); แผนที่ <string, string> parambody = new hashmap <> (); parambody.put ("client_id", "[email protected]"); parambody.put ("client_secret", "p@ssword_1") httpsclientutil.doget (httpsclient, url, null, null); System.out.println (ผลลัพธ์);}}ข้อมูลส่งคืน:
<? xml version = "1.0" encoding = "utf-8"?>? <token> JKF8RL0SW+SKKFLJ8RBKI5HP1BEQK8PRCUTZPPBINQMYKRMXY1KWCJMCFT191ZPP88VV1AGHW8OYNWJEYS 0AxPlugax89EJCOWNBIKCC1UVFYESXHLKTCJQYUFIVEVHREQXJPHNCLQYWP+XSE5OD9X8VKFKK7INNTMRZQK7YBTZ /e3U7GSWM/5CVAHFL6O9REQ9CWPXAVZNOHYVNXSOHSZDO+BXATXXA1XPALYALLY/8H/UAP4N4DLZDJJJJ3B8T1XH+CRRIOM OPXF7C5WKHHHTOKEOEXW+XOPQKKSX5CKWWJPPUGIIFWF/PAQWG+JUOSVT7QGDPV8PMWJ9DWEWJTDXGUDG == </Token>
เวอร์ชันใหม่ 4.5.3
ต้องการการรับรอง
แพ็คเกจ com.darren.test.https.v45; นำเข้า java.io.file; นำเข้า java.io.fileinputstream; นำเข้า java.security.keystore; นำเข้า javax.net.ssl.sslcontext org.apache.http.conn.ssl.sslconnectionsocketFactory; นำเข้า org.apache.http.conn.ssl.trustselfsignedstrategy; นำเข้า org.apache.http.ssl.sslcontexts; {} @Override โมฆะสาธารณะ preperecertificate () พ่นข้อยกเว้น {// รับคีย์คีย์คีย์คีย์สโตร์ Truststore = keystore.getInstance (keystore.getDefaultType ()); fileInputStream = new FileInputStream (ไฟล์ใหม่ ( FileInputStream Instream = ใหม่ FileInputStream (ไฟล์ใหม่ ("C: /USERS/ZHDA6001/DOWNLOADS/XXX.KEYSTORE")); ลอง {// รหัสผ่านของคีย์คีย์ Library Truststore.load (Instream, "รหัสผ่าน" .tochararray ());} ในที่สุด {instream.close ();} sslcontext sslcontext = sslcontexts.custom (). loadTrustMaterial this.connectionsocketFactory = ใหม่ sslconnectionsocketFactory (sslContext);}}ข้ามการรับรอง
แพ็คเกจ com.darren.test.https.v45; นำเข้า java.security.cert.certificateException; นำเข้า Java.security.cert.x509certificate; นำเข้า Javax.ssl.sslcontext; นำเข้า Javax.net.ssl.Trustmanager; org.apache.http.conn.ssl.sslconnectionsocketFactory; คลาสสาธารณะ httpstrustclient ขยาย httpsclient {public httpstrustclient () {} @Override โมฆะสาธารณะ preperecertificate () sslContext.getInstance ("TLS"); x509trustManager tm = ใหม่ x509trustManager () {@Override โมฆะสาธารณะ checkClientTrusted (x509Certificate [] chain, strytype) โยน certificateException CertificateException {} @Override โมฆะสาธารณะตรวจสอบความน่าเชื่อถือ (X509Certificate [] โซ่, สตริง AuthType) พ่นใบรับรอง {} @Override สาธารณะ x509Certificate [] getacceptEdissuers () {return null;}}; // null); this.connectionsocketFactory = ใหม่ sslconnectionsocketFactory (ctx);}}สรุป
แพ็คเกจ com.darren.test.https.v45; นำเข้า org.apache.http.config.registry; นำเข้า org.apache.http.config.registryBuilder นำเข้า org.apache.http.conn.socket.connectionsocketactory; org.apache.http.impl.client.closeablehttpclient นำเข้า org.apache.http.impl.client.httpclientbuilder; นำเข้า org.apache.http.impl.client.httpclients; httpsClient ขยาย httpclientbuilder {private closeablehttpclient ไคลเอนต์การเชื่อมต่อที่ได้รับการป้องกันการเชื่อมต่อที่มีการเชื่อมต่อที่มีการเชื่อมต่อ;/** * เริ่มต้น httpsclient * * @return กลับไปที่อินสแตนซ์ปัจจุบัน this.client;}/*** เตรียมการตรวจสอบใบรับรอง** @throws Exception*/Public Public Void Preparecertificate () โยนข้อยกเว้น;/*** ลงทะเบียนโปรโตคอลและพอร์ตวิธีนี้สามารถเขียนใหม่ได้ SocketFactoryRegistry = RegistryBuilder. <การเชื่อมต่อ LONCECTIONACTORY> สร้าง (). register ("http", plainconnectionsocketfactory.instance). register ("https", this.connectionsocketfactory) .build (); POOLINGHTTPClientConnectionManager (SocketFactoryRegistry); httpClients.custom (). setConnectionManager (connManager); // สร้างวัตถุ httpClient ที่กำหนดเองนี้ client = httpClients.custom () setConnectionManager (connmanager) .build (); httpclients.createdefault ();}}เครื่องมือ:
แพ็คเกจ com.darren.test.https.v45; นำเข้า java.util.arraylist; นำเข้า java.util.list; นำเข้า java.util.map นำเข้า java.util.set; นำเข้า org.apache.http.htttentity; org.apache.http.namevaluePair; นำเข้า org.apache.http.client.httpclient; นำเข้า org.apache.http.client.entity.urlencodedFormentity; นำเข้า org.apache.http.client.methods.httpget; org.apache.http.client.methods.httprequestbase; นำเข้า org.apache.http.message.basicamevaluepair; นำเข้า org.apache.http.util.entityutils; httpClient, rl string, map <string, string> paramheader, map <string, string> parambody) พ่นข้อยกเว้น {return dopost (httpClient, url, paramheader, parambody, default_charset); {string result = null; httppost httppost = new httppost (url); setheader (httppost, paramheader); setbody (httppost, parambody, charset); httpresponse = httpClient.execute (resentity! = null) {result = entityUtils.toString (ความไม่พอใจ, charset);}} return result;} สตริงคงที่สาธารณะ doget (httpClient httpClient, url สตริง, แผนที่, สตริง> paramhead, แผนที่ <สตริง, สตริง> พารามิเตอร์) default_charset);} public Static String doget (httpClient httpClient, url สตริง, แผนที่ <สตริง, สตริง> paramheader, แผนที่ <สตริง, สตริง> parambody, สตริง charset) โยนข้อยกเว้น {สตริงผลลัพธ์ = null; httpget httpget = httpget httpClient.execute (httpget); if (ตอบสนอง! = null) {httpentity resentity = response.getEntity (); ถ้า (resentity! = null) {result = entityutils.toString (resentity, charset); {// set header if (paramheader! = null) {set <string> keyset = paramheader.keyset (); สำหรับ (คีย์สตริง: คีย์เซ็ต) {request.addheader (คีย์, paramheader.get (คีย์));}}} โมฆะคงที่ส่วนตัว setbody (httppost httppost, แผนที่ <สตริง, สตริง> พารามิเตอร์, สตริง charset) arraylist <namevaluePair> (); ตั้งค่า <string> keyset = parambody.keyset (); สำหรับ (คีย์สตริง: คีย์) {list.add (ใหม่ bearsNamevaluePair (key, parambody.get (key));} if (list.size () charset); httppost.setentity (เอนทิตี);}}}}คลาสทดสอบ:
แพ็คเกจ com.darren.test.https.v45; นำเข้า java.util.hashmap; นำเข้า java.util.map; นำเข้า org.apache.http.client.httpclient; คลาสสาธารณะ httpsclienttest null; // httpClient = new httpStrustClient (). init (); httpClient = ใหม่ httpscertifiedClient (). init (); string url = "https://1.2.6.2:8011/xxx/api/gettoken";//string url =" https://1.2.6.2:8011/xxx/api/gethealth "; แผนที่ <สตริง, สตริง> paramheader = ใหม่ hashmap <> (); paramheader.put ("ยอมรับ", "แอปพลิเคชัน/xml"); แผนที่ <สตริง, สตริง> parambody = ใหม่ hashmap <> (); parambody.put ("client_id", "[email protected]"); httpsclientutil.dopost (httpClient, url, paramheader, parambody); // string result = httpsClientutil.doget (httpsClient, url, null, null); System.out.println (ผลลัพธ์);}}ผลลัพธ์:
<? xml version = "1.0" encoding = "utf-8"?>? <token> rxitf9 // 7nxwxjs2cjijyhltvzunvmzxxeqtgn0u07sc9ysjeibpqte3hcjulskoxpeuyguveweei9jv7/wi klrzxykc3ospatsm0kcbckphu0tb2cn/nfzv9fmlueowfbdyz+n0seii9k+0gp7920dfencn17wujvmc0u2jwvm5fa JQKMILWODXZ6A0DQ+D7DQDJWVCWXBVJ2ILHYIB3PR805VPPMI9ATXRVAKO0ODA006WEJFOFCGYG5P70WPJ5RBLBLBL85V FY9WCVKD1R7J6NVJHXGH2GNIMHKJEJORMJDXW2GKIUSIWSELI/XPSWAO7/CTWNWTNCTGK8PX2ZUB0ZFA == </token>
2. httpurlconnection
@ControllerPublic RESTFULACTION {@AutoWired UserserVice UserserVice; // แก้ไข @RequestMapping (value = "put/{param}", method = requestMethod.put) สาธารณะ @ResponseBody String (@PathVariable String param) {return " requestmethod.post) public @ResponseBody สตริงโพสต์ (@PathVariable สตริงพารามิเตอร์, รหัสสตริง, ชื่อสตริง) {system.out.println ("id:"+id); system.out.println ("ชื่อ:"+ชื่อ); สตริงลบ (@PathVariable สตริงพารามิเตอร์) {return "ลบ:" + param;} // find @requestmapping (value = "get/{param}", method = requestMethod.get) public @ResponseBody String get (@PathVariable String Param) "DealCon/{param}") public @ResponseBody String (@PathVariable String param) {ลอง {string url = "http: // localhost: 8080/tao-manager-web/" url (url+= (param+"/xxx"); (httpurlConnection) restserviceurl .OpenConnection (); // param ป้อนตัวพิมพ์เล็กและแปลงเพื่อรับโพสต์ลบใส่ httpconnection.setRequestMethod (param.touppercase ()); สวิตช์เอาท์พุท httpConnection.setDooutput (จริง); // httpConnection.setDoInput (จริง); // ส่งพารามิเตอร์สตริงอินพุต = "& id ="+ urlencoder.encode ("abc", "UTF-8"); อินพุต+ = "& name ="+ "+ urlencoder.encode ("" Ahhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh ห์ห์ห์ห์ห์ห์ห์ปห์ห์ห์ห์ห์ห์ห์ห์ห์ ห์ห์ห์ห์ห์ห์ห์ปห์ห์ห์ห์ห์ห์ห์ห์ห์ hhhhhhhhhhhhhhhhhhhhhhhhHHHHHHHHHHH httpConnection.getOutputStream (); outputStream.write (input.getBytes ()); outputStream.flush ();} ถ้า (httpConnection.getResponsecode ()! = 200) ResponseBuffer = ใหม่ bufferedReader (ใหม่ inputStreamReader ((httpConnection.getInputStream ()))); string output; system.out.println ("เอาต์พุตจากเซิร์ฟเวอร์: /n"); {system.out.println (เอาท์พุท);} httpconnection.disconnect ();} catch (malformedurlexception e) {e.printstacktrace ();} catch (ioexception e) {e.printstacktrace ();3. สปริงของสปริง
เพิ่ม Springmvc.xml
<!-กำหนดค่า RestTemplate-> <!-โรงงานไคลเอนต์ http-> <bean id = "httpClientfactory"> <property name = "ConnectTimeOut" value = "10,000" /> <property name = "readtimeout" value = "10,000" /> /> </ebean>
ผู้ควบคุม
@ControllerPublic คลาส RestTemplateAction {@AutoWired ส่วนตัว RESTTEMPLATE เทมเพลต; @RequestMapping ("RESTTEM") สาธารณะ @ResponseBody ผู้ใช้ RestTem (วิธีการสตริง) {ผู้ใช้ผู้ใช้ = null; // ค้นหาว่า ("get" "http: // localhost: 8080/tao-manager-web/get/{id}", user.class, "wuwuwuwu"); // ความแตกต่างระหว่าง getForentity และ getForObject คือคุณสามารถรับค่าส่งคืนและสถานะข้อมูลส่วนหัว getForentity ("http: // localhost: 8080/tao-manager-web/get/{id}", user.class, "wuwuwuwuwuwu"); system.out.println (re.getStatusCode ()); ("โพสต์" .equals (วิธีการ)) {httpheaders ส่วนหัว = ใหม่ httpheaders (); headers.add ("x-auth-token", uuid.randomuuid (). toString ()); multivaluemap <string, สตริง> postparameters = new LinkedMultival "ahhhhhh"); postparameters.add ("ชื่อ", "เวอร์ชันบางส่วน"); httpentity <multivaluemap <สตริง, สตริง >> requestentity = httpentity ใหม่ <multivalueMap <สตริง, สตริง >> "http: // localhost: 8080/tao-manager-web/post/aaa", requestentity, user.class); // delete} อื่นถ้า ("ลบ" .Equals (วิธีการ)) {template.delete ("http: // localhost: 8080/tao-manager-web/delete/{id}", "aaa"); {template.put ("http: // localhost: 8080/tao-manager-web/put/{id}", null, "bbb");} return user;}}}ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้เกี่ยวกับการพูดคุยสั้น ๆ เกี่ยวกับวิธีที่ Java เรียกว่าอินเทอร์เฟซ API RESTFUL ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องกับ Java ในเว็บไซต์นี้ หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!