Springboot整合飞书向群组/指定个人发送消息/飞书登录

Springboot整合飞书向群组发送消息

  1. 飞书开放平台创建企业自建应用

image.png

  1. 添加应用能力-机器人

image.png

  1. 创建完成后,进入应用详情页,可以在首页看到 App Id 和 App Secret

image.png
image.png

  1. 在飞书pc端创建一群机器人

image.png
image.png
image.png
image.png
image.png

  1. 此处可以拿到该机器人的webhook地址,通过https的方式,也可以调用发送消息

image.png

  1. 从右侧菜单中,进入“安全设置”页面,配置回调地址

image.png

  1. Springboot进行整合通过发送http请求
package com.admin.manager.core;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.admin.manager.api.StartApplication;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.request.AuthFeishuRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zr 2024/3/25
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = StartApplication.class)
@Slf4j
public class LarkTest {
    @Test
    public void name() {
        sendMessage("test");
    }
    public static void sendMessage(String msg){
        String webHookUrl = "https://open.feishu.cn/open-apis/bot/v2/hook/e3d13a69-e777-4499-a1c9-e1ae0580a248";
        //请求的JSON数据,这里用map在工具类里转成json格式
        Map<String,Object> json=new HashMap();
        Map<String,Object> text=new HashMap();
        json.put("msg_type", "text");
        text.put("text", "项目告警通知:" + msg);
        json.put("content", text);
        //发送post请求
        String result = HttpRequest.post(webHookUrl).body(JSON.toJSONString(json), "application/json;charset=UTF-8").execute().body();
        System.out.println(result);
    }
}
  1. 测试通过,后续可以自行封装工具类或service

image.png

Springboot整合飞书向指定人员发送消息

其实这个就是两个步骤

  1. 获取人员列表信息

image.png

  1. 从人员列表中选出一个人员,拿到userId,发送对应消息即可

image.png

飞书开放平台-接口列表
飞书开放平台-接口调试平台
image.png
image.png

image.png

SDK 使用文档:https://github.com/larksuite/oapi-sdk-java/tree/v2_main
image.png

如果不需要通过机器人给群发送消息可以先不用webHookUrl

lark:
  webHookUrl: https://open.feishu.cn/open-apis/bot/v2/hook/xxxx
  appId: cli_xxxx
  appSecret: oiB2zcxxxx
  • getEmployees原飞书接口的返回对象属性很多,我只取了userId和name封装为LarkUser,有需要的可以自行参照文档取出自己需要的值,具体字段在Employee中
  • Client client = Client.newBuilder(“YOUR_APP_ID”, “YOUR_APP_SECRET”).build();是飞书官方提供的sdk,可以通过client直接对接口进行操作
package com.admin.manager.core.service;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.admin.manager.core.exception.BusinessException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lark.oapi.Client;
import com.lark.oapi.service.ehr.v1.model.Employee;
import com.lark.oapi.service.ehr.v1.model.ListEmployeeReq;
import com.lark.oapi.service.ehr.v1.model.ListEmployeeResp;
import com.lark.oapi.service.im.v1.model.CreateMessageReq;
import com.lark.oapi.service.im.v1.model.CreateMessageReqBody;
import com.lark.oapi.service.im.v1.model.CreateMessageResp;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 飞书工具
 *
 * @author zr 2024/3/26
 */
@Service
@Slf4j
public class LarkService {


    public static Client client;

    @Value("${lark.appId}")
    private String appId;

    @Value("${lark.appSecret}")
    private String appSecret;

    @Value("${lark.webHookUrl}")
    private String webHookUrl;


    @PostConstruct
    public void init() {
        this.client =  Client.newBuilder(appId, appSecret).build();
    }

    /**
     *
     * @param msg
     */
    public  void sendMessageToGroup(String msg) {
        //请求的JSON数据,这里用map在工具类里转成json格式
        Map<String, Object> json = new HashMap();
        Map<String, Object> text = new HashMap();
        text.put("text", "要素修改通知:" + msg);
        json.put("msg_type", "text");
        json.put("content", text);
        //发送post请求
        String result = HttpRequest.post(webHookUrl).body(JSON.toJSONString(json), "application/json;charset=UTF-8").execute().body();
        JSONObject res = JSON.parseObject(result);
        Integer code = (Integer) res.get("code");
    }

