2024年9月,本人在做微信分享前端部分的iOS、安卓和H5的页面和功能时踩了不少坑,于是写了这篇文章,内容包括微信分享在上面三个端的技术点和坑点、解决办法,微信开放标签的相关适配,以及ReactNative的特别处理部分。

原文链接:http://www.kovli.com/2024/12/18/wx-share/

作者:Kovli

重要通知:红宝书第5版2024年12月1日出炉了,感兴趣的可以去看看,https://u.jd.com/saQw1vP

红宝书第五版中文版

红宝书第五版英文原版pdf下载(访问密码: 9696)

一、前期准备:微信开放平台、微信公众平台注册并审核通过

1、微信开放平台入口
2、微信公众平台入口
3、官网域名,分享用网页的域名(可以是二级域名)部署完成,ICP备案完成。
Tip1:微信开放平台认证一次性的三百。公众平台首次认证三百,认证到期后每年需要再年审三百。平台网页:https://developers.weixin.qq.com/community/develop/doc/000c040991c220d8dcea6324e56000
Tip2:官网域名用于iOS的Universal Links,分享用网页的域名用于放到js接口安全域名里面,凡是在js接口安全域名里的网页在微信里打开都可以使用开放标签和对应的微信js接口。后面会说怎么放。
Tip3:注册和申请这两个平台的同时,移动应用也添加和关联进去,后面要用到APPID,另外移动应用需要开启微信分享功能,详见文档。

二、客户端SDK集成:

1、友盟分享集成 开发文档
2、微信官网自行集成 开发文档
本人用的是友盟分享集成,也可以微信官网自行集成,如果友盟分享已经集成了那至少微信文档里SDK的集成这一步已经完成了。
不要遗漏文档里任何一处,以免后面遇到不该遇到的坑。
注意iOS需要配置Universal Links:参考文档

有个需要服务端或运维小伙伴配合的步骤,就是创建个文件名为apple-app-site-association的文件,没有后缀,里面的内容如下,

根据自己的参数来修改里面appID和paths的内容
{
"applinks": {
"apps": [],
"details": [
{
"appID":"苹果teamID.com.aaa.bbb"
"paths": ["/app/*"]
}
]
}
}

然后让后端或者运维小伙伴,把这个文件放在官网的服务器根目录下。

比如服务器地址是: https://www.baidu.com/ ,把文件放在这根目录下后,访问 https://www.baidu.com/apple-app-site-association ,这文件就会被下载下来。

然后根目录新建一个.well-known文件夹,里面也放一份这个文件,这样会先去根目录找,如果没找到还会去.well-known文件夹找

三、微信分享H5页面开发(本人用的是Vue2)

H5开发需要适配两个端:手机浏览器端和微信浏览器端

1、手机浏览器的适配比较简单,跳转APP采用Schema逻辑(iOS和安卓均可)。

H5
// 打开app 目前采用的方法 用于适配非微信端打开的网页跳转app并传参
openApp() {
const sendInfo = {
key: value
}
const schemaInfo = JSON.stringify(sendInfo)
const appScheme = 'yourSchema://yourshare域名/pagePath?schemaInfo=' + schemaInfo // 替换为你的 app 的 URL scheme
const fallbackUrl = '应用宝链接' // 替换为你的 app 在应用商店的链接 const u = navigator.userAgent
const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
if (isiOS) {
window.location.href = appScheme // ios对应的app协议
setTimeout(function () {
let hidden = window.document.hidden || window.document.mozHidden || window.document.msHidden || window.document.webkitHidden
if (typeof hidden === 'undefined' || hidden == false) {
// App store下载地址
window.location.href = fallbackUrl
}
}, 500)
} else {
window.location.href = appScheme // 安卓对应的app协议
setTimeout(function () {
let hidden = window.document.hidden || window.document.mozHidden || window.document.msHidden || window.document.webkitHidden
if (typeof hidden === 'undefined' || hidden == false) {
// 应用宝下载地址
window.location.href = fallbackUrl
}
}, 1500)
}
},

