采纳示例

  前言:在SharePoint2013中,提供Search REST service搜索服务,你可以在自己的客户端搜索方法或者移动应用程序中使用,该服务支持REST web request。你可以使用KeyWord Query Language(KQL)或者FAST Query Language(FQL)来对Search REST Service进行搜索查询,并且,试用与远程客户端应用程序、移动应用程序和其他应用程序。

  1. SharePoint 2013使用_api来标识出 REST SERVICE,REST Service其实是 client.svc web service的一部分,但为了简化 REST URI的构造以及缩短REST URI的长度,使用 _api 来替代 _vti_bin/client.svc,例如, 你可以使用  来替代  _api 惯例;可参考此文章中的 Reference the SharePoint 2013 REST service in your endpoint URI 章节;

转发自:

一、   Search REST service

支持方式:

Search REST service支持 HTTP POST方式和 HTTP GET requests方式

 

GET requests:

URL:

Get方式你有两种传参方式,如下:

;)

POST requests:

URL:

在Post方式中,你可以使用JavaScript Object Notation (JSON)方式传参

 

Post方式的场景有三种:

Get方式传参,Url超出长度限制,只有使用Post方式;

查询条件非常复杂,Get方式难以满足需要,使用Post方式;

对于某些特定参数,只支持Post方式。

SharePoint 2013 REST Syntax Posters.pdf

gin是go语言环境下的一个web框架, 它类似于Martini, 官方声称它比Martini有更好的性能, 比Martini快40倍, Ohhhh….看着不错的样子, 所以就想记录一下gin的学习. gin的github代码在这里:gin源码. gin的效率获得如此突飞猛进, 得益于另一个开源项目httprouter, 项目地址:httprouter源码. 下面主要记录一下gin的使用.

二、Get方式查看返回XML

1、  在我配置好的搜索页面上,搜索“北京”,如下图,有4个结果

图片 1

2、  使用Get方式返回xml,在_api/search/query 后面添加querytext参数”北京”的Escape值“北京”

'

 图片 2

(返回的xml截图)

3、单个项目的XML节点

图片 3图片 4

<d:element m:type="SP.SimpleDataRow">
  <d:Cells>
    <d:element m:type="SP.KeyValue">
      <d:Key>Rank</d:Key>
      <d:Value>10.3831567764282</d:Value>
      <d:ValueType>Edm.Double</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>DocId</d:Key>
      <d:Value>52</d:Value>
      <d:ValueType>Edm.Int64</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>WorkId</d:Key>
      <d:Value>52</d:Value>
      <d:ValueType>Edm.Int64</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>Title</d:Key>
      <d:Value>北京</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>Author</d:Key>
      <d:Value>系统帐户</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>Size</d:Key>
      <d:Value>120</d:Value>
      <d:ValueType>Edm.Int64</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>Path</d:Key>
      <d:Value>http://url/DocLib/北方城市/北京.txt</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>Description</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>Write</d:Key>
      <d:Value>2013-08-21T02:22:46.0000000Z</d:Value>
      <d:ValueType>Edm.DateTime</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>CollapsingStatus</d:Key>
      <d:Value>0</d:Value>
      <d:ValueType>Edm.Int64</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>HitHighlightedSummary</d:Key>
      <d:Value>
        <c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都<c0>北京</c0>是首都
      </d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>HitHighlightedProperties</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>contentclass</d:Key>
      <d:Value>STS_ListItem_DocumentLibrary</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>PictureThumbnailURL</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>ServerRedirectedURL</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>ServerRedirectedEmbedURL</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>ServerRedirectedPreviewURL</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>FileExtension</d:Key>
      <d:Value>txt</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>ContentTypeId</d:Key>
      <d:Value>0x01010027E858607844AC42AD371DFAA2B2557C</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>ParentLink</d:Key>
      <d:Value>http://url/DocLib/北方城市</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>ViewsLifeTime</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>ViewsRecent</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>SectionNames</d:Key>
      <d:Value/>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>SectionIndexes</d:Key>
      <d:Value/>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>SiteLogo</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>SiteDescription</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>deeplinks</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>importance</d:Key>
      <d:Value>0</d:Value>
      <d:ValueType>Edm.Int64</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>SiteName</d:Key>
      <d:Value>http://url</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>IsDocument</d:Key>
      <d:Value>true</d:Value>
      <d:ValueType>Edm.Boolean</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>LastModifiedTime</d:Key>
      <d:Value>2013-08-21T02:22:46.0000000Z</d:Value>
      <d:ValueType>Edm.DateTime</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>FileType</d:Key>
      <d:Value>txt</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>IsContainer</d:Key>
      <d:Value>false</d:Value>
      <d:ValueType>Edm.Boolean</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>WebTemplate</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>SecondaryFileExtension</d:Key>
      <d:Value>txt</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>docaclmeta</d:Key>
      <d:Value m:null="true"/>
      <d:ValueType>Null</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>OriginalPath</d:Key>
      <d:Value>http://url/DocLib/北方城市/北京.txt</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>PartitionId</d:Key>
      <d:Value>0c37852b-34d0-418e-91c6-2ac25af4be5b</d:Value>
      <d:ValueType>Edm.Guid</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>UrlZone</d:Key>
      <d:Value>1</d:Value>
      <d:ValueType>Edm.Int32</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>AAMEnabledManagedProperties</d:Key>  <d:Value>AttachmentURI;deeplinks;DefaultEncodingURL;ExternalMediaURL;HierarchyUrl;OrgParentUrls;OrgUrls;OriginalPath;ParentLink;Path;PictureThumbnailURL;PictureURL;PublishingImage;recommendedfor;ServerRedirectedEmbedURL;ServerRedirectedPreviewURL;ServerRedirectedURL;SiteLogo;SitePath;SPSiteURL;UserEncodingURL</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>RenderTemplateId</d:Key>
      <d:Value>~sitecollection/_catalogs/masterpage/Display Templates/Search/Item_Default.js</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
    <d:element m:type="SP.KeyValue">
      <d:Key>piSearchResultId</d:Key>
      <d:Value>3_1</d:Value>
      <d:ValueType>Edm.String</d:ValueType>
    </d:element>
  </d:Cells>
