微信小程序: 获取accessToken,手机号, 小程序二维码,openId与unionId 公共配置类(核心篇)

news2024/12/27 12:33:59

全文目录,一步到位

  • 1.前言简介
    • 1.1 专栏传送门
  • 2. 微信小程序公用功能
    • 2.1 配置准备工作
      • 2.1.1 配置文件准备(单体放`yml`中 微服务放`配置中心`)
      • 2.1.2 获取配置文件中的小程序配置
      • 2.1.3 设置redis配置
    • 2.2 创建不同功能工具类
      • 2.2.1 创建微信服务工具类`WechatServiceUtils`
      • 2.2.2 创建RedisCache
    • 2.3 各个功能传送门
      • 2.3.1 获取accessToken
      • 2.3.2 获取手机号
      • 2.3.3 获取小程序二维码(不限制)
      • 2.3.4 获取openId与unionId
  • 3. 文章的总结
    • 3.1 本文总结
    • 3.2 本文统一说明


1.前言简介

本文是微信小程序公共类 以下功能均使用 此文章 代码

  • 获取accessToken
  • 手机号
  • 小程序二维码
  • openId与UnionId

最下面有传送门, 传送到每个功能 避免多次封装
远程调用均使用restTemplate (springboot自带, 操作简单)
使用其他请随意…

1.1 专栏传送门

===> 微信小程序相关操作专栏 <===

2. 微信小程序公用功能

2.1 配置准备工作

2.1.1 配置文件准备(单体放yml中 微服务放配置中心)

(特别注意 这里面包含大部分微信小程序配置)
appidsecret 填写上
ps: 里面部分配置可以删除

  • 过期时间
  • 启动执行
  • 登录url
  • 其他业务 如获取手机号, 获取小程序二维码等
# 微信核心参数
wechat:
  # 小程序
  mini-app:
    # 请求url
    requestUrl: /wxMiniLogin
    # 请求方法
    requestMethod: POST
    # appid
    appId: ?
    # app秘钥
    appSecret: ?
    # 微信基础请求网址
    wxBaseRequestUrl: https://api.weixin.qq.com
    # 获取access_token必备参数
    grantType: client_credential
    # 微信获取access_token的url
    aTokenUrl: ${wechat.mini-app.wxBaseRequestUrl}/cgi-bin/token?grant_type=${wechat.mini-app.grantType}&appid=%s&secret=%s
    # 要分钟(尽量少于120分钟) 一天上限2000次 这里一天最多请求24次 可增加定时刷新缓存等
    expiredTime: 70
    # 是否执行服务启动执行
    serverStartAutoRun: false
    # 微信登录提供的接口(GET)
    wxLoginUrlTemplate: ${wechat.mini-app.wxBaseRequestUrl}/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code
    # 微信获取手机号接口
    wxGetPhoneUrl: ${wechat.mini-app.wxBaseRequestUrl}/wxa/business/getuserphonenumber?access_token=%s
    #微信获取二维码(不限制)post请求
    wxACodeUnLimitUrl: ${wechat.mini-app.wxBaseRequestUrl}/wxa/getwxacodeunlimit?access_token=%s
    #微信获取二维码(限制)post请求
    wxACodeUrl: ${wechat.mini-app.wxBaseRequestUrl}/wxa/getwxacode?access_token=%s
    # 微信获取二维码(限制)post请求
    wxAQrcodeUrl: ${wechat.mini-app.wxBaseRequestUrl}/cgi-bin/wxaapp/createwxaqrcode?access_token=%s

2.1.2 获取配置文件中的小程序配置

使用@ConfigurationProperties注解对应

  • 具体介绍我没有写: 找了一篇写的比较全的链接
  • => 传送门: @ConfigurationProperties使用方式
  • 当然 可以使用@Value替换上面这种(二选一)

代码如下, 名字对应配置文件名称, 注释自己加一下吧

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 小程序获取配置类
 *
 * @author pzy
 * @version 0.1.0
 * @description TODO
 */
@Slf4j
@Data
@Component
@ConfigurationProperties(prefix = "wechat.mini-app")
public class WechatConfigProperties {

    private String requestUrl;

    private String requestMethod;

    private String appId;