2、微信浏览器端的适配,需要使用微信的开放标签来处理H5和APP的跳转逻辑

微信开放标签:

1、绑定域名加入JS接口安全域名
登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
2、使用前需将「 JS 接口安全域名绑定的服务号」绑定在「移动应用的微信开放平台账号」下,并确保服务号与此开放平台账号同主体且均已认证。请前往 微信开放平台-管理中心-公众号详情-接口信息 设置域名与所需跳转的移动应用。
具体流程参考这篇说明文档:

https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_H5_Launch_APP.html

3、根据开发文档开发适配微信端网页开放标签,具体流程参考这篇文档:

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_Open_Tag.html

注意:
1、安全角度考虑,下面这段所需的参数从服务器接口获取,不要放前端
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [], // 必填,需要使用的JS接口列表
openTagList: [] // 可选,需要使用的开放标签列表,例如['wx-open-launch-app']
});
2、网页的域名和审核通过的js安全域名Host完全一致 + 第一点里面的config初始化成功 + 要在微信里面打开此网页 = 能显示微信开放标签里的内容且点击能跳转到APP,缺一不可
3、开放标签里放不了本地的图,本地的图可以上传到oss上生成链接的形式展示
<wx-open-launch-app
v-if="iswx"
id="launch-btn"
style="width:100%; position: relative; display: flex; flex-direction: row; align-items: center; justify-content: center;height: 44px; background-color: #F7F8FA"
:extinfo="getSchemaInfo"
appid="yourWxAppId"
@error="handleError"
@launch="handleLaunch"
>
<component is="script" type="text/wxtag-template">
<div style="position: relative; display: flex; flex-direction: row; align-items: center; justify-content: center; height: 44px"
@click="onButtonClick">
<div style="font-size: 14px; font-weight: 400; color: #388BFF; line-height: 20px; text-align: center">固定在底部的条条</div>
<img style="width: 14px; height: 14px; margin-left: 4px;" src="https://yourResources.oss-cn-hangzhou.aliyuncs.com/yourPic.png" alt="">
</div>
</component>
</wx-open-launch-app>
4、开放标签里不能使用postion为fixed和absolute的样式,无效,如果需要可以在开放标签里设置style,加fixed或absolute

参考5里面的代码

5、一个取巧的办法是开放标签可以是透明的盖住普通浏览器样式的页面组件,实现微信端点击跳转APP且无需适配开放标签里面的样式
<wx-open-launch-app
v-if="iswx"
id="launch-btn"
style="max-width: 100%; height: 68px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #F1F2F4; position: fixed; top: 0; left: 0; right: 0; width: 100%; margin: auto; z-index: 99;"
@error="handleError"
@launch="handleLaunch"
:extinfo="getSchemaInfo"
appid="yourWxAppId"
>
<script type="text/wxtag-template">
<div style="opacity: 0; width: 100%; height: 68px;"></div>
</script>
</wx-open-launch-app>
6 也可以根据网页是否在微信里打开的来进一步适配浏览器和微信的页面

如上的代码里有个iswx

let ua = window.navigator.userAgent.toLowerCase()
// 通过正则表达式匹配ua中是否含有MicroMessenger字符串
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
this.iswx = true
} else {
this.iswx = false
}

四、客户端处理跳转逻辑

参考开发文档

1、安卓部分 - 浏览器通过schema跳转

安卓 MainActivity.java文件里
  @Override
