华为HarmonyOS打造开放、合规的广告生态 - 激励广告

场景介绍

激励广告是一种全屏幕的视频广告,用户可以选择点击观看,以换取相应奖励。

接口说明

接口名

描述

loadAd(adParam: AdRequestParams, adOptions: AdOptions, listener: AdLoadListener): void

请求单广告位广告,通过AdRequestParams、AdOptions进行广告请求参数设置,通过AdLoadListener监听广告请求回调。

showAd(ad: Advertisement, options: AdDisplayOptions, context?: common.UIAbilityContext): void

展示广告,通过AdDisplayOptions进行广告展示参数设置。

开发步骤

  1. 获取OAID。

    如果想要为用户更精准的推送广告,可以在请求参数AdRequestParams中添加oaid属性。

    如何获取OAID参见获取OAID信息。

    说明

    使用以下示例中提供的测试广告位必须先获取OAID信息。

  2. 请求单广告位广告。

    需要先创建一个AdLoader对象,通过AdLoader的loadAd方法请求广告,最后通过AdLoadListener,来监听广告的加载状态。

    请求广告关键参数如下所示:

    请求广告参数名

    类型

    必填

    说明

    adType

    number

    请求广告类型,激励广告类型为7。

    adId

    string

    广告位ID。

    • 如果仅调测广告,可使用测试广告位ID:testx9dtjwj8hp。
    • 如果要接入正式广告,则需要申请正式的广告位ID。可在应用发布前进入流量变现官网,点击“开始变现”,登录鲸鸿动能媒体服务平台进行申请,具体操作详情请参见展示位创建。

    oaid

    string

    开放匿名设备标识符,用于精准推送广告。不填无法获取到个性化广告。

    示例代码如下所示:
     
    1. import { advertising, identifier } from '@kit.AdsKit';
    2. import { common } from '@kit.AbilityKit';
    3. import { hilog } from '@kit.PerformanceAnalysisKit';
    4. import { BusinessError } from '@kit.BasicServicesKit';
    5. @Entry
    6. @Component
    7. struct Index {
    8. private ads: Array<advertising.Advertisement> = [];
    9. private context = getContext(this) as common.UIAbilityContext;
    10. private oaid: string = '';
    11. aboutToAppear() {
    12. try {
    13. // 使用Promise回调方式获取OAID
    14. identifier.getOAID().then((data: string) => {
    15. this.oaid = data;
    16. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in getting adsIdentifierInfo by promise');
    17. }).catch((error: BusinessError) => {
    18. hilog.error(0x0000, 'testTag', '%{public}s', `Failed to get adsIdentifierInfo, message: ${error.message}`);
    19. })
    20. } catch (error) {
    21. hilog.error(0x0000, 'testTag', '%{public}s', `Catch err, code: ${error.code}, message: ${error.message}`);
    22. }
    23. }
    24. build() {
    25. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
    26. Row() {
    27. Button('requestAd').onClick(() => {
    28. let load: advertising.AdLoader = new advertising.AdLoader(this.context);
    29. this.requestAd(load);
    30. }).width('45%')
    31. }
    32. }
    33. }
    34. private requestAd(adLoader: advertising.AdLoader): void {
    35. const adRequestParam: advertising.AdRequestParams = {
    36. // 广告类型:激励广告
    37. adType: 7,
    38. // 'testx9dtjwj8hp'为测试专用的广告位ID,App正式发布时需要改为正式的广告位ID
    39. adId: 'testx9dtjwj8hp',
    40. // 开放匿名设备标识符
    41. oaid: this.oaid
    42. };
    43. const adOption: advertising.AdOptions = {
    44. // 设置是否请求非个性化广告
    45. nonPersonalizedAd: 0,
    46. // 是否允许流量下载0:不允许,1:允许,不设置以广告主设置为准
    47. allowMobileTraffic: 0,
    48. // 是否希望根据 COPPA 的规定将您的内容视为面向儿童的内容: -1默认值,不确定 0不希望 1希望
    49. tagForChildProtection: -1,
    50. // 是否希望按适合未达到法定承诺年龄的欧洲经济区 (EEA) 用户的方式处理该广告请求: -1默认值,不确定 0不希望 1希望
    51. tagForUnderAgeOfPromise: -1,
    52. // 设置广告内容分级上限: W: 3+,所有受众 PI: 7+,家长指导 J:12+,青少年 A: 16+/18+,成人受众
    53. adContentClassification: 'A'
    54. };
    55. const adLoaderListener: advertising.AdLoadListener = {
    56. onAdLoadFailure: (errorCode: number, errorMsg: string) => {
    57. hilog.error(0x0000, 'testTag', '%{public}s',
    58. `Failed to request ad, message: ${errorMsg}, error code: ${errorCode}`);
    59. },
    60. onAdLoadSuccess: (ads: Array<advertising.Advertisement>) => {
    61. hilog.info(0x0000, 'testTag', '%{public}s', `Succeeded in requesting ad`);
    62. this.ads.push(...ads);
    63. },
    64. };
    65. adLoader.loadAd(adRequestParam, adOption, adLoaderListener);
    66. }
    67. }

  3. 事件订阅。

    开发者需要在App中订阅com.huawei.hms.pps.action.PPS_REWARD_STATUS_CHANGED事件来监听激励广告页面变化并接收奖励信息。示例代码中的订阅方法registerPPSReceiver()需要在每次展示广告前调用 。

    在订阅到公共事件后,可以从CommonEventData的parameters参数中使用"reward_ad_status"作为key值获取激励广告页面变化状态,使用"reward_ad_data"作为key值获取奖励信息,属性rewardType用来获取奖励物品的名称,rewardAmount用来获取奖励物品的数量。

    示例代码如下所示:

     
    1. import { commonEventManager, BusinessError } from '@kit.BasicServicesKit';
    2. import { hilog } from '@kit.PerformanceAnalysisKit';
    3. const KEY_REWARD_DATA = "reward_ad_data";
    4. const KEY_REWARD_STATUS = "reward_ad_status";
    5. export class RewardAdStatusHandler {
    6. // 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
    7. private subscriber: commonEventManager.CommonEventSubscriber | null = null;
    8. // 订阅方法,需要在每次展示广告前调用
    9. public registerPPSReceiver(): void {
    10. if (this.subscriber) {
    11. this.unRegisterPPSReceiver();
    12. }
    13. // 订阅者信息
    14. const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
    15. events: ['com.huawei.hms.pps.action.PPS_REWARD_STATUS_CHANGED'],
    16. // publisherBundleName被设置为"com.huawei.hms.adsservice",这意味着只有来自该包名的事件才会被订阅者接受和处理。
    17. // 如果没有明确声明publisherBundleName,那么订阅者可能会收到来自其它包名的伪造事件,从而导致安全性问题或误导。
    18. publisherBundleName: 'com.huawei.hms.adsservice'
    19. };
    20. // 创建订阅者回调
    21. commonEventManager.createSubscriber(subscribeInfo, (err: BusinessError, commonEventSubscriber:
    22. commonEventManager.CommonEventSubscriber) => {
    23. if (err) {
    24. hilog.error(0x0000, 'testTag', '%{public}s',
    25. `createSubscriber error, code: ${err.code}, message: ${err.message}`);
    26. return;
    27. }
    28. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in creating subscriber');
    29. this.subscriber = commonEventSubscriber;
    30. // 订阅公共事件回调
    31. if (!this.subscriber) {
    32. hilog.warn(0x0000, 'testTag', '%{public}s', 'Need create subscriber');
    33. return;
    34. }
    35. commonEventManager.subscribe(this.subscriber, (err: BusinessError, commonEventSubscriber:
    36. commonEventManager.CommonEventData) => {
    37. if (err) {
    38. hilog.error(0x0000, 'testTag', '%{public}s', `Subscribe error, code: ${err.code}, message: ${err.message}`);
    39. } else {
    40. hilog.info(0x0000, 'testTag', '%{public}s', 'Subscribe data');
    41. const status: string = commonEventSubscriber?.parameters?.[KEY_REWARD_STATUS];
    42. switch (status) {
    43. case AdStatus.AD_OPEN:
    44. hilog.info(0x0000, 'testTag', '%{public}s', 'onAdOpen');
    45. break;
    46. case AdStatus.AD_CLICKED:
    47. hilog.info(0x0000, 'testTag', '%{public}s', 'onAdClick');
    48. break;
    49. case AdStatus.AD_CLOSED:
    50. hilog.info(0x0000, 'testTag', '%{public}s', 'onAdClose');
    51. this.unRegisterPPSReceiver();
    52. break;
    53. case AdStatus.AD_REWARDED:
    54. const rewardData: Record<string, string | number> = commonEventSubscriber?.parameters?.[KEY_REWARD_DATA];
    55. const rewardType: string = rewardData?.rewardType as string;
    56. const rewardAmount: number = rewardData?.rewardAmount as number;
    57. hilog.info(0x0000, 'testTag', '%{public}s',
    58. `onAdReward, rewardType: ${rewardType}, rewardAmount: ${rewardAmount}`);
    59. break;
    60. case AdStatus.AD_VIDEO_START:
    61. hilog.info(0x0000, 'testTag', '%{public}s', 'onAdVideoStart');
    62. break;
    63. case AdStatus.AD_COMPLETED:
    64. hilog.info(0x0000, 'testTag', '%{public}s', 'onAdCompleted');
    65. break;
    66. default:
    67. break;
    68. }
    69. }
    70. });
    71. });
    72. }
    73. // 取消订阅
    74. public unRegisterPPSReceiver(): void {
    75. commonEventManager.unsubscribe(this.subscriber, (err: BusinessError) => {
    76. if (err) {
    77. hilog.error(0x0000, 'testTag', '%{public}s', `Unsubscribe error, code: ${err.code}, message: ${err.message}`);
    78. } else {
    79. hilog.info(0x0000, 'testTag', '%{public}s', 'Succeeded in unsubscribing');
    80. this.subscriber = null;
    81. }
    82. });
    83. }
    84. }
    85. enum AdStatus {
    86. AD_OPEN = 'onAdOpen',
    87. AD_CLICKED = 'onAdClick',
    88. AD_CLOSED = 'onAdClose',
    89. AD_REWARDED = 'onAdReward',
    90. AD_VIDEO_START = 'onVideoPlayBegin',
    91. AD_COMPLETED = 'onVideoPlayEnd'
    92. }

  4. 展示广告。

    ads为步骤2请求到的广告信息,调用showAd方法来展示广告。示例代码如下所示:
     
    1. import { advertising } from '@kit.AdsKit';
    2. import { common } from '@kit.AbilityKit';
    3. @Entry
    4. @Component
    5. struct Index {
    6. private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
    7. // 步骤2中请求到的广告内容
    8. private ads: Array<advertising.Advertisement> = [];
    9. private displayOptions: advertising.AdDisplayOptions = {
    10. // 激励广告视频播放是否静音
    11. mute: true
    12. };
    13. build() {
    14. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
    15. Row() {
    16. Button('showAd').onClick(() => {
    17. this.showAd();
    18. }).width('45%')
    19. }
    20. }
    21. }
    22. private showAd() {
    23. let load: advertising.AdLoader = new advertising.AdLoader(this.context);
    24. // 此处ads[0]表示请求到的第一个广告,用户根据实际情况选择
    25. advertising.showAd(this.ads[0], this.displayOptions, this.context);
    26. }
    27. }

