Java企业微信服务商代开发获取AccessToken示例

news2024/9/21 11:05:41

这里主要针对的是企业微信服务商代开发模式 文档地址

在这里插入图片描述

可以看到里面大致有三种token,一个是服务商的token,一个是企业授权token,还有一个是应用的token
这里面主要有下面几个参数
首先是服务商的 corpid 和 provider_secret ,这个可以在 应用管理-通用开发参数 里面查看

在这里插入图片描述

然后是企业的 corpid 和企业的永久授权码 permanent_code ,这两个是需要在企业授权的的时候通过回调获取的,具体请参考官方文档 获取永久授权码

最后就是应用的 suite_id 和 suite_secret 还需要一个 suite_ticket ,前面两个在应用信息里面就可以看到,suite_ticket 这个也是需要通过回调获取 ,具体参考官方文档 推送suite_ticket

在这里插入图片描述

拿到这些参数后就好说了,剩下的都是调接口
直接上代码

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.qyzj.common.base.exception.BusinessException;
import com.qyzj.common.base.util.HttpsRequestUtil;
import com.qyzj.common.redis.constant.CacheKey;
import com.qyzj.common.redis.util.RedisUtil;
import com.qyzj.service.task.constant.WeiXinProviderConst;
import com.qyzj.service.task.constant.WeixinCorpKeyConst;
import com.qyzj.service.task.constant.WeixinCorpUrlConst;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author Sakura
 * @date 2024/7/2 11:48
 */
@Component
@Log
public class WxTokenUtil {

    @Autowired
    private RedisUtil redisUtil;

    // 获取服务商token
    // 这里有一个问题,企业微信本身可能会使token提前失效,所以有时需要强制重新获取token,详情见官方文档
    // https://developer.work.weixin.qq.com/document/path/91200
    // 所以此处加了一个cache用来判断是否需要走缓存拿token,正常情况默认走缓存即可
    public String getProviderAccessToken(Boolean cache) {
        try {
            // 如果Redis里面有则直接取Redis里面的
            if (cache &&redisUtil.hasKey(CacheKey.KEY_CORP_PROVIDER_ACCESS_TOKEN)) {
                return redisUtil.get(CacheKey.KEY_CORP_PROVIDER_ACCESS_TOKEN).toString();
            }

            // 封装请求参数
            JSONObject json = new JSONObject();
            json.put("corpid", WeiXinProviderConst.corpId);
            json.put("provider_secret", WeiXinProviderConst.providerSecret);

            // 请求微信接口
            String accessTokenStr = HttpsRequestUtil.sendPostRequest(WeixinCorpUrlConst.PROVIDER_ACCESS_TOKEN, json.toJSONString());
            log.info("get provider access token return :" + accessTokenStr);
            JSONObject accessTokenJson = JSON.parseObject(accessTokenStr);
            // 获取 access_token
            String accessToken = accessTokenJson.getString(WeixinCorpKeyConst.providerAccessToken);
            //官方 expires_in 为 2个小时, 这里设置100分钟
            redisUtil.set(CacheKey.KEY_CORP_PROVIDER_ACCESS_TOKEN, accessToken, CacheKey.expireTime100);

            return accessToken;
        } catch (Exception e) {
            log.info("get provider access token error");
            e.printStackTrace();
            throw new BusinessException("get provider access token error");
        }
    }

    // 获取企业授权token
    public String getCorpAccessToken(String corpId, String permanentCode) {
        try {
            // 如果Redis里面有则直接取Redis里面的
            if (redisUtil.hasKey(CacheKey.KEY_CORP_ACCESS_TOKEN + "_" + corpId)) {
                return redisUtil.get(CacheKey.KEY_CORP_ACCESS_TOKEN + "_" + corpId).toString();
            }
            String accessTokenUrl = WeixinCorpUrlConst.CORP_ACCESS_TOKEN
                    .replace("#{CORP_ID}", corpId)
                    .replace("#{CORP_SECRET}", permanentCode);
            String accessTokenStr = HttpsRequestUtil.sendGetRequest(accessTokenUrl);
            log.info("get corp access token return :" + accessTokenStr);
            JSONObject accessTokenJson = JSON.parseObject(accessTokenStr);
            // 获取 access_token
            String accessToken = accessTokenJson.getString(WeixinCorpKeyConst.accessToken);
            //官方 expires_in 为 2个小时, 这里设置 100 分钟
            redisUtil.set(CacheKey.KEY_CORP_ACCESS_TOKEN + "_" + corpId, accessToken, CacheKey.expireTime100);

            return accessToken;
        } catch (Exception e) {
            log.info("get corp access token error");
            e.printStackTrace();
            throw new BusinessException("get corp access token error");
        }
    }