public void onNewIntent(Intent intent){
super.onNewIntent(intent);
setIntent(intent);
} @Override
protected void onResume() {
super.onResume();
Intent intent = getIntent(); if (!intentHex.equals("") && intentHex.equals(Integer.toHexString(System.identityHashCode(intent)))) {
// 获取 scheme 名称 重复的intent 不予处理
} else {
intentHex = Integer.toHexString(System.identityHashCode(intent));
String scheme = intent.getScheme();
Uri uri = intent.getData();
if(scheme!= null && uri != null) {
if (uri.getScheme().equals("yourSchema")) {
String schemaInfo = uri.getQueryParameter("schemaInfo");
try {
// 原生的可以处理跳转逻辑,ReactNative的这里可以发送到RN端
MainApplication application = (MainApplication) this.getApplicationContext(); WritableMap map = Arguments.createMap();
map.putString("schemaInfo", schemaInfo); ReactInstanceManager reactInstanceManager = application.getReactNativeHost().getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if(reactContext != null) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("Demo_EmitterKey", map);
} else {
reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext context) { Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
/**
*要执行的操作
*/ context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("Demo_EmitterKey", map);
}
}, 4000);//4秒后执行Runnable中的run方法 reactInstanceManager.removeReactInstanceEventListener(this); }
});
} } catch (SecurityException e) { // TODO: Display a yellow box about this
} }
}
} }

安卓部分 - 微信页面通过开放标签跳转

WXEntryActivity文件里

/**
* 从微信启动App
*
* @param req
*/
@Override
public void onReq(BaseReq req) {
super.onReq(req); //获取开放标签传递的extinfo数据逻辑
try {
if (req.getType() == ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX && req instanceof ShowMessageFromWX.Req) {
ShowMessageFromWX.Req showReq = (ShowMessageFromWX.Req) req;
WXMediaMessage mediaMsg = showReq.message;
String extInfo = mediaMsg.messageExt;
// 原生这里已经可以处理跳转逻辑了
}
} catch (Exception e) {
e.printStackTrace();
} }

2、iOS部分 - 浏览器通过schema跳转

参考这篇帖子

iOS AppDelete.mm文件里
// 支持所有iOS系统
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url sourceApplication:sourceApplication annotation:annotation];
if (!result) {
// 其他如支付等SDK的回调
} //开启SDK Log
[WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString *log) {
NSLog(@"WeChatSDK: %@", log);
}]; // 在调用WXApi的handle方法前,须先调用registerApp注册。ret为注册结果,若注册失败,请根据sdk的log排查原因
BOOL ret = [WXApi registerApp:@"微信的AppID" universalLink:@"https://your域名/app/"]; if ([WXApi handleOpenURL:url delegate:self]) {
/// handled by OpenSDK
} // 上面做了微信开放标签的适配 if ([[url scheme] isEqualToString:@"yourSchema"]) {
NSString *inputString = [url query];
// 找到等号的位置
NSUInteger equalSignIndex = [inputString rangeOfString:@"="].location;
if (equalSignIndex != NSNotFound) {
// 提取等号后面的字符串
NSString *schemaInfo = [inputString substringFromIndex:equalSignIndex + 1]; NSLog(@"schemaInfo: %@", schemaInfo); if (![schemaInfo isEqualToString:@""]) {
NSDictionary *schemaInfoDic = @{@"schemaInfo":schemaInfo}; //这里原生的就可以跳转了,ReactNative的则把消息全部转给JS
NSMutableDictionary *mutableDic = [NSMutableDictionary dictionaryWithDictionary:schemaInfoDic]; //把消息全部转给JS
[[NSNotificationCenter defaultCenter] postNotificationName:@"SendSchemaInfoToRN" object:mutableDic?mutableDic:@{}];
} else {
NSLog(@"empty schemaInfo");
}
} else {
NSLog(@"No '=' found.");
}
} return result;
} - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options
{
BOOL result = [[UMSocialManager defaultManager] handleOpenURL:url options:options];
if (!result) {
// 其他如支付等SDK的回调
} //开启SDK Log
[WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString *log) {
NSLog(@"WeChatSDK: %@", log);
}]; // 在调用WXApi的handle方法前,须先调用registerApp注册。ret为注册结果,若注册失败,请根据sdk的log排查原因
BOOL ret = [WXApi registerApp:@"微信的Appid" universalLink:@"https://your域名/app/"]; if ([WXApi handleOpenURL:url delegate:self]) {
/// handled by OpenSDK
} // 上面做了微信开放标签的适配 if ([[url scheme] isEqualToString:@"yourSchema"]) {
NSString *inputString = [url query];
// 找到等号的位置
NSUInteger equalSignIndex = [inputString rangeOfString:@"="].location;
if (equalSignIndex != NSNotFound) {
// 提取等号后面的字符串
NSString *schemaInfo = [inputString substringFromIndex:equalSignIndex + 1]; NSLog(@"schemaInfo: %@", schemaInfo); if (![schemaInfo isEqualToString:@""]) {
NSDictionary *schemaInfoDic = @{@"schemaInfo":schemaInfo}; //这里原生的就可以跳转了,ReactNative的则把消息全部转给JS
NSMutableDictionary *mutableDic = [NSMutableDictionary dictionaryWithDictionary:schemaInfoDic]; //把消息全部转给JS
[[NSNotificationCenter defaultCenter] postNotificationName:@"SendSchemaInfoToRN" object:mutableDic?mutableDic:@{}];
} else {
NSLog(@"empty schemaInfo.");
}
} else {
NSLog(@"No '=' found.");
}
} return result;
}

