.Net之接口小知識

目的

通過一個簡單的項目,在原來的文章基礎上完善一下常用的幾種WebApi編寫方式以及請求方式,一方面是用于給我一個前端朋友用來學習調用接口,另一方面讓我測試HttpClient的一些效果。

本文示例代碼環境:vs2022、net6

準備

新創建了一個.Net WebAPI程序,安裝組件

<ItemGroup><PackageReference?Include="AutoMapper.Extensions.Microsoft.DependencyInjection"?Version="11.0.0"?/><PackageReference?Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson"?Version="6.0.1"?/><PackageReference?Include="Swashbuckle.AspNetCore"?Version="6.3.1"?/><PackageReference?Include="Swashbuckle.AspNetCore.Newtonsoft"?Version="6.3.1"?/>
</ItemGroup>

ConfigureServices配置NewtonsoftJson以及Automapper和操作數據庫代碼(為了省事,刪除了一些不影響當前效果的代碼)

public?void?ConfigureServices(IServiceCollection?services)
{services.AddControllers().AddNewtonsoftJson();services.AddEndpointsApiExplorer();services.AddSwaggerGen(c?=>{c.SwaggerDoc("v1",?new?OpenApiInfo?{?Title?=?"MyWebApi",?Version?=?"v1"?});});//注入AutoMapperservices.AddAutoMapper(Assembly.GetExecutingAssembly().DefinedTypes.Where(t?=>?typeof(Profile).GetTypeInfo().IsAssignableFrom(t.AsType())).Select(t?=>?t.AsType()).ToArray());
}

注意:在Net core3.0以后,微軟移除了Newtonsoft.Json,而使用了System.Text.Json,所以依賴于Newtonsoft.Json的組件將不可用,需要安裝 Microsoft.AspNetCore.Mvc.NewtonsoftJson 包

因為僅僅作為演示,所以我只是新增一個控制器,里面包含了get、post、put、patch、delete幾種類型的接口。這里先不貼代碼,一點一點看。通過一個用戶的添加、修改、刪除作為一個演示的流程。

記得配置允許跨域請求,要不js請求會因為跨域問題而報錯。詳情看此處

數據來源就是控制器里面的一個靜態變量,格式如下

public?class?UserDto
{public?long?UserId?{?get;?set;?}public?string?Name?{?get;?set;?}public?string?Sex?{?get;?set;?}
}

靜態變量如下

private?static?readonly?List<UserDto>?_userDtoList?=?Enumerable.Range(0,?100).Select(t?=>?new?UserDto{Name?=?"張三"?+?t,Sex?=?"男",UserId?=?6974150586715897857?+?t}).ToList();

后端請求的方法我使用的是HttpClient,并且做成了一個公共類,部分需要用到的如下

public?class?HttpClientHelper:?IHttpHelper
{private?readonly?System.Net.Http.HttpClient?_client;///?<summary>///?構造函數///?</summary>///?<param?name="httpClientFactory"></param>public?HttpClientHelper(IHttpClientFactory?httpClientFactory){_client?=?httpClientFactory.CreateClient();}private?void?VerifyParam(string?url,?string?jwtToken,?IDictionary<string,?string>?headers){_client.DefaultRequestHeaders.Clear();if?(string.IsNullOrWhiteSpace(url)){throw?new?ArgumentNullException("url不能為null");}if?(!string.IsNullOrWhiteSpace(jwtToken)){_client.DefaultRequestHeaders.Add("Authorization",?$"Bearer?{jwtToken}");}if?(headers?.Count?>?0){foreach?(var?(key,?value)?in?headers){_client.DefaultRequestHeaders.Add(key,?value);}}}private?static?async?Task<T>?ConvertResponseResult<T>(HttpResponseMessage?httpResponse){//確保成功完成,不是成功就返回具體錯誤信息httpResponse.EnsureSuccessStatusCode();var?resStr?=?await?httpResponse.Content.ReadAsStringAsync();if?(typeof(T)?==?typeof(string))return?(T)Convert.ChangeType(resStr,?typeof(string));return?JsonConvert.DeserializeObject<T>(resStr);}
}