    // SuiteTicket是通过回调获取的,企微每10分钟会推送一次
    // 如果没有可手动在服务商企业微信后台刷新
    public String getSuiteTicket() {
        // 如果Redis里面有则直接取Redis里面的
        if (redisUtil.hasKey(CacheKey.KEY_CORP_SUITE_TICKET)) {
            return redisUtil.get(CacheKey.KEY_CORP_SUITE_TICKET).toString();
        } else {
            log.info("get suite ticket error");
            throw new BusinessException("get suite ticket error");
        }

    }

    // 获取应用token
    // 注意suiteTicket是从回调接口获取的
    // 注意该token需要配置ip白名单
    public String getSuiteAccessToken() {
        try {
            // 如果Redis里面有则直接取Redis里面的
            if (redisUtil.hasKey(CacheKey.KEY_SUITE_ACCESS_TOKEN)) {
                return redisUtil.get(CacheKey.KEY_SUITE_ACCESS_TOKEN).toString();
            }
            // 封装请求参数
            JSONObject json = new JSONObject();
            json.put(WeixinCorpKeyConst.suiteId, WeiXinProviderConst.suiteId);
            json.put(WeixinCorpKeyConst.suiteSecret, WeiXinProviderConst.suiteSecret);
            json.put(WeixinCorpKeyConst.suiteTicket, getSuiteTicket());

            String accessTokenStr = HttpsRequestUtil.sendPostRequest(WeixinCorpUrlConst.SUITE_ACCESS_TOKEN, json.toJSONString());
            log.info("get suite access token return :" + accessTokenStr);
            JSONObject accessTokenJson = JSON.parseObject(accessTokenStr);
            //获取 accessToken
            String accessToken = accessTokenJson.getString(WeixinCorpKeyConst.suiteAccessToken);
            //官方 expires_in 为 2个小时, 这里设置 100分钟
            redisUtil.set(CacheKey.KEY_SUITE_ACCESS_TOKEN, accessToken, CacheKey.expireTime100);

            return accessToken;
        } catch (Exception e) {
            log.info("get suite access token error");
            e.printStackTrace();
            throw new BusinessException("get suite access token error");
        }

    }
}

这里面用到的 HttpsRequestUtil 工具类

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * @author Sakura
 * @date 2024/6/24 17:07
 */
public class HttpsRequestUtil {

    public static String sendPostRequest(String urlString, String jsonInputString) throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为POST
        connection.setRequestMethod("POST");

        // 设置请求头
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("Accept", "application/json");

        // 启用输出流,用于发送请求数据
        connection.setDoOutput(true);

        try (OutputStream os = connection.getOutputStream()) {
            byte[] input = jsonInputString.getBytes("utf-8");
            os.write(input, 0, input.length);
        }

        // 获取响应
        try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            return response.toString();
        } finally {
            // 关闭连接
            connection.disconnect();
        }
    }

    public static String sendGetRequest(String urlString) throws IOException {
        URL url = new URL(urlString);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // 设置请求方法为GET
        connection.setRequestMethod("GET");

        // 设置请求头
        connection.setRequestProperty("Accept", "application/json");

        // 获取响应
        try (BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8"))) {
            StringBuilder response = new StringBuilder();
            String responseLine;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            return response.toString();
        } finally {
            // 关闭连接
            connection.disconnect();
        }
    }

}

还有企业微信的两个基本配置类