</d:element>

View Code

4、解疑,我看到这个结果,很奇怪,为什么我的网站中有4条结果,REST返回了5条,详细查看每个SimpleDateRow发现,最后一个居然是之前做BCS测试的时候的结果,XML附后。 

<d:element m:type="SP.KeyValue">
<d:Key>Path</d:Key>
<d:Value>bdc3://blobdatacontent_blobdatacontent/Default/00000000%2D0000%2D0000%2D0000%2D000000000000/1394/BlobDataContent/1396?s_id=iAwAAAA==&s_ce=048g24810001020408000h20005s</d:Value>
<d:ValueType>Edm.String</d:ValueType>
</d:element>

 

工具:Chrome浏览器中的 Advanced Rest Client Application插件

###1. 安装gin 使用命令go get github.com/gin-gonic/gin就可以. 我们使用gin的时候引入相应的包就OKimport "github.com/gin-gonic/gin".

三、   Get 方式 - XML调用实例

1、  调用效果图,如下:

图片 5

2、  后台方法:

 1 public void gvDateBind()
 2 {
 3     string keywords = "'"   System.Web.HttpUtility.UrlEncode(tbKeyWord.Text)   "'";
 4     string strRes = "http://url/_api/search/query?querytext="   keywords;
 5 
 6     WebClient wc = new WebClient();
 7     wc.Encoding = System.Text.Encoding.UTF8;
 8     NetworkCredential nc = new NetworkCredential("username", "password", "ad");
 9     wc.Credentials = nc;
10     string str = wc.DownloadString(strRes);
11 
12     XmlDocument doc = new XmlDocument();
13     doc.LoadXml(str);
14     XmlNodeList xnodelist = doc.GetElementsByTagName("d:Rows");
15     XmlNode node = xnodelist[0];
16 
17     DataTable dt = new DataTable();
18     dt.Columns.Add("标题");
19     dt.Columns.Add("作者");
20     dt.Columns.Add("描述");
21     dt.Columns.Add("链接");
22 
23     XmlNodeList xlist = node.ChildNodes;
24 
25     foreach (XmlNode xnode in xlist)
26     {
27         XmlNodeList nn = xnode.ChildNodes[0].ChildNodes;
28         DataRow dr = dt.NewRow();
29 
30         foreach (XmlNode nnode in nn)
31         {
32             switch (nnode.ChildNodes[0].InnerText)
33             {
34                 case "Title":
35                     dr["标题"] = nnode.ChildNodes[1].InnerText;
36                     break;
37                 case "Author":
38                     dr["作者"] = nnode.ChildNodes[1].InnerText;
39                     break;
40                 case "HitHighlightedSummary":
41                     dr["描述"] = nnode.ChildNodes[1].InnerText;
42                     break;
43                 case "Path":
44                     dr["链接"] = nnode.ChildNodes[1].InnerText;
45                     break;
46             }
47         }
48         dt.Rows.Add(dr);
49     }
50 
51     gvSearchResult.DataSource = dt;
52     gvSearchResult.DataBind();
53 }

Get方式-Xml调用示例

 

###2. 使用方法

 四、   POST方式 - JSON调用实例

1、调用结果显示

图片 6

 

2、核心代码

 

$.ajax(
               {
                   url: http://url/_api/search/postquery,
                   type: "Post",
                   dataType: "application/json;odata=verbose",
                   data: JSON.stringify({
                       'request': {
                           'Querytext': queryText,
                           'StartRow': 1,
                           'RowLimit': 8,
                           'SelectProperties': {
                               'results': ['Title', 'ContentSource', 'DisplayAuthor', 'Path']
                           },
                           'TrimDuplicates': true,
                           'Refiners': 'companies,contentclass,FileType(filter=6/0/*)',
                           //'RefinementFilters': { 'results': ['filetype:equals("txt")'] }
                       }
                   }),
                   headers: {
                       "accept": "application/json;odata=verbose",
                       "content-type": "application/json;odata=verbose",
                       "X-RequestDigest": xRequestDigest
                   },
                   complete: ProcessSearchResult
               });

注:本来自己想写个调用JSON的博客,但是看到CSDN上有人写过了,自己就不写了,把最重要的那段代码贴给大家参考,大家有兴趣可以参考下,博客地址附后!

 

  1. Search REST API的query(GET)可以设置返回json格式的结果,存储在data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results中,results是个数据集合,序号从0开始;

  2. 使用REST API获取(GET)数据时,若返回多条记录,则返回值存储在data.d.results中,results是个数据集合,序号从0开始,每一个result包含一个对象单元信息,例如:一个List Item的所有属性,如代码所示;若返回单条记录,则返回值存储在data.d中;

<1> 一种最简单的使用GET/POST方法

五、   常用的查询参数:

查询关键字(querytext)

'

 

JSON实例:

{

'__metadata' : {'type' : 'Microsoft.Office.Server.Search.REST.SearchRequest'},

'Querytext' : 'sharepoint'

}

 

起始行(StartRow)

 

JSON实例:

{

'__metadata' : {'type' : 'Microsoft.Office.Server.Search.REST.SearchRequest'},

'Querytext' : 'sharepoint',

'StartRow' : '10'

}

 

返回行限制(RowLimit)

 

JSON实例:

{

'__metadata' : {'type' : 'Microsoft.Office.Server.Search.REST.SearchRequest'},

'Querytext' : 'sharepoint',

'RowLimit' : '30'

}

 

选择属性(SelectProperties)

'

 

JSON实例:

{

'__metadata' : {'type' : 'Microsoft.Office.Server.Search.REST.SearchRequest'},

'Querytext' : 'sharepoint',

'SelectProperties' : {

    'results' : [

          'Title,

          Author'

          ]

}

}

 