    private String appSecret;

    private String wxBaseRequestUrl;

    private String grantType;

    private String aTokenUrl;

    private Integer expiredTime;

    private Boolean serverStartAutoRun;

    private String wxLoginUrlTemplate;

    /**
     * 获取手机号
     */
    private String wxGetPhoneUrl;

    /**
     * 二维码无限制url(主)
     */
    private String wxACodeUnLimitUrl;

    private String wxACodeUrl;

    private String wxAQrcodeUrl;




    /**
     * 生成微信登录请求地址
     *
     * @param code code
     * @return 请求地址
     */
    public String getWxLoginUrl(String code) {
        return String.format(wxLoginUrlTemplate, appId, appSecret, code);
    }

    /**
     * 生成微信ACCESS_TOKEN请求地址
     * <p>
     * 模板样式: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
     *
     * @return 请求地址
     */
    public String getATokenUrl() {
        return String.format(aTokenUrl, appId, appSecret);
    }


    /**
     * 获取手机号url post请求
     *
     * @param accessToken
     * @return
     */
    public String getPhoneUrl(String accessToken) {
        return String.format(wxGetPhoneUrl, accessToken);
    }

    /**
     * 获取不限制的微信二维码url
     *
     * @param accessToken
     * @return
     */
    public String getWxACodeUnLimitUrl(String accessToken) {
        return String.format(wxACodeUnLimitUrl, accessToken);
    }

    /**
     * 获取(限制一)的微信二维码url
     *
     * @param accessToken
     * @return
     */
    public String getWxACodeUrl(String accessToken) {
        return String.format(wxACodeUrl, accessToken);
    }

    /**
     * 获取(限制二)的微信二维码url
     *
     * @param accessToken
     * @return
     */
    public String getWxAQrcodeUrl(String accessToken) {
        return String.format(wxAQrcodeUrl, accessToken);
    }
}

2.1.3 设置redis配置

spring: 
  redis:
    # 地址
    host: 192.168.1.130
    # 端口,默认为6379
    port: 6379
    # 数据库索引
    database: 0
    # 密码
    password: 123456
    # 连接超时时间
    timeout: 10s
    lettuce:
      pool:
        # 连接池中的最小空闲连接
        min-idle: 5
        # 连接池中的最大空闲连接
        max-idle: 10
        # 连接池的最大数据库连接数
        max-active: 50
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
        max-wait: 5000ms

2.2 创建不同功能工具类

2.2.1 创建微信服务工具类WechatServiceUtils

RestTemplate 直接可以使用
WechatConfigProperties 请见 2.1.2
RedisCache 请见2.2.2

