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

news2024/10/6 18:22:51

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换用户信息了

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

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

相关文章

人大金仓报The connection attempt failed.Reason:Connection reset解决办法

在连接人大京仓数据库 的时候报下面的错误 解决办法&#xff1a; 更换这里的IP地址就行&#xff0c;不要用127.0.0.1&#xff0c;然后就可以了

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

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

华为认证HCIE考试过程的小细节|备考注意事项

大家好&#xff0c;我是来自武汉软件工程职业学院计算机网络专业的李同学&#xff0c;我在2024年1月3日通过了华为Datacom-HCIE认证&#xff0c;在此把我的一些考证心得分享给正在备考的同学们。 感谢讯方的老师们 我能通过HCIE考试&#xff0c;离不开各位讯方老师的教导。感…

碳课堂|如何开展碳排放核算? ISO 14064-2 项目层次要点解读

为提高企业组织碳排放报告信誉度&#xff0c;国际标准化组织&#xff08;ISO&#xff09;发布了ISO14064标准&#xff0c;其中《ISO 14064-2 项目层次上对温室气体减排和清除增加的量化、监测和报告的规范及指南》提供了项目策划阶段的原则要求&#xff0c;以及项目实施阶段的量…

Jmeter性能测试(五)

一、Jmeter参数化常用方式 1、CSV 数据文件设置 2、查询数据库(JDBC Connection Configuration) 二、CSV 数据文件设置 1、准备一个txt文件(不需要写表头&#xff0c;直接写你要用的数据就行了&#xff0c;多个字段用英文逗号隔开) 2、添加一个CSV 数据文件设置(放全局最上…

PyQt5批量生成Checkbox及批量检查Checkbox的勾选状态

批量生成Checkbox并添加到TableWidget中 for i in range(10):checkbox_i QCheckBox(fCheckbox_{i}) # 生成Checkbox并命名为Checkbox_iself.ui_1.tableWidget_1.setCellWidget(i,1,checkbox_i) 批量检查勾选状态 # 批量生成Checkbox并存入列表 list_Checkbox_1 [] for …

工程伦理课堂记录

文章目录 0. 导论0.1 工程伦理教育的意义0.2 工程伦理教育要实现的目标 1. 工程与伦理1.1 工程伦理学科的产生1.2 工程和技术1.3 工程概念的理解演进1.4 工程的过程1.5 工程的特点1.6 工程活动的七个维度总结 2. 伦理2.1 道德伦理的概念2.2 道德伦理的关系2.3 伦理规范2.4 伦理…

Vue3---router(安装、路由跳转、路由守卫、本地存储)

Vue3—router&#xff08;安装、路由跳转、路由守卫、本地存储&#xff09; 目录 Vue3---router&#xff08;安装、路由跳转、路由守卫、本地存储&#xff09;基础使用安装创建路由 路由跳转无参跳转js写法html写法 有参跳转queryparams 路由守卫额外&#xff1a;本地存储sessi…

旧衣回收小程序开发:线上回收模式成为行业发展趋势

当下人们生活水平在不断提高&#xff0c;对衣服的要求也在增加&#xff0c;更新速度越来越快&#xff0c;闲置下来的旧衣服也在增加&#xff0c;为了减少浪费&#xff0c;旧衣回收行业受到了大众的关注。旧衣回收对我国资源回收、环境保护具有非常大的意义。 在互联网时代下&a…

练英语口语的app哪个好?6个软件教你快速练习英语口语

练英语口语的app哪个好&#xff1f;6个软件教你快速练习英语口语 练习英语口语对于提高语言能力非常重要&#xff0c;而现代科技为我们提供了许多方便实用的应用来帮助我们快速有效地进行口语练习。以下是六款优质的英语口语练习应用&#xff0c;它们结合了各种学习方式和技术…

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

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

解决Redis的键值前出现类似\xAC\xED\x00\x05t\x00*这样的字符序列

文章目录 1.问题2.解决方法3.StringRedisTemplate和RedisTemplate的区别 1.问题 在使用RedisTemplate对Redis进行操作时,发现Reids键值对前有\xAC\xED\x00\x05t\x00*这样的字符序列 如图所示: 虽说不影响使用,但是听影响观感的 2.解决方法 查找了很多方法,可以指定RedisTem…

笔试强训Day20 动态规划 模拟

经此一役小红所向无敌 题目链接&#xff1a;A-经此一役小红所向无敌_牛客小白月赛37 (nowcoder.com) 思路&#xff1a; 水题 直接跟思路即可。 AC code&#xff1a; #include<iostream> using namespace std; typedef long long LL; LL a1,a2,b1,b2,t1,t2,sum; int m…

Observability:监控与可观察性不同的 3 个原因

作者&#xff1a;来自 Elastic Elastic Observability Team 监控和可观察性通常可以互换使用&#xff0c;但它们并不完全相同。 监控是可观察性的重要组成部分&#xff0c;但可观察性远远超出了传统监控实践的范围。 主要区别&#xff1a;监控从各个组件收集数据 —— 时间和内…

高阶RAG-ReRank

1.背景-现RAG存在的问题 现在很明显&#xff0c;仅仅依靠向量检索技术不足以开发 RAG 应用程序&#xff0c;尤其是在生产环境中部署。 以下为案例&#xff1a; 关键词搜索容易返回不回答问题的结果稠密检索容易返回不正确的结果 实际RAG检索中也有很多类型问题&#xff0c;…

stm32 st7735驱动 详解

初始化指令 void LCD_Init(void) { #if USE_SIM_SPILCD_SIM_SPI_GPIO_Init(); #endifLCD_RES_0();//复位HAL_Delay(100);LCD_RES_1();HAL_Delay(100);LCD_BLK_1();//打开背光HAL_Delay(100);//************* Start Initial Sequence **********//LCD_SPI_Send_Cmd(0x11); //Sl…

链表面试题目:反转一个单链表的两种方法(解析+代码)

我们继续来看一下单链表的题目和代码吧&#xff0c;把学习的知识运用到实际中&#xff0c;大家加油 先看OJ题目 OJ题目&#xff08;反转单链表&#xff09; 双指针法 1.创建两个指针&#xff0c;为pre curr&#xff0c;curr指向头结点&#xff0c;curr用来遍历链表 2.curr指向…

VisualGDB : 在windows上开发和调试Linux代码(一)

传送门&#xff1a; 《VisualGDB &#xff1a; 解决编码导致的编译错误》 一、补充windows上 VisualGDB的安装 这里给大家附一个官方的下载路径&#xff1a;https://visualgdb.com/download/&#xff0c;根据自己的系统选择下载 笔者另附一个云盘的下载路径 VisualGDB https…

129423-53-6,Na+荧光探针一种可透过细胞的钠选择性荧光指示剂

引言&#xff1a;在化学研究的海洋中&#xff0c;优质的化学试剂是实验成功的关键。今天&#xff0c;我要为大家分享一款备受好评的化学试剂——SBFI AM。这款试剂以其独特的性能和广泛的应用领域&#xff0c;赢得了众多科研人员的青睐。 中文名称&#xff1a;钠离子荧光探针 …

不止是搭建 | 极空间虚拟机安装一个可做生产力的Ubuntu桌面系统以及后续优化

不止是搭建 | 极空间虚拟机安装一个可做生产力的Ubuntu桌面系统以及后续优化 哈喽小伙伴们好&#xff0c;偶是Stark-C~ 我在上篇极空间文章中不是给小伙伴们分享了使用虚拟机安装软路由固件『iStoreOS』的教程嘛&#xff1a; 打造Docker完全体&#xff0c; 开箱即用的各类插…