public class WeixinCorpUrlConst {
    /**
     * 获取 provider_access_token 的 url
     */
    public static final String PROVIDER_ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/service/get_provider_token";

    /**
     * 获取 suite_access_token 的 url
     */
    public static final String SUITE_ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token";
    /**
     * 获取 pre_auth_code 的 url
     */
    public static final String PRE_AUTH_CODE = "https://qyapi.weixin.qq.com/cgi-bin/service/get_pre_auth_code?suite_access_token=";
    /**
     * 前端授权页面 的 url
     */
    public static final String URL_AUTH_PAGE = "https://open.work.weixin.qq.com/3rdapp/install";
    /**
     * 前端登录页面 的 url
     */
    public static final String URL_LOGIN_PAGE = "https://open.work.weixin.qq.com/wwopen/sso/3rd_qrConnect";
    /**
     * 获取 permanent_code 的 url
     */
    public static final String PERMANENT_CODE = "https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code?suite_access_token=";
    /**
     * 获取 企业授权 access_token 的 url
     */
    public static final String CORP_ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=#{CORP_ID}&corpsecret=#{CORP_SECRET}";
    /**
     * 获取 企业应用 access_token 的 url
     */
    public static final String ACCESS_TOKEN = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
    /**
     * 获取 应用信息 的 url
     */
    public static final String AGENT_INFO = "https://qyapi.weixin.qq.com/cgi-bin/agent/get?access_token=#{ACCESS_TOKEN}&agentid=#{AGENT_ID}";
    /**
     * 获取 部门列表 的 url
     */
    public static final String DEPARTMENT_LIST = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=#{ACCESS_TOKEN}";
    /**
     * 获取 部门成员列表 的 url
     */
    public static final String USER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=#{ACCESS_TOKEN}&department_id=#{DEPARTMENT_ID}&fetch_child=1";
    /**
     * 获取 成员信息 的 url
     */
    public static final String USER_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token=#{ACCESS_TOKEN}&userid=#{USER_ID}";

    /**
     * 获取 企业管理员 的 url
     */
    public static final String ADMIN_USER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/service/get_admin_list?suite_access_token=";
    /**
     * 第三方应用:获取 企业成员登录信息 的 url
     */
    public static final String PROVIDER_LOGIN_INFO = "https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info?access_token=";
    /**
     * 自建应用:获取 企业成员登录信息 的 url
     */
    public static final String LOCAL_LOGIN_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=#{ACCESS_TOKEN}&code=#{CODE}";

    public static final String LOGIN_DETAIL_INFO = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail?access_token=#{ACCESS_TOKEN}";

    /**
     * 批量获取 客户列表 的 url
     */
    public static final String BATCH_CUSTOMER_LIST = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token=#{ACCESS_TOKEN}";
    /**
     * 获取 客户详情 的 url
     */
    public static final String CUSTOMER_INFO = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get?access_token=#{ACCESS_TOKEN}&external_userid=#{EXTERNAL_USERID}";
    /**
     * 修改 客户备注信息 的url
     */
    public static final String UPDATE_CUSTOMER_REMARK = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remark?access_token=#{ACCESS_TOKEN}";
    /**
     * 编辑 客户标签 的url
     */
    public static final String MARK_CUSTOMER_TAG = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/mark_tag?access_token=#{ACCESS_TOKEN}";

    /**
     * 获取 企业标签 的 url
     */
    public static final String TAG_GROUP_LIST = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_corp_tag_list?access_token=";

    /**
     * 添加 企业标签 的 url
     */
    public static final String ADD_TAG_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_corp_tag?access_token=";

    /**
     * 修改 企业标签 的 url
     */
    public static final String UPDATE_TAG_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/edit_corp_tag?access_token=";

    /**
     * 删除 企业标签 的 url
     */
    public static final String DELETE_TAG_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/del_corp_tag?access_token=";