/**
 * 微信服务工具类
 *
 * @author pzy
 * @version 0.1.0
 * @description: TODO
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class WechatServiceUtils {

    /**
     * 远程调用
     */
    private final RestTemplate restTemplate;

    /**
     * redis缓存
     */
    private final RedisCache redisCache;

    /**
     * 微信统一配置
     */
    private final WechatConfigProperties wechatConfigProperties;

    /**
     * 1. 获取微信登录认证信息
     *
     * @param wxCommonReqDto
     * @return
     */
    public Map<String, String> getWxMiniAuth(WxCommonReqDto wxCommonReqDto) {
        String code = wxCommonReqDto.getWxCode();
        //秘钥
        String encryptedIv = wxCommonReqDto.getIv();
        //加密数据
        String encryptedData = wxCommonReqDto.getEncryptedData();

        JSONObject wxAuthResponse = null;
        String sessionKey = "";
        String openid = "";
        try {
            //1. 想微信服务器发送请求获取用户信息
            String url = wechatConfigProperties.getWxLoginUrl(code);
            log.info("===> 请求微信url是: {}", url);

            //2. 远程调用微信接口
            String res = restTemplate.getForObject(url, String.class);
            wxAuthResponse = JSONObject.parseObject(res);

            //3. 解析返回参数 报错则进行对应处理
            /*校验1: wx请求不是null*/
            if (wxAuthResponse != null) {

                /*校验2: 响应对象是否正确*/
                CheckUtils.responseCheck(wxAuthResponse);

                //3.1 获取session_key和openid
                sessionKey = wxAuthResponse.getString("session_key");
                openid = wxAuthResponse.getString("openid");
                log.info("===> openid:  {}", openid);

                /*校验3: 响应信息是否正常*/
                if (StringUtils.isBlank(sessionKey) || StringUtils.isBlank(openid)) {
                    log.error("小程序授权失败,session_key或open_id是空!");
                    throw new ServiceException("抱歉, 小程序授权失败,缺少关键返回参数!");
                }
                log.info("===> 微信回调信息: {}", wxAuthResponse);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("抱歉, 小程序授权失败!");
        }

        //4. 获取微信信息并制作token
        /*校验:(选用)如果获取union_id 需要进行解密*/
        Map<String, String> map = new HashMap<>();
        String token = "";
        if (StringUtils.isNotBlank(encryptedIv) && StringUtils.isNotBlank(encryptedData)) {
            String decryptResult = "";
            try {
                //如果没有绑定微信开放平台,解析结果是没有unionid的。
                decryptResult = AESUtils.decrypt(sessionKey, encryptedIv, encryptedData);

                if (StringUtils.hasText(decryptResult)) {
                    //如果解析成功,获取token
                    map.put("type", String.valueOf(1));
                    map.put("decryptResult", decryptResult);
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new ServiceException("微信登录失败!");
            }
        } else {
            //如果前端只传wxCode 没有unionId的需求 只要openId的
            map.put("type", String.valueOf(2));
            map.put("decryptResult", openid);
        }

        /*校验: 数据为空的情况*/
        if (StringUtils.isBlank(map.get("type")) || StringUtils.isBlank(map.get("decryptResult"))) {
            throw new ServiceException(ResponseEnum.A10007);
        }


        return map;
    }

    /**
     * 2. 获取缓存中的AccessToken
     * <p>
     * 没有从微信拉取[可配合定时]
     *
     * @return accessToken
     */
    public String getRedisCacheAccessToken() {
        /*校验: 缓存中有accessToken的key*/
        if (redisCache.hasKey(CacheConstants.WX_ACCESS_TOKEN)) {

            log.info("二级缓存数据取出accessToken成功!");

            return redisCache.getCacheObject(CacheConstants.WX_ACCESS_TOKEN);
        }
        //这里不用三目(不好看~~)
        return getWxMiniAccessToken();
    }


    /**
     * 3. 访问微信官方获取两小时的 accessToken
     *
     * @return accessToken
     */
    public String getWxMiniAccessToken() {
        Map<String, String> query = new HashMap<>();
        query.put("grant_type", wechatConfigProperties.getGrantType());//client_credential
        query.put("secret", wechatConfigProperties.getAppSecret());
        query.put("appid", wechatConfigProperties.getAppId());
        try {
            String aTokenUrl = wechatConfigProperties.getATokenUrl();
//            ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(aTokenUrl, query, JSONObject.class);
            ResponseEntity<JSONObject> responseEntity = restTemplate.getForEntity(aTokenUrl, JSONObject.class, query);
            HttpStatus statusCode = responseEntity.getStatusCode(); //状态码

//            System.out.println(responseEntity.getHeaders());//获取到头信息

            /*校验: 如果接口成功 200*/
            if (Objects.equals(statusCode.value(), 200)) {
                JSONObject responseJsonBody = responseEntity.getBody();//响应体


                log.info("[请求微信小程序官方接口] => 获取accessToken请求成功返回值:{}", responseJsonBody);

                if (responseJsonBody == null) {
                    log.info("微信小程序获取accessToken请求返回result是null!");
                    throw new ServiceException(ResponseEnum.A10005);
                }
                //获取accessToken
                String accessToken = responseJsonBody.getString("access_token");
                if (StringUtils.isBlank(accessToken)) {
                    log.info("微信小程序获取accessToken请求返回access_token是null!");
                    throw new ServiceException(ResponseEnum.A10005);
                }
                //放入缓存中
                redisCache.setCacheObject(CacheConstants.WX_ACCESS_TOKEN, accessToken, wechatConfigProperties.getExpiredTime(), TimeUnit.MINUTES);

                return accessToken;
            } else {
                log.error("微信HttpStatus的StatusCode不是200 {}", statusCode.value());
                throw new ServiceException(ResponseEnum.A10005);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("微信小程序获取accessToken请求异常信息 {}", e.getMessage());
            throw new ServiceException(ResponseEnum.A10005);
        }

    }

    /**
     * 错误码	错误描述	解决方案
     * -1	    system error	                                [系统繁忙,此时请开发者稍候再试]
     * 40029	code 无效	                                    [js_code无效]
     * 45011	api minute-quota reach limit mustslower retry   [next minute API 调用太频繁,请稍候再试]
     * 40013	invalid appid	                                [请求appid身份与获取code的小程序appid不匹配]
     * 错误码
     *
     * @param code js_code
     * @return phone
     */
    public String getPhoneByCode(String code) {
        String phoneUrl = wechatConfigProperties.getPhoneUrl(getRedisCacheAccessToken());

        Map<String, Object> map = new HashMap<>();
        map.put("code", code);

        JSONObject jsonObject = sendPostRestTemplate(phoneUrl, map, JSONObject.class);
        System.out.println(jsonObject);

        if (jsonObject.containsKey("errcode")) {

            /*如果异常码是0 说明正常*/
            if (!Objects.equals(String.valueOf(jsonObject.get("errcode")), "0")) {
                log.error("===> 获取手机号的异常信息 : {}", jsonObject + "");

                throw new ServiceException("获取失败: " + jsonObject.get("errmsg"), (Integer) jsonObject.get("errcode"));
            }
        }

        JSONObject phoneInfo = jsonObject.getJSONObject("phone_info");

        return phoneInfo.getString("phoneNumber");
    }


    /**
     * 生成小程序带参数二维码
     * https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.getUnlimited.html#HTTPS%20%E8%B0%83%E7%94%A8
     */
    @SneakyThrows
    public InputStream getUnlimitedWxQrCode(WxCodeUnlimitedReqDTO wxCodeUnlimitedReqDTO, String accessToken) {

        Map<String, Object> params = new HashMap<>();
        params.put("scene", wxCodeUnlimitedReqDTO.getScene());
        params.put("page", wxCodeUnlimitedReqDTO.getPage());
        params.put("path", wxCodeUnlimitedReqDTO.getPage());
        params.put("env_version", wxCodeUnlimitedReqDTO.getEnvVersion());
        params.put("width", wxCodeUnlimitedReqDTO.getWidth());
        params.put("auto_color", wxCodeUnlimitedReqDTO.getAutoColor());//自动配置线条颜色

        ResponseEntity<byte[]> response = restTemplate.postForEntity(wechatConfigProperties.getWxACodeUnLimitUrl(accessToken), JSON.toJSONString(params), byte[].class);
        System.out.println(JSON.toJSONString(params));

        byte[] buffer = response.getBody();
//        System.out.println(Base64.getEncoder().encodeToString(buffer));

        assert buffer != null;
        return new ByteArrayInputStream(buffer);
    }

    /**
     * 远程调用 restTemplate方法 post请求
     *
     * @param url
     * @param body
     * @return
     */
    public <T> T sendPostRestTemplate(String url, Map<String, Object> body, Class<T> responseType) {
        return restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(body, null), responseType).getBody();
    }
}

2.2.2 创建RedisCache

redis的增删改查操作 记得配置序列化与反序列化
文章传送门: ===> redis高级(序列化与反序列化) <===

@Component
public class RedisCache {
    @Autowired
    public RedisTemplate redisTemplate;

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key   缓存的键值
     * @param value 缓存的值
     */
    public <T> void setCacheObject(final String key, final T value) {

        redisTemplate.opsForValue().set(key, value);
    }

    /**
     * 缓存基本的对象,Integer、String、实体类等
     *
     * @param key      缓存的键值
     * @param value    缓存的值
     * @param timeout  时间
     * @param timeUnit 时间颗粒度
     */
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout) {
        return expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 设置有效时间
     *
     * @param key     Redis键
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return true=设置成功;false=设置失败
     */
    public boolean expire(final String key, final long timeout, final TimeUnit unit) {
        return Boolean.TRUE.equals(redisTemplate.expire(key, timeout, unit));
    }

    /**
     * 获取有效时间
     *
     * @param key Redis键
     * @return 有效时间
     */
    public long getExpire(final String key) {

        if (StringUtils.isBlank(key)) {
            throw new IllegalArgumentException("key cannot be null");
        }

        return redisTemplate.getExpire(key);
    }

    /**
     * 判断 key是否存在
     *
     * @param key 键
     * @return true 存在 false不存在
     */
    public Boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 获得缓存的基本对象。
     *
     * @param key 缓存键值
     * @return 缓存键值对应的数据
     */
    public <T> T getCacheObject(final String key) {
        ValueOperations<String, T> operation = redisTemplate.opsForValue();
        return operation.get(key);
    }

    /**
     * 删除单个对象
     *
     * @param key
     */
    public boolean deleteObject(final String key) {
        return Boolean.TRUE.equals(redisTemplate.delete(key));
    }

    /**
     * 删除集合对象
     *
     * @param collection 多个对象
     * @return
     */
    public boolean deleteObject(final Collection collection) {
        return redisTemplate.delete(collection) > 0;
    }

    /**
     * 缓存List数据
     *
     * @param key      缓存的键值
     * @param dataList 待缓存的List数据
     * @return 缓存的对象
     */
    public <T> long setCacheList(final String key, final List<T> dataList) {
        Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
        return count == null ? 0 : count;
    }

    /**
     * 获得缓存的list对象
     *
     * @param key 缓存的键值
     * @return 缓存键值对应的数据
     */
    public <T> List<T> getCacheList(final String key) {
        return redisTemplate.opsForList().range(key, 0, -1);
    }

    /**
     * 缓存Set
     *
     * @param key     缓存键值
     * @param dataSet 缓存的数据
     * @return 缓存数据的对象
     */
    public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet) {
        BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
        Iterator<T> it = dataSet.iterator();
        while (it.hasNext()) {
            setOperation.add(it.next());
        }
        return setOperation;
    }

    /**
     * 获得缓存的set
     *
     * @param key
     * @return
     */
    public <T> Set<T> getCacheSet(final String key) {
        return redisTemplate.opsForSet().members(key);
    }

    /**
     * 缓存Map
     *
     * @param key
     * @param dataMap
     */
    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
        if (dataMap != null) {
            redisTemplate.opsForHash().putAll(key, dataMap);
        }
    }

    /**
     * 获得缓存的Map
     *
     * @param key
     * @return
     */
    public <T> Map<String, T> getCacheMap(final String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 往Hash中存入数据
     *
     * @param key   Redis键
     * @param hKey  Hash键
     * @param value 值
     */
    public <T> void setCacheMapValue(final String key, final String hKey, final T value) {
        redisTemplate.opsForHash().put(key, hKey, value);
    }

    /**
     * 获取Hash中的数据
     *
     * @param key  Redis键
     * @param hKey Hash键
     * @return Hash中的对象
     */
    public <T> T getCacheMapValue(final String key, final String hKey) {
        HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
        return opsForHash.get(key, hKey);
    }

    /**
     * 获取多个Hash中的数据
     *
     * @param key   Redis键
     * @param hKeys Hash键集合
     * @return Hash对象集合
     */
    public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys) {
        return redisTemplate.opsForHash().multiGet(key, hKeys);
    }

    /**
     * 删除Hash中的某条数据
     *
     * @param key  Redis键
     * @param hKey Hash键
     * @return 是否成功
     */
    public boolean deleteCacheMapValue(final String key, final String hKey) {
        return redisTemplate.opsForHash().delete(key, hKey) > 0;
    }

    /**
     * 获得缓存的基本对象列表(全部的key)
     *
     * @param pattern 字符串前缀
     * @return 对象列表
     */
    public Collection<String> keys(final String pattern) {
        return redisTemplate.keys(pattern);
    }
}

