是学习和联系Android小项目的使用资料.排名完全是根据 GitHub 搜索 Java 语言选择 (Best Match) 得到的结果, 然后过滤了跟 Android 不相关的项目, 所以排名并不具备任何官方效力, 仅供参考学习, 方便初学者快速了解当前一些流行的 Android 开源库。
文件:url80.ctfile.com/f/25127180-745422874-4fe882?p=551685 (访问密码: 551685)
这啥意思呢?这个字符串序列代表的就是受支持的 HTTP 请求方式。比如,如果此属性返回 GET POST,那么被修饰的对象既支持 HTTP-GET 请求,也支持 HTTP-POST 请求。咱们在写 Web API 时最熟悉的这几个特性类就是实现了 IActionHttpMethodProvider 接口。
复制代码
[HttpGet]
[HttpPost]
[HttpPut]
[HttpDelete]
[HttpHead]
[HttpPatch]
[HttpOptions]
复制代码
这几个特性类不仅实现了 IActionHttpMethodProvider 接口,还实现了 IRouteTemplateProvider。所以它们可以当 [Route] 特性来用,又可以限制 HTTP 请求方式,一举两得。
咱们在实际项目中,如果希望一个操作方法同时支持多种请求方法,可以叠加使用以上特性类。比如
[HttpPut]
[HttpPost]
public float GetAFloat()
还可以自己定义一个特性类,实现 IActionHttpMethodProvider 接口,从 HttpMethods 属性返回一组请求方式。
复制代码
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CustHttpmethodsAttribute : Attribute, IActionHttpMethodProvider
{
private readonly string[] _httpmethods;
// 构造函数
public CustHttpmethodsAttribute(params string[] httpmethods)
{
_httpmethods = httpmethods;
}
// 这个是实现接口的成员
public IEnumerable<string> HttpMethods => _httpmethods;
}
复制代码
很简单的一个类,HttpGet 等特性类只能应用到操作方法上,这里老周把限制放宽一些,让其可以应用到类和方法上,即可以用在控制器和操作方法上面。
通过构造函数的参数可以传递一个或 N 个HTTP请求方式。正因为如此,该特性类在同一个目标上就不需要多次应用了,所以,我把 AllowMultiple 设置为 false。
接下来,测试一下这厮能不能用。
复制代码
[CustHttpmethods(“PUT”, “POST”), Route(“manage/[action]”)]
public class StudentController : ControllerBase
{
public IActionResult AddNew(Student stu)
{
// 要是 StuSerail 或 Name 属性没找到
// IsValid 就返回 false
if(!ModelState.IsValid)
{
return Content(“数据无效”);
}
return Content($"添加成功!\n学号:{stu.StuSerial}\n姓名:{stu.Name}\n年龄:{stu.Age}\n微信名称:{stu.WXName}");
}
}
复制代码
下面是 Student 类的定义。
复制代码
public class Student
{
///
/// 学号
///
[BindRequired]
public long StuSerial { get; set; }
///
/// 姓名
///
[BindRequired]
public string? Name { get; set; } = “宇宙人”;
///
/// 微信名字
///
public string? WXName { get; set; } = “钓鱼佬”;
///
/// 年龄
///
public int Age { get; set; } = 0;
}
复制代码
应用了 BindRequired 特性的意思就是:在模型绑定时,如果没能在客户端提交的数据中找到这些属性的值,那么模型的绑定状态(Model State)就会设置 IsValid 属性为 false。在 Student 类中,StuSerial 和 Name 属性要求必须绑定有效。
根据上述代码的设计,Student 控制器中的所有操作都只允许 HTTP-PUT 和 HTTP-POST 两种请求。下面咱们来验证一下,前面写的 CustHttpmethods 特性是否生效。
这里老周用 .NET Tools 提供的 http-repl 工具来测试——嗯,别多想,肯定是个命令行工具。如果你还没安装,可以用这条命令安装它。
dotnet tool install -g Microsoft.dotnet-httprepl
其中,-g 表示安装到用户的默认路径中。
用法:httprepl http://localhost:1254,回车后进入交互模式,只要输入相关命令即可。如 get post delete put patch 等,帮助信息可以用 help 来查看。
咱们把 echo 选项打开,这样该工具就会显示请求的 HTTP 消息。
echo on
运行应用程序,试试 HTTP-GET 能不能访问。
get /manage/addnew?stuserial=123456&name=小吴&age=22
得到的响应消息如下:
显然,GET 方法无法通过。
那试试 POST 。
post /manage/addnew -h “Content-Type=application/x-www-form-urlencoded” -c stu.stuserial=123456&stu.name=小明&stu.age=24&stu.wxname=二哈
-h 表示要添加的 HTTP 消息头,多个头可以多次使用-h,总之一个头用一次-h;-c 表示正文(body)。
这一次提交很顺利,得到服务器的正确回应。
正文部分的 stu 前缀可以省略。
stuserial=123456&name=小高&age=20&wxname=工具人
POST 请求没有问题,再试试 PUT。
put /manage/addnew -h Content-Type:application/x-www-form-urlencoded -c stuserial=67980&name=小张&age=19&wxname=扫雷冠军
请求也成功完成,服务器有正确的响应。
咱们继续实验。刚才测试的都是标准的 HTTP 请求方式,要是咱们来个非规范的会怎么样呢?比如,弄个叫 “SET” 的请求方法。
[CustHttpmethods(“SET”), Route(“manage/[action]”)]
public class StudentController : ControllerBase
{
……
}
实验继续。
这一次咱们不能用 http-repl 工具了,因为 SET 不是规范的请求方式,测试工具不支持。但可以写个控制台应用程序来测试。
复制代码
// 这一行主要是为了等服务器运行起来
// 当此项目与服务器项目一起启动时用得上
await Task.Delay(1000);
Uri rootUrl = new(“https://localhost:12550”);
HttpClient client = new();
// form-data
IDictionary<string, string> data = new Dictionary<string, string>()
{
[“stuserial”] = “76008”,
[“name”] = “小青”,
[“age”] = “19”,
[“wxname”] = “南方小鲟”
};
FormUrlEncodedContent content = new FormUrlEncodedContent(data);
HttpRequestMessage reqmsg = new HttpRequestMessage();
// 这个不是标准的,得自己写上
reqmsg.Method = new HttpMethod(“SET”);
reqmsg.RequestUri = new Uri(rootUrl, “/manage/addnew”);
reqmsg.Content = content;
// 发送
var resp = await client.SendAsync(reqmsg);
Console.WriteLine(
"
响
应
代
码
:
(
i
n
t
)
r
e
s
p
.
S
t
a
t
u
s
C
o
d
e
"
)
;
C
o
n
s
o
l
e
.
W
r
i
t
e
L
i
n
e
(
"响应代码:{(int)resp.StatusCode}"); Console.WriteLine(
"响应代码:(int)resp.StatusCode");Console.WriteLine(“响应内容:\n{await resp.Content.ReadAsStringAsync()}”);
// 这两行只是为了让程序能停下来罢了,没其他用途
Console.WriteLine();
Console.ReadKey();