【第三方】微信登录

news2024/9/23 12:46:36

目录

  • 前言
  • 小程序登录
    • 步骤说明
    • 前端
      • 效果
      • 涉及到的接口
        • 登录凭证:wx.login
        • 获取用户信息:wx.getUserInfo
    • 后端
      • 涉及到接口
        • 小程序登录
      • 代码展示
  • 微信扫码登录

前言

微信官方文档,需要对接哪个模块就从哪里进入。
在这里插入图片描述
由于本次我们需要的是小程序的登录。所以就选择第一个。

介绍一下 API服务端
在这里插入图片描述

小程序登录

步骤说明

小程序登录步骤:

  1. 开发者客户端调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器
  2. 开发者服务器 调用 auth.code2Session 接口,换取 用户唯一标识 OpenID用户在微信开放平台账号下的唯一标识UnionID(若当前小程序已绑定到微信开放平台账号) 和 会话密钥 session_key

如果需要的话,开发者客户端 可以调用 wx.getUserInfo ,获取到 codeencryptedData, iv,再传回给 开发者服务器,去进行解密,解密成功后就可以拿到 用户信息。

前端

效果

用户信息功能页中注明:

用户信息功能页用于帮助插件获取用户信息,包括 openid 和昵称等,相当于 wx.loginwx.getUserInfo 的功能。

在基础库版本 2.3.1 前,用户信息功能页是插件中唯一的获取 code 和用户信息的方式;

自基础库版本 2.3.1 起,用户在该功能页中进行过授权后,插件可以直接调用 wx.login 和 wx.getUserInfo:
在这里插入图片描述

涉及到的接口

登录凭证:wx.login

在这里插入图片描述

获取用户信息:wx.getUserInfo

在这里插入图片描述

后端

以Java代码为展示。

涉及到接口

小程序登录

在这里插入图片描述

代码展示

可以参考链接:https://blog.51cto.com/u_16099229/7857781

从前面可以得到,前端会返回给后端一些数据。所以,就新建一个实体类来进行接受数据。

@Data
public class WechatMPLoginParams {
    /**
     * uuid 用户uuid
     * code 微信返回code 用于与微信交互获取openid 等信息
     * encryptedData 微信返回加密信息
     * iv 微信返回
     * image 微信头像
     * nickname 微信用户昵称
     */
    private String uuid, code, encryptedData, iv, image, nickName;
}

yaml配置

wechat:
  AppID: 
  AppSecret: 

依赖

        <hutool-all.version>5.7.18</hutool-all.version>

            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>${hutool-all.version}</version>
            </dependency>

控制层

    /**
     * 小程序自动登录
     *
     * @param params 请求参数
     * @return
     */
    @PostMapping("/login/auto-login")
    @ApiOperation(value = "小程序自动登录")
    public AjaxResult autoLogin(@RequestBody WechatMPLoginParams params) {
        return AjaxResult.success(connectService.miniProgramAutoLogin(params));
    }

业务层

