Rest API 开发 学习笔记
概述
REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表示方式。获得这些表徵致使这些应用程序转变了其状态。随着不断获取资源的表示方式,客户端应用不断地在转变着其状态,所谓表述性状态转移(Representational State Transfer)。
这一观点不是凭空臆造的,而是通过观察当前Web互联网的运作方式而抽象出来的。Roy Fielding 认为,
“设计良好的网络应用表现为一系列的网页,这些网页可以看作的虚拟的状态机,用户选择这些链接导致下一网页传输到用户端展现给使用的人,而这正代表了状态的转变。”
REST是设计风格而不是标准。REST通常基于使用HTTP,URI,和XML以及HTML这些现有的广泛流行的协议和标准。
REST的要求
RESTful Web 服务
RESTful Web 服务(也称为 RESTful Web API)是一个使用HTTP并遵循REST原则的Web服务。它从以下三个方面资源进行定义:URI,比如:。
§ Web服务接受与返回的互联网媒体类型,比如:JSON,XML ,YAML 等。
§ Web服务在该资源上所支持的一系列请求方法(比如:POST,GET,PUT或DELETE)。
该表列出了在实现RESTful Web 服务时HTTP请求方法的典型用途。
HTTP 请求方法在RESTful Web 服务中的典型应用
资源
GET
PUT
POST
DELETE
一组资源的URI,比如
列出 URI,以及该资源组中每个资源的详细信息(后者可选)。
使用给定的一组资源替换当前整组资源。
在本组资源中创建/追加一个新的资源。 该操作往往返回新资源的URL。
删除 整组资源。
单个资源的URI,比如
获取 指定的资源的详细信息,格式可以自选一个合适的网络媒体类型(比如:XML、JSON等)
替换/创建 指定的资源。并将其追加到相应的资源组中。
把指定的资源当做一个资源组,并在其下创建/追加一个新的元素,使其隶属于当前资源。
删除 指定的元素。
PUT 和 DELETE 方法是幂等方法。GET方法是安全方法 (不会对服务器端有修改,因此也是幂等的)。
不像基于SOAP的Web服务,RESTful Web服务并没有的“正式”标准。 这是因为REST是一种架构,而SOAP只是一个协议。虽然REST不是一个标准,但在实现RESTful Web服务时可以使用其他各种标准(比如HTTP,URL,XML,PNG等)。
REST的优点
Rest 开发
首先先定义接口IRestHandler:
/// <summary> /// The IRestHandler is an interface which provides Delete,Get,Post and Put methods. /// </summary> public interface IRestHandler : ICloneable { /// <summary> /// Delete method for RestHandler /// </summary> /// <param name="processor">The rest processor.</param> /// <param name="authenticated">if set to <c>true</c> [authenticated].</param> /// <returns>The http response</returns> RestHandlerResponse Delete(IRestProcessor processor, bool authenticated); /// <summary> /// Get method for RestHandler /// </summary> /// <param name="processor">The rest processor.</param> /// <param name="authenticated">if set to <c>true</c> [authenticated].</param> /// <returns>The http response</returns> RestHandlerResponse Get(IRestProcessor processor, bool authenticated); /// <summary> /// Post method for RestHandler /// </summary> /// <param name="processor">The rest processor.</param> /// <param name="authenticated">if set to <c>true</c> [authenticated].</param> /// <returns>The http response</returns> RestHandlerResponse Post(IRestProcessor processor, bool authenticated); /// <summary> /// Put method for RestHandler /// </summary> /// <param name="processor">The rest processor.</param> /// <param name="authenticated">if set to <c>true</c> [authenticated].</param> /// <returns>The http response</returns> RestHandlerResponse Put(IRestProcessor processor, bool authenticated); }我们要定义一个HttpListener,先定义一个接口IRestListener:
/// <summary> /// Listen an ip point and accept connection. /// </summary> public interface IRestListener : IDisposable { /// <summary> /// Gets or sets the max allowed connections to this listener. /// </summary> int MaxConnections { get; set; } /// <summary> /// Gets or sets desktop rest manager. /// </summary> DesktopRestManager DesktopRestManager { get; set; } /// <summary> /// Gets a value that indicate if it is listening. /// </summary> bool IsRunning { get; } /// <summary> /// Gets or sets the server address information. /// </summary> IPEndPoint ServerAddress { get; set; } string Protocol { get; set; } /// <summary> /// Start a listener. /// </summary> /// <returns>The ip end point to listen.</returns> bool Start(TcpListener listener, IPEndPoint address); /// <summary> /// Stop the listener. /// </summary> /// <returns>True if successfully, else false.</returns> bool Stop(); }
接下来实现
public class HttpListener : IRestListener { public HttpListener(DesktopRestManager drm) { this.desktopRestManager = drm; this.isRunning = false; MaxConnections = 50; this.serverAddress = new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 10000); this.Protocol = "Http"; } #region IRestServer Members //public event ServerStatusChangedHandler ServerStatusChanged; public DesktopRestManager DesktopRestManager { get { return this.desktopRestManager; } set { this.desktopRestManager = value; } } public bool IsRunning { get { return this.isRunning; } } public IPEndPoint ServerAddress { get { return this.serverAddress; } set { this.serverAddress = value; } } public int MaxConnections { get; set; } public string Protocol { get; set; } public bool Start(TcpListener tcpListener, IPEndPoint address) { this.ServerAddress = address; this.listener = tcpListener; this.isRunning = true; Thread th = new Thread(new ThreadStart(this.Listening)); th.Start(); return true; } public bool Stop() { bool success = true; ; if (this.isRunning == true) { try { this.isRunning = false; if (listener != null) { listener.Stop(); } } catch (SocketException socketEx) { _traceLog.InfoFormat("Stop http rest server: {0}", socketEx.Message); success = false; } } return success; } #endregion #region IDisposable Members public void Dispose() { this.Stop(); } #endregion #region Private Methods private void Listening() { while (this.isRunning) { TcpClient tcpClient = null; try { tcpClient = listener.AcceptTcpClient(); HttpConnection connection = new HttpConnection(tcpClient); RestProcessor rh = new RestProcessor(this.desktopRestManager); Thread processThread = new Thread(new ParameterizedThreadStart(req => connection.SendResponse(rh.HandleRequest(req as RestHandlerRequest)))); processThread.Name = "RestManager_Http_ProcessRequest"; processThread.Start(connection.GetRequest()); } catch (SocketException socketEx) { if (this.isRunning) { _traceLog.InfoFormat("Socket exception: {0}", socketEx.Message); } else { _traceLog.Info("The use stop the http listener."); } if (tcpClient != null && tcpClient.Connected) { tcpClient.Close(); } } catch (System.ArgumentNullException ex) { _traceLog.ErrorFormat("Error occured: {0}", ex.Message); } catch (System.OutOfMemoryException ex) { _traceLog.ErrorFormat("Error occured: {0}", ex.Message); } catch (System.Threading.ThreadStateException ex) { _traceLog.ErrorFormat("Error occured: {0}", ex.Message); } catch (System.InvalidOperationException ex) { _traceLog.ErrorFormat("Error occured: {0}", ex.Message); } catch (ApplicationException ex) { _traceLog.ErrorFormat("Error occured: {0}", ex.Message); } } this.Stop(); } #endregion #region Private Members private DesktopRestManager desktopRestManager; private bool isRunning; private IPEndPoint serverAddress; private TcpListener listener; private static LogManager _traceLog = new LogManager("RestManager-HttpListener"); #endregion }