    /**
     * 获取 客户群列表 的 url
     */
    public static final String GROUP_CHAT_LIST = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/list?access_token=#{ACCESS_TOKEN}";
    /**
     * 获取 客户群详情 的 url
     */
    public static final String GROUP_CHAT_INFO = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/get?access_token=#{ACCESS_TOKEN}";
    /**
     * 查询 联系我 的 url
     */
    public static final String GET_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_contact_way?access_token=#{ACCESS_TOKEN}";
    /**
     * 添加 联系我 的 url
     */
    public static final String ADD_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_contact_way?access_token=#{ACCESS_TOKEN}";
    /**
     * 更新 联系我 的 url
     */
    public static final String UPDATE_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/update_contact_way?access_token=#{ACCESS_TOKEN}";
    /**
     * 删除 联系我 的 url
     */
    public static final String DEL_CONTACT_WAY = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/del_contact_way?access_token=#{ACCESS_TOKEN}";
    /**
     * 发送 欢迎语  的 url
     */
    public static final String SEND_WELCOME_MSG = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=#{ACCESS_TOKEN}";
    /**
     * 上传 临时素材 的 url
     */
    public static final String UPLOAD_MEDIA = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=";
    /**
     * 添加 入群欢迎语素材  的 url
     */
    public static final String ADD_GROUP_WELCOME_TEMPLATE = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/group_welcome_template/add?access_token=#{ACCESS_TOKEN}";
    /**
     * 更新 入群欢迎语素材  的 url
     */
    public static final String UPDATE_GROUP_WELCOME_TEMPLATE = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/group_welcome_template/edit?access_token=#{ACCESS_TOKEN}";
    /**
     * 删除 入群欢迎语素材  的 url
     */
    public static final String DEL_GROUP_WELCOME_TEMPLATE = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/group_welcome_template/del?access_token=#{ACCESS_TOKEN}";
    /**
     * 发送 应用消息  的 url
     */
    public static final String SEND_APPLICATION_MESSAGE = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=#{ACCESS_TOKEN}";
    /**
     * 获取待分配的离职成员列表 的url
     */
    public static final String DIMISSION_WAIT_ALLOT_CLIENT = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_unassigned_list?access_token=#{ACCESS_TOKEN}";
    /**
     * 分配离职成员的客户
     */
    public static final String DIMISSION_ALLOT_Client = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/resigned/transfer_customer?access_token=#{ACCESS_TOKEN}";
    /**
     *  分配离职成员的客户群
     */
    public static final String DIMISSION_ALLOT_GROUP = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/transfer?access_token=#{ACCESS_TOKEN}";
    /**
     * 创建企业群发
     */
    public static final String ADD_CORP_MASS_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_msg_template?access_token=#{ACCESS_TOKEN}";
    /**
     * 编辑客户企业标签
     */
    public static final String EDIT_CUSTOMER_CORP_TAG = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/mark_tag?access_token=#{ACCESS_TOKEN}";
    /**
     * 获取企业的jsapi_ticket
     */
    public static final String CORP_JS_API_TICKET = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=";
    /**
     * 获取应用的jsapi_ticket
     */
    public static final String AGENT_JS_API_TICKET = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?type=agent_config&access_token=";
    /**
     * 获取 开通了会话存档的员工
     */
    public static final String MSG_AUDIT_EMPLOYEE = "https://qyapi.weixin.qq.com/cgi-bin/msgaudit/get_permit_user_list?access_token=#{ACCESS_TOKEN}";
    /**
     * corpid转换 的 url
     */
    public static final String CORPID_TO_OPENCORPID = "https://qyapi.weixin.qq.com/cgi-bin/service/corpid_to_opencorpid?provider_access_token=";
    /**
     * userid转换 的 url
     */
    public static final String USERID_TO_OPENUSERID = "https://qyapi.weixin.qq.com/cgi-bin/batch/userid_to_openuserid?access_token=";

    public static final String GET_NEW_EXTERNAL_USERID = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_new_external_userid?access_token=";

    public static final String UNIONID_TO_EXTERNAL_USERID = "https://qyapi.weixin.qq.com/cgi-bin/idconvert/unionid_to_external_userid?access_token=";

    public static final String EXTERNAL_USERID_TO_PENDING_ID = "https://qyapi.weixin.qq.com/cgi-bin/idconvert/batch/external_userid_to_pending_id?access_token=";