2.3 各个功能传送门

2.3.1 获取accessToken

在这里插入图片描述

官方文档地址: => 获取接口调用凭据 <=
文章传送门:

2.3.2 获取手机号

在这里插入图片描述

官方文档地址: => 获取手机号 <=
文章传送门:

2.3.3 获取小程序二维码(不限制)

在这里插入图片描述

官方文档地址: => 获取不限制的小程序码 <=
文章传送门:

2.3.4 获取openId与unionId

在这里插入图片描述

官方文档地址: => 小程序登录 <=
文章传送门:

3. 文章的总结

3.1 本文总结

本文使用的技术栈

  • springboot相关操作
  • restTemplate远程调用使用方式
  • redisTemplate 操作redis的操作
  • redis的序列化与反序列化

3.2 本文统一说明

本篇涵盖大部分的微信小程序操作(无支付), 统一封装
2.3 中统一传送到具体功能配置
避免多次配置, 传送门内的功能细节不在这篇介绍
特别注意: 文章传送门会在近期完善, 这是本专栏的第一篇, 之后也会围绕此篇进行更新, 接入支付等等



作者: pingzhuyan

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

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

相关文章

在windows上安装好anaconda后,输入conda命令出现 OSError: [WinError 123] 文件名、目录名或卷标语法不正确。