@Slf4j
@Service
public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> implements ConnectService {

    static final boolean AUTO_REGION = true;

    @Value("${wechat.AppID}")
    private String WECHAT_APPID;
    @Value("${wechat.AppSecret}")
    private String WECHAT_APPSECRET;
    
    @Override
    @Transactional
    public String miniProgramAutoLogin(WechatMPLoginParams params) {
        HashMap cacheData = (HashMap) cache.get(CachePrefix.WECHAT_SESSION_PARAMS.getPrefix() + params.getUuid());
        Map<String, String> map = new HashMap<>(3);
        // 1. 这里最重要的是获取到 session key、unionId 、openId 
        // 先从缓存中,查看是否已经保存了用户小程序登录的信息
        if (StringUtils.isEmpty(cacheData)) {
            // 得到微信小程序联合登陆信息,并存进缓存里面
            getWechatMsgByCache(params, map);
        } else {
        	// 直接从缓存中获取到微信小程序联合登陆信息
            map = (Map<String, String>) cacheData;
            // System.out.println("cache: " + map.get("openId"));
        }
        // 2. 微信联合登陆
        return phoneMpBindAndLogin(map, params, map.get("openId"), map.get("unionId"));
    }
    
    /**
     * 微信小程序联合登陆信息并存储session key、unionId 、openId信息
     * 
     * @param params 参数
     * @param map 联合登录信息
     */
    private void getWechatMsgByCache(WechatMPLoginParams params, Map<String, String> map) {
        // System.out.println(params.getCode());
        JSONObject json = this.getConnect(params.getCode());
        // System.out.println(json);
        // 存储session key、unionId 、openId  后续登录用得到
        String sessionKey = json.getStr("session_key");
        String unionId = json.getStr("unionid");
        String openId = json.getStr("openid");


        map.put("sessionKey", sessionKey);
        map.put("unionId", unionId);
        map.put("openId", openId);
        cache.put(CachePrefix.WECHAT_SESSION_PARAMS.getPrefix() + params.getUuid(), map, 900L);
    }
    /**
     * 通过微信返回等code 获取openid 等信息
     *
     * @param code 微信code
     * @return 微信返回的信息
     */
    public JSONObject getConnect(String code) {
//        WechatConnectSettingItem setting = getWechatMPSetting();
        String url = "https://api.weixin.qq.com/sns/jscode2session?" +
                "appid=" + WECHAT_APPID + "&" +
                "secret=" + WECHAT_APPSECRET + "&" +
                "js_code=" + code + "&" +
                "grant_type=authorization_code";
        // log.info("微信返回等code 获取openid 等信息 " + url);
        String content = HttpUtils.doGet(url, "UTF-8", 100, 1000);
        // log.info(content);
        return JSONUtil.parseObj(content);
    }
	
	    @Transactional(rollbackFor = Exception.class)
    public String phoneMpBindAndLogin(Map<String, String> map, WechatMPLoginParams params) {
    	String sessionKey = map.get("sessionKey");
        String encryptedData = params.getEncryptedData();
        String iv = params.getIv();
        String unionId = map.get("unionId");
        String openId= map.get("openId");
        // 1. 解密获取用户信息
        JSONObject userInfo = this.getUserInfo(encryptedData, sessionKey, iv);
        // log.info("联合登陆返回:{}", userInfo.toString());
        // 2. 通过解密获得的电话号码查询是否存在该用户
        String phone = (String) userInfo.get("purePhoneNumber");
        SysUser user = new SysUser();
        List<SysUser> userList = sysUserService.selectUserInfoList(user);
        // 2.1 不存在该用户
        if (StringUtils.isEmpty(userList)) {
            throw new Exception("非员工手机号码,不允许进行微信绑定登录!");
        }
        // 2.2 存在该用户
        LoginUser loginUser = new LoginUser();
        SysUser sysUser = userList.get(0) ;
        BeanUtils.copyProperties(sysUser, loginUser);
        loginUser.setUser(sysUser);
        sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
        sysUser.setLoginDate(DateUtils.getNowDate());
        sysUser.setopenid(openId);
        sysUser.setUnionId(unionId);
        sysUserService.updateUserProfile(sysUser);
        // 3.  生成token
        return myTokenService.createToken(loginUser);
    }
    
    /**
     * 解密,获取微信信息
     *
     * @param encryptedData 加密信息
     * @param sessionKey    微信sessionKey
     * @param iv            微信揭秘参数
     * @return 用户信息
     */
    public JSONObject getUserInfo(String encryptedData, String sessionKey, String iv) {

        log.info("encryptedData:{},sessionKey:{},iv:{}", encryptedData, sessionKey, iv);
        //被加密的数据
        byte[] dataByte = Base64.getMimeDecoder().decode(encryptedData);
        //加密秘钥
        byte[] keyByte = Base64.getMimeDecoder().decode(sessionKey);
        //偏移量
        byte[] ivByte = Base64.getMimeDecoder().decode(iv);
        try {
            //如果密钥不足16位,那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + (keyByte.length % base != 0 ? 1 : 0);
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            //初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            //初始化
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters);
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, StandardCharsets.UTF_8);
                return JSONUtil.parseObj(result);
            }
        } catch (Exception e) {
            log.error("解密,获取微信信息错误", e);
        }
        throw new ServiceException("联合第三方登录,授权信息错误", 20012);
    }
}    