    public static final String FINISH_OPENID_MIGRATION = "https://qyapi.weixin.qq.com/cgi-bin/service/finish_openid_migration?provider_access_token=";
}
public class WeixinCorpKeyConst {
    public static String errcode = "errcode";
    public static String errmsg = "errmsg";

    // 服务商相关
    public static String corpId = "corpid";
    public static String authCorpId = "auth_corpid";
    public static String corpName = "corp_name";
    public static String suiteId = "suite_id";
    public static String suiteSecret = "suite_secret";
    public static String providerSecret = "provider_secret";
    public static String corpSecret = "corpsecret";
    public static String suiteTicket = "suite_ticket";
    public static String suiteAccessToken = "suite_access_token";
    public static String providerAccessToken = "provider_access_token";
    public static String preAuthCode = "pre_auth_code";
    public static String authCode = "auth_code";
    public static String permanentCode = "permanent_code";
    public static String authCorpInfo = "auth_corp_info";
    public static String authInfo = "auth_info";
    public static String agent = "agent";
    public static String agentId = "agentid";
    public static String accessToken = "access_token";

}

WeiXinProviderConst 就不贴了,里面就是记录上面那几个参数的

到这里可以发现,其实对接企业微信并不难,麻烦的地方就在于各种配置各种参数,然后就是回调,回调这个后面有空我也会整理出来

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

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

相关文章

等保定级指南(PPT原件)

新版网络安全等级保护定级指南网络安全等级保护工作的作用对象,主要包括基础信息网络、工业控制系统、云计算平台、物联网、使用移动互联技术的网络和大数据等。 软件全套精华资料包清单部分文件列表: 工作安排任务书,可行性分析报告&#xf…

前端自动化测试(一):揭秘自动化测试秘诀

目录 [TOC](目录)前言自动化测试 VS 手动测试测试分类何为单元测试单元测试的优缺点优点缺点 测试案例测试代码 测试函数的封装实现 expect 方法实现 test 函数结语 正文开始 , 如果觉得文章对您有帮助,请帮我三连订阅,谢谢💖&…

7月投稿警惕!6本On Hold期刊被数据库剔除!

本周投稿推荐 SCI&EI • 1区计算机类,3.5-4.0(1个月录用) • CCF推荐,1区-Top(3天初审) EI • 各领域沾边均可(2天录用) 知网(CNKI)、谷歌学术 •…

nginx的配置和使用

一、nginx支持win和linux版本的下载,选择合适的版本进行安装 二、配置文件注解 重点的几个参数进行注释: 1、listen 要监听的服务的端口,符合这个端口的才会被监听 server_name要监听的服务地址,可能是ip,也可能是域名&#xf…

流量书单,互联网营销必读

《流量池》杨飞 《增长黑客》肖恩埃利斯(Sean Ellis)、摩根布朗(Morgan Brown) 《增长五线》王赛 《参与感》黎万强 《场景革命》吴声 《网络营销实战密码》昝辉 《网络营销推广实战宝典》江礼坤 《超级IP,互联网新物种方法论》吴声 《周鸿祎自述&#xff0…

Golden Software Surfer v25 解锁版下载与安装教程 (三维绘图软件)

前言 Golden Software Surfer 是一款三维绘图软件,具备强大的插值功能和绘制图件能力,可用来处理XYZ数据,轻松绘制专业三维图。该软件有着很直观的用户界面,尽管不支持中文,但是很用户在熟悉流程以后依然能够轻松学会…

《计算机网络》(学习笔记)

目录 一、计算机网络体系结构 1.1 计算机网络概述 1.1.1 计算机网络的概念 1.1.2 计算机网络的组成 1.1.3 计算机网络的功能 1.1.4 电流交换、报文交换和分组交换 1.1.5 计算机网络的分类 1.1.6 计算机网络的性能指标 1.2 计算机网络体系结构与参考模型 1.2.1 计算机…

SpringCloud Nacos的配置与使用