下载anaconda后使用conda命令就会报错&#xff0c;重装几次后无效。于是潜心解决发现问题&#xff1a; 报错&#xff1a; OSError: [WinError 123] 文件名、目录名或卷标语法不正确。 在这里是路径无效&#xff0c;“.”应该是“&#xff1a;”本身没有问题。路径的错误在意…

Java集合 List接口

List接口操作 Java的List接口是Java集合框架中的一部分&#xff0c;它表示有序的集合。List接口提供了许多常用的方法&#xff0c;以下是其中的一些例子&#xff1a; 增加元素 add(E e)&#xff1a;将指定的元素插入此列表的末尾。 List<String> list new ArrayList…

linux kernel 内存踩踏之KASAN_SW_TAGS(二)

一、背景 linux kernel 内存踩踏之KASAN&#xff08;一&#xff09;_kasan版本跟hasan版本区别-CSDN博客 上一篇简单介绍了标准版本的KASAN使用方法和实现&#xff0c;这里将介绍KASAN_SW_TAGS和KASAN_HW_TAGS 的使用和背后基本原理&#xff0c;下图是三种方式的对比&#x…

C++11---(1)

目录 一、C11简介 二、列表初始化 2.1、{ } 初始化 三、变量类型推导 3.1、auto 3.2、decltype 为什么需要decltype 四、final和override 4.1、final 4.2、override 五、默认成员函数控制 5.1、default修饰函数 5.2、delete修饰函数 六、nullptr 一、C11简介 C11是…