校验激励广告服务端验证回调

服务端验证回调是指鲸鸿动能平台发送给媒体服务器的网址请求,其中带有特定的查询参数,用来通知媒体服务器某位用户因为与激励视频广告互动而应予以奖励,从而规避欺骗的行为。

奖励用户

  • 在给用户发奖励时,要把握好用户体验和奖励验证之间的平衡。由于服务器端回调会存在延迟的情况,因此我们建议客户端立即奖励用户,同时在收到服务器端回调时对所有奖励进行验证。这种做法可确保奖励符合发放条件,同时提供良好的用户体验。
  • 对于某些应用而言,奖励是否达到发放条件非常重要,用户可适当接受延迟。这时,推荐做法是等待服务器端回调完成验证,再向用户发放奖励。

校验服务端验证回调

说明

App上架至华为应用市场(AppGallery)时间超过12小时才可以收到回调。

  1. 设置激励广告的奖励配置。

    您在鲸鸿动能媒体服务平台上申请激励视频广告位时选择“媒体管理(点击媒体名)> 新增展示位 > 选择激励视频(点击下一步,进入编辑页面)”,设置奖励类型和奖励数量,并点击“高级设置”,设置服务器端验证的URL。如下图:

  2. (可选)设置自定义数据customData和userId。

    ads为步骤2请求到的广告信息,调用showAd方法来展示广告。

    您在App中展示激励广告之前设置自定义数据customData和userId。示例代码如下所示:

     
    1. import { advertising } from '@kit.AdsKit';
    2. import { common } from '@kit.AbilityKit';
    3. @Entry
    4. @Component
    5. struct Index {
    6. private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;
    7. // 步骤2中请求到的广告内容
    8. private ads: Array<advertising.Advertisement> = [];
    9. private displayOptions: advertising.AdDisplayOptions = {
    10. // 激励广告视频播放是否静音
    11. mute: true,
    12. // 设置自定义数据
    13. customData: 'CUSTOM_DATA',
    14. // 设置自定义数据
    15. userId: '1234567'
    16. };
    17. build() {
    18. Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
    19. Row() {
    20. Button('showAd').onClick(() => {
    21. this.showAd();
    22. }).width('45%')
    23. }
    24. }
    25. }
    26. private showAd() {
    27. let load: advertising.AdLoader = new advertising.AdLoader(this.context);
    28. // 此处ads[0]表示请求到的第一个广告,用户根据实际情况选择
    29. advertising.showAd(this.ads[0], this.displayOptions, this.context);
    30. }
    31. }

    说明

    如果没有设置customData和userId,不影响发放奖励事件上报但是服务端验证的参数中没有这两个字段。如果设置customData和userId,必须在展示广告之前设置并且URLEncode之后,长度不超过1024个字符,否则影响服务端验证。

  3. 获取要验证的内容。

    用户观看完激励广告时,鲸鸿动能平台服务端会把需要验证的参数以及keyId和sign传给媒体提供的URL:https://www.example.com/feedback(即步骤1中配置的验证URL)。请求体样例:

     
    1. {
    2. "adId" : "testx9dtjwj8hp",
    3. "data" : "CUSTOM_DATA",
    4. "keyId" : "12345678",
    5. "rewardAmount" : "10",
    6. "rewardName" : "金币",
    7. "sign" : "OA33u6mypnhE4hbmF32N/ibYi1uXt72nDDyYMwjDI6JXVVFKePZYo4F7Fuk2MaG......",
    8. "uniqueId" : "3361626337333932313435313430373438383561376265636130393939313166",
    9. "userId" : "1234567"
    10. }

    服务器端验证回调查询参数说明:

    参数名称

    类型

    是否必选

    描述

    adId

    String

    激励视频广告位ID

    data

    String

    自定义数据字符串

    keyId

    String

    验证回调的密钥

    rewardAmount

    String

    奖励数量

    rewardName

    String

    奖励奖品

    sign

    String

    回调的签名

    uniqueId

    String

    获奖事件生成的十六进制的标识符

    userId

    String

    用户ID

  4. 组装验证参数

    验证内容(除sign、keyId)格式顺序如下:

    adId={adId}&data={data}&rewardAmount={rewardAmount}&rewardName={rewardName}&uniqueId={uniqueId}&userId={userId}

    其中‘{}’里面表示参数的值,且参数顺序不能变。如果参数为null或者空字符串,则URL中不拼接该参数。然后用SHA256计算散列值,得到paramContentData。示例代码如下所示:

     
    1. String adId = request.getParameter("adId");
    2. String data = request.getParameter("data");
    3. ...
    4. String userId = request.getParameter("userId");
    5. String param = "adId=" + adId + "&data=" + data + "&rewardAmount=" + rewardAmount + "&rewardName=" + rewardName + "&uniqueId=" + uniqueId + "&userId=" + userId;
    6. String sha256Value = Sha256Util.digest(param);
    7. byte[] paramContentData = sha256Value.getBytes(Charset.forName("UTF-8"));
  5. 获取公钥列表。

    a. 在鲸鸿动能媒体服务平台上查看对应的帐户信息时选择“账户”。

    通过点击上图所示的“获取密钥”按钮弹出如下所示的弹框,获取“开发者ID”和“密钥”。

    b. 您根据应用分发区域不同,需要使用对应站点的接口URL去获取公钥列表,不同站点对应的接口URL如下所示:

    • 中国:https://ppscrowd-drcn.op.hicloud.com/action-lib-track/publickeys

    将body通过密钥进行HMAC-SHA256加密得到签名,替换到Authorization中,并设置“开发者ID”和Authorization到Header中。示例代码如下所示:

     
    1. String data = "";
    2. String url = "https://ppscrowd-dre.op.dbankcloud.com/action-lib-track/publickeys";
    3. String authorization = "Digest validTime=\"{0}\", response=\"{1}\"";
    4. // 开发者ID
    5. String userId = "YOUR_PUBLISHER_ID";
    6. // 密钥
    7. String key = "YOUR_KEY";
    8. HttpClient httpclient = HttpClients.createDefault();
    9. HttpGet request = new HttpGet();
    10. try {
    11. // 将body通过密钥进行HMAC-SHA256加密得到签名,替换到Authorization中
    12. String validTime = String.valueOf(System.currentTimeMillis());
    13. String body = validTime + ":/publickeys";
    14. byte[] keyBytes = Base64.decodeBase64(key);
    15. byte[] bodyBytes = body.getBytes(Charsets.UTF_8);
    16. Mac mac = Mac.getInstance("HmacSHA256");
    17. SecretKey secretKey = new SecretKeySpec(keyBytes, "HmacSHA256");
    18. mac.init(secretKey);
    19. byte[] signatureBytes = mac.doFinal(bodyBytes);
    20. String signature = (signatureBytes == null) ? null : Hex.encodeHexString(signatureBytes);
    21. authorization = MessageFormat.format(authorization, validTime, signature);
    22. // 设置开发者ID和Authorization到Header中
    23. request.setURI(new URI(url));
    24. request.setHeader("userId", userId);
    25. request.setHeader("Authorization", authorization);
    26. HttpResponse response = httpclient.execute(request);
    27. data = EntityUtils.toString(response.getEntity());
    28. } catch (Exception e) {
    29. System.out.println(e.getMessage());
    30. }

    返回data消息体(publicKey已匿名化):

     
    1. {
    2. "keys": [
    3. {
    4. "keyId":"12345678",
    5. "publicKey":"LS0tLS1*******************************************************"
    6. },
    7. {
    8. "keyId": "22345678",
    9. "publicKey":"LS0tLS1*******************************************************"
    10. }
    11. ]
    12. }

    返回消息结构体:

    参数名称

    类型

    是否必选

    描述

    keys

    List<key>

    返回公钥列表

    • key结构体:

    参数名称

    类型

    是否必选

    描述

    keyId

    String

    密钥ID

    publicKey

    String

    公钥

  6. 执行验证。

    a. 根据keyId从公钥列表中找到对应的base64编码后的publicKey。

    b. 将paramContentData、publicKey、sign和SHA256withRSA数字签名算法的入参,执行验证。

    示例代码如下所示:

     
    1. public static boolean verify(byte[] data, String publicKey, String sign, String signatureAlgorithm) {
    2. try {
    3. byte[] keyBytes = base64Decode(publicKey);
    4. X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    5. KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    6. PublicKey publicK = keyFactory.generatePublic(keySpec);
    7. Signature signature = Signature.getInstance(signatureAlgorithm);
    8. signature.initVerify(publicK);
    9. signature.update(data);
    10. return signature.verify(base64Decode(sign));
    11. } catch (InvalidKeyException | SignatureException | UnsupportedEncodingException | InvalidKeySpecException | NoSuchAlgorithmException e) {
    12. return false;
    13. }
    14. }
    15. private static byte[] base64Decode(String encoded) throws UnsupportedEncodingException {
    16. return Base64.decodeBase64(encoded.getBytes("UTF-8"));
    17. }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/58068.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自由学习记录(18)