Spring Cloud Nacos的配置与使用 文章目录 Spring Cloud Nacos的配置与使用1. 简单介绍2. 环境搭建3. 服务注册/服务发现4. Nacos 负载均衡4.1 服务下线4.2 权重配置4.3 同集群优先访问 5. Nacos 健康检查5.1 两种健康检查机制5.2 服务实例类型 6.Nacos 环境隔离6.1 创建namesp…

QT开发笔记:常用控件

常用控件: 站在巨人的肩膀上,Qt中已经提供了大量的内置控件(按钮、文本框、单选按钮、复选按钮、下拉框) 可直接学习其特性使用方法使用。 控件 Widget 界面上的各种元素,各种部分的统称。 HTML 包含很多标签&#…

解决 Shiro 重复调用 doGetAuthenticationInfo 导致异常处理错误的问题

遇到一个 Shiro 中反复调用 doGetAuthenticationInfo 导致异常没有被成功处理的问题,经过一些源码调试,发现了问题的所在,只需在继承 BasicHttpAuthenticationFilter 的类中重写 onAccessDenied 方法即可。 文章目录 1.问题环境2.问题描述3.问…

【数学 分类讨论】2029. 石子游戏 IX

本文涉及知识 质数、最大公约数、菲蜀定理 LeetCode 2029. 石子游戏 IX Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stones[i] 是第 i 个石子的价值。 Ali…

在 Kubernetes 中设置 Pod 优先级及其调度策略详解

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] &#x1f4f1…

Gson的基本使用:解析Json格式数据 序列化与反序列化

目录 一,Gson和Json 1,Gson 2,Json 3,Gson处理对象的几个重要点 4,序列化和反序列化 二,Gson的使用 1,Gson的创建 2,简单对象序列化 3,对象序列化,格…

vue学习笔记(十一)——开发心得(axios的封装、promise细节、vue-router开发中的使用)

1. axios的网络请求的封装 1.1 为什么要封装api? 代码分层,便于以后的修改,无需触碰逻辑页面 目标: 网络请求,不散落在各个逻辑页面里,封装起来方便以后修改 1.2 封装api步骤 ① 在项目 src 下新建目录 utlis &am…

海外发稿:打造希腊媒体宣发新局面

随着全球经济一体化的不断深入,企业对于海外市场的拓展需求日益迫切。在这个过程中,媒体宣发作为一种有效的市场推广手段,已经成为企业出海的重要策略之一。希腊,作为欧洲的重要经济体,拥有丰富的文化底蕴和众多的历史…

如何使用Python实现语音转文字/字幕

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 语音转文字/字幕 📒📝 Python实现📝 便捷封装⚓️ 相关链接 ⚓️📖 介绍 📖 想象一下,在观看一部无字幕的电影或者需要快速整理会议录音时,如果有一个魔法工具能瞬间将音频转化为清晰的文字,那该是多么便捷!今天,…

MPU6050三轴传感器

1.背景: MPU6050 是由 InvenSense(现为 TDK 旗下公司)生产的一款集成了三轴加速度计和三轴陀螺仪的微机电系统(MEMS)传感器。它可以测量物体在三个轴上的加速度和旋转角速度,被广泛应用于消费电子、工业控制…

微前端--single-spa

微前端 使用微前端的挑战: 子应用切换,应用相互隔离,互补干扰,子应用之前的通信,多个子应用并存,用户状态的存储,免登。 常用技术方案 路由分发式微前端 通过http服务的反向代理 http {serv…

光盘防水嘛 ? DVD+R 刻录光盘泡水实验

首发日期 2024-07-20, 以下为原文内容: 同志们好, 欢迎来到 胖喵穷人实验室 ! 这里专注于 低成本, 低难度, 低风险 的 “三低” 小实验. 胖喵穷人实验室 (PM-PLab-E)正式名称: 紫腹巨蚊 (Toxorhynchites gravelyi) 系列穷人 (Poor people) 实验室风险警告: 低风险并不是零风险…

47.简易电压表的设计与验证(2)

(1)Verilog 代码: module adc_collect(input clk ,input reset_n ,input [7:0] adc_data ,output clk_adc );wire clk_adc_a ;…