    /**
     * 发送消息给指定userid的员工
     * @param userId
     * @param msg
     * @return
     * @throws Exception
     */
    public  Boolean sendMessageToPerson(String userId, String msg) throws Exception {

        HashMap<String, String> content = new HashMap<>();
        content.put("text", msg);

        // 创建请求对象
        CreateMessageReq req = CreateMessageReq.newBuilder()
                .receiveIdType("user_id")
                .createMessageReqBody(CreateMessageReqBody.newBuilder()
                        .receiveId(userId)
                        .msgType("text")
                        .content(JSON.toJSONString(content))
                        .uuid(UUID.randomUUID().toString())
                        .build())
                .build();

        // 发起请求
        CreateMessageResp resp = client.im().message().create(req);

        // 处理服务端错误
        if (!resp.success()) {
            log.info(String.format("code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
            throw new BusinessException("飞书接口调用失败");
        }
        return true;
    }

    /**
     * 获取飞书员工列表
     *
     * @return
     */
    public  List<LarkUser> getEmployees() throws Exception {
        // 创建请求对象
        ListEmployeeReq req = ListEmployeeReq.newBuilder()
                .userIdType("user_id")
                .build();

        // 发起请求
        ListEmployeeResp resp = client.ehr().employee().list(req);
        // 处理服务端错误
        if (!resp.success()) {
            log.info(String.format("code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
            throw new BusinessException("飞书接口调用失败");
        }
        Employee[] items = resp.getData().getItems();
        List<LarkUser> larkUsers = Arrays.stream(items).map(x -> {
            LarkUser larkUser = new LarkUser();
            larkUser.setUserId(x.getUserId());
            larkUser.setName(x.getSystemFields().getName());
            return larkUser;
        }).collect(Collectors.toList());
        return larkUsers;
    }

    /**
     * 获取tenantAccessToken
     *
     * @return 返回null代表失败
     */
    public  String getAccessToken() {
        String url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/";

        HashMap<String, Object> query = new HashMap<>();
        query.put("app_id", "cli_a68bb76781b8500e");
        query.put("app_secret", "oiB2zcIy3MVno2JjWRLBxgJqU2xZ5qWi");
        String res = HttpUtil.post(url, query);
        JSONObject resObject = JSON.parseObject(res);
        Integer code = (Integer) resObject.get("code");
        if (code == 0) {
            String appAccessToken = (String) resObject.get("app_access_token");
            String tenantAccessToken = (String) resObject.get("tenant_access_token");
            return tenantAccessToken;
        } else {
            return null;
        }


    }

    @Data
    public static class LarkUser{
        public String userId;
        public String name;
    }

}

此处是需要userId,应该是选择指定的人来进行发送,因为是测试而我的账号刚好最后一个,所以我取集合的最后一个元素

package com.admin.manager.core;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.admin.manager.api.StartApplication;
import com.admin.manager.core.service.LarkService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import lombok.extern.slf4j.Slf4j;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.*;

/**
 * @author zr 2024/3/25
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = StartApplication.class)
@Slf4j
public class LarkTest {
    @Autowired
    private LarkService larkService;

    @Test
    public void name() {
        try {
            List<LarkService.LarkUser> employees = larkService.getEmployees();
            System.out.println(employees);
            LarkService.LarkUser larkUser = employees.get(employees.size() - 1);
            larkService.sendMessageToPerson(larkUser.getUserId(), "test");

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

image.png

从右侧菜单中,进入“权限管理”页面,配置应用权限(选择自己所需的权限)

注:

  • 如需获取用户邮箱,请添加“获取用户邮箱”权限
  • 如需获取用户手机号,请添加“获取用户手机号”权限
  • 其他必选如“获取用户 userid”、“获取用户统一ID”、“获取用户基本信息”
  • 其他权限,请开发者根据自身要求添加

image.png

Springboot-JustAuth整合飞书登录

  1. 配置飞书回调地址http://localhost:8084/oauth/callback/FEISHU可以本地调试,其他环境需要更换ip或域名

image.png

  1. 配置人员(配置可以登录的人员,我这里设置的是全部人员,就不用手动加人了,也可以指定人员)

image.png

  1. 引入依赖
        <dependency>
            <groupId>me.zhyd.oauth</groupId>
            <artifactId>JustAuth</artifactId>
            <version> 1.16.4</version>
        </dependency>
  1. 配置
lark:
  #机器人地址(自己创建的)
  webHookUrl: https://open.feishu.cn/open-apis/bot/v2/hook/e3dxxxx
  #飞书回调地址
  loginHookUrl: http://localhost:8084/oauth/callback/FEISHU
  #登录成功重定向地址(根据自己需要配置)
  redirectUrl: http://localhost:9528/dashboard
  #token有效期
  expiry: 12
  #飞书appId
  appId: cli_a69e5b6e0xxxx
  #飞书appSecret
  appSecret: ZQ1nqsQ4i4FovYxxxxx
  1. 对应service
package com.admin.manager.core.service;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.admin.manager.core.exception.BusinessException;
import com.admin.manager.core.model.Result;
import com.admin.manager.core.model.dto.LarkUserInfo;
import com.admin.manager.core.model.dto.SsoResultResDto;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lark.oapi.Client;
import com.lark.oapi.service.ehr.v1.model.Employee;
import com.lark.oapi.service.ehr.v1.model.ListEmployeeReq;
import com.lark.oapi.service.ehr.v1.model.ListEmployeeResp;
import com.lark.oapi.service.im.v1.model.CreateMessageReq;
import com.lark.oapi.service.im.v1.model.CreateMessageReqBody;
import com.lark.oapi.service.im.v1.model.CreateMessageResp;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthFeishuRequest;
import me.zhyd.oauth.request.AuthRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 飞书工具
 *
 * @author zr 2024/3/26
 */
@Service
@Slf4j
public class LarkService {


    public static Client client;

    @Value("${lark.appId}")
    private String appId;

    @Value("${lark.appSecret}")
    private String appSecret;

    @Value("${lark.redirectUrl}")
    public String redirectUrl;

    @Value("${lark.expiry}")
    public Integer expiry;


    @Value("${lark.webHookUrl}")
    private String webHookUrl;

    @Value("${lark.loginHookUrl}")
    private String loginHookUrl;

    @Autowired
    //此处ssoService是获取用户信息,可以改成自己所需要的用户信息服务
    private SsoService ssoService;


    @PostConstruct
    public void init() {
        this.client =  Client.newBuilder(appId, appSecret).build();
    }

    /**
     *
     * @param msg
     */
    public  void sendMessageToGroup(String msg) {
        //请求的JSON数据,这里用map在工具类里转成json格式
        Map<String, Object> json = new HashMap();
        Map<String, Object> text = new HashMap();
        text.put("text", "要素修改通知:" + msg);
        json.put("msg_type", "text");
        json.put("content", text);
        //发送post请求
        String result = HttpRequest.post(webHookUrl).body(JSON.toJSONString(json), "application/json;charset=UTF-8").execute().body();
        JSONObject res = JSON.parseObject(result);
        Integer code = (Integer) res.get("code");
    }

    /**
     * 发送消息给指定userid的员工
     * @param userId
     * @param msg
     * @return
     * @throws Exception
     */
    public  Boolean sendMessageToPerson(String userId, String msg) throws Exception {

        HashMap<String, String> content = new HashMap<>();
        content.put("text", msg);

        // 创建请求对象
        CreateMessageReq req = CreateMessageReq.newBuilder()
                .receiveIdType("union_id")
                .createMessageReqBody(CreateMessageReqBody.newBuilder()
                        .receiveId(userId)
                        .msgType("text")
                        .content(JSON.toJSONString(content))
                        .uuid(UUID.randomUUID().toString())
                        .build())
                .build();

        // 发起请求
        CreateMessageResp resp = client.im().message().create(req);

        // 处理服务端错误
        if (!resp.success()) {
            log.info(String.format("code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
            throw new BusinessException("飞书接口调用失败");
        }
        return true;
    }

    /**
     * 获取飞书员工列表
     *
     * @return
     */
    public  List<LarkUser> getEmployees() throws Exception {
        // 创建请求对象
        ListEmployeeReq req = ListEmployeeReq.newBuilder()
                .userIdType("open_id")
                .build();

        // 发起请求
        ListEmployeeResp resp = client.ehr().employee().list(req);
        // 处理服务端错误
        if (!resp.success()) {
            log.info(String.format("code:%s,msg:%s,reqId:%s", resp.getCode(), resp.getMsg(), resp.getRequestId()));
            throw new BusinessException("飞书接口调用失败");
        }
        Employee[] items = resp.getData().getItems();
        List<LarkUser> larkUsers = Arrays.stream(items).map(x -> {
            LarkUser larkUser = new LarkUser();
            larkUser.setUserId(x.getUserId());
            larkUser.setName(x.getSystemFields().getName());
            return larkUser;
        }).collect(Collectors.toList());
        return larkUsers;
    }

    /**
     * 获取tenantAccessToken
     *
     * @return 返回null代表失败
     */
    public  String getAccessToken() {
        String url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/";

        HashMap<String, Object> query = new HashMap<>();
        query.put("app_id", "cli_a68bb76781b8500e");
        query.put("app_secret", "oiB2zcIy3MVno2JjWRLBxgJqU2xZ5qWi");
        String res = HttpUtil.post(url, query);
        JSONObject resObject = JSON.parseObject(res);
        Integer code = (Integer) resObject.get("code");
        if (code == 0) {
            String appAccessToken = (String) resObject.get("app_access_token");
            String tenantAccessToken = (String) resObject.get("tenant_access_token");
            return tenantAccessToken;
        } else {
            return null;
        }


    }

    public AuthRequest getAuthRequest() {
        return  new AuthFeishuRequest(AuthConfig.builder()
                .clientId(appId)
                .clientSecret(appSecret)
                .redirectUri(loginHookUrl)
                .build());
    }
//    http://127.0.0.1:8084/oauth/render
    public Result<SsoResultResDto.SsoUserInfo> login(AuthCallback callback) {
        AuthRequest authRequest = getAuthRequest();
        AuthResponse<AuthUser> authResponse = authRequest.login(callback);
        log.info("飞书登录返回:{}",JSON.toJSONString(authResponse));
        if (authResponse.ok()){
            JSONObject  data = (JSONObject) authResponse.getData().getRawUserInfo().get("data");

            log.info(JSON.toJSONString(data));
            LarkUserInfo larkUserInfo = data.toJavaObject(LarkUserInfo.class);
            AuthToken token = authResponse.getData().getToken();
            //此处ssoService是获取用户信息,可以改成自己所需要的用户信息服务
            Result<SsoResultResDto.SsoUserInfo> ssoUserInfo = ssoService.getSsoUserInfoByOpenId(larkUserInfo.getUnionId());
            log.info("SsoUserInfo 返回:{}",JSON.toJSONString(authResponse));
            return ssoUserInfo;
        }else {
            return Result.failure(authResponse.getMsg());
        }
    }
    @Data
    public static class LarkUser{
        public String userId;
        public String name;
    }
}

  1. 对应Controller
package com.admin.manager.api.controller;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import com.admin.manager.core.model.Result;
import com.admin.manager.core.model.dto.SsoResultResDto;
import com.admin.manager.core.service.LarkService;
import com.admin.manager.core.util.RedisUtil;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.request.AuthFeishuRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author zr 2024/3/28
 */
@RestController
@Api(tags = "认证")
@RequestMapping("/oauth")
public class RestAuthController {


    @Autowired
    private LarkService larkService;

    @GetMapping("/render")
    @ApiOperation(value = "飞书登录")
    public void renderAuth(HttpServletResponse response) throws IOException {
        AuthRequest authRequest = larkService.getAuthRequest();
        response.sendRedirect(authRequest.authorize(AuthStateUtils.createState()));
    }

    @GetMapping("/callback/FEISHU")
    @ApiOperation(value = "飞书回调")
    public void  callback(AuthCallback callback, HttpServletResponse response) throws IOException {
        Result<SsoResultResDto.SsoUserInfo> res = larkService.login(callback);
        //此处生成一个12位的token
        String token = RandomUtil.randomString(12);
        //重定向携带该token
        String redirectUrl = larkService.redirectUrl + "?token=" + token;
        //将token存入redis
        RedisUtil.StringOps.setEx("admin:"+token, JSON.toJSONString(res.getResult()), larkService.expiry, TimeUnit.HOURS);
        response.sendRedirect(redirectUrl);

    }

    //重定向后前端拿到token访问这个接口拿到用户信息
    @GetMapping("/auth")
    @ApiOperation(value = "获取用户信息")
    public Result<SsoResultResDto.SsoUserInfo> auth(@RequestParam("token") String token) {
        
        String userInfo = RedisUtil.StringOps.get("admin:" + token);
        if (StringUtils.isNotEmpty(userInfo)){
            SsoResultResDto.SsoUserInfo ssoUserInfo = JSON.parseObject(userInfo, SsoResultResDto.SsoUserInfo.class);
            return Result.success(ssoUserInfo);
        }else {
            return Result.failure("未登录");
        }

    }
}

  1. 测试

http://localhost:8084/oauth/render(记得换端口)
image.png
登录成功后,飞书会回调/oauth/callback/FEISHU接口,我这里是示范地址记得修改
image.png
之后前端就可以调用/oauth/auth接口拿token换用户信息了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

为什么说RK3562可以碾压PX30?

在如今的科技市场中&#xff0c;处理器的性能直接决定了设备的运行速度和用户体验。今天&#xff0c;我们将对比瑞芯微旗下的两款处理器&#xff1a;PX30与RK3562。RK3562比PX30的性价比究竟高在哪里&#xff1f; PX30 瑞芯微PX30是一款高性能的四核应用处理器&#xff0c;专…

Android单行字符串末尾省略号加icon,图标可点击

如图 设置仅显示单行字符串&#xff0c;末尾用省略号&#xff0c;加跟一个icon&#xff0c;icon可点击 tvName.text "test"val drawable ResourcesCompat.getDrawable(resources, R.mipmap.icon_edit, null)tvName.setCompoundDrawablesWithIntrinsicBounds(null,…

故障——蓝桥杯十三届2022国赛大学B组真题

问题分析 这道题纯数学&#xff0c;考察贝叶斯公式 AC_Code #include <bits/stdc.h> using namespace std; typedef pair<int,double> PI; bool cmp(PI a,PI b){if(a.second!b.second)return a.second>b.second;return a.first<b.first; } int main() {i…

在Leaflet中点对象使用SVG和Canvas两种模式的对比

目录 前言 一、关于SVG和Canvas 1、SVG知识 2、Canvas知识 3、优缺点 二、SVG和Canvas在Leaflet的使用 1、相关类图 2、Leaflet的默认展示方式 三、SVG和Canvas实例及性能对比 1、SVG模式及性能对比 2、Canvas优化 总结 前言 众所周知&#xff0c;在Leaflet当中&#…

vue3配置element-plus时间选择器中文显示

修改main.js import ElementPlus from element-plus import element-plus/dist/index.css // 引入中文包 import zhCn from "element-plus/es/locale/lang/zh-cn"; const app createApp(App) app.use(ElementPlus,{ locale: zhCn, }) //挂载 app.mount(#app)

白盒测试:覆盖测试及测试用例设计

白盒测试&#xff1a;覆盖测试及测试用例设计 一、实验目的 1、掌握白盒测试的概念。 2、掌握逻辑覆盖法。 二、实验任务 某工资计算程序功能如下&#xff1a;若雇员月工作小时超过40小时&#xff0c;则超过部分按原小时工资的1.5倍的加班工资来计算。若雇员月工作小时超过…

数据库系统理论——关系数据库

文章目录 一、关系&#xff08;数据结构&#xff09;1、概述2、名词解释3、关系模式、关系数据库、关系数据库模式4、基本关系的性质 二、关系操作&#xff08;数据操作&#xff09;三、关系的完整性1、实体完整性2 、参照完整性3、用户自定义的完整性 四、关系代数五、习题 前…

Twitch赠送暗区突围测试资格 超简单暗区突围测试资格领取教程

作为直播界的领航者&#xff0c;Twitch平台不仅是全球游戏文化直播的中心舞台&#xff0c;更是频繁联袂各路游戏大作&#xff0c;为粉丝们奉上别具匠心的互动盛宴&#xff0c;让观赛的同时解锁诱人的游戏内惊喜。正值《暗区突围》PC版测试的热潮涌动&#xff0c;Twitch乘势加强…

详细分析McCabe环路复杂度(附例题)

目录 前言1. 基本知识2. 例题 前言 该知识点常出在408或者软考中&#xff0c;对此此文重点讲讲理论知识以及例题 对于例题平时看到也会更新 1. 基本知识 McCabe环路复杂度是一种用于衡量软件代码复杂性的指标&#xff0c;主要是通过计算代码中的控制流图中的环路数量来衡量…

华为数据之道第一部分导读

目录 导读 第一部分 序 第1章 数据驱动的企业数字化转型 非数字原生企业的数字化转型挑战 业态特征&#xff1a;产业链条长、多业态并存 运营环境&#xff1a;数据交互和共享风险高 IT建设过程&#xff1a;数据复杂、历史包袱重 数据质量&#xff1a;数据可信和一致化…

逆向中webpack需要补充的模块很多怎么办

如下面这种典型的形式 进入i找到加载器 找到加载器所在函数r,在 return e[a].call(c.exports, c, c.exports, r),打上断点。 在控制台打印e,会发现它总共有的模块&#xff0c;这些模块需要我们在别的webpack中复制&#xff0c;有时很多&#xff0c;很麻烦。 我们可以注入代码在…

es6语法总结

【1】语法 &#xff08;1&#xff09;声明变量(let-var-const) 变量提升&#xff1a; 是JavaScript引擎在代码执行前将变量的声明部分提升到作用域顶部的行为。尽管变量的声明被提升了&#xff0c;变量的赋值&#xff08;即初始化&#xff09;仍然保留在原来的位置。因此&…

紫外激光打标机适合在哪些材料表面进行标记

紫外激光打标机适合在多种材料表面进行标记&#xff0c;特别是那些对热敏感或者需要高精度、高清晰度标记的材料。以下是一些常见的适用材料&#xff1a; 1. 塑料&#xff1a;紫外激光打标机在塑料材料上表现尤为出色&#xff0c;因为紫外激光的短波长和高能量密度使得它能够在…

基于树莓派的六足机器人方案设计+源代码+工程内容说明

文章目录 源代码下载地址项目介绍项目内容说明简单预览 项目备注源代码下载地址 源代码下载地址 点击这里下载源码 项目介绍 项目内容说明 hardware为项目相关硬件设计 机械结构为六足机器人的3d建模工程&#xff0c;包括本体和云台遥控器在ESP32最小开发板上集成了MPU605…

ChatGPT DALL-E绘图,制作各种表情包,实现穿衣风格的自由切换

DALL-E绘图功能探索&#xff1a; 1、保持人物形象一致&#xff0c;适配更多的表情、动作 2、改变穿衣风格 3、小女孩的不同年龄段展示 4、不同社交平台的个性头像创作 如果不会写代码&#xff0c;可以问GPT。使用地址&#xff1a;我的GPT4 视频&#xff0c;B站会发&#…

茅台申购,多平台签到与通知 | 使用极空间NAS部署一个神级脚本『DailyCheckIn』

茅台申购&#xff0c;多平台签到与通知 | 使用极空间NAS部署一个神级脚本『DailyCheckIn』 哈喽小伙伴们好&#xff0c;我是Stark-C~&#xff0c;今天为大家分享一个极空间上非常实用且好玩的项目。 小伙伴们都知道&#xff0c;目前很多平台为了促进用户的活跃度和黏性&#…

ENVI拓展工具资源去哪里找

ENVI拓展工具资源去哪里找&#xff1f; 文章目录 ENVI拓展工具资源去哪里找&#xff1f;前言网站&#xff08;链接见文末&#xff09;ENVI应用商店&#xff08;App Store&#xff09;ENVI官方提供第三方制作自己制作 总结参考 前言 ENVI 拓展工具是指 ENVI 软件的扩展功能或插…

WordPress插件:链接自动识别转为超链接

WordPress插件&#xff1a;链接自动识别转为超链接 <?phpfunction open_links_in_new_tab() {add_filter(the_content, make_clickable);function autoblank($text) {$return str_replace(<a, <a target"_blank", $text);return $return;}add_filter(th…

海外市场成 ISV 新掘金地?生成式 AI 如何加速业务创新实践?Zilliz 有话说

期望了解 Zilliz 最新动态&#xff1f;想要与 Zilliz 线下探讨 AI 时代向量数据库的全球化布局思考及典型实践&#xff1f; 机会来啦&#xff01;5 月 10 日&#xff0c;Zilliz 将闪现亚马逊云科技的两场活动现场&#xff08;苏州、西安&#xff09;&#xff0c;与大家共话行业…

【Kubernetes集群一主二从安装教程】

文章目录 环境准备主机间做信任安装ansible工具 升级内核版本使用elrepo源升级内核查看最新版内核安装最新的内核版本设置系统默认内核设置默认内核为我们刚才升级的内核版本 初始化关闭防火墙关闭selinux关闭swap修改主机名修改hosts文件将桥接的IPv4流量传递到iptables的链配…