功能类

package com.higentec.system.common.utils.http;

import java.io.*;
import java.net.*;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.higentec.system.common.constant.Constants;
import com.higentec.system.common.utils.StringUtils;

/**
 * 通用http发送方法
 * 
 * @author higentec
 */
public class HttpUtils
{
    private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url 发送请求的 URL
     * @return 所代表远程资源的响应结果
     */
    public static String sendGet(String url)
    {
        return sendGet(url, StringUtils.EMPTY);
    }

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url 发送请求的 URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param)
    {
        return sendGet(url, param, Constants.UTF8);
    }

    /**
     * 向指定 URL 发送GET方法的请求
     *
     * @param url 发送请求的 URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @param contentType 编码类型
     * @return 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param, String contentType)
    {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try
        {
            String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
            log.info("sendGet - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (in != null)
                {
                    in.close();
                }
            }
            catch (Exception ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }

    /**
     * 向指定 URL 发送POST方法的请求
     *
     * @param url 发送请求的 URL
     * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param)
    {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        try
        {
            String urlNameString = url;
            log.info("sendPost - {}", urlNameString);
            URL realUrl = new URL(urlNameString);
            URLConnection conn = realUrl.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            out = new PrintWriter(conn.getOutputStream());
            out.print(param);
            out.flush();
            in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            log.info("recv - {}", result);
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
        }
        finally
        {
            try
            {
                if (out != null)
                {
                    out.close();
                }
                if (in != null)
                {
                    in.close();
                }
            }
            catch (IOException ex)
            {
                log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
            }
        }
        return result.toString();
    }

    public static String sendSSLPost(String url, String param)
    {
        StringBuilder result = new StringBuilder();
        String urlNameString = url + "?" + param;
        try
        {
            log.info("sendSSLPost - {}", urlNameString);
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
            URL console = new URL(urlNameString);
            HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("Accept-Charset", "utf-8");
            conn.setRequestProperty("contentType", "utf-8");
            conn.setDoOutput(true);
            conn.setDoInput(true);

            conn.setSSLSocketFactory(sc.getSocketFactory());
            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
            conn.connect();
            InputStream is = conn.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String ret = "";
            while ((ret = br.readLine()) != null)
            {
                if (ret != null && !"".equals(ret.trim()))
                {
                    result.append(new String(ret.getBytes("ISO-8859-1"), "utf-8"));
                }
            }
            log.info("recv - {}", result);
            conn.disconnect();
            br.close();
        }
        catch (ConnectException e)
        {
            log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
        }
        catch (SocketTimeoutException e)
        {
            log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
        }
        catch (IOException e)
        {
            log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
        }
        catch (Exception e)
        {
            log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
        }
        return result.toString();
    }

    private static class TrustAnyTrustManager implements X509TrustManager
    {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
        {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
        {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers()
        {
            return new X509Certificate[] {};
        }
    }


    /**
     * get 请求 静态方法
     *
     * @param link
     * @param encoding
     * @return
     */
    public static String doGet(String link, String encoding, int connectTimeout, int readTimeout) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(link);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(connectTimeout);
            conn.setReadTimeout(readTimeout);
            BufferedInputStream in = new BufferedInputStream(
                    conn.getInputStream());
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            for (int i = 0; (i = in.read(buf)) > 0; ) {
                out.write(buf, 0, i);
            }
            out.flush();
            String s = out.toString(encoding);
            return s;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
    }

    private static class TrustAnyHostnameVerifier implements HostnameVerifier
    {
        @Override
        public boolean verify(String hostname, SSLSession session)
        {
            return true;
        }
    }
}