iOS部分 - 微信页面通过开放标签跳转

在通过Schema跳转的代码基础上,加上下面这段

- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray * __nullable restorableObjects))restorationHandler
{
if (![[UMSocialManager defaultManager] handleUniversalLink:userActivity options:nil]) {
// 其他SDK的回调
NSLog ( @"其他SDK的回调11");
}
NSLog ( @"其他SDK的回调22"); //开启SDK Log
[WXApi startLogByLevel:WXLogLevelDetail logBlock:^(NSString *log) {
NSLog(@"WeChatSDK: %@", log);
}]; // 在调用WXApi的handle方法前,须先调用registerApp注册。ret为注册结果,若注册失败,请根据sdk的log排查原因
BOOL ret = [WXApi registerApp:@"微信的Appid" universalLink:@"https://your域名/app/"];
if ([WXApi handleOpenUniversalLink:userActivity delegate:self]) {
/// handled by OpenSDK
} // 触发回调方法
[RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
NSURL *url = userActivity.webpageURL;
if (url && [TencentOAuth CanHandleUniversalLink:url]) {
return [TencentOAuth HandleUniversalLink:url];
} return YES;
} -(void) onReq:(BaseReq*)req
{
if([req isKindOfClass:[GetMessageFromWXReq class]])
{
// 微信请求App提供内容, 需要app提供内容后使用sendRsp返回
NSString *strTitle = [NSString stringWithFormat:@"微信请求App提供内容"];
NSString *strMsg = @"微信请求App提供内容,App要调用sendResp:GetMessageFromWXResp返回给微信"; }
else if([req isKindOfClass:[ShowMessageFromWXReq class]])
{
ShowMessageFromWXReq* temp = (ShowMessageFromWXReq*)req;
WXMediaMessage *msg = temp.message; //显示微信传过来的内容
WXAppExtendObject *obj = msg.mediaObject; NSString *strTitle = [NSString stringWithFormat:@"微信请求App显示内容"];
NSString *strMsg = [NSString stringWithFormat:@"标题:%@ \n内容:%@ \n附带信息:%@ \n缩略图:%u bytes\n\n", msg.title, msg.description, obj.extInfo, msg.thumbData.length]; }
else if([req isKindOfClass:[LaunchFromWXReq class]])
{
//从微信启动App
LaunchFromWXReq* temp = (LaunchFromWXReq*)req;
WXMediaMessage *msg = temp.message; NSLog ( @"req:%@", msg.messageExt); NSDictionary *schemaInfoDic = @{@"schemaInfo":msg.messageExt}; //把消息全部转给JS
NSMutableDictionary *mutableDic = [NSMutableDictionary dictionaryWithDictionary:schemaInfoDic]; NSLog(@"Schema 收到微信回调参数 #####%@",mutableDic); //把消息全部转给JS
[[NSNotificationCenter defaultCenter] postNotificationName:@"SendSchemaInfoToRN" object:mutableDic?mutableDic:@{}];
}
}

3、ReactNative的特殊处理

ReactNative在获取到浏览器或者微信传来的ScehmaInfo后,发送消息到JS的操作在前面的代码里都写进去了,可以看对应的注释。
安卓由于ReactNative就一个MainActivity,拿到微信传过来的数据后还需要特殊处理。

WXEntryActivity文件里

/**
* 从微信启动App
*
* @param req
*/
@Override
public void onReq(BaseReq req) {
super.onReq(req); //获取开放标签传递的extinfo数据逻辑
try {
if (req.getType() == ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX && req instanceof ShowMessageFromWX.Req) {
ShowMessageFromWX.Req showReq = (ShowMessageFromWX.Req) req;
WXMediaMessage mediaMsg = showReq.message;
String extInfo = mediaMsg.messageExt; // 原生这里已经可以处理跳转逻辑了,ReactNative需要特殊处理下,判断MainActivity是否存在,也就是说APP是否处于杀死状态 if (ActivityUtils.isActivityExistsInStack(MainActivity.class)) {
// 发送到RN端
MainApplication application = (MainApplication) this.getApplicationContext(); WritableMap map = Arguments.createMap();
map.putString("schemaInfo", extInfo); ReactInstanceManager reactInstanceManager = application.getReactNativeHost().getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); if (reactContext != null) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("Demo_EmitterKey", map);
} else {
reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext context) { Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
/**
*要执行的操作
*/
context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("Demo_EmitterKey", map);
}
}, 4000);//4秒后执行Runnable中的run方法
reactInstanceManager.removeReactInstanceEventListener(this); }
});
}
} else {
// 如果APP处于启动状态,则到MainActivity里处理逻辑
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("keySendToMainActivity", extInfo);
startActivity(intent);
}
}
} catch (Exception e) {
e.printStackTrace();
} }