动画事件的碰撞器触发 Physics 类的常用方法 RaycastHit hit; if (Physics.Raycast(origin, direction, out hit, maxDistance)) {Debug.Log("Hit: " hit.collider.name); } Physics.Raycast&#xff1a;从指定点向某个方向发射射线&#xff0c;检测是否与碰撞体…

【elkb】创建用户和角色

在使用中我们不能把超管的用户信息给到所有者&#xff0c;我们需要为不用的使用场景创建不同的用户。 登录管理员用户 打开管理页面 创建角色 点击角色&#xff0c;创建角色 填写角色信息 设置Kibana 权限 最后点击创建角色 创建用户 点击用户--->创建用户 填写信息 登录…

【论文复现】语言模型中的多模态链式推理

&#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐、摄影的一位博主。 &#x1f4d7;本文收录于论文复现系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏C语言初阶、C…

Mysql常用语法一篇文章速成

文章目录 前言前置环境数据库的增删改查查询数据查询所有条件查询多条件查询模糊查询分页查询排序查询分组查询⭐️⭐️关联查询关联分页查询 添加数据insert插入多条记录不指定列名(适用于所有列都有值的情况) 更新数据更新多条记录更新多个列更新不满足条件的记录 删除统计数…

“不可原谅的漏洞”论文导读