操作

請求頭傳遞token只是為了演示請求頭傳遞參數的寫法,token為偽值

GET

從web服務檢索數據。傳遞參數的本質是url字符串拼接,Request-Head頭部傳遞,Request-Body中不能傳遞(嚴格點說不建議,因為我使用Apifox等工具可以在body中傳值,swagger會提示 Request with GET/HEAD method cannot have body)

Query格式

編寫用戶id查詢用戶信息接口

[HttpGet("user/details")]
public?UserDto?GetUserDetails(long?userId)
{if?(!_userDtoList.Any(t?=>?t.UserId?==?userId))throw?new?ParameterException("未找到用戶標識");return?_userDtoList.Find(t?=>?t.UserId?==?userId);
}

前端請求

$(function?()?{$.ajax({type:?"get",url:?"http://localhost:5000/api/HttpSample/user/details?userId=6974150586715897857",headers:?{?"Authorization":?"Bearer?123456"?},contentType:?"application/json",success:?function?(data,?status)?{if?(status?==?"success")?{console.log(JSON.stringify(data));}}});var?postdata?=?{?userId:?"6974150586715897857"?};$.ajax({type:?"get",headers:{"Authorization":"Bearer?123456"},url:?"http://localhost:5000/api/HttpSample/user/details",data:?postdata,success:?function?(data,?status)?{?if?(status?==?"success")?{console.log(JSON.stringify(data));}??}});
});

后端請求

var?token?=?"123456";//此處token是偽值
var?result?=?await?_httpHelper.GetAsync<ResultModel<UserDto>>("http://localhost:5000/api/HttpSample/user/details?userId=6974150586715897857",?token);

這里的_httpHelper是注入的IHttpHelper(下面其他的方法一樣),對應的GetAsync為

