Go语言入门篇-JSON&http调用
一。Decoder
1 /(一)Decoder 2 func DecoderExample(){ 3 const jsonStream = ` 4 { "Name" : "Ed" , "Text" : "Knock knock." } 5 { "Name" : "Sam" , "Text" : "Who's there?" } 6 { "Name" : "Ed" , "Text" : "Go fmt." } 7 { "Name" : "Sam" , "Text" : "Go fmt who?" } 8 { "Name" : "Ed" , "Text" : "Go fmt yourself!" } 9 ` 10 type Message struct { 11 Name , Text string 12 } 13 dec := json. NewDecoder ( strings. NewReader ( jsonStream ) ) 14 for { 15 var m Message 16 if err := dec. Decode ( & m ) ; err == io. EOF { 17 break 18 } else if err != nil { 19 log . Fatal ( err ) 20 } 21 fmt. Printf ( "%s: %s \n " , m. Name , m. Text ) 22 /* 23 执行结果: 24 Ed: Knock knock. 25 Sam: Who's there? 26 Ed: Go fmt. 27 Sam: Go fmt who? 28 Ed: Go fmt yourself! 29 */ 30 } 31 }
二。对象转换为JSON的方法(函数)为 json.Marshal()
1 //(二)Marshal序列化JSON格式(对象-》JSON) 2 func marshalExample(){ 3 type ColorGroup struct { 4 ID int 5 Name string 6 Colors [ ] string 7 } 8 group := ColorGroup { 9 ID : 1 , 10 Name : "Reds" , 11 Colors : [ ] string { "Crimson" , "Red" , "Ruby" , "Maroon" } , 12 } 13 b , err := json. Marshal ( group ) 14 if err != nil { 15 fmt. Println ( "error:" , err ) 16 } 17 os. Stdout . Write ( b ) 18 /* 19 运行结果: 20 {"ID":1,"Name":"Reds","Colors":["Crimson","Red","Ruby","Maroon"]} 21 */ 22 }
三。JSON 转换回对象的方法(函数)为 json.Unmarshal()
1 //(三)unmarshal:反序列化json格式(JSON->对象) 2 func unmarshalExample(){ 3 var jsonBlob = [ ] byte ( ` [ 4 { "Name" : "Platypus" , "Order" : "Monotremata" } , 5 { "Name" : "Quoll" , "Order" : "Dasyuromorphia" } 6 ] ` ) 7 type Animal struct { 8 Name string 9 Order string 10 } 11 var animals [ ] Animal 12 err := json. Unmarshal ( jsonBlob , & animals ) 13 if err != nil { 14 fmt. Println ( "error:" , err ) 15 } 16 fmt. Printf ( "%+v" , animals ) 17 /* 18 运行结果: 19 [{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}] 20 */ 21 }
四。项目需求
参照go http传递json数据:https://blog.csdn.net/lanyang123456/article/details/78702873
golang学习室:https://www.kancloud.cn/digest/batu-go/153529
需求:
go调用java语言,传递json格式参数,并接收java返回的响应数据。(go建立http连接,传递请求参数,接收返回结果)
java端,返回json格式数据
1。Controller
1 package com.csvalue.controller; 2 import cfca.ra.common.vo.request.CertServiceRequestVO; 3 import cfca.ra.common.vo.request.TxRequestVO; 4 import cfca.ra.common.vo.response.CertServiceResponseVO; 5 import cfca.ra.common.vo.response.TxResponseVO; 6 import cfca.ra.toolkit.RAClient; 7 import cfca.ra.toolkit.exception.RATKException; 8 import com.alibaba.fastjson.JSON; 9 import com.csvalue.common.ResponseCode; 10 import com.csvalue.common.ResponseResult; 11 import com.csvalue.model.CertificateParam; 12 import com.csvalue.model.CertificateResult; 13 import org.slf4j.LoggerFactory; 14 import org.springframework.stereotype.Controller; 15 import org.springframework.web.bind.annotation.RequestBody; 16 import org.springframework.web.bind.annotation.RequestMapping; 17 import org.springframework.web.bind.annotation.RequestMethod; 18 import org.springframework.web.bind.annotation.ResponseBody; 19 20 @Controller 21 @RequestMapping("/cfca") 22 public class ApplyCertificateController { 23 24 final org.slf4j.Logger log = LoggerFactory.getLogger(getClass()); 25 26 @ResponseBody 27 @RequestMapping(value = "/applyCertificate", method = {RequestMethod.GET,RequestMethod.POST}) 28 public ResponseResult<CertificateResult> applyCertificate(@RequestBody CertificateParam certificateParam) { 29 log.info("接收到获取证书的参数:",JSON.toJSONString(certificateParam)); 30 CertificateResult certificateResult=new CertificateResult(); 31 try { 32 RAClient client = ApplyCertificateConfig.getRAClient(); 33 TxRequestVO txRequestVO = new TxRequestVO(); 34 txRequestVO.setTxCode("0000"); 35 TxResponseVO txResponseVO = (TxResponseVO) client.process(txRequestVO); 36 if(!"0000".equals(txResponseVO.getResultCode())){ 37 return ResponseResult.error(ResponseCode.DISCONNECT); 38 } 39 //设置请求参数 40 CertServiceRequestVO certServiceRequestVO=setCertServiceRequestVO(certificateParam); 41 //接收返回结果 42 CertServiceResponseVO certServiceResponseVO = (CertServiceResponseVO) client.process(certServiceRequestVO); 43 44 log.info("ResultCode:",certServiceResponseVO.getResultCode()); //0000 45 log.info("resultMsg:",certServiceResponseVO.getResultMessage()); //成功 46 //成功获取证书 47 if (RAClient.SUCCESS.equals(certServiceResponseVO.getResultCode())) { 48 //设置返回结果 49 certificateResult=setCertificateResult(certServiceResponseVO); 50 log.info("返回申请证书结果:",JSON.toJSON(certificateResult)); 51 }else if("3108".equals(certServiceResponseVO.getResultCode())){ 52 return ResponseResult.error(ResponseCode.NO_MATCH_CERTIFICATE); 53 }else if("900214".equals(certServiceResponseVO.getResultCode())){ 54 return ResponseResult.error(ResponseCode.PUBKEY_IS_USED); 55 }else{ 56 return ResponseResult.error(ResponseCode.FAIL); 57 } 58 } catch (RATKException e) { 59 log.error(e.getMessage(), e); 60 return ResponseResult.error(ResponseCode.FAIL); 61 } 62 return ResponseResult.success(certificateResult); 63 } 64 65 /*设置请求参数*/ 66 public CertServiceRequestVO setCertServiceRequestVO(CertificateParam certificateParam){ 67 CertServiceRequestVO certServiceRequestVO = new CertServiceRequestVO(); 68 certServiceRequestVO.setTxCode("1101"); 69 certServiceRequestVO.setCaName(certificateParam.getCaName()); 70 certServiceRequestVO.setCertType(certificateParam.getCertType()); 71 certServiceRequestVO.setCustomerType(certificateParam.getCustomerType()); 72 certServiceRequestVO.setUserName(certificateParam.getUserName()); 73 certServiceRequestVO.setIdentType(certificateParam.getIdentType()); 74 certServiceRequestVO.setIdentNo(certificateParam.getIdentNo()); 75 certServiceRequestVO.setKeyLength(certificateParam.getKeyLength()); 76 certServiceRequestVO.setKeyAlg(certificateParam.getKeyAlg()); 77 certServiceRequestVO.setBranchCode(certificateParam.getBranchCode()); 78 certServiceRequestVO.setEmail(certificateParam.getEmail()); 79 certServiceRequestVO.setP10(certificateParam.getP10()); 80 return certServiceRequestVO; 81 } 82 83 /*设置返回结果*/ 84 public CertificateResult setCertificateResult(CertServiceResponseVO certServiceResponseVO){ 85 CertificateResult certificateResult=new CertificateResult(); 86 certificateResult.setDn(certServiceResponseVO.getDn()); 87 certificateResult.setSequenceNo(certServiceResponseVO.getSequenceNo()); 88 certificateResult.setSerialNo(certServiceResponseVO.getSerialNo()); 89 certificateResult.setSignatureCert(certServiceResponseVO.getSignatureCert()); 90 certificateResult.setStartTime(certServiceResponseVO.getStartTime()); 91 certificateResult.setEndTime(certServiceResponseVO.getEndTime()); 92 certificateResult.setEncryptionCert(certServiceResponseVO.getEncryptionCert()); 93 certificateResult.setEncryptionCertSub(certServiceResponseVO.getEncryptionCertSub()); 94 certificateResult.setSignatureCert(certServiceResponseVO.getSignatureCert()); 95 certificateResult.setEncryptionPrivateKey(certServiceResponseVO.getEncryptionPrivateKey()); 96 certificateResult.setEncryptionPrivateKeySub(certServiceResponseVO.getEncryptionPrivateKeySub()); 97 return certificateResult; 98 } 99 }
2。model
1 package com.csvalue.model; 2 3 import java.io.Serializable; 4 5 public class CertificateParam implements Serializable { 6 private String caName; 7 private String certType; 8 private String customerType; 9 private String userName; 10 private String identType; 11 private String identNo; 12 private String keyAlg; 13 private String keyLength; 14 private String branchCode; 15 private String email; 16 private String p10; 17 18 public String getCaName() { 19 return caName; 20 } 21 22 public void setCaName(String caName) { 23 this.caName = caName; 24 } 25 26 public String getCertType() { 27 return certType; 28 } 29 30 public void setCertType(String certType) { 31 this.certType = certType; 32 } 33 34 public String getCustomerType() { 35 return customerType; 36 } 37 38 public void setCustomerType(String customerType) { 39 this.customerType = customerType; 40 } 41 42 public String getUserName() { 43 return userName; 44 } 45 46 public void setUserName(String userName) { 47 this.userName = userName; 48 } 49 50 public String getIdentType() { 51 return identType; 52 } 53 54 public void setIdentType(String identType) { 55 this.identType = identType; 56 } 57 58 public String getIdentNo() { 59 return identNo; 60 } 61 62 public void setIdentNo(String identNo) { 63 this.identNo = identNo; 64 } 65 66 public String getKeyAlg() { 67 return keyAlg; 68 } 69 70 public void setKeyAlg(String keyAlg) { 71 this.keyAlg = keyAlg; 72 } 73 74 public String getKeyLength() { 75 return keyLength; 76 } 77 78 public void setKeyLength(String keyLength) { 79 this.keyLength = keyLength; 80 } 81 82 public String getBranchCode() { 83 return branchCode; 84 } 85 86 public void setBranchCode(String branchCode) { 87 this.branchCode = branchCode; 88 } 89 90 public String getEmail() { 91 return email; 92 } 93 94 public void setEmail(String email) { 95 this.email = email; 96 } 97 98 public String getP10() { 99 return p10; 100 } 101 102 public void setP10(String p10) { 103 this.p10 = p10; 104 } 105 }
1 package com.csvalue.model; 2 3 import java.io.Serializable; 4 5 /* 6 * 申请证书返回结果 7 * */ 8 public class CertificateResult implements Serializable { 9 private String dn; 10 private String serialNo; 11 private String signatureCert; 12 private String sequenceNo; 13 private String encryptionCert; 14 private String encryptionPrivateKey; 15 private String signatureCertSub; 16 private String encryptionCertSub; 17 private String encryptionPrivateKeySub; 18 private String startTime; 19 private String endTime; 20 21 public String getDn() { 22 return dn; 23 } 24 25 public void setDn(String dn) { 26 this.dn = dn; 27 } 28 29 public String getSerialNo() { 30 return serialNo; 31 } 32 33 public void setSerialNo(String serialNo) { 34 this.serialNo = serialNo; 35 } 36 37 public String getSignatureCert() { 38 return signatureCert; 39 } 40 41 public void setSignatureCert(String signatureCert) { 42 this.signatureCert = signatureCert; 43 } 44 45 public String getSequenceNo() { 46 return sequenceNo; 47 } 48 49 public void setSequenceNo(String sequenceNo) { 50 this.sequenceNo = sequenceNo; 51 } 52 53 public String getStartTime() { 54 return startTime; 55 } 56 57 public void setStartTime(String startTime) { 58 this.startTime = startTime; 59 } 60 61 public String getEndTime() { 62 return endTime; 63 } 64 65 public void setEndTime(String endTime) { 66 this.endTime = endTime; 67 } 68 69 public String getEncryptionCert() { 70 return encryptionCert; 71 } 72 73 public void setEncryptionCert(String encryptionCert) { 74 this.encryptionCert = encryptionCert; 75 } 76 77 public String getEncryptionPrivateKey() { 78 return encryptionPrivateKey; 79 } 80 81 public void setEncryptionPrivateKey(String encryptionPrivateKey) { 82 this.encryptionPrivateKey = encryptionPrivateKey; 83 } 84 85 public String getSignatureCertSub() { 86 return signatureCertSub; 87 } 88 89 public void setSignatureCertSub(String signatureCertSub) { 90 this.signatureCertSub = signatureCertSub; 91 } 92 93 public String getEncryptionCertSub() { 94 return encryptionCertSub; 95 } 96 97 public void setEncryptionCertSub(String encryptionCertSub) { 98 this.encryptionCertSub = encryptionCertSub; 99 } 100 101 public String getEncryptionPrivateKeySub() { 102 return encryptionPrivateKeySub; 103 } 104 105 public void setEncryptionPrivateKeySub(String encryptionPrivateKeySub) { 106 this.encryptionPrivateKeySub = encryptionPrivateKeySub; 107 } 108 }
3。返回结果:
1 { 2 "code": 200, 3 "msg": "成功", 4 "data": { 5 "dn": "bb", 6 "serialNo": "2027277471", 7 "signatureCert": "aa", 8 "sequenceNo": "36", 9 "encryptionCert": "", 10 "encryptionPrivateKey": "", 11 "signatureCertSub": null, 12 "encryptionCertSub": null, 13 "encryptionPrivateKeySub": null, 14 "startTime": "20180914165223", 15 "endTime": "20200914165223" 16 } 17 }
******注意:******
使用postman测试java接口,是否能够成功调用
SpringMVC @RequestBody请求参数在postman中的请求
Step1:设置header中两个参数
Step2:设置json参数
go端,调用java端,传递请求参数及接收返回的JSON数据
1。callJava.go
1 package lib 2 3 import ( 4 "net/http" 5 "fmt" 6 "git.jd.com/baas/identity/cachain/common" 7 "encoding/json" 8 "strings" 9 "io/ioutil" 10 "log" 11 "git.jd.com/baas/identity/cachain/api" 12 ) 13 14 type EnrollCfca struct { 15 AuditId int `json:"auditId"` 16 CaName string `json:"caName"` 17 CertType string `json:"certType"` 18 CustomerType string `json:"customerType"` 19 UserName string `json:"userName"` 20 IdentType string `json:"identType"` 21 IdentNo string `json:"identNo"` 22 KeyAlg string `json:"keyAlg"` 23 KeyLength string `json:"keyLength"` 24 BranchCode string `json:"branchCode"` 25 Email string `json:"email"` 26 P10 string `json:"p10"` 27 } 28 29 type ResultCfca struct{ 30 Code int `json:"code"` 31 Msg string `json:"msg"` 32 Data api.CfcaInfo `json:"data"` 33 } 34 35 func enrollCFCA(w http.ResponseWriter, r *http.Request, h UserHandler) { 36 logger.Debugf("Enter enrollCFCA...") 37 defer logger.Debugf("Leave enrollCFCA...") 38 39 SetHeader(w) 40 41 var errMsg string 42 43 rareReq := EnrollCfca{} 44 if err := ReadRequest(r, &rareReq); err != nil { 45 logger.Errorf("read request err:%s", err.Error()) 46 errMsg = fmt.Sprintf("Failure to read body:%s", err.Error()) 47 common.SendResponse(w, common.ERR_READ_REQUEST, errMsg) 48 return 49 } 50 51 logger.Debugf("user enrollCFCA info: %+v", rareReq) 52 53 //1。调用java,从CFCA获取证书 54 resultCfca := callJava(rareReq) 55 56 if resultCfca.Code != 200 { 57 common.SendResponse(w, common.ERR_FAILURE, resultCfca.Msg) 58 return 59 } 60 61 resultCfca.Data.AuditId=rareReq.AuditId 62 63 //开启一个事务 64 tx, err := h.DBConn.Begin() 65 if err != nil { 66 logger.Errorf("Fail to begin a transaction,err:%s", err.Error()) 67 common.SendResponse(w, common.ERR_SQL_TRANSACTION, "Fail to begin transacton,err:"+err.Error()) 68 return 69 } 70 71 //1.将数据存储到数据库 72 err = h.SaveCfcaDataToDB(resultCfca.Data) 73 74 if err != nil { 75 logger.Errorf("Error insert cfcainfo into database err:%s", err.Error()) 76 common.SendResponse(w, common.ERR_SQL_INSERT, "Fail insert cfcainfo!user:"+rareReq.UserName+",err:"+err.Error()) 77 tx.Rollback() 78 return 79 } 80 tx.Commit() 81 return 82 } 83 //调用java 84 func callJava(javaParam EnrollCfca) ResultCfca{ 85 url := "http://localhost:8888/cfca/applyCertificate" 86 contentType := "application/json;charset=utf-8" 87 javaJsonParam, errs := json.Marshal(javaParam) //转换成JSON返回的是byte[] 88 if errs != nil { 89 fmt.Println(errs.Error()) 90 } 91 fmt.Println(string(javaJsonParam)) 92 93 //发送请求 94 req, err := http.NewRequest("POST", url, strings.NewReader(string(javaJsonParam))) 95 if err != nil { 96 panic(err) 97 } 98 req.Header.Set("Content-Type", contentType) 99 client := &http.Client{} 100 resp, err := client.Do(req) 101 if err != nil { 102 panic(err) 103 } 104 defer resp.Body.Close() 105 //响应 106 response, err := ioutil.ReadAll(resp.Body) 107 fmt.Println("response:", string(response)) 108 if err != nil { 109 log.Println("Read failed:", err) 110 return ResultCfca{} 111 } 112 log.Println("response:", string(response)) 113 114 //cfca返回结果 115 resultcfca := ResultCfca{} 116 json.Unmarshal([]byte(string(response)), &resultcfca) //json解析到结构体里面 117 fmt.Println("resultcfca",resultcfca) //输入结构体 118 fmt.Println("code",resultcfca.Code) 119 120 return resultcfca 121 }
2。api.go
1 package api 2 type CfcaInfo struct { 3 AuditId int `db:"auditId" json:"auditId"` 4 Dn string `db:"dn" json:"dn"` 5 SerialNo string `db:"serialNo" json:"serialNo"` 6 SignatureCert string `db:"signatureCert" json:"signatureCert"` 7 SequenceNo string `db:"sequenceNo" json:"sequenceNo"` 8 StartTime string `db:"startTime" json:"startTime"` 9 EndTime string `db:"endTime" json:"endTime"` 10 EncryptionCert string `db:"encryptionCert" json:"encryptionCert"` 11 EncryptionPrivateKey string `db:"encryptionPrivateKey" json:"encryptionPrivateKey"` 12 SignatureCertSub string `db:"signatureCertSub" json:"signatureCertSub"` 13 EncryptionCertSub string `db:"encryptionCertSub" json:"encryptionCertSub"` 14 EncryptionPrivateKeySub string `db:"encryptionPrivateKeySub" json:"encryptionCertSub"` 15 }
3。ra.go
1 package ra 2 const (saveEnrollCfca = `INSERT INTO cfca_info(auditId,dn,serialNo,signatureCert,sequenceNo,encryptionCert,encryptionPrivateKey,signatureCertSub,encryptionCertSub,encryptionPrivateKeySub,startTime,endTime) 3 VALUES(:auditId,:dn,:serialNo,:signatureCert,:sequenceNo,:encryptionCert,:encryptionPrivateKey,:signatureCertSub,:encryptionCertSub,:encryptionPrivateKeySub,:startTime,:endTime)` 4 ) 5 type DBConn struct { 6 *sqlx.DB 7 } 8 9 func (d *DBConn) SaveCfcaDataToDB(enrollResult api.CfcaInfo) error { 10 logger.Debugf("Enter SaveCfcaDataToDB ...") 11 defer logger.Debugf("Leave SaveCfcaDataToDB ...") 12 13 err := d.checkDB() 14 if err != nil { 15 logger.Errorf("check db err:%s", err.Error()) 16 return err 17 } 18 19 res, err := d.NamedExec(saveEnrollCfca, enrollResult) 20 21 if err != nil { 22 logger.Errorf("Error adding cfcaInfo %s to the database: %s", enrollResult.AuditId, err) 23 return err 24 } 25 26 numRowsAffected, err := res.RowsAffected() 27 if err != nil { 28 logger.Errorf("Error adding cfcaInfo %s affected err: %s", enrollResult.AuditId, err) 29 return err 30 } 31 32 if numRowsAffected == 0 { 33 return fmt.Errorf("Failed to add cfcaInfo %s to the database:", enrollResult.AuditId) 34 } 35 36 if numRowsAffected != 1 { 37 return fmt.Errorf("Expected to add one record to the datab ase, but %d records were added", numRowsAffected) 38 } 39 return nil 40 }
五。项目需求
参考博客:
http://www.cnblogs.com/Goden/p/4658287.html
http://www.01happy.com/golang-http-client-get-and-post/
项目需求:
go调用java传递string类型参数
Java端代码:
1 /* 2 * 撤销证书 3 * */ 4 @ResponseBody 5 @RequestMapping(value = "/revokeCertificate", method = RequestMethod.POST) 6 public ResponseResult revokeCertificate(String dn) { 7 log.info("接收到撤销的dn参数:", dn); 8 try { 9 RAClient client = CertificateConfig.getRAClient(); 10 CertServiceRequestVO certServiceRequestVO = new CertServiceRequestVO(); 11 certServiceRequestVO.setTxCode("2901"); 12 // certServiceRequestVO.setLocale(locale); 13 certServiceRequestVO.setDn(dn); 14 CertServiceResponseVO certServiceResponseVO = (CertServiceResponseVO) client.process(certServiceRequestVO); 15 log.info("撤销证书返回状态码和状态值:",certServiceResponseVO.getResultCode(),certServiceResponseVO.getResultMessage()); 16 if(!RAClient.SUCCESS.equals(certServiceResponseVO.getResultCode())){ //成功状态 17 return ResponseResult.error(Integer.parseInt(certServiceResponseVO.getResultCode()),certServiceResponseVO.getResultMessage()); 18 } 19 System.out.println(certServiceResponseVO.getResultCode()); 20 System.out.println(certServiceResponseVO.getResultMessage()); 21 } catch (RATKException e) { 22 log.error(e.getMessage(), e); 23 return ResponseResult.error(ResponseCode.FAIL); 24 } 25 return ResponseResult.success(ResponseCode.OK); 26 }
PostMan测试
Go端调用java实现传递url和参数
1 /* 2 吊销证书 3 */ 4 func revokeCfcaCert(userName string, h UserHandler) error { 5 logger.Debugf("enter revokeCert") 6 defer logger.Debugf("leave revokeCert") 7 8 if userName == "" { 9 return errors.New("userName is null") 10 } 11 //1.根据用户名查询dn值 12 cfcaInfo, err := h.DBGetCfcaInfo(userName) 13 14 log.Println("获取cfcaInfo:", cfcaInfo) 15 16 if err != nil { 17 return err 18 } 19 20 //2.调用java撤销cfca证书 21 resultCfca := callJavaRevoke(cfcaInfo.Dn) 22 23 log.Println("吊销证书resultCfca:", resultCfca) 24 25 if resultCfca.Code != 0000 { 26 //return fmt.Errorf(resultCfca.Msg) 27 return errors.New(resultCfca.Msg) 28 } 29 return nil 30 } 31 32 func callJavaRevoke(dn string) ResultCfca { 33 url := "http://localhost:8888/cfca/revokeCertificate" 34 contentType := "application/x-www-form-urlencoded" 35 //发送请求 36 req, err := http.NewRequest("POST", url, strings.NewReader("dn="+dn)) 37 if err != nil { 38 panic(err) 39 } 40 req.Header.Set("Content-Type", contentType) 41 client := &http.Client{} 42 resp, err := client.Do(req) 43 if err != nil { 44 panic(err) 45 } 46 defer resp.Body.Close() 47 //响应 48 response, err := ioutil.ReadAll(resp.Body) 49 fmt.Println("response:", string(response)) 50 if err != nil { 51 log.Println("Read failed:", err) 52 return ResultCfca{} 53 } 54 log.Println("response:", string(response)) 55 56 //cfca返回结果 57 resultcfca := ResultCfca{} 58 json.Unmarshal([]byte(string(response)), &resultcfca) //json解析到结构体里面 59 fmt.Println("resultcfca", resultcfca) //输入结构体 60 fmt.Println("code", resultcfca.Code) 61 return resultcfca 62 }
体胖还需勤跑步,人丑就该多读书!