文章《Unforgivable Vulnerabilities》由Steve Christey 2007年撰写&#xff0c;主要探讨了在软件安全领域中那些本可以避免的漏洞&#xff0c;即“不可原谅的漏洞”。这些漏洞通常由于开发者忽视了基本的安全开发实践而存在&#xff0c;且容易被发现和利用。文章提出了建立一套…

文件夹无法访问?全面解析与高效恢复策略

一、文件夹无法访问的困境 在日常的计算机使用中&#xff0c;我们时常会遇到文件夹无法访问的尴尬情况。这种故障表现为双击文件夹时&#xff0c;系统毫无反应&#xff0c;或者弹出“无法访问&#xff0c;拒绝访问”的错误提示。更令人头疼的是&#xff0c;有时文件夹内的文件…

Spring @RequestMapping 注解

文章目录 Spring RequestMapping 注解一、引言二、RequestMapping注解基础1、基本用法2、处理多个URI 三、高级用法1、处理HTTP方法2、参数和消息头处理 四、总结 Spring RequestMapping 注解 一、引言 在Spring框架中&#xff0c;RequestMapping 注解是构建Web应用程序时不可…

VLAN间通信以及ospf配置

目录 1.基础知识介绍 1.1 什么是VLAN&#xff1f; 1.2 VLAN有什么用&#xff1f; 1.3 不同VLAN如何实现通信&#xff1f; 1.4 什么是路由汇总&#xff1f; 1.4.1 路由汇总的好处&#xff1a; 2. 实验 2.1 网络拓扑设计 2.2 实验配置要求 2.2.1 三层交换配置&#xff…