public?async?Task<T>?GetAsync<T>(string?url,?string?jwtToken?=?"",?IDictionary<string,?string>?headers?=?null)
{VerifyParam(url,?jwtToken,?headers);var?response?=?await?_client.GetAsync(url).ConfigureAwait(false);return?await?ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具請求

url:http://localhost:5000/api/HttpSample/user/details?userId=6974150586715897857

并且再請求頭增加:Authorization,值為Bearer xxxx

返回結果如下

cdc838d3af1b12a4db12287956a6605b.png
img

POST

在web服務上創建新的數據項。約定用于向服務端提交數據操作,請求時候參數放在參數FromBody傳遞

Json格式

演示添加用戶操作

請求類

public?class?UserDto
{public?long?UserId?{?get;?set;?}public?string?Name?{?get;?set;?}public?string?Sex?{?get;?set;?}
}

接口代碼示例

[HttpPost("user/add")]
public?bool?Add([FromBody]?UserDto?request)
{if?(_userDtoList.Any(t?=>?t.UserId?==?request.UserId))throw?new?ParameterException("用戶標識已經存在");Console.WriteLine(DateTime.Now?+?"???"?+?HttpContext.Request.Headers["Authorization"].FirstOrDefault());_userDtoList.Add(request);return?true;
}

前端請求

$(function?()?{var?param?=?{?userId:?"8974150586715897867",?name:?"老八",?sex:?"女"?};$.ajax({type:?"post",dataType:?'json',contentType:?"application/json",headers:?{?"Authorization":?"Bearer?123456"?},url:?"http://localhost:5000/api/HttpSample/user/add",data:?JSON.stringify(param),success:?function?(data)?{if?(status?==?"success")?{console.log(JSON.stringify(data));}}});
});

后端請求

var?token?=?"123456";//此處token是偽值
var?url?=?"http://localhost:5000/api/HttpSample/user/add";var?usedto?=?new?UserDto
{UserId?=?123456,Name?=?"李四",Sex?=?"女"
};var?result?=?await?_httpHelper.PostAsync<ResultModel<bool>>(url,?usedto,?token);public?async?Task<T>?PostAsync<T>(string?url,?object?data,?string?jwtToken?=?"",?IDictionary<string,?string>?headers?=?null)
{VerifyParam(url,?jwtToken,?headers);var?jsonData?=?data?is?string???data.ToString()?:?JsonConvert.SerializeObject(data);using?var?content?=?new?StringContent(jsonData????string.Empty,?Encoding.UTF8,?"application/json");var?response?=?await?_client.PostAsync(url,?content).ConfigureAwait(false);return?await?ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具請求

傳遞參數格式為json格式,請求頭部默認添加:"Content-Type", "application/json"

12c4437fd6470eb5d6f5ab5c214d5b54.png
img

x-www-form-unlencoded格式

更新用戶姓名

[HttpPost("user/updatename")]
public?bool?UpdateName([FromForm]?long?userId,?[FromForm]?string?name)
{var?entity?=?_userDtoList.Find(t?=>?t.UserId?==?userId);if?(entity?is?null)throw?new?ParameterException("用戶標識不存在");entity.Name?=?name;return?true;
}

前端請求

$(function?()?{var?postdata?=?{?userId:?"6974150586715897857",?name:?"趙六"?};$.ajax({type:?"post",headers:?{?"Authorization":?"Bearer?123456"?},url:?"http://localhost:5000/api/HttpSample/user/updatename",data:?postdata,success:?function?(data,?status)?{if?(status?==?"success")?{console.log(JSON.stringify(data));}}});
});

后端請求

var?token?=?"123456";//此處token是偽值
var?url?=?"http://localhost:5000/api/HttpSample/user/updatename";
var?dic?=?new?Dictionary<string,?string>
{{?"userId","6974150586715897857"},{?"name","王五"}
};
var?result?=?await?_httpHelper.PostFormDataAsync<ResultModel<bool>>(url,?dic,?token);public?async?Task<T>?PostFormDataAsync<T>(string?url,?Dictionary<string,?string>?data,?string?jwtToken?=?"",?IDictionary<string,?string>?headers?=?null)
{VerifyParam(url,?jwtToken,?headers);var?httpContent?=?new?FormUrlEncodedContent(data);var?response?=?await?_client.PostAsync(url,?httpContent).ConfigureAwait(false);return?await?ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具請求

選擇post請求,參數在Body,然后選擇x-www-form-unlencoded格式。

41303d6d0113af3944c72d658f6ad98b.png
img

Form-data格式

模擬上傳用戶頭像操作

[HttpPost("user/uploadImg")]
public?string?Upload([FromForm]?IFormFile?img,?[FromForm]?long?userId)
{if?(img?is?null)throw?new?ParameterException("用戶頭像不能為null");Console.WriteLine(HttpContext.Request.Headers["Authorization"].FirstOrDefault());var?entity?=?_userDtoList.Find(t?=>?t.UserId?==?userId);if?(entity?is?null)throw?new?ParameterException("用戶標識不存在");return?img.FileName;
}

注意:當你上傳大于30000000字節長度的文件時候,需要修改上傳文件的默認限制

前端請求

$(function?()?{$("#tijiao").click(function?()?{//logoimg是<input?type="file"?id="logoimg""?/>var?files?=?$("#logoimg").prop('files');?//獲取到文件列表var?formData?=?new?FormData();formData.append("userId",?"6974150586715897857");formData.append("img",?files[0],?"1122.jpg");//圖片文件流console.log(formData);$.ajax({type:?'post',url:?"http://localhost:5000/api/HttpSample/user/uploadImg",headers:?{"Authorization":?"Bearer?123456"},mimeType:?"multipart/form-data",processData:?false,contentType:?false,data:?formData,success:?function?(data)?{//后端Httpclient請求成功后返回過來的結果console.log(data);}});});
});

后端請求

var?url?=?"http://localhost:5000/api/HttpSample/user/uploadImg";var?formData?=?new?MultipartFormDataContent();var?bytes?=?System.IO.File.ReadAllBytes("D:\\Downloads\\11111.jpg");
var?byteContent?=?new?ByteArrayContent(bytes);
byteContent.Headers.ContentDisposition?=?new?System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
{Name?=?"img",FileName?=?"111.jpg"
};
formData.Add(byteContent);//?寫法一
formData.Add(new?StringContent("6974150586715897857"),?"userId");//?寫法二
var?byteContent2?=?new?ByteArrayContent(Encoding.UTF8.GetBytes("天氣"));
byteContent2.Headers.ContentDisposition?=?new?System.Net.Http.Headers.ContentDispositionHeaderValue("form-data")
{Name?=?"name",
};
formData.Add(byteContent2);var?headerDic?=?new?Dictionary<string,?string>
{{?"Authorization","Bearer?123456"},
};var?result?=?await?_httpHelper.PostFormDataAsync<ResultModel<string>>(url,?formData,?headerDic);public?async?Task<T>?PostFormDataAsync<T>(string?url,?MultipartFormDataContent?data,?IDictionary<string,?string>?headers?=?null)
{VerifyParam(url,?"",?headers);var?result?=?await?_client.PostAsync(url,?data).ConfigureAwait(false);return?await?ConvertResponseResult<T>(result);
}

接口工具請求

選擇Body=>form-data

442b97ef3e80051774a12b0114241b04.png
img

PUT

更新web服務上的數據項。

Json格式

更新用戶信息

[HttpPut("user/update")]
public?bool?Update(UserDto?userDto)
{if?(userDto?is?null)throw?new?ParameterException("參數不能為空");Console.WriteLine(DateTime.Now?+?"????"?+?HttpContext.Request.Headers["Authorization"].FirstOrDefault());var?currUser?=?_userDtoList.Find(t?=>?t.UserId?==?userDto.UserId);if?(currUser?is?null)throw?new?ParameterException("用戶標識不存在");currUser.Name?=?userDto.Name;currUser.Sex?=?userDto.Sex;return?true;
}

前端請求

$(function?()?{var?param?=?{?userId:?"6974150586715897859",?name:?"老八",?sex:?"女"?};$.ajax({type:?"put",dataType:?'json',contentType:?"application/json",headers:?{?"Authorization":?"Bearer?123456"?},url:?"http://localhost:5000/api/HttpSample/user/update",data:?JSON.stringify(param),success:?function?(data,?status)?{if?(status?==?"success")?{console.log(JSON.stringify(data));}}});
});

后端請求

var?token?=?"123456";//此處token是偽值var?usedto?=?new?UserDto
{UserId?=?6974150586715897859,Name?=?"老八",Sex?=?"女"
};var?url?=?"http://localhost:5000/api/HttpSample/user/update";var?result?=?await?_httpHelper.PutAsync<ResultModel<bool>>(url,?usedto,?token);
return?JsonConvert.SerializeObject(result);public?async?Task<T>?PutAsync<T>(string?url,?object?data,?string?jwtToken?=?"",?IDictionary<string,?string>?headers?=?null)
{VerifyParam(url,?jwtToken,?headers);var?jsonData?=?data?is?string???data.ToString()?:?JsonConvert.SerializeObject(data);using?var?content?=?new?StringContent(jsonData????string.Empty,?Encoding.UTF8,?"application/json");var?response?=?await?_client.PutAsync(url,?content).ConfigureAwait(false);return?await?ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具請求

URL:http://localhost:5000/api/HttpSample/user/update

參數傳遞:Body=>json

262d545306d12cf61b9f270ebb88a94e.png
img

DELETE

刪除web服務上的數據項。

Query格式

刪除用戶信息

[HttpDelete("user")]
public?bool?Delete(long?userId)
{var?entity?=?_userDtoList.Find(t?=>?t.UserId?==?userId);if?(entity?is?null)throw?new?ParameterException("用戶標識不存在");Console.WriteLine(DateTime.Now?+?"????"?+?HttpContext.Request.Headers["Authorization"].FirstOrDefault());_userDtoList.Remove(entity);return?true;
}

前端請求

$(function?()?{$.ajax({type:?"DELETE",url:?"http://localhost:5000/api/HttpSample/user?userId=6974150586715897861",headers:?{?"Authorization":?"Bearer?123456"?},success:?function?(data,?status)?{if?(status?==?"success")?{console.log(JSON.stringify(data));}}});
});

后端請求

var?token?=?"123456";//此處token是偽值
var?url?=?"http://localhost:5000/api/HttpSample/user?userId=6974150586715897862";var?result?=?await?_httpHelper.DeleteAsync<ResultModel<bool>>(url,?token);public?async?Task<T>?DeleteAsync<T>(string?url,?string?jwtToken?=?"",?IDictionary<string,?string>?headers?=?null)
{VerifyParam(url,?jwtToken,?headers);var?response?=?await?_client.DeleteAsync(url).ConfigureAwait(false);return?await?ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具請求

URL:http://localhost:5000/api/HttpSample/user?userId=6974150586715897859

fc4b77707795155246d583ce18e2df6c.png
img

Patch

通過描述有關如何修改項的一組說明,更新web服務上的數據項。

請求格式如下:

[{"op" : "replace", "path" : "/PassWord", "value" : "222222"}]

op屬性指示操作的類型,path屬性指示要更新的元素,value屬性提供新值。

add:添加屬性或數組元素。對于現有屬性:設置值。

remove:刪除屬性或數組元素。

replace:替換操作

為了支持該請求方式,需要安裝nuget包Microsoft.AspNetCore.Mvc.NewtonsoftJson。

參考文檔:https://docs.microsoft.com/zh-cn/aspnet/core/web-api/jsonpatch?view=aspnetcore-6.0

Json格式

在此用于更新數據

[HttpPatch("user/update2/{userId}")]
public?UserDto?Update2([FromRoute]?long?userId,?JsonPatchDocument<UserDto>?jsonPatch,?[FromServices]?IMapper?mapper)
{var?entity?=?_userDtoList.Find(t?=>?t.UserId?==?userId);if?(entity?is?null)throw?new?ParameterException("用戶標識無效");var?dto?=?mapper.Map<UserDto>(entity);jsonPatch.ApplyTo(dto,?ModelState);var?user?=?_userDtoList.Find(t?=>?t.UserId?==?userId);mapper.Map(dto,?user);return?user;
}

前端請求

演示根據用戶id去更新用戶的姓名

$(function?()?{var?par?=?[{?"op":?"replace",?"path":?"/name",?"value":?"老六"?}];$.ajax({type:?"Patch",url:?"http://localhost:5000/api/HttpSample/user/update2/6974150586715897857",headers:?{?"Authorization":?"Bearer?123456"?},contentType:?"application/json",data:?JSON.stringify(par),success:?function?(result)?{console.log(result);}});
});

后端請求

var?token?=?"123456";//此處token是偽值
var?url?=?"http://localhost:5000/api/HttpSample/user/update2/6974150586715897859";
var?content?=?"[{\"op\":\"replace\",\"path\":\"/name\",\"value\":\"小七七\"}]";
var?result?=?await?_httpHelper.PatchAsync<ResultModel<UserDto>>(url,?content,?token);public?async?Task<T>?PatchAsync<T>(string?url,?object?data,?string?jwtToken?=?"",?IDictionary<string,?string>?headers?=?null)
{VerifyParam(url,?jwtToken,?headers);var?jsonData?=?data?is?string???data.ToString()?:?JsonConvert.SerializeObject(data);using?var?content?=?new?StringContent(jsonData????string.Empty,?Encoding.UTF8,?"application/json");var?response?=?await?_client.PatchAsync(url,?content).ConfigureAwait(false);return?await?ConvertResponseResult<T>(response).ConfigureAwait(false);
}

接口工具請求

參數傳遞:Body=>json

60190503e0c042d112a6a214187bf3bf.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/282776.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/282776.shtml
英文地址,請注明出處:http://en.pswp.cn/news/282776.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

你所不知道的setTimeout

JavaScript提供定時執行代碼的功能&#xff0c;叫做定時器&#xff08;timer&#xff09;&#xff0c;主要由setTimeout()和setInterval()這兩個函數來完成。它們向任務隊列添加定時任務。初始接觸它的人都覺得好簡單&#xff0c;實時上真的如此么&#xff1f;這里記載下&#…

android 特效繪圖,Android繪圖機制與處理技巧——Android圖像處理之圖形特效處理...

Android變形矩陣——Matrix對于圖像的圖形變換&#xff0c;Android系統是通過矩陣來進行處理的&#xff0c;每個像素點都表達了其坐標的X、Y信息。Android的圖形變換矩陣是一個3x3的矩陣&#xff0c;如下圖所示&#xff1a;72F0CAC1-14FB-40F8-A430-8F542B09DC4E.png當使用變換…

WPF 使用 DrawingContext 繪制刻度條

WPF 使用 DrawingContext 繪制刻度條控件名&#xff1a;Ruler作者&#xff1a;WPFDevelopersOrg原文鏈接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers框架使用大于等于.NET40&#xff1b;Visual Studio 2022;項目使用 MIT 開源許可協議&#xff1b;定義I…

純css實現漂亮又健壯的tooltip

前言 tooltip的實現有多種方式&#xff0c;下面是一個tooltip成長史。 預覽 https://codepen.io/moddx/pen/... 原始版 最簡單的莫過于就用原始title屬性&#xff0c;像這樣&#xff1a; <button title"tips">button</button> 缺點是體驗是差了點&#x…

個人中心的html,個人中心.html

&#xfeff;個人中心$axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; };$axure.utils.getOtherPath function() { return resources/Other.html; };$axure.utils.getReloadPath function() { return resources/reload.html; };…

使用CMD命令修改Windows本地賬戶密碼

2019獨角獸企業重金招聘Python工程師標準>>> 一、以管理員身份運行cmd命令 二、在命令提示符窗口中輸入命令符&#xff1a;net user Administrator 123&#xff0c;然后按回車鍵“Enter”。(Administrator是你的win8用戶名&#xff0c;123是重新設置的密碼。) ? 三…

Android 編譯時:m、mm、mmm、mma、mmma的區別

m&#xff1a;編譯整個安卓系統 makes from the top of the tree mm&#xff1a;編譯當前目錄下的模塊&#xff0c;當前目錄下需要有Android.mk這個makefile文件&#xff0c;否則就往上找最近的Android.mk文件。 builds all of the moudles in the current directory mma&#…

java線程安全問題原因及解決辦法

1.為什么會出現線程安全問題 計算機系統資源分配的單位為進程&#xff0c;同一個進程中允許多個線程并發執行&#xff0c;并且多個線程會共享進程范圍內的資源&#xff1a;例如內存地址。當多個線程并發訪問同一個內存地址并且內存地址保存的值是可變的時候可能會發生線程安全問…

html語言怎么添加圖片,我想問你一下,你是怎么在html中插入本地圖片?非常感謝...

滿意答案小蜜蜂手工2013.10.03采納率&#xff1a;43% 等級&#xff1a;12已幫助&#xff1a;7929人img{float:right}在下面的段落中&#xff0c;我們添加了一個樣式為 float:right 的圖像。結果是這個圖像會浮動到段落的右側。This is some text. This is some text. This i…

數組實現矩陣逐層向內層加1

package java1701;public class javaMain { public static void main(String[] args) { // 逐層加 // 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 // 1 2 2 2 2 1 1 2 2 2 1 1 2 2 1 1 2 1 // 1 2 3 3 2 1 1 2 3 2 1 1 2 2 1 1 1 1 // 1 2 3 …

EntityFrameworkCore上下文如何實現繼承?

【導讀】如果我們存在基礎設施服務和其他服務&#xff0c;我們會定義屬于基礎設施服務的上下文以及其他服務的上下文&#xff0c; 而且會獨立部署&#xff0c;此時其他服務需要使用基礎服務&#xff0c;我們都會暴露基礎服務接口給到其他服務調用&#xff0c;這也是常規操作若在…

Unity 游戲框架搭建 (九) 減少加班利器-QConsole

為毛要實現這個工具? 在我小時候,每當游戲在真機運行時,我們看到的日志是這樣的。 沒高亮啊,還有亂七八糟的堆棧信息,好干擾日志查看,好影響心情。 還有就是必須始終連著usb線啊&#xff0c;我想要想躺著測試。。。 以上種種原因,QConsole誕生了。 如何使用? 使用方式和QLog…

android藍牙多次后,android – 如何防止BluetoothGattCallback一次多次執行

我的服務有一個BluetoothGattCallback實例public class MyService extends Service {private BluetoothGattCallback callback;Overridepublic void onCreate() {super.onCreate();callback new BluetoothGattCallback() {Overridepublic synchronized void onConnectionState…

美觀又實用,10 款強大的開源 Javascript 圖表庫

2019獨角獸企業重金招聘Python工程師標準>>> 隨著發展&#xff0c;現代 Web 設計在改善體驗和功能的同時&#xff0c;對于美觀的追求也越來越高&#xff0c;可視化、交互式、動態等元素和效果似乎已成為標配。 以下是為開發者推薦的 10 款開源 Javascript 圖表庫&am…

EF CORE 7 RC1 發布

原文鏈接&#xff1a;https://devblogs.microsoft.com/dotnet/announcing-ef7-rc1/[1]原文作者&#xff1a;Jeremy Likness翻譯&#xff1a;沙漠盡頭的狼(谷歌翻譯加持)Entity Framework Core 7 (EF7) Release Candidate 1 已發布&#xff01;該團隊專注于解決缺陷、小幅改進以…

0 重新學習Ubuntu -- 這一段沒怎么學習

在完成了前面的幾個學習后&#xff0c;再沒有進行系統的學習。 雖然在真機上安裝系統&#xff0c;每天都打開&#xff0c;完成以下的工作&#xff1a; 升級軟件用來查看相關的網站在Ubuntu上&#xff0c;現在可以完成辦公、上網、娛樂。 但專業的學習&#xff0c;例如編程方面進…

自定義地圖怎么做成html,自定義html為谷歌地圖制作標記

好吧&#xff0c;似乎Custom Overlays會做我想要的。這是ping層&#xff1a;function PingLayer(bounds, map) {this.bounds bounds;this.setMap(map);}PingLayer.prototype new google.maps.OverlayView();PingLayer.prototype.onAdd function() {var div document.create…

HDU5248:序列變換(二分)

序列變換 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1348 Accepted Submission(s): 593Problem Description給定序列A{A1,A2,...,An}, 要求改變序列A中的某些元素&#xff0c;形成一個嚴格單調的序列B&am…

微服務太分散?使用Fundebug集中式bug監控

摘要&#xff1a; 微服務日志分散&#xff0c;可以使用Fundebug的異常監控將它們集中起來。 當一個項目復雜到一定程度&#xff0c;功能越來越多&#xff0c;隨之對應的模塊也越來越多。 如果都放在一個大的項目下面&#xff0c;共同開發&#xff0c;整合發布&#xff0c;那么會…

html404頁面怎么添加,網站要如何設置自定義404頁面?

之前我們講述過網站設置404頁面對于優化或是用戶體驗的重要意義&#xff0c;大家可移步到《網站為什么要設置404頁面》查看&#xff0c;今天我們講解的是網站要如何設置自己的404頁面。現在大多數空間商都有了404設置的功能&#xff0c;我們可將404頁面上傳至空間里面&#xff…