restful 订阅
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务使能接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。 [1] 展开全文
RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义。RESTFUL适用于移动互联网厂商作为业务使能接口的场景,实现第三方OTT调用移动网络资源的功能,动作类型为新增、变更、删除所调用资源。 [1]
信息
创始人
Roy Fielding
外文名
Representational State Transfer
应用场景
适用于移动互联网厂商作为业务使能接口的场景
所属领域
计算机科学技术
中文名
RESTful
实    质
一种网络应用程序的设计风格和开发方式
RESTful相关定义
REST(英文:Representational State Transfer,简称 REST)描述了一个架构样式的网络系统,比如 web 应用程序。它首次出现在 2000 年 Roy Fielding 的博士论文中,Roy Fielding是 HTTP 规范的主要编写者之一。在目前主流的三种Web服务交互方案中,REST相比于SOAP(Simple Object Access protocol,简单对象访问协议)以及XML-RPC更加简单明了,无论是对URL的处理还是对Payload的编码,REST都倾向于用更加简单轻量的方法设计和实现。值得注意的是REST并没有一个明确的标准,而更像是一种设计的风格。 [2]  REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是,客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在请求之间的任何时间点重启,客户端不会得到通知。此外,无状态请求可以由任何可用服务器回答,这十分适合云计算之类的环境。客户端可以缓存数据以改进性能。在服务器端,应用程序状态和功能可以分为各种资源。资源是一个有趣的概念实体,它向客户端公开。资源的例子有:应用程序对象、数据库记录、算法等等。每个资源都使用 URI (Universal Resource Identifier) 得到一个唯一的地址。所有资源都共享统一的接口,以便在客户端和服务器之间传输状态。使用的是标准的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。Hypermedia 是应用程序状态的引擎,资源表示通过超链接互联。
收起全文
精华内容
下载资源
问答
  • RESTful

    千次阅读 2019-10-13 13:04:37
    一、RESTful RESTful,一种通用的前后台交互方式 RESTful一般是指这种格式: (1)使用HTTP POST(或GET)进行数据交互 (2)请求数据和应答数据均为JSON格式(或XML) 二、RESTful接口的实现 RESTful的前端...

    一、RESTful

    RESTful,一种通用的前后台交互方式

    RESTful一般是指这种格式:

    (1)使用HTTP POST(或GET)进行数据交互

    (2)请求数据和应答数据均为JSON格式(或XML)

    二、RESTful接口的实现

    RESTful的前端实现

    前端:在发送请求时,把请求转成JSON字符串

    $.ajax({
    				type:"POST",    /*请求类型-POST/GET*/
    				url:"AddStudent?mode=admin&token=12930289",   /*服务URI,用相对地址*/
    				data:jsonStr,          /*附加请求参数*/
    				dataType:"json",   /*期望服务器返回的数据类型*/
    				success: function(resp)  /*已经将服务器返回的数据转成JS 对象*/
    				{
    					if(resp.error==0)
    					alert("提交成功");
    					else
    					alert("出错:"+resp.reason);
    				},
    				error: function(jqXHR, textstatus, errorThrown)
    				{
    					alert("错误:" +jqXHR.status);
    				}
    			});	

    后端:手工读取请求数据,转成JSONObject,然后再做处理

    //读取请求数据,转化为字符串
    String reqText = readAsText(request.getInputStream(), "utf-8");
    		
    //转化为json
    JSONObject jreq = new JSONObject(reqText);

    三、RESTful附加URL参数

    一般来说,使用RESTful接口时,所有的请求参数放在JSON中即可。但有的时候,还有少许参数放在URL里面。

    演示代码:

    前端:

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>AJAX POST</title>
    		<script type="text/javascript" src="JS/jquery-3.3.1.min.js"></script>
    		
    		<style>
    			.main
    			{
    				width: 500px;
    				margin: 10px auto;    		
    			}
    			.main input,select{
    				width: 250px;
    				padding: 4px;
    				margin: 2px;
    			}
    		</style>
    	</head>
    	<body>
    		<div class="main">
    			学号: <input type='text' class='id' />  <br>  <!-- name: 即参数名 -->
    	    	姓名: <input type='text' class='name' /> <br>
    	    	手机: <input type='text' class='phone' /> <br>
    	    	性别: <select class='sex' style="width: 260px;">
    	    		<option value='male'> 男 </option>
    	    		<option value='female'> 女 </option>
    	    	</select> <br><br>
    	    	<button onclick="submit()">提交</button>
    		</div>
    	</body>
    	<script>
    		function submit()
    		{
    			var req = {};
    			
    			req.id = $(".main .id").val().trim();
    			req.name = $(".main .name").val().trim();
    			req.phone = $(".main .phone").val().trim();
    			req.sex = $(".main .sex").val().trim();
    			
    			/*在发送请求时,把请求转成json对象*/
    			var jsonStr = JSON.stringify(req);
    			console.log(jsonStr);
    			
    			$.ajax({
    				type:"POST",    /*请求类型-POST/GET*/
    				url:"AddStudent?mode=admin&token=12930289",   /*服务URI,用相对地址*/
    				data:jsonStr,          /*附加请求参数*/
    				dataType:"json",   /*期望服务器返回的数据类型*/
    				success: function(resp)  /*已经将服务器返回的数据转成JS 对象*/
    				{
    					if(resp.error==0)
    					alert("提交成功");
    					else
    					alert("出错:"+resp.reason);
    				},
    				error: function(jqXHR, textstatus, errorThrown)
    				{
    					alert("错误:" +jqXHR.status);
    				}
    			});	
    		}
    	</script>
    </html>

    后端核心代码:

    package my;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Writer;
    import java.util.HashMap;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.json.JSONObject;
    
    /**
     * Servlet implementation class AddStudent
     */
    @WebServlet("/AddStudent")
    public class AddStudent extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
        /**
         * @see HttpServlet#HttpServlet()
         */
        public AddStudent() {
            super();
            // TODO Auto-generated constructor stub
        }
    
    	/**
    	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		// TODO Auto-generated method stub
    		response.getWriter().append("Served at: ").append(request.getContextPath());
    	}
    
    	/**
    	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
    	 */
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) 
    								throws ServletException, IOException {
    		String reqText = readAsText(request.getInputStream(), "UTF-8");
    		
    		System.out.println(reqText);
    		
    		//转化为JSON
    		JSONObject jreq = new JSONObject(reqText);
    		
    		//URL末尾,由问号引导的字符串(在restful中也有部分参数在URL中
    		//例如:url:"AddStudent?mode=admin&token=12930289",   /*服务URI,用相对地址*/
    		String query = request.getQueryString();
    		System.out.println(query);
    		HashMap<String, String>ppp = parseQuery(query);
    		System.out.println(ppp);
    		
    		int id = jreq.getInt("id");
    		String name = jreq.getString("name");
    		String phone = jreq.getString("phone");
    		boolean sex = "male".equals(jreq.getString("sex")); 
    		
    		// 添加到数据库
    		Student s = new Student(id, name, sex, phone);
    		DemoDB.i.add( s );
    		
    		// 返回应答数据
    		JSONObject jresp = new JSONObject();
    		jresp.put("error", 0); // 错误码,0表示成功
    		jresp.put("reason", "OK"); // 错误原因描述, 如果没有错误则提示OK
    		response.setCharacterEncoding("UTF-8");
    		response.setContentType("text/plain");
    		Writer writer = response.getWriter();
    		writer.write( jresp.toString(2));
    		writer.close();
    		
    	}
    	
    	//从Stream中读取数据直到读取完毕
    	public String readAsText(InputStream StreamIn, String charset) throws IOException
    	{
    		ByteArrayOutputStream cache = new ByteArrayOutputStream(1024*16);
    		byte[] data = new byte[1024];
    		
    		while(true)
    		{
    			int n =StreamIn.read(data);
    			if(n<0)break;
    			if(n==0)continue;
    			
    			//缓存起来
    			cache.write(data, 0 ,n);
    			if(cache.size()>1024*512)
    				break;
    		}
    		
    		return cache.toString(charset);
    	}
    	
    	//转为HashMap
    	public HashMap<String, String>parseQuery(String query)
    	{
    		HashMap<String, String>parms = new HashMap<String, String>();
    		
    		String[] ppp = query.split("&");
    		
    		for(String p : ppp)
    		{
    			String[] kv = p.split("=");
    			
    			String key = kv[0];
    			String value = "";
    			if(kv.length>1)value = kv[1];
    			
    			parms.put(key, value);
    		}
    		
    		return parms;
    	}
    
    }
    

    四、快速创建REST服务

    -首先自定义设计一个抽象类AfSimpleREST继承与HttpServlet

    -里面定义一个抽象方法,用于子类对前端传回的JSON格式字符串的数据进行分析

    package my;
    
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.Writer;
    
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.json.JSONObject;
    
    import af.AfWebException;
    
    public abstract class AfSimpleREST extends HttpServlet
    {
    	protected boolean enableErrorLog = false; // 是否打印异常输出
    	protected boolean niceJSONFormat = true; // 输出的JSON是否综进 (缩进影响运行效率)
    	protected int MAX_REQUEST_SIZE = 1024 * 512; // 允许上传的JSON最大长度
    	protected String charset = "UTF-8";
    	
    	// 子类须重写这个方法,进行业务处理
    	// 处理返回后,可以返回 JSONObject, JSONArray, 或int long String 等基本类型
    	protected abstract Object execute(HttpServletRequest request,
    											HttpServletResponse response,
    											JSONObject jreq)throws Exception;
    
    	@Override
    	protected void doGet(HttpServletRequest request, HttpServletResponse response) 
    										throws ServletException, IOException
    	{
    		// 无论是 GET/POST, 均统一处理
    		doPost(request, response);
    	}
    
    	@Override
    	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    	{
    		String requestURI = request.getRequestURI();
    		
    		
    		// 处理请求数据
    		JSONObject jresp = new JSONObject();		
    		try{
    			// 读取请求数据, 转成字符串, 转成 JSON
    			String reqText = readAsText(request.getInputStream(), charset, MAX_REQUEST_SIZE);
    			JSONObject jreq = null;
    			if(reqText.length()>0) jreq = new JSONObject(reqText);
    			
    			// 子类应重写 execute() 方法
    			Object data = execute(request, response, jreq);
    			jresp.put("error", 0); // 错误码,0表示成功
    			jresp.put("reason", "OK"); // 错误原因描述, 如果没有错误则提示OK
    			if(data != null)
    				jresp.put("data", data); // 
    		}
    		catch(AfWebException e)
    		{
    			String reason = e.getMessage();		
    			System.out.println("** 出错: " + requestURI + ", 原因: " + reason);
    			
    			if(enableErrorLog) e.printStackTrace();
    			
    			// 应签数据
    			jresp.put("error", e.error); // 错误码,0表示成功
    			jresp.put("reason", reason); // 错误原因描述, 如果没有错误则提示OK
    		}
    		catch(Exception e)
    		{
    			String reason = e.getMessage();
    			if(reason == null) reason = e.getClass().getName();			
    			System.out.println("** 出错: " + requestURI + ", 原因: " + reason);
    			
    			if(enableErrorLog) e.printStackTrace();
    			
    			// 应签数据
    			jresp.put("error", -1); // 错误码,0表示成功
    			jresp.put("reason", e.getMessage()); // 错误原因描述, 如果没有错误则提示OK
    		}
    		
    		// 是否按可读风格生成JSON ( 缩进格式 or 紧凑格式 )
    		String jsonstr = niceJSONFormat ? jresp.toString(2) : jresp.toString();
    		
    		// 发送应答给客户端
    		response.setCharacterEncoding(charset);
    		response.setContentType("text/plain");
    		//response.setHeader("Connection", "close");
    		Writer writer = response.getWriter();
    		writer.write( jsonstr );
    		writer.close();	
    	}
    	
    	public static String readAsText(InputStream streamIn, String charset, int maxSize)
    			throws IOException 
    	{
    		ByteArrayOutputStream cache = new ByteArrayOutputStream(1024*16);  
            byte[] data = new byte[1024]; 
            
            int numOfWait = 0;
            while (true)
            {
            	int n = streamIn.read(data); // n: 实际读取的字节数
            	if(n < 0) break; // 连接已经断开
            	if(n == 0) 
            	{
            		if( numOfWait ++ >= 3) break; // 此种情况不得连续3次
            		try{ Thread.sleep(5);}catch(Exception e){}
            		continue;// 数据未完 //  
            	}
            	numOfWait = 0;
    
            	// 缓存起来
            	cache.write(data, 0, n);        	
            	if(cache.size() > maxSize) // 上限, 最多读取512K
            		break;
            }  
            
            return cache.toString(charset);
    	}
    	
    
    }
    

    子类继承:

    package my;
    
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.json.JSONObject;
    
    @WebServlet("/AddBook")
    public class AddBook extends AfSimpleREST
    {
    
    	@Override
    	protected Object execute(HttpServletRequest request, 
    								HttpServletResponse response, 
    									JSONObject jreq) throws Exception
    	{
    		String id = jreq.getString("id");
    		String name = jreq.getString("name");
    		String phone = jreq.getString("phone");
    		String pub = jreq.getString("pub");
    		System.out.println("编号:"+id+"作者:"+name+"手机号:"+phone+"出版社:"+pub);
    		return null;
    	}
    
    }
    

    前端代码:

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="utf-8">
    		<title>AJAX POST</title>
    		<script type="text/javascript" src="JS/jquery-3.3.1.min.js"></script>
    		
    		<style>
    			.main
    			{
    				width: 500px;
    				margin: 10px auto;    		
    			}
    			.main input,select{
    				width: 250px;
    				padding: 4px;
    				margin: 2px;
    			}
    		</style>
    	</head>
    	<body>
    		<div class="main">
    			书号: <br><input type='text' class='id' />  <br>  <!-- name: 即参数名 -->
    	    	书名: <br><input type='text' class='name' /> <br>
    	    	手机: <br><input type='text' class='phone' /> <br>
    	    	出版社: <br><input type='text' class='pub' /> <br><br>
    	    	<button onclick="submit()">提交</button>
    		</div>
    	</body>
    	<script>
    		function submit()
    		{
    			var req = {};
    			
    			req.id = $(".main .id").val().trim();
    			req.name = $(".main .name").val().trim();
    			req.phone = $(".main .phone").val().trim();
    			req.pub = $(".main .pub").val().trim();
    			
    			/*在发送请求时,把请求转成json对象*/
    			var jsonStr = JSON.stringify(req);
    			console.log(jsonStr);
    			
    			$.ajax({
    				type:"POST",    /*请求类型-POST/GET*/
    				url:"AddBook",   /*服务URI,用相对地址*/
    				data:jsonStr,          /*附加请求参数*/
    				dataType:"json",   /*期望服务器返回的数据类型*/
    				success: function(resp)  /*已经将服务器返回的数据转成JS 对象*/
    				{
    					if(resp.error==0)
    					alert("提交成功");
    					else
    					alert("出错:"+resp.reason);
    				},
    				error: function(jqXHR, textstatus, errorThrown)
    				{
    					alert("错误:" +jqXHR.status);
    				}
    			});	
    		}
    	</script>
    </html>

     

    展开全文
  • restful

    千次阅读 2020-02-27 11:39:02
    restful架构风格 研究软件和网络的交叉点 表现层状态转换 设计规范-> 专属域名 /http(s)协议/ 要求路径为名词复数 格式传输为json djangorestful框架 序列化 serializer/Modelserilizer/...

    restful架构风格

    • 研究软件和网络的交叉点
    • 表现层状态转换
    • 设计规范-> 专属域名 /http(s)协议/ 要求路径为名词复数
    • 格式传输为json
    • djangorestful框架
      • 序列化 serializer/Modelserilizer/HyperLinkedModelSerializer
      • 提供了数据验证手段 is_valid exists
    • 跨域问题
      • 如果客户端不是浏览器就不存在这个问题
      • 同源策略 ip/端口/协议 都必须相同
      • 服务器解决(响应头允许)、客户端(本地搭建反向代理)
    展开全文
  • 面试官:你连RESTful都不知道我怎么敢要你?

    万次阅读 多人点赞 2019-11-06 00:33:54
    干货,2019 RESTful最贱实践

    效率工具前文传送门

    01 前言

    回归正题,看过很多RESTful相关的文章总结,参齐不齐,结合工作中的使用,非常有必要归纳一下关于RESTful架构方式了,RESTful只是一种架构方式的约束,给出一种约定的标准,完全严格遵守RESTful标准并不是很多,也没有必要。但是在实际运用中,有RESTful标准可以参考,是十分有必要的。

    实际上在工作中对api接口规范、命名规则、返回值、授权验证等进行一定的约束,一般的项目api只要易测试、足够安全、风格一致可读性强、没有歧义调用方便我觉得已经足够了,接口是给开发人员看的,也不是给普通用户去调用。

    02 RESTful的来源

    REST:Representational State Transfer(表象层状态转变),如果没听说过REST,你一定以为是rest这个单词,刚开始我也是这样认为的,后来发现是这三个单词的缩写,即使知道了这三个单词理解起来仍然非常晦涩难懂。如何理解RESTful架构,最好的办法就是深刻理解消化Representational State Transfer这三个单词到底意味着什么。

    1.每一个URI代表一种资源;

    2.客户端和服务器之间,传递这种资源的某种表现层;

    3.客户端通过四个HTTP动词(get、post、put、delete),对服务器端资源进行操作,实现”表现层状态转化”。

    是由美国计算机科学家Roy Fielding(百度百科没有介绍,真是尴尬了)。Adobe首席科学家、Http协议的首要作者之一、Apache项目联合创始人。

    03 RESTful6大原则

    REST之父Roy Fielding在论文中阐述REST架构的6大原则。

    1. C-S架构

    数据的存储在Server端,Client端只需使用就行。两端彻底分离的好处使client端代码的可移植性变强,Server端的拓展性变强。两端单独开发,互不干扰。

    2. 无状态

    http请求本身就是无状态的,基于C-S架构,客户端的每一次请求带有充分的信息能够让服务端识别。请求所需的一些信息都包含在URL的查询参数、header、body,服务端能够根据请求的各种参数,无需保存客户端的状态,将响应正确返回给客户端。无状态的特征大大提高的服务端的健壮性和可拓展性。

    当然这总无状态性的约束也是有缺点的,客户端的每一次请求都必须带上相同重复的信息确定自己的身份和状态(这也是必须的),造成传输数据的冗余性,但这种确定对于性能和使用来说,几乎是忽略不计的。

    3.统一的接口

    这个才是REST架构的核心,统一的接口对于RESTful服务非常重要。客户端只需要关注实现接口就可以,接口的可读性加强,使用人员方便调用。

    4.一致的数据格式

    服务端返回的数据格式要么是XML,要么是Json(获取数据),或者直接返回状态码,有兴趣的可以看看博客园的开放平台的操作数据的api,post、put、patch都是返回的一个状态码 。

    自我描述的信息,每项数据应该是可以自我描述的,方便代码去处理和解析其中的内容。比如通过HTTP返回的数据里面有 [MIME type ]信息,我们从MIME type里面可以知道数据的具体格式,是图片,视频还是JSON,客户端通过body内容、查询串参数、请求头和URI(资源名称)来传送状态。服务端通过body内容,响应码和响应头传送状态给客户端。这项技术被称为超媒体(或超文本链接)。

    除了上述内容外,HATEOS也意味着,必要的时候链接也可被包含在返回的body(或头部)中,以提供URI来检索对象本身或关联对象。下文将对此进行更详细的阐述。

    如请求一条微博信息,服务端响应信息应该包含这条微博相关的其他URL,客户端可以进一步利用这些URL发起请求获取感兴趣的信息,再如分页可以从第一页的返回数据中获取下一页的URT也是基于这个原理。

    4.系统分层

    客户端通常无法表明自己是直接还是间接与端服务器进行连接,分层时同样要考虑安全策略。

    5.可缓存

    在万维网上,客户端可以缓存页面的响应内容。因此响应都应隐式或显式的定义为可缓存的,若不可缓存则要避免客户端在多次请求后用旧数据或脏数据来响应。管理得当的缓存会部分地或完全地除去客户端和服务端之间的交互,进一步改善性能和延展性。

    6.按需编码、可定制代码(可选)

    服务端可选择临时给客户端下发一些功能代码让客户端来执行,从而定制和扩展客户端的某些功能。比如服务端可以返回一些 Javascript 代码让客户端执行,去实现某些特定的功能。
    提示:REST架构中的设计准则中,只有按需编码为可选项。如果某个服务违反了其他任意一项准则,严格意思上不能称之为RESTful风格。

    03 RESTful的7个最佳实践

    1. 版本

    如github开放平台
    https://developer.github.com/v3/

    就是将版本放在url,简洁明了,这个只有用了才知道,一般的项目加版本v1,v2,v3?好吧,这个加版本估计只有大公司大项目才会去使用,说出来不怕尴尬,我真没用过。有的会将版本号放在header里面,但是不如url直接了当。

    https://example.com/api/v1/
    

    2.参数命名规范

    query parameter可以采用驼峰命名法,也可以采用下划线命名的方式,推荐采用下划线命名的方式,据说后者比前者的识别度要高,可能是用的人多了吧,因人而异,因团队规范而异吧。

    https://example.com/api/users/today_login 获取今天登陆的用户 
    https://example.com/api/users/today_login&sort=login_desc 获取今天登陆的用户、登陆时间降序排列
    

    3.url命名规范

    API 命名应该采用约定俗成的方式,保持简洁明了。在RESTful架构中,每个url代表一种资源所以url中不能有动词,只能有名词,并且名词中也应该使用复数。实现者应使用相应的Http动词GET、POST、PUT、PATCH、DELETE、HEAD来操作这些资源即可

    不规范的的url,冗余没有意义,形式不固定,不同的开发者还需要了解文档才能调用。

    https://example.com/api/getallUsers GET 获取所有用户 
    https://example.com/api/getuser/1 GET 获取标识为1用户信息 
    https://example.com/api/user/delete/1 GET/POST 删除标识为1用户信息 
    https://example.com/api/updateUser/1 POST 更新标识为1用户信息 
    https://example.com/api/User/add POST 添加新的用户
    

    规范后的RESTful风格的url,形式固定,可读性强,根据users名词和http动词就可以操作这些资源

    https://example.com/api/users GET 获取所有用户信息 
    https://example.com/api/users/1 GET 获取标识为1用户信息 
    https://example.com/api/users/1 DELETE 删除标识为1用户信息 
    https://example.com/api/users/1 Patch 更新标识为1用户部分信息,包含在body中 
    https://example.com/api/users POST 添加新的用户
    

    4. 统一返回数据格式

    对于合法的请求应该统一返回数据格式,这里演示的是json

    • code——包含一个整数类型的HTTP响应状态码。
    • status——包含文本:”success”,”fail”或”error”。HTTP状态响应码在500-599之间为”fail”,在400-499之间为”error”,其它均为”success”(例如:响应状态码为1XX、2XX和3XX)。这个根据实际情况其实是可要可不要的。
    • message——当状态值为”fail”和”error”时有效,用于显示错误信息。参照国际化(il8n)标准,它可以包含信息号或者编码,可以只包含其中一个,或者同时包含并用分隔符隔开。
    • data——包含响应的body。当状态值为”fail”或”error”时,data仅包含错误原因或异常名称、或者null也是可以的

    返回成功的响应json格式

    {
      "code": 200,
      "message": "success",
      "data": {
        "userName": "123456",
        "age": 16,
        "address": "beijing"
      }
    }
    

    返回失败的响应json格式

    {
      "code": 401,
      "message": "error  message",
      "data": null
    }
    

    下面这个ApiResult的泛型类是在项目中用到的,拓展性强,使用方便。返回值使用统一的 ApiResult 或 ApiResult
    错误返回 使用 ApiResult.Error 进行返回; 成功返回,要求使用 ApiResult.Ok 进行返回

    public class ApiResult: ApiResult
        {
            public new static ApiResult<T> Error(string message)
            {
                return new ApiResult<T>
                {
                    Code = 1,
                    Message = message,
                };
            }
            [JsonProperty("data")]
            public T Data { get; set; }
        }
        public class ApiResult
        {
            public static ApiResult Error(string message)
            {
                return new ApiResult
                {
                    Code = 1,
                    Message = message,
                };
            }
    
            public static ApiResult<T> Ok<T>(T data)
            {
                return new ApiResult<T>()
                {
                    Code = 0,
                    Message = "",
                    Data = data
                };
            }
            /// <summary>
            /// 0 是 正常 1 是有错误
            /// </summary>
            [JsonProperty("code")]
            public int Code { get; set; }
            [JsonProperty("msg")]
            public string Message { get; set; }
    
            [JsonIgnore]
            public bool IsSuccess => Code == 0;
        }
    

    5. http状态码

    在之前开发的xamarin android博客园客户端的时候,patch、delete、post操作时body响应里面没有任何信息,仅仅只有http status code。HTTP状态码本身就有足够的含义,根据http status code就可以知道删除、添加、修改等是否成功。(ps:有点linux设计的味道哦,没有返回消息就是最好的消息,表示已经成功了)服务段向用户返回这些状态码并不是一个强制性的约束。简单点说你可以指定这些状态,但是不是强制的。常用HTTP状态码对照表
    HTTP状态码也是有规律的

    • 1**请求未成功
    • 2**请求成功、表示成功处理了请求的状态代码。
    • 3**请求被重定向、表示要完成请求,需要进一步操作。 通常,这些状态代码用来重定向。
    • 4** 请求错误这些状态代码表示请求可能出错,妨碍了服务器的处理。
    • 5**(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。 这些错误可能是服务器本身的错误,而不是请求出错。

    6. 合理使用query parameter

    在请求数据时,客户端经常会对数据进行过滤和分页等要求,而这些参数推荐采用HTTP Query Parameter的方式实现

    比如设计一个最近登陆的所有用户
    https://example.com/api/users?recently_login_day=3
    
    搜索用户,并按照注册时间降序
    https://example.com/api/users?recently_login_day=3
    
    搜索用户,并按照注册时间升序、活跃度降序
    https://example.com/api/users?q=key&sort=create_title_asc,liveness_desc
    
    关于分页,看看博客园开放平台分页获取精华区博文列表
    https://api.cnblogs.com/api/blogposts/@picked?pageIndex={pageIndex}&pageSize={pageSize} 
    返回示例: 
    [ 
    { 
    “Id”: 1, 
    “Title”: “sample string 2, 
    “Url”: “sample string 3, 
    “Description”: “sample string 4, 
    “Author”: “sample string 5, 
    “BlogApp”: “sample string 6, 
    “Avatar”: “sample string 7, 
    “PostDate”:2017-06-25T20:13:38.892135+08:00, 
    “ViewCount”: 9, 
    “CommentCount”: 10, 
    “DiggCount”: 11 
    }, 
    { 
    “Id”: 1, 
    “Title”: “sample string 2, 
    “Url”: “sample string 3, 
    “Description”: “sample string 4, 
    “Author”: “sample string 5, 
    “BlogApp”: “sample string 6, 
    “Avatar”: “sample string 7, 
    “PostDate”:2017-06-25T20:13:38.892135+08:00, 
    “ViewCount”: 9, 
    “CommentCount”: 10, 
    “DiggCount”: 11 
    } 
    ]
    

    7. 多表、多参数连接查询如何设计URL

    这是一个比较头痛的问题,在做单个实体的查询比较容易和规范操作,但是在实际的API并不是这么简单而已,这其中常常会设计到多表连接、多条件筛选、排序等。
    比如我想查询一个获取在6月份的订单中大于500元的且用户地址是北京,用户年龄在22岁到40岁、购买金额降序排列的订单列表

    https://example.com/api/orders?order_month=6&order_amount_greater=500&address_city=北京&sort=order_amount_desc&age_min=22&age_max=40
    

    从这个URL上看,参数众多、调用起来还得一个一个仔细对着,而且API本身非常不容易维护,命名看起来不是很容易,不能太长,也不能太随意。

    在.net WebAPI总我们可以使用属性路由,属性路由就是讲路由附加到特定的控制器或操作方法上装饰Controll及其使用[Route]属性定义路由的方法称为属性路由。

    这种好处就是可以精准地控制URL,而不是基于约定的路由,简直就是为这种多表查询量身定制似的的。 从webapi 2开发,现在是RESTful API开发中最推荐的路由类型。
    我们可以在Controll中标记Route

    [Route(“api/orders/{address}/{month})] 
    

    Action中的查询参数就只有金额、排序、年龄。减少了查询参数、API的可读性和可维护行增强了。

    https://example.com/api/orders/beijing/6?order_amount_greater=500&sort=order_amount_desc&age_min=22&age_max=40
    

    这种属性路由比如在博客园开放的API也有这方面的应用,如获取个人博客随笔列表

    请求方式:GET 
    请求地址:https://api.cnblogs.com/api/blogs/{blogApp}/posts?pageIndex={pageIndex} 
    (ps:blogApp:博客名)
    

    作者信息:
    【文章信息】:
    作者-张林
    原文链接-https://blog.csdn.net/kebi007/article/details/102927209
    【原创公众号】:dotNet全栈开发。
    【简介】:CSDN 博客专家, xamarin跨平台开发者,博客园app开发者(ps:虽然下载量还行10万+,并没有什么大用)这是一个坚持原创的技术公众号,每天坚持推送各种 dotNet 基础/进阶文章,编程技巧,爬虫实战,面试经验,xamarin开发系列不定期分享各类资源。
    【福利】:送你新人大礼包一份,关注微信公众号,后台回复:“CSDN” 即可获取!
    版权声明:本文为CSDN博主「dotNet全栈开发」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    ————————————————
    版权声明:本文为CSDN博主「dotnet全栈开发」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/kebi007/article/details/103655685

    展开全文
  • restful风格

    万次阅读 多人点赞 2018-08-24 11:55:19
    使用RESTful操作资源 【GET】 /users # 查询用户信息列表 【GET】 /users/1001 # 查看某个用户信息 【POST】 /users # 新建用户信息 【PUT】 /users/1001 # 更新用户信息(全部字段) 【PATCH】 /users/1001 # 更新...

    概念

             一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

     

    URL定义

    资源:互联网所有的事物都可以被抽象为资源 
    资源操作:使用POST、DELETE、PUT、GET,使用不同方法对资源进行操作。 
    分别对应 添加、 删除、修改、查询。 


    传统方式操作资源 

    http://127.0.0.1/item/queryUser.action?id=1   查询,GET 
    http://127.0.0.1/item/saveUser.action             新增,POST 
    http://127.0.0.1/item/updateUser.action          更新,POST 
    http://127.0.0.1/item/deleteUser.action?id=1  删除,GET或POST

     

    请求方式

    可以通过 GET、 POST、 PUT、 PATCH、 DELETE 等方式对服务端的资源进行操作。其中,GET 用于查询资源,POST 用于创建资源,PUT 用于更新服务端的资源的全部信息,PATCH 用于更新服务端的资源的部分信息,DELETE 用于删除服务端的资源。

    这里使用“用户”的案例进行回顾通过 GET、 POST、 PUT、 PATCH、 DELETE 等方式对服务端的资源进行操作。

     

    使用RESTful操作资源 

    【GET】 /users # 查询用户信息列表

    【GET】 /users/1001 # 查看某个用户信息

    【POST】 /users # 新建用户信息

    【PUT】 /users/1001 # 更新用户信息(全部字段)

    【PATCH】 /users/1001 # 更新用户信息(部分字段)

    【DELETE】 /users/1001 # 删除用户信息

    之前的操作是没有问题的,大神认为是有问题的,有什么问题呢?你每次请求的接口或者地址,都在做描述,例如查询的时候用了queryUser,新增的时候用了saveUser ,修改的时候用了updateUser,其实完全没有这个必要,我使用了get请求,就是查询.使用post请求,就是新增的请求,PUT就是修改,delete就是删除,我的意图很明显,完全没有必要做描述,这就是为什么有了restful.

     

    API设计风格基本规则

    1.使用名词而不是动词

    不要使用:

    /getAllUsers
    /createNewUser
    /deleteAllUser

    2.Get方法和查询参数不应该涉及状态改变

    使用PUT, POST 和DELETE 方法 而不是 GET 方法来改变状态,不要使用GET 进行状态改变:

    3.使用复数名词

    不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。

    /cars 而不是 /car
    /users 而不是 /user
    /products 而不是 /product
    /settings 而部署 /setting

    4. 使用子资源表达关系

    如果一个资源与另外一个资源有关系,使用子资源:

    GET /cars/711/drivers/ 返回 car 711的所有司机
    GET /cars/711/drivers/4 返回 car 711的4号司机

    5.使用Http头声明序列化格式

    在客户端和服务端,双方都要知道通讯的格式,格式在HTTP-Header中指定

    Content-Type 定义请求格式
    Accept 定义系列可接受的响应格式

    6.为集合提供过滤 排序 选择和分页等功能

    Filtering过滤:

    使用唯一的查询参数进行过滤:

    GET /cars?color=red 返回红色的cars
    GET /cars?seats<=2 返回小于两座位的cars集合

    Sorting排序:

    允许针对多个字段排序

    GET /cars?sort=-manufactorer,+model

    这是返回根据生产者降序和模型升序排列的car集合

    Field selection

    移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。

    GET /cars?fields=manufacturer,model,id,color

    Paging分页

    使用 limit 和offset.实现分页,缺省limit=20 和offset=0;

    GET /cars?offset=10&limit=5

    为了将总数发给客户端,使用订制的HTTP头: X-Total-Count.

    链接到下一页或上一页可以在HTTP头的link规定,遵循Link规定:

    Link: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",
    <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",
    <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",
    <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; rel="prev",

    7.版本化你的API

    使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5.

    一般在Url后面使用?v

    /blog/api/v1

    8. 使用Http状态码处理错误

    如果你的API没有错误处理是很难的,只是返回500和出错堆栈不一定有用

    Http状态码提供70个出错,我们只要使用10个左右:

    200 – OK – 一切正常
    201 – OK – 新的资源已经成功创建
    204 – OK – 资源已经成功擅长

    304 – Not Modified – 客户端使用缓存数据

    400 – Bad Request – 请求无效,需要附加细节解释如 "JSON无效"
    401 – Unauthorized – 请求需要用户验证
    403 – Forbidden – 服务器已经理解了请求,但是拒绝服务或这种请求的访问是不允许的。
    404 – Not found – 没有发现该资源
    422 – Unprocessable Entity – 只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失。

    500 – Internal Server Error – API开发者应该避免这种错误。

    使用详细的错误包装错误:

    {

      "errors": [

       {

        "userMessage": "Sorry, the requested resource does not exist",

        "internalMessage": "No car found in the database",

        "code": 34,

        "more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"

       }

      ]

    }

    9.允许覆盖http方法

    一些代理只支持POST 和 GET方法, 为了使用这些有限方法支持RESTful API,需要一种办法覆盖http原来的方法。

    使用订制的HTTP头 X-HTTP-Method-Override 来覆盖POST 方法.

     

    Restful风格的springMVC配搭ajax请求的例子

    总而言之restful是一种旧技术新风格

    展开全文
  • RESTful-源码

    2021-03-29 00:29:25
    RESTful
  • Restful-源码

    2021-03-06 14:43:35
    Restful
  • RestFul风格

    万次阅读 2021-01-02 21:25:01
    RestFul 风格 概念 Restful就是一个资源定位及资源操作的风格。不是标准也不是协议,只是一种风格。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 功能 资源:互联网所有的事物都可以被抽象...
  • springboot restful

    2016-08-13 11:47:20
    springboot restful spring restful
  • restful api

    2017-06-20 23:17:59
    restful api
  • Restfulapi restfulapi实践
  • RESTful API接口设计标准及规范;

    万次阅读 多人点赞 2019-01-12 11:42:10
    RESTful发展背景及简介 网络应用程序,分为前端和后端两个部分。当前的发展趋势,就是前端设备层出不穷(手机、平板、桌面电脑、其他专用设备…)。因此,必须有一种统一的机制,方便不同的前端设备与后端进行通信。...
  • RESTful Architecture

    2018-06-17 11:28:20
    Foundations of RESTful Architecture, the basic,soap
  • Restful WebService

    2016-05-20 14:25:11
    Restful 简单例子
  • RESTful api设计

    2021-03-08 14:52:32
    RESTful api设计
  • webservice RESTful

    2017-12-05 14:05:34
    webservice 的RESTful风格,请求格式和返回格式都是json
  • restful例子

    2014-07-19 10:52:20
    restful例子
  • RESTful Services

    2017-11-09 19:52:57
    RESTful Services Web Services expose their data and functionality trough resources identified by URI
  • restful.zip

    2021-03-25 16:24:53
    springBoot + restful 代码示例
  • expressJS-restfulAPI 尝试restfulAPI
  • RESTful WebService

    2016-03-26 05:24:46
    RESTful WebService是比基于SOAP消息的WebService简单的多的一种轻量级Web服务,RESTful WebService是没有状态的,发布和调用都非常的轻松容易。 下面写一个最简单的Hello World例子,以便对RESTful WebService有...
  • restlet restful

    2017-11-14 11:17:52
    restlet restful,web工程,可直接运行。启动后,main方法作为client运行调用服务端。服务器数据之间沟通利器,绝对不坑。
  • 春暖花开 Spring Restful教程
  • Restful-APi:RESTful API培训2020
  • RestFul API 案例

    2018-07-31 20:25:56
    RestFul API 案例 新手入门帮助 包括RestFulRestFul Api的介绍 也包括案例代码
  • 轻松创建 RESTful API 响应 此包使您能够创建 RESTful API 响应,而无需考虑底层 HTTP 层的细节。 您提供数据,包将处理输出格式和状态代码。 在应用程序错误的情况下,也可以创建 RESTful 错误响应。 该包针对与...
  • restful api guidelines

    2019-08-18 09:01:32
    restful api guidelines restful api guidelines restful api guidelines
  • restful 测试工具

    2021-06-18 15:48:34
    测试restful接口工具,java编写,不用安装,解压即可运行。方便实用。
  • RESTFul API

    2018-03-13 17:32:05
    定义:URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作。RESTful API 设计指南RESTful 架构详解《HTTP协议:菜鸟入门系列》如何给老婆解释什么是RESTful

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 188,038
精华内容 75,215
关键字:

restful