Spring Boot 注解大全:全面解析 Spring Boot 常用注解及其应用场景

Spring Boot 注解大全:全面解析 Spring Boot 常用注解及其应用场景 简介 Spring Boot 是一个基于 Spring 框架的简化开发框架,它旨在简化 Spring 应用的初始搭建和开发过程。Spring Boot 提供了一系列的注解,使得开发者可以更加方便地进行应用开发和配置。本文将详细介绍 S…

SQL Server身份验证模式

SQL Server是一个广泛使用的关系数据库管理系统&#xff0c;通常使用两种身份验证模式&#xff1a;Windows身份验证和SQL Server身份验证。理解这些身份验证方式的概念与更改方式的操作&#xff0c;对于数据库管理员和开发者至关重要。本文将详细介绍身份验证方式的概念以及如何…

ArcGIS005:ArcMap常用操作101-150例动图演示

摘要&#xff1a;本文涵盖了GIS软件操作的多方面内容&#xff0c;包括地图文档的新建、打开、保存及版本兼容性处理&#xff1b;错误与警告的查阅及帮助文档的使用技巧&#xff1b;地图打印比例尺的调整与地图信息的完善&#xff1b;图层操作的撤销与恢复&#xff0c;界面元素的…

从零开始的c++之旅——继承

1. 继承 1.继承概念及定义 继承是面向对象编程的三大特点之一&#xff0c;它使得我们可以在原有类特性的基础之上&#xff0c;增加方法 和属性&#xff0c;这样产生的新的类&#xff0c;称为派生类。 继承 呈现了⾯向对象程序设计的层次结构&#xff0c;以前我们接触的…

