微信分享前端开发全程详解含iOS、安卓、H5、ReactNative以及微信开放标签的适配和使用
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以及微信开放标签的适配和使用的更多相关文章
- IOS开发之----详解在IOS后台执行
文一 我从苹果文档中得知,一般的应用在进入后台的时候可以获取一定时间来运行相关任务,也就是说可以在后台运行一小段时间. 还有三种类型的可以运行在后以,1.音乐2.location 3.voip 文二 ...
- 微信小程序开发之详解生命周期方法
生命周期是指一个小程序从创建到销毁的一系列过程 在小程序中 ,通过App()来注册一个小程序 ,通过Page()来注册一个页面 先来看一张小程序项目结构 从上图可以看出,根目录下面有包含了app.js ...
- Extjs MVC开发模式详解
Extjs MVC开发模式详解 在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开发模式, ...
- 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)
最近新浪.百度.腾讯.京东.大众点评.淘宝等流行的网站都加大了招聘HTML5的力度,HTML5开发人员成了抢手货,本次连载的是由大众点评前端工程师和一淘网前端工程师基情奉献的<HTML5网页开发 ...
- 当里个当,免费的HTML5连载来了《HTML5网页开发实例详解》连载(一)
读懂<HTML5网页开发实例详解>这本书 你还在用Flash嘛?帮主早不用了 乔布斯生前在公开信“Flash之我见”中预言:像HTML 5这样在移动时代中创立的新标准,将会在移动设备上获得 ...
- ubuntu apache2配置详解(含虚拟主机配置方法)
ubuntu apache2配置详解(含虚拟主机配置方法) 在Windows下,Apache的配置文件通常只有一个,就是httpd.conf.但我在Ubuntu Linux上用apt-get inst ...
- ext.js的mvc开发模式详解
ext.js的mvc开发模式详解和环境配置 在JS的开发过程中,大规模的JS脚本难以组织和维护,这一直是困扰前端开发人员的头等问题.Extjs为了解决这种问题,在Extjs 4.x版本中引入了MVC开 ...
- 《Android NFC 开发实战详解 》简介+源码+样章+勘误ING
<Android NFC 开发实战详解>简介+源码+样章+勘误ING SkySeraph Mar. 14th 2014 Email:skyseraph00@163.com 更多精彩请直接 ...
- C++的性能C#的产能?! - .Net Native 系列《二》:.NET Native开发流程详解
之前一文<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATIVE初窥> 获得很多朋友支持和鼓励,也更让我坚定做这项技术的推广者,希望能让更多的朋友了解这项技术,于是先从官方 ...
- Cocos2d-x 3.X手游开发实例详解
Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...
随机推荐
- 斐波那契数列(Java实现)
斐波那契数列 题目描述: 悲波那契数列(Fibonacci sequence)又称黄金分割数列,因数学家莱昂纳多·裴波那契(LeonardodaFibonacci)以兔子繁殖为例子而引入,故又称为&q ...
- 数据分层 ODS DW DM层级
在数据仓库的设计过程中,数据分层是一种重要的组织方式,能够提高数据处理效率和数据质量.数据分层通常包括原始数据(Operational Data Store,ODS).明细数据(Data Wareho ...
- 在 MySQL 创造类似 PipelineDB 的流视图(continuous view)
公司的系统采用的是 Google Cloud SQL 提供的 MySQL 数据库,由于历史原因,数据库成本极高,需要对它进行优化缩减成本. 相比 PostgresSQL,MySQL 主要缺少以下特性, ...
- 【Java】关于Maven仓库地址
仓库 如果你没有配置阿里云仓库镜像源,可以到这里来找 https://mvnrepository.com/ 如果你配置了阿里云仓库镜像源,可以来这里找 https://developer.aliyun ...
- 【Python】【爬虫】【爬狼】002_自定义获取网页源码的函数
在上一篇笔记([Python][爬虫系列][爬狼]001_urllib_get_获取响应结果页面代码 - 萌狼蓝天 - 博客园 (cnblogs.com/mllt))我们将一个网页,解析为了文档(源码 ...
- Java保留两位小数的几种写法总结
转载 本文列举了几个方法: 1. 使用java.math.BigDecimal 2. 使用java.text.DecimalFormat 3. 使用java.text.NumberFormat 4. ...
- 【杂谈】Kafka 消息偏移量:如何高效地定位和管理消息?
前言 在 Kafka 中,消息偏移量是什么?是文件中的索引吗?又是如何通过偏移量快速定位消息的?本文将深入探讨这些问题,帮助你更好地理解 Kafka 的偏移量机制. Kafka 的偏移量是什么? Ka ...
- 抖音技术分享:飞鸽IM桌面端基于Rust语言进行重构的技术选型和实践总结
本文由ELab团队公众号授权发布,原题<Rust语言在IM客户端的实践>,来自抖音电商前端团队的分享,本文有修订和改动. 1.引言 本文将介绍飞鸽IM前端团队如何结合Rust对飞鸽客户端接 ...
- 微信小游戏直播在Android端的跨进程渲染推流实践
本文由微信开发团队工程师"virwu"分享. 1.引言 近期,微信小游戏支持了视频号一键开播,将微信升级到最新版本,打开腾讯系小游戏(如跳一跳.欢乐斗地主等),在右上角菜单就可以看 ...
- 【漏洞分析】20250105-SorraStaking:奖励金额计算错误,每次取款都有大收益
背景信息 2024-12-21 11:58:11 (UTC) 准备交易:https://app.blocksec.com/explorer/tx/eth/0x72a252277e30ea6a37d2d ...