MainActivity文件里

@Override
protected void onCreate(Bundle savedInstanceState) {
MainApplication.getInstance().setMainActivity(this);
super.onCreate(null); ... // 这里加上这些内容
if (getIntent().getStringExtra("keySendToMainActivity") != null && !"".equals(getIntent().getStringExtra("keySendToMainActivity"))) {
// 发送到RN端
MainApplication application = (MainApplication) this.getApplicationContext(); WritableMap map = Arguments.createMap();
map.putString("schemaInfo", getIntent().getStringExtra("keySendToMainActivity")); ReactInstanceManager reactInstanceManager = application.getReactNativeHost().getReactInstanceManager();
ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); if(reactContext != null) {
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("Demo_EmitterKey", map);
} else {
reactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext context) { Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
/**
*要执行的操作
*/ context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("Demo_EmitterKey", map);
}
}, 4000);//4秒后执行Runnable中的run方法
reactInstanceManager.removeReactInstanceEventListener(this);
}
});
}
}
}

版权声明:

转载时请注明作者Kovli以及本文地址:

http://www.kovli.com/2024/12/18/wx-share/


微信分享前端开发全程详解含iOS、安卓、H5、ReactNative以及微信开放标签的适配和使用的更多相关文章

  1. IOS开发之----详解在IOS后台执行

    文一 我从苹果文档中得知,一般的应用在进入后台的时候可以获取一定时间来运行相关任务,也就是说可以在后台运行一小段时间. 还有三种类型的可以运行在后以,1.音乐2.location 3.voip 文二 ...

  2. 微信小程序开发之详解生命周期方法

    生命周期是指一个小程序从创建到销毁的一系列过程 在小程序中 ,通过App()来注册一个小程序 ,通过Page()来注册一个页面 先来看一张小程序项目结构 从上图可以看出,根目录下面有包含了app.js ...

  3. Extjs MVC开发模式详解

    Extjs MVC开发模式详解   在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开发模式, ...

  4. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)

    最近新浪.百度.腾讯.京东.大众点评.淘宝等流行的网站都加大了招聘HTML5的力度,HTML5开发人员成了抢手货,本次连载的是由大众点评前端工程师和一淘网前端工程师基情奉献的<HTML5网页开发 ...

  5. 当里个当,免费的HTML5连载来了《HTML5网页开发实例详解》连载(一)

    读懂<HTML5网页开发实例详解>这本书 你还在用Flash嘛?帮主早不用了 乔布斯生前在公开信“Flash之我见”中预言:像HTML 5这样在移动时代中创立的新标准,将会在移动设备上获得 ...

  6. ubuntu apache2配置详解(含虚拟主机配置方法)

    ubuntu apache2配置详解(含虚拟主机配置方法) 在Windows下,Apache的配置文件通常只有一个,就是httpd.conf.但我在Ubuntu Linux上用apt-get inst ...

  7. ext.js的mvc开发模式详解

    ext.js的mvc开发模式详解和环境配置 在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开 ...

  8. 《Android NFC 开发实战详解 》简介+源码+样章+勘误ING

    <Android NFC 开发实战详解>简介+源码+样章+勘误ING SkySeraph Mar. 14th  2014 Email:skyseraph00@163.com 更多精彩请直接 ...

  9. C++的性能C#的产能?! - .Net Native 系列《二》:.NET Native开发流程详解

    之前一文<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATIVE初窥> 获得很多朋友支持和鼓励,也更让我坚定做这项技术的推广者,希望能让更多的朋友了解这项技术,于是先从官方 ...

  10. Cocos2d-x 3.X手游开发实例详解

    Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...