JavaScript_00001_00000

contents 简介变量与数据类型自动类型转换强制类型转换 简介 变量与数据类型 根据变量定义的范围不同&#xff0c;变量有全局变量和局部变量之分。直接定义的变量是全局变量&#xff0c;全局变量可以被所有的脚本访问&#xff1b;在函数里定义的变量称为局部变量&#xff0c;…

17-k8s控制器资源-job控制

job控制器&#xff1a;就是一次性任务的pod控制器&#xff0c;pod完成作业后不会重启&#xff0c;其重启策略是&#xff1a;Never 1&#xff0c;job控制器案例描述 启动一个pod&#xff0c;执行完成一个事件&#xff0c;然后pod关闭&#xff1b; 事件&#xff1a;计算π的值&a…

【初始RabbitMQ】工作队列的实现

工作队列 工作队列&#xff08;又称为任务队列&#xff09;的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。 相反我们安排任务在之后执行。我们把任务封装为消息并将其发送到队列。在后台运行的工作进 程将弹出任务并最终执行作业。当有多个工作线程…

.NET Core WebAPI中使用Log4net 日志级别分类并记录到数据库

一、效果 记录日志为文档 记录日志到数据库 二、添加NuGet包 三、代码配置 <?xml version"1.0" encoding"utf-8" ?> <log4net><!-- Debug日志 --><appender name"RollingFileDebug" type"log4net.Appender.Roll…

【RL】Value Iteration and Policy Iteration(利用迭代算法求解贝尔曼最优等式)

Lecture 4: Value Iteration and Policy Iteration Value Iteration Algorithm 对于Bellman最优公式&#xff1a; v f ( v ) m a x π ( r γ P π v ) \mathbf{v} f(\mathbf{v}) max_{\pi}(\mathbf{r} \gamma \mathbf{P}_{\pi} \mathbf{v}) vf(v)maxπ​(rγPπ​v) …