如果需要单独从微信小程序获取用户手机号码,可参考:

  • 微信开发文档—— 获取手机号
  • 详细教程:微信小程序获取用户手机号码教程(前端+后端):https://blog.csdn.net/qq_51235856/article/details/131158254

微信扫码登录

微信登录——授权登录获取用户信息:https://blog.csdn.net/YXXXYX/article/details/127338450

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

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

相关文章

【解决方案】环保设备用电与电网数据集中展示平台的应用与研究

摘 要&#xff1a;近年来&#xff0c;信息化不断推进&#xff0c;政府工作方式以及职能不断改革&#xff0c;许多省级环保部门开展环保与信息技术的融合&#xff0c;用于推进环保的发展。本文基于环境监测研究省级环保与电网数据集中展示平台的应用。环境监测是环保工作的重要组…

百度APP iOS端包体积50M优化实践(七)编译器优化

一. 前言 百度APP iOS端包体积优化系列文章的前六篇重点介绍了包体积优化整体方案、图片优化、资源优化、代码优化、无用类优化、HEIC图片优化实践和无用方法清理&#xff0c;图片优化是从无用图片、Asset Catalog和HEIC格式三个角度做深度优化&#xff1b;资源优化包括大资源…

YOLOv8改进 | 2023 | Deformable-LKA可变形大核注意力(涨点幅度超高)

一、本文介绍 本文给大家带来的改进内容是Deformable-LKA&#xff08;可变形大核注意力&#xff09;。Deformable-LKA结合了大卷积核的广阔感受野和可变形卷积的灵活性&#xff0c;有效地处理复杂的视觉信息。这一机制通过动态调整卷积核的形状和大小来适应不同的图像特征&…

iOS17桌面待办事项提醒小组件,让的iPhone变身提醒神器

在现代社会&#xff0c;每天都有太多的事情需要处理&#xff0c;而我经常发现自己在繁忙中遗漏一些重要的事项。曾经&#xff0c;我每次都要在纸上记下要做的事情&#xff0c;可事后发现&#xff0c;这也没能解决我的忘性问题。 直到我尝试了一个新的方式&#xff0c;我的iPho…

自动驾驶:传感器初始标定

手眼标定 机器人手眼标定AxxB&#xff08;eye to hand和eye in hand&#xff09;及平面九点法标定 Ax xB问题求解&#xff0c;旋转和平移分步求解法 手眼标定AXXB求解方法&#xff08;文献总结&#xff09; 基于靶的方法 相机标定 (1) ApriTag (2) 棋盘格&#xff1a;cv::f…

直面多云困境,聊聊F5分布式云的破局之道

在数字化浪潮的大背景下&#xff0c;我们迎来了一个万物上云的时代。Gartner的调查数据显示&#xff0c;81%的公有云用户选择两个或两个以上的云服务供应商。对企业来说&#xff0c;充分利用多云网络可以实现业务的成功转型和增长。然而机遇与挑战并存&#xff0c;本文从多云网…

基于SSM的图书馆管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

[足式机器人]Part2 Dr. CAN学习笔记-数学基础Ch0-2 特征值与特征向量

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-数学基础Ch0-2 特征值与特征向量 1. 定义1.1 线性变换1.2 求解特征值&#xff0c;特征向量1.3 应用&#xff1a;对角化矩阵——解耦Decouple 2. Summary 1. 定义 A v ⃗ λ v ⃗ A\vec{v}\lambd…

chromium通信系统-ipcz系统(五)-ipcz系统代码实现-信道和共享内存

chromium通信系统-ipcz系统(二)-ipcz系统代码实现-同Node通信一文中我们分析了同Node通信的过程&#xff0c;在分析跨Node&#xff08;跨进程&#xff09;通信过程前&#xff0c;为了缩小篇幅&#xff0c;作为承上启下&#xff0c;我们先来分析一下Ipcz的通信信道和共享内存机制…

Cmake搭建QNX编译环境