扩展名(RefinementFilters)

")'

 

JSON实例:

{

'__metadata' : {'type' : 'Microsoft.Office.Server.Search.REST.SearchRequest'},

'Querytext' : 'sharepoint',

'RefinementFilters' : {

'results' : ['fileExtension:equals("docx")']

}

}

 

排序(SortList)

'

 

JSON实例:

{

'__metadata' : {'type':'Microsoft.Office.Server.Search.REST.SearchRequest'},

'Querytext' : 'sharepoint',

'SortList' :

{

    'results' : [

        {

                'Property':'Created',

                'Direction': '0'

        },

        {

                'Property':'FileExtension',

                'Direction': '1'

        }

    ]

}

}

 

返回总长度(SummaryLength)

 

JSON实例:

{

'__metadata':{'type':'Microsoft.Office.Server.Search.REST.SearchRequest'},

'Querytext' : 'sharepoint',

'Summarylength' : '150'

}

 

参考链接:

1、SharePoint Search REST API overview

2、Jquery(Ajax) 调用 SharePoint 2013 Search Rest API 并使用Josn反回结果并简单显示

图片 7图片 8

gin服务端代码是:

{
"__metadata":{"id":"b719e719-e4cc-445c-9c7c-0250aba4338a",
"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)",
"etag":""4"","type":"SP.Data.TasksListItem"},
"FirstUniqueAncestorSecurableObject":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/FirstUniqueAncestorSecurableObject"}},
"RoleAssignments":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/RoleAssignments"}},
"AttachmentFiles":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/AttachmentFiles"}},
"ContentType":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/ContentType"}},
"FieldValuesAsHtml":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/FieldValuesAsHtml"}},
"FieldValuesAsText":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/FieldValuesAsText"}},
"FieldValuesForEdit":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/FieldValuesForEdit"}},
"File":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/File"}},
"Folder":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/Folder"}},
"ParentList":{"__deferred":{"uri":"https://gjq-11683d04060f3b.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'b44e6daf-ee1e-4249-987f-2f9305cdc884')/Items(1)/ParentList"}},
"FileSystemObjectType":0,
"Id":1,
"ContentTypeId":"0x0108005943A401D04CAD47AE81ABAA54AA39A3",
"Title":"Test",
"PredecessorsId":{"__metadata":{"type":"Collection(Edm.Int32)"},"results":[]},
"Priority":"(2) Normal",
"Status":"Not Started",
"PercentComplete":0.79,
"AssignedToId":11,
"TaskGroupId":null,
"Body":"<div></div>",
"StartDate":"2014-08-10T16:00:00Z",
"DueDate":"2014-08-27T16:00:00Z",
"RelatedItems":null,
"WorkflowLink":null,
"OffsiteParticipant":null,
"OffsiteParticipantReason":null,
"WorkflowOutcome":null,
"WorkflowName":null,
"GUID":"2c618f60-7fae-4689-a652-52458ae60dd6",
"ID":1,
"Modified":"2014-08-12T03:41:59Z",
"Created":"2014-08-11T01:57:18Z",
"AuthorId":11,
"EditorId":11,
"OData__UIVersionString":"4.0",
"Attachments":false
}

// func1: 处理最基本的GETfunc func1(c*gin.Context){// 回复一个200OK,在client的http-get的resp的body中获取数据c.String(http.StatusOK,"test1 OK")}// func2: 处理最基本的POSTfunc func2(c*gin.Context){// 回复一个200 OK, 在client的http-post的resp的body中获取数据c.String(http.StatusOK,"test2 OK")}func main(){// 注册一个默认的路由器router:=gin.Default()// 最基本的用法router.GET("/test1",func1)router.POST("/test2",func2)// 绑定端口是8888router.Run(":8888")}

View Code

客户端代码是:

  1. 使用REST API的一些建议:

func main(){// 调用最基本的GET,并获得返回值resp,_:=http.Get(" 调用最基本的POST,并获得返回值resp,_=http.Post("

  • If you’re not using the cross-domain library, include an X-RequestDigest header to send the form digest value in all POST requests and a content-lengthheader for POST requests that send data in the request body.

  • If you're not making cross-domain requests, remove SP.AppContextSite(@target) and ?@target='<host web url>' from the endpoint URI.

  • If you’re using OAuth, include an Authorization header ("Authorization": "Bearer " <access token>) to send the OAuth access token.

  • If you want the server to return responses in Atom format, remove the "accept": "application/json; odata=verbose" header.

在服务端, 实例化了一个router, 然后使用GET和POST方法分别注册了两个服务, 当我们使用HTTP GET方法的时候会使用GET注册的函数, 如果使用HTTP POST的方法, 那么会使用POST注册的函数. gin支持所有的HTTP的方法例如: GET, POST, PUT, PATCH, DELETE 和 OPTIONS等. 看客户端中的代码, 当调用http.Get(", 服务端接收到请求, 并根据/test1将请求路由到func1函数进行 处理. 同理, 调用http.Post("", "",strings.NewReader(""))时候, 会使用func2函数处理. 在func1和func2中, 使用gin.Context填充了一个String的回复. 当然也支持JSON, XML, HTML等其他一些格式数据. 当执行c.String或者c.JSON时, 相当于向http的回复缓冲区写入了 一些数据. 最后调用router.Run(“:8888”)开始进行监听,Run的核心代码是:

  1. 使用REST API获取对象信息时,只能获取到当前级别信息,类似于Client Object Model,比如 /_api/web/lists可以获得所有list信息,但没有list item的信息;例如:一个List的所有属性,

func(engine*Engine)Run(addrstring)(err error){debugPrint("Listening and serving HTTP on %sn",addr)defer func(){debugPrintError(err)}()// 核心代码err=http.ListenAndServe(addr,engine)return}

图片 9图片 10

其本质就是http.ListenAndServe(addr, engine).

{
"__metadata":
  {
  "id":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')",
  "uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')",
  "etag":""3"",
  "type":"SP.List"
  },
"FirstUniqueAncestorSecurableObject":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/FirstUniqueAncestorSecurableObject"}},
"RoleAssignments":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/RoleAssignments"}},
"ContentTypes":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/ContentTypes"}},
"CreatablesInfo":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/CreatablesInfo"}},
"DefaultView":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/DefaultView"}},
"DescriptionResource":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/DescriptionResource"}},
"EventReceivers":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/EventReceivers"}},
"Fields":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/Fields"}},
"Forms":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/Forms"}},
"InformationRightsManagementSettings":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/InformationRightsManagementSettings"}},
"Items":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/Items"}},
"ParentWeb":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/ParentWeb"}},
"RootFolder":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/RootFolder"}},
"TitleResource":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/TitleResource"}},
"UserCustomActions":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/UserCustomActions"}},
"Views":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/Views"}},
"WorkflowAssociations":{"__deferred":{"uri":"https://gjq-11683d04060f3f.sharepoint.com/BasicOperationApp/_api/Web/Lists(guid'9b64f833-6b28-4bf4-b02d-31e6f1d649e6')/WorkflowAssociations"}},
"AllowContentTypes":true,"BaseTemplate":100,"BaseType":0,"ContentTypesEnabled":false,"CrawlNonDefaultViews":false,"Created":"2014-08-12T05:22:25Z",
"DefaultContentApprovalWorkflowId":"00000000-0000-0000-0000-000000000000",
"Description":"",
"Direction":"none",
"DocumentTemplateUrl":null,
"DraftVersionVisibility":0,
"EnableAttachments":true,
"EnableFolderCreation":false,
"EnableMinorVersions":false,
"EnableModeration":false,
"EnableVersioning":false,
"EntityTypeName":"AccordionList",
"ForceCheckout":false,
"HasExternalDataSource":false,
"Hidden":false,
"Id":"9b64f833-6b28-4bf4-b02d-31e6f1d649e6",
"ImageUrl":"/_layouts/15itgen.png?rev=37",
"IrmEnabled":false,
"IrmExpire":false,
"IrmReject":false,
"IsApplicationList":false,
"IsCatalog":false,
"IsPrivate":false,
"ItemCount":3,
"LastItemDeletedDate":"2014-08-12T05:22:25Z",
"LastItemModifiedDate":"2014-08-13T06:16:41Z",
"ListItemEntityTypeFullName":"SP.Data.AccordionListItem",
"MultipleDataList":false,
"NoCrawl":false,
"ParentWebUrl":"/",
"ParserDisabled":false,
"ServerTemplateCanCreateFolders":true,
"TemplateFeatureId":"00bfea71-de22-43b2-a848-c05709900100",
"Title":"Accordion"
}

注意: helpRead函数是用于读取response的Body的函数, 你可以自己定义, 本文中此函数定义为:

View Code

// 用于读取resp的bodyfunc helpRead(resp*http.Response){defer resp.Body.Close()body,err:=ioutil.ReadAll(resp.Body)iferr!=nil{fmt.Println("ERROR2!: ",err)}fmt.Println(string(body))}

  1. REST Search API时,默认的rowlimit是10,即默认返回10条记录;

  2. 使用REST API的POST方法创建新内容时,返回的信息存储在data.d中,比如data.d.Id;

  3. REST API 不能修改文件夹的Name,详情请参考此处或者此处;

<2> 传递参数

  1. REST API在更新file内容时,只能使用PUT,更新文件的metadata时,需要将文件看作一个item;

    If you want to update a file's metadata, you'll have to construct an endpoint that reaches the file as a list item. You can do this because each folder is also a list, and each file is also a list item. Construct an endpoint that looks like this: https:///_api/web/lists/getbytitle('Documents')/items(). Working with lists and list items with REST explains how to update a list item's metadata.

  2. 使用REST API获取item信息时,Look Up字段会发生一些变化,比如:有一个内部名称为Zone的列,查询出来的数据中找不到Zone列,而会有个ZoneId字段,值为被查询item的ID值;如果想得到Zone的显示名称,可使用$expand来获取:

    1. 在$select=中可以写上Zone/Id,Zone/ColumnX;
    2. 在$expand=中必须写上Zone;

      注:Zone为当前列表的Look up字段;ColumnX为被查询列表的任何字段的内部名称;

传递参数有几种方法, 对应到gin使用几种不同的方式来解析.

10. 如果不使用cross-domain类库,在进行POST操作时,都要在headers中添加X-RequestDigest参数,默认赋值是$("#__REQUESTDIGEST").val();

**第一种:**使用gin.Context中的Param方法解析

11. 过滤操作需要使用$filter,例如,只需要Title字段以“B”开头的数据:$filter=startswith(Title, 'B');只需要Title字段包含“B”的数据:$filter=substringof('B',Title);

对应的服务端代码为:

图片 11

// func3: 处理带参数的path-GETfunc func3(c*gin.Context){// 回复一个200 OK// 获取传入的参数name:=c.Param("name")passwd:=c.Param("passwd")c.String(http.StatusOK,"参数:%s %s  test3 OK",name,passwd)}// func4: 处理带参数的path-POSTfunc func4(c*gin.Context){// 回复一个200 OK// 获取传入的参数name:=c.Param("name")passwd:=c.Param("passwd")c.String(http.StatusOK,"参数:%s %s  test4 OK",name,passwd)}// func5: 注意':'和'*'的区别func func5(c*gin.Context){// 回复一个200 OK// 获取传入的参数name:=c.Param("name")passwd:=c.Param("passwd")c.String(http.StatusOK,"参数:%s %s  test5 OK",name,passwd)}func main(){router:=gin.Default()// TODO:注意':'必须要匹配,'*'选择匹配,即存在就匹配,否则可以不考虑router.GET("/test3/:name/:passwd",func3)router.POST("/test4/:name/:passwd",func4)router.GET("/test5/:name/*passwd",func5)router.Run(":8888")}

  1. REST API - GET

           $.ajax({

                  url: "https://XXX.sharepoint.com/_api/web/lists/GetByTitle('XXX')/items",
                  type: "GET",
                  headers: {"Accept": "application/json;odata=verbose"},
                  success: function(data){
                      if(data.d.results){
                          var $selectObj = $("<select id='deptSelect'></select>");
                          $.each(data.d.results, function(index, item){
                              $selectObj.append($("<option></option>").attr("value", item.ID   item.Title).text(item.Title));
                          });
                          $("#getDiv").append($selectObj);
                          $("#getDiv").append("<br/>" JSON.stringify(data.d.results));
                      }
                  },
                  error: function(xhr){
                      alert(xhr.status ': ' xhr.statusText);
                  }
              });
    

客户端测试代码是:

注意:由于服务器端分页的限制,默认情况下,每次只能获取100条数据,但可以使用$top参数来指定一次要获取多少条数据,但最大不能超过5000;还可以使用__next来获取下一页的100条数据,请参考此处;

func main(){// GET传参数,使用gin的Param解析格式: /test3/:name/:passwdresp,_=http.Get(" POST传参数,使用gin的Param解析格式: /test3/:name/:passwdresp,_=http.Post(" 注意Param中':'和'*'的区别resp,_=http.Get("

  1. REST API - POST (create)

            var newItem={

                  "__metadata":{"type": "SP.Data.Region_x0020_ApproversListItem"},
                  "Title": "Test Dept",
                  "Region": "GCN"
              };
    
              $.ajax({
                  url: "https://XXX.sharepoint.com/_api/web/lists/GetByTitle('XXX')/items",
                  type: "POST",
                  contentType: "application/json;odata=verbose",
                  data: JSON.stringify(newItem),
                  headers: {
                      "Accept": "application/json;odata=verbose",
                      "X-RequestDigest": $("#__REQUESTDIGEST").val()
                  },
                  success: function(data){
                      alert(JSON.stringify(data.d.Id));
                  },
                  error: function(xhr){
                      alert(xhr.status ': ' xhr.statusText);
                  }
              });
    
  2. REST API - POST (update)

            var updatedItem={

                  "__metadata":{"type":"SP.Data.Region_x0020_ApproversListItem"},
                  "Title": "Test Dept Again"
              };
    
            $.ajax({
                  url: "https://XXX.sharepoint.com/_api/web/lists/GetByTitle('XXX')/items(40)",
                  type: "POST",
                  contentType: "application/json;odata=verbose",
                  data: JSON.stringify(updatedItem),
                  headers:{
                      "ACCEPT": "application/json;odata=verbose",
                      "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                      "X-HTTP-METHOD": "MERGE",
                      "IF-MATCH": "*"
                  },
                  success: function(){ //此处没有data参数
                      getListItem();
                  },
                  error: function(xhr){
                      alert(xhr.status ': ' xhr.statusText);
                  }
              });
    
  3. REST API - DELETE

            $.ajax({

                  url: "https://XXX.sharepoint.com/_api/web/lists/GetByTitle('XXX')/items(43)",
                  type: "POST",
                  headers:{
                      "Accept": "application/json;odata=verbose",
                      "X-Http-Method": "DELETE",
                      "X-RequestDigest": $("#__REQUESTDIGEST").val(),
                      "If-Match": "*"
                  },
                  success: function(data){
                      alert(JSON.stringify(data));
                  },
                  error: function(xhr){
                      alert(xhr.status ': ' xhr.statusText);
                  }
              });
    

注意上面定义参数的方法有两个辅助符号: ‘:’和’*’. 如果使用’:’参数方法, 那么这个参数是必须要匹配的, 例如上面的router.GET(“/test3/:name/:passwd”, func3), 当请求URL是 类似于, 如果是 或者. 但是如果使用’*‘参数, 那么这个参数是可选的. router.GET(“/test5/:name/*passwd”, func5) 可以匹配, 也可以匹配. 需要注意的一点是, 下面这个URL是不是能够 匹配呢? , 注意TAO后面没有’/’, 这个其实就要看有没有一个路由是到, 如果有, 那么指定的那个函数进行处理, 如果没有, 然后被当前注册的函数进行处理.

16. 在进行POST操作时,需要先得到metadata中的type属性值,方法是:

**第二种:**使用gin.Context中的Query方法解析

  1. SharePoint 2016及 Office 365支持 REST API批量操作(Batch),可参考此处;

  2. REST API 使用的uri中,SharePoint名称(比如,列表名,列名)是大小写敏感的,oData的名称是大小写不敏感;在使用$filter等条件语句进行筛选对比时,非数字类型值需要添加单引号,比如 userName eq 'ABC';

  3. 使用REST API获取当前用户的登录名:

  4. 创建一个 Custom REST Service,可参考此文章;重要一点是:无需修改Web Config文件,只需要在.svc文件声明中加入以下代码即可:

    <%@ ServiceHost Language="C#" Debug="true" Service="SPRESTService.CustomRESTService, $SharePoint.Project.AssemblyFullName$"

    CodeBehind="CustomRESTService.svc.cs" 
    Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory,
    Microsoft.SharePoint.Client.ServerRuntime, Version=15.0.0.0, Culture=neutral,
    PublicKeyToken=71e9bce111e9429c"%>
    

这个类似于正常的URL中的参数传递, 先看服务端代码:

如需在声明中使用 token 符 "$SharePoint.Project.AssemblyFullName$",需要在project文件(.csproj文件) 中加入以下代码:

// 使用Query获取参数func func6(c*gin.Context){// 回复一个200 OK// 获取传入的参数name:=c.Query("name")passwd:=c.Query("passwd")c.String(http.StatusOK,"参数:%s %s  test6 OK",name,passwd)}// 使用Query获取参数func func7(c*gin.Context){// 回复一个200 OK// 获取传入的参数name:=c.Query("name")passwd:=c.Query("passwd")c.String(http.StatusOK,"参数:%s %s  test7 OK",name,passwd)}func main(){router:=gin.Default()// 使用gin的Query参数形式,/test6?firstname=Jane&lastname=Doerouter.GET("/test6",func6)router.POST("/test7",func7)router.Run(":8888")}

<PropertyGroup>
    ...
    <SandboxedSolution>False</SandboxedSolution>
    <TokenReplacementFileExtensions>svc</TokenReplacementFileExtensions>
</PropertyGroup>

客户端测试代码是:

  1. 在Custom REST Service时, 每个 OperationContract的 Name属性用于标识这个操作,是唯一的,在返回值中可以体现出来,返回值为 Name 'Result',例如,在ajax回调函数中使用时即为 response.GetAllPresidentsResult ;UriTemplate属性是访问此操作的路径,也是唯一的;

func main(){// 使用Query获取参数形式/test6?firstname=Jane&lastname=Doeresp,_=http.Get("

图片 12

这种方法的参数也是接在URL后面, 形如. 服务器可以使用name := c.Query(“name”)这种 方法来解析参数.

  1. 若要获取一个web根目录下的所有folder,可以使用一下REST API:

    url/_api/web/folders

**第三种:**使用gin.Context中的PostForm方法解析

得到的结果即是在SPD中看到的样子:

我们需要将参数放在请求的Body中传递, 而不是URL中. 先看服务端代码:

图片 13

// 参数是form中获得,即从Body中获得,忽略URL中的参数func func8(c*gin.Context){message:=c.PostForm("message")extra:=c.PostForm("extra")nick:=c.DefaultPostForm("nick","anonymous")c.JSON(200,gin.H{"status":"test8:posted","message":message,"nick":nick,"extra":extra,})}func main(){router:=gin.Default()// 使用post_form形式,注意必须要设置Post的type,// 同时此方法中忽略URL中带的参数,所有的参数需要从Body中获得router.POST("/test8",func8)router.Run(":8888")}

REST返回的结果可能还会包含一下以"_vti_"开头的文档库或列表地址,这些是FrontPage的遗产物,无需在意,详情可参考此文章;

客户端代码是:

  1. SharePoint REST API中的 /folders 和 /files 接口都只能得到当前文件夹下的 子文件夹 或者 文件,而不能递归读取所有 子文件夹 或 文件;

    url/sites/jacky/_api/Web/GetFolderByServerRelativeUrl('/sites/jacky/Documents')/Files url/sites/jacky/_api/Web/GetFolderByServerRelativeUrl('/sites/jacky/Documents')/Folders

func main(){// 使用post_form形式,注意必须要设置Post的type,同时此方法中忽略URL中带的参数,所有的参数需要从Body中获得resp,_=http.Post("

而 /items 接口却可以得到一个 list 或者 library 所有item,包括文件和文件夹;

由于我们使用了request Body, 那么就需要指定Body中数据的形式, 此处是form格式, 即application/x-www-form-urlencoded. 常见的几种http提交数据方式有: application/x-www-form-urlencoded; multipart/form-data; application/json; text/xml. 具体使用请google.

http://host url/sites/jacky/_api/Web/Lists(guid'9957f1e6-a35a-4888-a770-d5325c5cfe74')/Items

在服务端, 使用message := c.PostForm(“message”)方法解析参数, 然后进行处理.

  1. $expand 相当于扩展查询,将子查询对象的结果集成到当前这次调用中来,比如:

<3> 传输文件

使用  url/sites/jacky/_api/Web/GetFolderByServerRelativeUrl('/sites/jacky/Documents') 接口我们可以得到Documents 这个文件夹的一些信息,返回结果如下:

下面测试从client传输文件到server. 传输文件需要使用multipart/form-data格式的数据, 所有需要设定Post的类型是multipart/form-data.

图片 14

首先看服务端代码:

如果加上$expand 对象,将 REST URI 改为: url/sites/jacky/_api/Web/GetFolderByServerRelativeUrl('/sites/jacky/Documents')?$expand=Folders,Files 即 加上了 查询Folders 和 Files的子语句,返回的结果为:

// 接收client上传的文件// 从FormFile中获取相关的文件data!// 然后写入本地文件func func9(c*gin.Context){// 注意此处的文件名和client处的应该是一样的file,header,err:=c.Request.FormFile("uploadFile")filename:=header.Filenamefmt.Println(header.Filename)// 创建临时接收文件out,err:=os.Create("copy_" filename)iferr!=nil{log.Fatal(err)}deferout.Close()// Copy数据_,err=io.Copy(out,file)iferr!=nil{log.Fatal(err)}c.String(http.StatusOK,"upload file success")}func main(){router:=gin.Default()// 接收上传的文件,需要使用router.POST("/upload",func9)router.Run(":8888")}

图片 15

客户端代码是:

相当于,在查询当前文件夹信息的同时,也进行了下面两个查询,并将结果一次性返回:

func main(){// 上传文件POST// 下面构造一个文件buf作为POST的BODYbuf:=new(bytes.Buffer)w:=multipart.NewWriter(buf)fw,_:=w.CreateFormFile("uploadFile","images.png")//这里的uploadFile必须和服务器端的FormFile-name一致fd,_:=os.Open("images.png")defer fd.Close()io.Copy(fw,fd)w.Close()resp,_=http.Post("

http://host url/sites/jacky/_api/Web/GetFolderByServerRelativeUrl('/sites/jacky/Documents')/Files
http://host url/sites/jacky/_api/Web/GetFolderByServerRelativeUrl('/sites/jacky/Documents')/Folders

首先客户端本地需要有一张”images.png”图片, 同时需要创建一个Form, 并将field-name命名为”uploadFile”, file-name命名为”images.png”. 在服务端, 通过”uploadFile”可以得到文件信息. 客户端继续将图片数据copy到创建好的Form中, 将数据数据Post出去, 注意数据的类型指定! 在服务端, 通过file, header , err := c.Request.FormFile(“uploadFile”)获得文件信息, file中就是文件数据, 将其拷贝到本地文件, 完成文件传输.

25. 在使用$select时,如果需要选择的属性位于一个集合(例如 results)中,那么在路径中可以忽略掉 results (此为虚拟节点),直接写需要的属性,比如下图,如果需要选择 Title属性,不需要写成:$select=ListItemAllFields/RoleAssignments/results/Member/Users/results/Title,直接写成 $select=ListItemAllFields/RoleAssignments/Member/Users/Title 即可;

<4> binding数据

图片 16

gin内置了几种数据的绑定例如JSON, XML等. 简单来说, 即根据Body数据类型, 将数据赋值到指定的结构体变量中. (类似于序列化和反序列化)

26. 

看服务端代码:

// Binding数据// 注意:后面的form:user表示在form中这个字段是user,不是User, 同样json:user也是// 注意:binding:"required"要求这个字段在client端发送的时候必须存在,否则报错!typeLoginstruct{Userstring`form:"user" json:"user" binding:"required"`Passwordstring`form:"password" json:"password" binding:"required"`}// bind JSON数据func funcBindJSON(c*gin.Context){varjsonLogin// binding JSON,本质是将request中的Body中的数据按照JSON格式解析到json变量中ifc.BindJSON(&json)==nil{ifjson.User=="TAO"&&json.Password=="123"{c.JSON(http.StatusOK,gin.H{"JSON=== status":"you are logged in"})}else{c.JSON(http.StatusUnauthorized,gin.H{"JSON=== status":"unauthorized"})}}else{c.JSON(404,gin.H{"JSON=== status":"binding JSON error!"})}}// 下面测试bind FORM数据func funcBindForm(c*gin.Context){varformLogin// 本质是将c中的request中的BODY数据解析到form中// 方法一: 对于FORM数据直接使用Bind函数, 默认使用使用form格式解析,if c.Bind(&form) == nil// 方法二: 使用BindWith函数,如果你明确知道数据的类型ifc.BindWith(&form,binding.Form)==nil{ifform.User=="TAO"&&form.Password=="123"{c.JSON(http.StatusOK,gin.H{"FORM=== status":"you are logged in"})}else{c.JSON(http.StatusUnauthorized,gin.H{"FORM=== status":"unauthorized"})}}else{c.JSON(404,gin.H{"FORM=== status":"binding FORM error!"})}}func main(){router:=gin.Default()// 下面测试bind JSON数据router.POST("/bindJSON",funcBindJSON)// 下面测试bind FORM数据router.POST("/bindForm",funcBindForm)// 下面测试JSON,XML等格式的renderingrouter.GET("/someJSON",func(c*gin.Context){c.JSON(http.StatusOK,gin.H{"message":"hey, budy","status":http.StatusOK})})router.GET("/moreJSON",func(c*gin.Context){// 注意:这里定义了tag指示在json中显示的是user不是Uservarmsgstruct{Namestring`json:"user"`MessagestringNumberint}msg.Name="TAO"msg.Message="hey, budy"msg.Number=123// 下面的在client的显示是"user": "TAO",不是"User": "TAO"// 所以总体的显示是:{"user": "TAO", "Message": "hey, budy", "Number": 123c.JSON(http.StatusOK,msg)})//  测试发送XML数据router.GET("/someXML",func(c*gin.Context){c.XML(http.StatusOK,gin.H{"name":"TAO","message":"hey, budy","status":http.StatusOK})})router.Run(":8888")}

客户端代码:

func main(){// 下面测试binding数据// 首先测试binding-JSON,// 注意Body中的数据必须是JSON格式resp,_=http.Post("", "password": "123"}"))helpRead(resp)// 下面测试bind FORM数据resp,_=http.Post(" 下面测试接收JSON和XML数据resp,_=http.Get("

客户端发送请求, 在服务端可以直接使用c.BindJSON绑定到Json结构体上. 或者使用BindWith函数也可以, 但是需要指定绑定的数据类型, 例如JSON, XML, HTML等. Bind*函数的本质是读取request中的body数据, 拿BindJSON为例, 其核心代码是:

func(_ jsonBinding)Bind(req*http.Request,objinterface{})error{// 核心代码: decode请求的body到obj中decoder:=json.NewDecoder(req.Body)iferr:=decoder.Decode(obj);err!=nil{returnerr}returnvalidate(obj)}

<5> router group

router group是为了方便前缀相同的URL的管理, 其基本用法如下.

首先看服务端代码:

// router GROUP - GET测试func func10(c*gin.Context){c.String(http.StatusOK,"test10 OK")}func func11(c*gin.Context){c.String(http.StatusOK,"test11 OK")}// router GROUP - POST测试func func12(c*gin.Context){c.String(http.StatusOK,"test12 OK")}func func13(c*gin.Context){c.String(http.StatusOK,"test13 OK")}func main(){router:=gin.Default()// router Group是为了将一些前缀相同的URL请求放在一起管理group1:=router.Group("/g1")group1.GET("/read1",func10)group1.GET("/read2",func11)group2:=router.Group("/g2")group2.POST("/write1",func12)group2.POST("/write2",func13)router.Run(":8888")}

客户端测试代码:

func main(){// 下面测试router 的GROUPresp,_=http.Get("

在服务端代码中, 首先创建了一个组group1 := router.Group(“/g1”), 并在这个组下注册了两个服务, group1.GET(“/read1”, func10) 和group1.GET(“/read2”, func11), 那么当使用, 是可以路由 到上面注册的位置的. 同理对于group2 := router.Group(“/g2”)也是一样的.

<6> 静态文件服务

可以向客户端展示本地的一些文件信息, 例如显示某路径下地文件. 服务端代码是:

func main(){router:=gin.Default()// 下面测试静态文件服务// 显示当前文件夹下的所有文件/或者指定文件router.StaticFS("/showDir",http.Dir("."))router.Static("/files","/bin")router.StaticFile("/image","./assets/1.png")router.Run(":8888")}

首先你需要在服务器的路径下创建一个assert文件夹, 并且放入1.png文件. 如果已经存在, 请忽略.

测试代码: 请在浏览器中输入0.0.0.0:8888/showDir, 显示的是服务器当前路径下地文件信息:

图片 17

输入0.0.0.0:8888/files, 显示的是/bin目录下地文件信息:

图片 18

输入0.0.0.0:8888/image, 显示的是服务器下地./assets/1.png图片:

图片 19

<7> 加载模板templates

gin支持加载HTML模板, 然后根据模板参数进行配置并返回相应的数据.

看服务端代码

func main(){router:=gin.Default()// 下面测试加载HTML: LoadHTMLTemplates// 加载templates文件夹下所有的文件router.LoadHTMLGlob("templates/*")// 或者使用这种方法加载也是OK的: router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")router.GET("/index",func(c*gin.Context){// 注意下面将gin.H参数传入index.tmpl中!也就是使用的是index.tmpl模板c.HTML(http.StatusOK,"index.tmpl",gin.H{"title":"GIN: 测试加载HTML模板",})})router.Run(":8888")}

客户端测试代码是:

func main(){// 测试加载HTML模板resp,_=http.Get("

在服务端, 我们需要加载需要的templates, 这里有两种方法: 第一种使用LoadHTMLGlob加载所有的正则匹配的模板, 本例中使用的是*, 即匹配所有文件, 所以加载的是 templates文件夹下所有的模板. 第二种使用LoadHTMLFiles加载指定文件. 在本例服务器路径下有一个templates目录, 下面有一个index.tmpl模板, 模板的 内容是:

{ { .title } }

当客户端请求/index时, 服务器使用这个模板, 并填充相应的参数, 此处参数只有title, 然后将HTML数据返回给客户端.

你也可以在浏览器请求0.0.0.0:8888/index, 效果如下图所示:

图片 20

<8> 重定向

重定向相对比较简单, 服务端代码是:

func main(){router:=gin.Default()// 下面测试重定向router.GET("/redirect",func(c*gin.Context){c.Redirect(http.StatusMovedPermanently,"

客户端测试代码是:

func main(){// 下面测试重定向resp,_=http.Get("

当我们请求, 会重定向到.

<9> 使用middleware

这里使用了两个例子, 一个是logger, 另一个是BasiAuth, 具体看服务器代码:

funcLogger()gin.HandlerFunc{returnfunc(c*gin.Context){t:=time.Now()// 设置example变量到Context的Key中,通过Get等函数可以取得c.Set("example","12345")// 发送request之前c.Next()// 发送request之后latency:=time.Since(t)log.Print(latency)// 这个c.Write是ResponseWriter,我们可以获得状态等信息status:=c.Writer.Status()log.Println(status)}}func main(){router:=gin.Default()// 1router.Use(Logger())router.GET("/logger",func(c*gin.Context){example:=c.MustGet("example").(string)log.Println(example)})// 2// 下面测试BasicAuth()中间件登录认证//varsecrets=gin.H{"foo":gin.H{"email":"foo@bar.com","phone":"123433"},"austin":gin.H{"email":"austin@example.com","phone":"666"},"lena":gin.H{"email":"lena@guapa.com","phone":"523443"},}// Group using gin.BasicAuth() middleware// gin.Accounts is a shortcut for map[string]stringauthorized:=router.Group("/admin",gin.BasicAuth(gin.Accounts{"foo":"bar","austin":"1234","lena":"hello2","manu":"4321",}))// 请求URL: 0.0.0.0:8888/admin/secretsauthorized.GET("/secrets",func(c*gin.Context){// get user, it was set by the BasicAuth middlewareuser:=c.MustGet(gin.AuthUserKey).(string)ifsecret,ok:=secrets[user];ok{c.JSON(http.StatusOK,gin.H{"user":user,"secret":secret})}else{c.JSON(http.StatusOK,gin.H{"user":user,"secret":"NO SECRET :("})}})router.Run(":8888")}

客户端测试代码是:

func main(){// 下面测试使用中间件resp,_=http.Get(" 测试验证权限中间件BasicAuthresp,_=http.Get("

服务端使用Use方法导入middleware, 当请求/logger来到的时候, 会执行Logger(), 并且我们知道在GET注册的时候, 同时注册了匿名函数, 所有请看Logger函数中存在一个c.Next()的用法, 它是取出所有的注册的函数都执行一遍, 然后再回到本函数中, 所以, 本例中相当于是先执行了 c.Next()即注册的匿名函数, 然后回到本函数继续执行. 所以本例的Print的输出顺序是:

log.Println(example)

log.Print(latency)

log.Println(status)

如果将c.Next()放在log.Print(latency)后面, 那么log.Println(example)和log.Print(latency)执行的顺序就调换了. 所以一切都取决于c.Next()执行的位置. c.Next()的核心代码如下:

// Next should be used only in the middlewares.// It executes the pending handlers in the chain inside the calling handler.// See example in github.func(c*Context)Next(){c.index s:=int8(len(c.handlers))for;c.index

它其实是执行了后面所有的handlers.

关于使用gin.BasicAuth() middleware, 可以直接使用一个router group进行处理, 本质和logger一样.

<10> 绑定http server

之前所有的测试中, 我们都是使用router.Run(":8888")开始执行监听, 其实还有两种方法:

// 方法二http.ListenAndServe(":8888",router)// 方法三:server:=&http.Server{Addr:":8888",Handler:router,ReadTimeout:10*time.Second,WriteTimeout:10*time.Second,MaxHeaderBytes:1<<20,}server.ListenAndServe()

本文由亚洲必赢娱乐游戏发布于亚洲必赢网站登录,转载请注明出处:采纳示例

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。