【学习】软件测试中V模型、W模型、螺旋模型三者介绍

在软件工程的星辰大海之中&#xff0c;存在着三种独特的航路图&#xff1a;V模型、W模型以及螺旋模型。它们分别以各自的方式描绘了软件开发与测试的不同旅程。 首先映入眼帘的是V模型——一个以垂直线条贯穿始终的简洁图形。这个模型如同一座倒立的“V”字形山峰&#xff0c;…

SpringMVC笔记 一万字

此笔记来自于B站尚硅谷 文章目录 一、SpringMVC 简介1、什么是MVC2、什么是SpringMVC3、SpringMVC的特点 二、HelloWorld1、开发环境2、创建maven工程a>添加web模块b>打包方式&#xff1a;warc>引入依赖 3、配置web.xmla>默认配置方式b>扩展配置方式 4、创建请求…

【快速上手】pyspark 集群环境下的搭建(Standalone模式)

目录 前言 &#xff1a; 一、spark运行的五种模式 二、 安装步骤 安装前准备 1.第一步&#xff1a;安装python 2.第二步&#xff1a;在bigdata01上安装spark 3.第三步&#xff1a;同步bigdata01中的spark到bigdata02和03上 三、集群启动/关闭 四、打开监控界面验证 前…

三周精通FastAPI:31 使用 StaticFiles从目录中自动提供静态文件