1、确定QNX系统的架构 我们要如何确认QNX系统的架构呢&#xff1f; 连接我们的qnx开发板&#xff0c;输入下述指令。 uname -a以我的开发板为例子&#xff0c;版本信息如下&#xff1a; # uname -a QNX localhost 7.0.X 2022/04/21-10:05:23EDT SA8155_ADP_Star_v1.0.0_UFS…

数字与数学高频问题

关卡名 数字与数学高频问题 我会了✔️ 内容 1.掌握数组实现加法的方法 ✔️ 2.掌握高精度计算的实现方法 ✔️ 3.掌握幂运算的技巧 ✔️ 1. 数组实现加法专题 数字加法&#xff0c;小学生都会的问题&#xff0c;但是如果让你用数组来表示一个数&#xff0c;如何实现加法…

HMI和SCADA是什么?SCADA与HMI有何不同?

工业自动化领域最常见的话题之一就是“SCADA与HMI有何不同” &#xff1f; 人机界面 &#xff08;HMI&#xff09; 和监控与数据采集 &#xff08;SCADA&#xff09; 是工业自动化领域中经常互换使用的两个概念。在许多应用中&#xff0c;两个组件之间的边界经常存在混淆。这在…

【LeetCode:2477. 到达首都的最少油耗 | DFS + 贪心】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

[HTML]Web前端开发技术6(HTML5、CSS3、JavaScript )DIV与SPAN,盒模型,Overflow——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

Jupyter Notebook中设置Cell主题

1. 获取本机Jupyter的配置目录 C:\Users\Administrator>jupyter --data-dir C:\Users\Administrator\AppData\Roaming\jupyter2. 进入获取的目录&#xff0c;创建指定路径 C:\Users\Administrator>cd C:\Users\Administrator\AppData\Roaming\jupyter C:\Users\Adminis…

机器学习实验二:决策树模型

系列文章目录 机器学习实验一&#xff1a;线性回归机器学习实验二&#xff1a;决策树模型机器学习实验三&#xff1a;支持向量机模型机器学习实验四&#xff1a;贝叶斯分类器机器学习实验五&#xff1a;集成学习机器学习实验六&#xff1a;聚类 文章目录 系列文章目录一、实验…

kafka 3.x 学习笔记

kafka 3.x 学习笔记 在 kafka 2.8.0 版本之前&#xff0c;安装使用 kafka 需要配套安装 zookeeper&#xff0c;但在 2.8.0 版本之后&#xff0c;不再需要安装 zookeeper&#xff0c;本次学习笔记采用的 kafka 版本为 3.0.0。 文章目录 kafka 3.x 学习笔记一、kafka 定义1 什么是…

学习Opencv(蝴蝶书/C++)——4.图形和大型数组类型(上)

文章目录 1. cv::Mat类的成员变量1.1 flags1.2 cv::Mat::step2 存储方式,存储位置计算2.1 存储方式2.2 🌈存储位置计算2.2.1 基本计算公式2.2.1 step代码说明2.2.3 内存地址计算代码说明3 创建数据3.0 Mat的构成3.0.1 3.0版本之后的Mat3.0.2 cvMat3.1 构造函数3.2 🌈构造函…

Tomcat的启动关闭及日志说明

目录 1 启动Tomcat 1.1 启动 1.2 检查Tomcat启动是否正常 1.3 浏览器访问 2 关闭Tomcat 3 Tomcat日志说明 3.1 catalina.out 3.2 localhost.[日期].log 3.3 host-manager.[日期].log 3.4 manager.[日期].log 3.5 localhost_access_log.[日期].txt 1 启动Tomcat 1.1 启动 在…

Centos7.4安装nginx1.24.0_安装详细步骤---Linux工作笔记066

以前安装的太模糊了,干脆重新写一个: 1.首先下载对应的nginx-1.24.0.tar.gz安装文件 2.然后: 去执行命令 安装依赖 yum install -y gcc yum install -y pcre pcre-devel yum install -y zlib zlib-devel yum install -y openssl openssl-devel 3.然后:去解压 tar -zxvf ngi…