Midjourney绘图欣赏系列(一)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子,它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同,Midjourney 是自筹资金且闭源的,因此确切了解其幕后内容尚不清楚。我们知道它严重依赖机器学…

Python教程(26)——Python迭代器和生成器详解

迭代器 Python中的迭代器是一种对象&#xff0c;它可以迭代&#xff08;遍历&#xff09;一个可迭代对象&#xff08;比如列表、元组或字符串&#xff09;的元素。迭代器用于实现迭代器协议&#xff0c;即包含 __iter__() 方法和 __next__() 方法。 迭代器的工作原理是每次调…

2.11题目

#include <stdio.h> int main() { char a; while((a getchar()) ! -1) { if(a > A && a < Z) a32; putchar(ch); } return 0;} ———————————————— 版权声明&#xff1a;本文为博主原创文章…

2024年危险化学品经营单位主要负责人证模拟考试题库及危险化学品经营单位主要负责人理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年危险化学品经营单位主要负责人证模拟考试题库及危险化学品经营单位主要负责人理论考试试题是由安全生产模拟考试一点通提供&#xff0c;危险化学品经营单位主要负责人证模拟考试题库是根据危险化学品经营单位主…

【大模型 数据增强】LLMAAA:使用 LLMs 作为数据标注器

【大模型 数据增强】LLMAAA&#xff1a;使用 LLMs 作为数据标注器 提出背景算法步骤1. LLM作为活跃标注者&#xff08;LLMAAA&#xff09;2. k-NN示例检索与标签表述化3. 活跃学习策略4. 自动重权技术 LLMAAA 框架1. LLM Annotator2. Active Acquisition3. Robust Training 总结…

数据结构对链表的初步认识(一)

已经两天没有更新了&#xff0c;今天就写一篇数据结构的链表吧&#xff0c;巩固自己也传授知识&#xff0c;不知道各位是否感兴趣看看这一篇有关联表的文章。 目录 链表的概念与结构 单向链表的实现 链表各个功能函数 首先我在一周前发布了一篇有关顺序表的文章&#xff0c;…

【Linux系统化学习】缓冲区

目录 缓冲区 一个样例 现象解释 缓冲区存在的位置 缓冲区 在刚开始学习C语言的时候我们就听过缓冲区这个名词&#xff0c;很是晦涩难懂&#xff1b;在Linux下进程退出时也包含缓冲区&#xff0c;因此缓冲区到底是什么&#xff1f;有什么作用&#xff1f; 让我们先从一个小…

斯坦福大学全能家政服务机器人Mobile ALOHA以及“小群体大智慧”Zooids集群机器人

斯坦福大学成功研发出低成本自主进化克隆人类行为和任务的能力全能型家政服务机器人。 原文标题: 【Mobile ALOHA-Learning Bimanual Mobile Manipulation with Low-Cost Whole-Body Teleoperation】 论文链接:【Mobile ALOHA (mobile-aloha.github.io)】。 以及由斯坦福大学…

51单片机项目(32)——基于51单片机的温度检测及控制装置的proteus仿真

1.功能设定 使用DS18B20测定当前温度并实时显示在LCD1602屏幕&#xff0c;使用四个按键设定温度的上限、下限。当温度低于下限时&#xff0c;蜂鸣器报警同时开启升温装置&#xff1b;当温度大于上限时&#xff0c;蜂鸣器报警同时启动降温装置。 仿真图如下&#xff1a; 2.软件设…

【无标题】管理kvm 虚拟机

管理kvm 虚拟机 点击虚拟机 创建新的虚拟机 安装操作系统 设置root密码

中小学信息学奥赛CSP-J认证 CCF非专业级别软件能力认证-入门组初赛模拟题第三套(选择题)

CSP-J入门组初赛模拟练习题第三套 1、以下不是属于国家顶级域名的是 A、.au B、.cn C、.com D、.jp 答案&#xff1a;C 考点分析&#xff1a;主要考查域名相关知识&#xff0c;au是澳大利亚、cn是中国&#xff0c;jp是日本&#xff0c;答案C 2、2个10进制数1111和1010的异…