随机推荐

  1. httpclient 连接池测试

    为什么需要使用http连接池 1.降低延迟:如果不采用连接池,每次连接发起Http请求的时候都会重新建立TCP连接(经历3次握手),用完就会关闭连接(4次挥手),如果采用连接池则减少了这部分时间损耗, ...

  2. 限流中间件IpRateLimitMiddleware的使用

    前言 IpRateLimitMiddleware(Github: AspNetCoreRateLimit) 是ASPNETCore的一个限流的中间件,用于控制客户端调用API的频次, 如果客户端频繁访 ...

  3. 使用Maps SDK添加本地slpk

    SceneView m_sceneView; public void LoadSceneLayerFromSLPK(SceneView sceneView, string slpkPath) { if ...

  4. axmapcontrol的一点发现

    最近在做一个功能,从主窗体弹出子窗体(包含地图控件)显示地图.不过初始化的过程比较耗时(主要是连接远程数据),所以想改变鼠标样式为等待.本来是比较简单的思路 A:主窗体,B:子窗体 a.cursor= ...

  5. 微信开发者工具请求接口 Provisional headers are shown

    前情 最近全权负责公司小程序项目的开发,使用的uniapp技术栈. 坑 在和服务端联调的时候发现,接口pending很久,而且时不时的报Provisional headers are shown,而且 ...

  6. cajviewer逆向分析与漏洞挖掘

    文章首发于 https://mp.weixin.qq.com/s/7STPL-2nCUKC3LHozN6-zg 前言 CAJViewer是一个论文查看工具,主要用于查看caj文件格式的论文.本文介绍对 ...

  7. sqlserver配置分发实现主备

    方案总体说明 本方案采用"发布-订阅模式" 由主服务器进行发布消息,备份服务器进行订阅 当主服务器数据发生变更时,就会发布消息,备份服务器读取消息进行同步更新,中间过程延迟比较短. ...

  8. Centos更改SSH端口的方法

    1,vi sshd vi /etc/ssh/sshd_config 2,添加PORT #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress ...

  9. Python中构建全局字典的详细指南

    在Python编程中,全局变量是指在整个程序运行期间都可以访问的变量.全局字典作为一种特殊的全局变量,可以存储各种类型的数据,包括字符串.数字.列表.元组等,这使得它在数据管理和跨模块通信方面非常有用 ...

  10. Jetpack Compose学习(15)——Pager组件的使用(对标ViewPager)

    原文地址: Jetpack Compose学习(15)--Pager组件的使用(对标ViewPager)-Stars-One的杂货小窝 从名字可以看出,Pager这个就是ViewPager的替代产物 ...