官方文档&#xff1a;静态文件 - FastAPI 静态文件 您可以使用 StaticFiles从目录中自动提供静态文件。 使用StaticFiles 导入StaticFiles。"挂载"(Mount) 一个 StaticFiles() 实例到一个指定路径。 from fastapi import FastAPI from fastapi.staticfiles impo…

【双目视觉标定】——1原理与实践

0 前言 双目视觉定位是目前机器&#xff08;机器人&#xff09;等领域中使用得非常广泛的视觉定位技术&#xff0c;双目视觉是模拟人的视觉系统利用两个不同位置的摄像头的视差来确定物体的位置。由于有需要采集两个摄像头的图像共同参与计算&#xff0c;所以双目相机装配要求…

【最佳牛围栏——二分】

题目 思路 扩大数据&#xff0c;避免精度问题&#xff0c;拉到整数域解决不用枚举前缀和的 l 和 r&#xff0c;改为求可能 l 的最小值&#xff0c;线性做法不用记录长度来求平均值&#xff0c;改为用平均值处理数据&#xff08;这是第二条的前提&#xff09;&#xff0c;直接通…

[java][高级]MyBatisPlus

一、MyBatisPlus简介 1. 入门案例 问题导入 MyBatisPlus环境搭建的步骤&#xff1f; 1.1 SpringBoot整合MyBatisPlus入门程序 ①&#xff1a;创建新模块&#xff0c;选择Spring初始化&#xff0c;并配置模块相关基础信息 ②&#xff1a;选择当前模块需要使用的技术集&…

win10/11无休眠设置和断电后电池模式自动休眠而不是睡眠-用以省电

1、打开休眠设置选项 打开控制面板\所有控制面板项\电源选项\ 左侧的选择电源按钮的功能 默认状态没有休眠 1、管理员权限打开cmd或者power shell 2、输入一下指令&#xff0c;打开休眠选项 powercfg -hibernate on关闭后重新打开 控制面板\所有控制面板项\电源选项\左侧的选…