当前位置: 首页 > news >正文

java 通过 microsoft graph 调用outlook(二)

这次提供一些基础调用方式API

PS:

getMailFolders 接口返回的属性中,包含了未读邮件数量unreadItemCount  

一 POM文件

        <!--    office 365    --><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.3-jre</version></dependency><dependency><groupId>com.azure</groupId><artifactId>azure-identity</artifactId><version>1.11.1</version><scope>compile</scope></dependency><dependency><groupId>com.microsoft.graph</groupId><artifactId>microsoft-graph</artifactId><version>5.77.0</version></dependency><!--    office 365    -->

二 Service / Impl

service

package com.xxx.mail.service;import com.microsoft.graph.models.Attachment;
import com.microsoft.graph.models.MailFolder;
import com.microsoft.graph.models.Message;
import com.microsoft.graph.models.User;
import com.microsoft.graph.requests.MailFolderCollectionPage;
import com.microsoft.graph.requests.MailFolderCollectionResponse;
import com.microsoft.graph.requests.MessageCollectionPage;
import org.springframework.web.multipart.MultipartFile;import java.util.List;public interface IMailOffice365Service {/*** 用户信息** @param email* @return*/User getUser(String email);/*** 邮件文件夹* 可显示未读邮件数量* @param email 邮箱* @return*/MailFolderCollectionPage getMailFolders(String email);/*** 邮件列表** @param email* @return*/MessageCollectionPage getFolderMails(String email,String folderId,int page,int size);MessageCollectionPage getMails(String email,int page,int size);/*** 邮件** @param email* @return*/Message getMailById(String email, String messageId);/*** 带有图片的邮件** @param message* @return*/Message getMailByIdWithAttachment(Message message);/*** 发送邮件** @param sender* @param recipient* @param subject* @param body* @throws Exception*/void sendMail(String sender , String recipient , String subject, String body) throws Exception;/*** 发送邮件(多个收件人)** @param sender* @param recipients* @param subject* @param body* @throws Exception*/void sendMail(String sender ,List<String> recipients ,String subject, String body) throws Exception;/*** 发送邮件和附件(多个收件人)** @param sender* @param recipients* @param subject* @param body* @throws Exception*/void sendMail(String sender , List<String> recipients , String subject, String body, List<MultipartFile> files) throws Exception;/**** 回复** @param messageId* @param sender* @param recipient* @param subject* @param body* @throws Exception*/void replyMail(String messageId, String sender, String recipient, String subject, String body) throws Exception;/**** 回复** @param messageId* @param sender* @param recipients* @param subject* @param body* @throws Exception*/void replyMail(String messageId, String sender, List<String> recipients, String subject, String body) throws Exception;/**** 回复带附件** @param messageId* @param sender* @param recipients* @param subject* @param body* @throws Exception*/void replyMail(String messageId, String sender, List<String> recipients, String subject, String body, List<MultipartFile> files) throws Exception;/*** 添加附件* @param message* @param files* @return*/Message addAttarchment(Message message,List<MultipartFile> files);}

impl

package com.xxx.mail.service.impl;import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.xxx.mail.service.IMailOffice365Service;
import com.microsoft.graph.authentication.IAuthenticationProvider;
import com.microsoft.graph.authentication.TokenCredentialAuthProvider;
import com.microsoft.graph.models.*;
import com.microsoft.graph.requests.*;
import okhttp3.Request;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;@Service("mailOffice365Util")
public class MailOffice365Impl implements IMailOffice365Service {@Value("${mailOffice365.clientId}")private String clientId;@Value("${mailOffice365.tenantId}")private String tenantId;@Value("${mailOffice365.clientSecret}")private String clientSecret;@Value("${mailOffice365.graphUserScopes}")private String graphUserScopes;private IAuthenticationProvider authProvider;@PostConstructpublic void init() {auth();}/*** auth 授权*/private void auth() {ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder().clientId(clientId).tenantId(tenantId).clientSecret(clientSecret).build();authProvider = new TokenCredentialAuthProvider(Arrays.asList("https://graph.microsoft.com/.default"), clientSecretCredential);}/*** 获取用户信息** @param email 邮箱* @return*/public User getUser(String email) {GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();User user = graphClient.users(email).buildRequest().select("displayName,mail,userPrincipalName").get();return user;}/*** 邮件文件夹** @param email 邮箱* @return*/@Overridepublic MailFolderCollectionPage getMailFolders(String email) {GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();MailFolderCollectionPage result = graphClient.users(email).mailFolders().buildRequest().get();return result;}/*** 获取文件夹邮件** @param email 邮箱* @return*/public MessageCollectionPage getFolderMails(String email, String folderId, int page, int size) {GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();MessageCollectionPage message = graphClient.users(email).mailFolders().byId(folderId).messages().buildRequest().select("id,from,isRead,receivedDateTime,subject").skip(page * size).top(size).orderBy("receivedDateTime DESC").get();return message;}/*** 获取邮件** @param email 邮箱* @return*/public MessageCollectionPage getMails(String email, int page, int size) {GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();MessageCollectionPage message = graphClient.users(email).messages().buildRequest().select("id,from,isRead,receivedDateTime,subject").skip(page * size).top(size).orderBy("receivedDateTime DESC").get();return message;}/*** 邮件详情** @param email     邮箱* @param messageId 邮件id* @return*/@Overridepublic Message getMailById(String email, String messageId) {GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();Message message = graphClient.users(email)
//            .mailFolders("inbox").messages().byId(messageId).buildRequest().select("id,from,isRead,receivedDateTime,subject,body,hasAttachments").expand("attachments").get();return message;}/*** 获取带有图片的邮件** @param message 邮件* @return*/@Overridepublic Message getMailByIdWithAttachment(Message message) {//邮件内图片展示String emailBody = message.body.content;for (Attachment attachment : message.attachments.getCurrentPage()) {if (attachment.isInline.booleanValue()) {if ((attachment instanceof FileAttachment) && (attachment.contentType.contains("image"))) {FileAttachment fileAttachment = (FileAttachment) attachment;byte[] contentBytes = fileAttachment.contentBytes;String imageContentIDToReplace = "cid:" + fileAttachment.contentId;emailBody = emailBody.replace(imageContentIDToReplace,String.format("data:image;base64,%s", Base64.getEncoder().encodeToString(contentBytes)));}}}message.body.content = emailBody;return message;}/*** 发送邮件** @param sender    发件人* @param recipient 收件人* @param subject   主题* @param body      内容* @throws Exception*/public void sendMail(String sender, String recipient, String subject, String body) throws Exception {List<String> recipients = List.of(recipient);sendMail(sender, recipients, subject, body, null);}/*** 发送邮件(多个收件人)** @param sender     发件人* @param recipients 多收件人* @param subject    主题* @param body       内容* @throws Exception*/public void sendMail(String sender, List<String> recipients, String subject, String body) throws Exception {sendMail(sender, recipients, subject, body, null);}/*** 发送邮件(多个收件人)** @param sender     发件人* @param recipients 多收件人* @param subject    主题* @param body       内容* @param files      附件* @throws Exception*/@Overridepublic void sendMail(String sender, List<String> recipients, String subject, String body, List<MultipartFile> files) throws Exception {GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();// Ensure client isn't nullif (graphClient == null) {throw new Exception("Graph has not been initialized for user auth");}// Create a new messageMessage message = new Message();message.subject = subject;message.body = new ItemBody();message.body.content = body;message.body.contentType = BodyType.TEXT;//收件人if (recipients != null && recipients.size() > 0) {message.toRecipients = new ArrayList<>();for (String item : recipients) {Recipient toRecipient = new Recipient();toRecipient.emailAddress = new EmailAddress();toRecipient.emailAddress.address = item;message.toRecipients.add(toRecipient);}}//附件message = addAttarchment(message, files);// Send the messagegraphClient.users(sender).sendMail(UserSendMailParameterSet.newBuilder().withMessage(message).build()).buildRequest().post();}public void replyMail(String messageId, String sender, String recipient, String subject, String body) throws Exception {List<String> recipients = List.of(recipient);replyMail(messageId, sender, recipients, subject, body, null);}public void replyMail(String messageId, String sender, List<String> recipients, String subject, String body) throws Exception {replyMail(messageId, sender, recipients, subject, body, null);}@Overridepublic void replyMail(String messageId, String sender, List<String> recipients, String subject, String body, List<MultipartFile> files) throws Exception {GraphServiceClient<Request> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();Message message = new Message();message.subject = subject;message.body = new ItemBody();message.body.content = body;message.body.contentType = BodyType.TEXT;//收件人if (recipients != null && recipients.size() > 0) {message.replyTo = new ArrayList<>();for (String item : recipients) {Recipient toRecipient = new Recipient();toRecipient.emailAddress = new EmailAddress();toRecipient.emailAddress.address = item;message.replyTo.add(toRecipient);}}//附件message = addAttarchment(message, files);graphClient.users(sender).messages().byId(messageId).reply(MessageReplyParameterSet.newBuilder().withMessage(message)
//                        .withComment("helloasf").build()).buildRequest().post();}/*** 添加附件** @param message* @param files*/@Overridepublic Message addAttarchment(Message message, List<MultipartFile> files) {if (files != null && files.size() > 0) {List<Attachment> attachmentList = new ArrayList<>();for (MultipartFile file : files) {FileAttachment attachment = new FileAttachment();attachment.name = file.getOriginalFilename();attachment.oDataType = "#microsoft.graph.fileAttachment";attachment.contentType = "text/plain";try {attachment.contentBytes = file.getBytes();} catch (IOException e) {throw new RuntimeException(e);}attachmentList.add(attachment);}AttachmentCollectionResponse attachmentCollectionResponse = new AttachmentCollectionResponse();attachmentCollectionResponse.value = attachmentList;AttachmentCollectionPage attachmentCollectionPage = new AttachmentCollectionPage(attachmentCollectionResponse, null);message.attachments = attachmentCollectionPage;}return message;}}

三 调用

读取邮箱的权限,在第一篇中有说,不赘述了。

package com.xxx.mail.controller;import com.xxx.common.core.domain.R;
import com.xxx.common.satoken.utils.LoginHelper;
import com.xxx.common.web.core.BaseController;
import com.xxx.mail.service.IMailOffice365Service;
import com.microsoft.graph.models.Message;
import com.microsoft.graph.models.User;
import com.microsoft.graph.requests.MailFolderCollectionPage;
import com.microsoft.graph.requests.MessageCollectionPage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/mail365")
public class MailController extends BaseController {@AutowiredIMailOffice365Service mailOffice365Service;@GetMapping("/getUser")public R<User> getUser() {String account = LoginHelper.getLoginUser().getEmail();User user = mailOffice365Service.getUser(account);return R.ok(user);}@GetMapping("/getMailFolders")public R<MailFolderCollectionPage> getMailFolders() {String account = LoginHelper.getLoginUser().getEmail();MailFolderCollectionPage folder = mailOffice365Service.getMailFolders(account);return R.ok(folder);}@GetMapping("/getFolderMails")public R<MessageCollectionPage> getFolderMails(String folderId, int pageIndex) {String account = LoginHelper.getLoginUser().getEmail();MessageCollectionPage mails = mailOffice365Service.getFolderMails(account, folderId, pageIndex, 10);return R.ok(mails);}@GetMapping("/getMails")public R<MessageCollectionPage> getMails(int pageIndex) {String account = LoginHelper.getLoginUser().getEmail();MessageCollectionPage mails = mailOffice365Service.getMails(account, pageIndex, 10);return R.ok(mails);}@GetMapping("/getMailById")public R<Message> getMailById(String messageId) {String account = LoginHelper.getLoginUser().getEmail();Message mail = mailOffice365Service.getMailById(account, messageId);//转换邮件中的图片mail = mailOffice365Service.getMailByIdWithAttachment(mail);return R.ok(mail);}@PostMapping("/sendMail")public R<Void> sendMail(@RequestParam("recipients") List<String> recipients, @RequestParam("subject") String subject, @RequestParam("body") String body, @RequestParam(name = "files", required = false) List<MultipartFile> files) throws Exception {String account = LoginHelper.getLoginUser().getEmail();mailOffice365Service.sendMail(account, recipients, subject, body, files);return R.ok();}@PostMapping("/replyMail")public R<Void> replyMail(@RequestParam("messageId") String messageId, @RequestParam("recipients") List<String> recipients, @RequestParam("subject") String subject, @RequestParam("body") String body, @RequestParam(name = "files", required = false) List<MultipartFile> files) throws Exception {String account = LoginHelper.getLoginUser().getEmail();mailOffice365Service.replyMail(messageId, account, recipients, subject, body, files);return R.ok();}}

相关文章:

java 通过 microsoft graph 调用outlook(二)

这次提供一些基础调用方式API PS&#xff1a; getMailFolders 接口返回的属性中&#xff0c;包含了未读邮件数量unreadItemCount 一 POM文件 <!-- office 365 --><dependency><groupId>com.google.guava</groupId><artifactId>guava<…...

【机器学习】代价函数

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…...

[leetcode] 100. 相同的树

给你两棵二叉树的根节点 p 和 q &#xff0c;编写一个函数来检验这两棵树是否相同。 如果两个树在结构上相同&#xff0c;并且节点具有相同的值&#xff0c;则认为它们是相同的。 示例 1&#xff1a; 输入&#xff1a;p [1,2,3], q [1,2,3] 输出&#xff1a;true示例 2&a…...

08、Lua 函数

Lua 函数 Lua 函数Lua函数主要有两种用途函数定义解析&#xff1a;optional_function_scopefunction_nameargument1, argument2, argument3..., argumentnfunction_bodyresult_params_comma_separated 范例 : 定义一个函数 max()Lua 中函数可以作为参数传递给函数多返回值Lua函…...

【数据分析面试】1. 计算年度收入百分比(SQL)

题目 你需要为公司的营收来源生成一份年度报告。计算截止目前为止&#xff0c;在表格中记录的第一年和最后一年所创造的总收入百分比。将百分比四舍五入到两位小数。 示例&#xff1a; 输入&#xff1a; annual_payments 表 列名类型amountINTEGERcreated_atDATETIMEstatusV…...

数据库SQL语句速查手册

SQL 语句语法AND / ORSELECT column_name(s) FROM table_name WHERE condition AND|OR conditionALTER TABLEALTER TABLE table_name ADD column_name datatypeorALTER TABLE table_name DROP COLUMN column_nameAS (alias)SELECT column_name AS column_alias FROM table_name…...

智慧城市一屏统览,数字孪生综合治理

现代城市作为一个复杂系统&#xff0c;牵一发而动全身&#xff0c;城市化进程中产生新的矛盾和社会问题都会影响整个城市系统的正常运转。智慧城市是应对这些问题的策略之一。城市工作要树立系统思维&#xff0c;从构成城市诸多要素、结构、功能等方面入手&#xff0c;系统推进…...

Python读取PDF文字转txt,解决分栏识别问题,能读两栏

搜索了一下&#xff0c;大致有这些库能将PDF转txt 1. PyPDF/PyPDF2&#xff08;截止2024.03.28这两个已经合并成了一个&#xff09;pypdf PyPI 2. pdfplumber GitHub - jsvine/pdfplumber: Plumb a PDF for detailed information about each char, rectangle, line, et cete…...

微信支付平台与微信服务号关联配置要点

目录 JSAPI支付 前期资料及相关准备 申请微信服务号 服务号配置要点 微信认证 基本配置 功能设置 申请微信支付号 支付号配置要点 设置操作密码 API安全 开发设置 与服务号关联 小结 JSAPI支付 我们的开发应用场景以JSAPI支付为举例&#xff0c;这也是常用的一…...

C++类复习

C类 1. 类内成员函数隐式声明为inline class Str {int x;int y 3; public:inline void fun(){std::cout<<"pf,yes!"<<std::endl;} };这段代码不会报错&#xff0c;但是类内的成员函数隐式声明为inline函数&#xff0c;不需要单独写在前面。因此将成员…...

Spring使用(一)注解

Spring使用 资源 Spring 框架内部使用 Resource 接口作为所有资源的抽象和访问接口&#xff0c;在上一篇文章的示例代码中的配置文件是通过ClassPathResource 进行封装的&#xff0c;ClassPathResource 是 Resource 的一个特定类型的实现&#xff0c;代表的是位于 classpath …...

Linux基本指令篇

在前边&#xff0c;我们已经了解过了Linux操作系统的发展和应用&#xff0c;从该篇起&#xff0c;就正式进入对Linux的学习。 今天我们就来在Xshell上远程登录我们的云服务器。首先我们要知道自己云服务器的公网ip&#xff0c;然后修改一下密码。 点击跳转 修改完密码之后我们…...

CSS实现小车旅行动画实现

小车旅行动画实现 效果展示 CSS 知识点 灵活使用 background 属性下的 repeating-linear-gradient 实现路面效果灵活运用 animation 属性与 transform 实现小车和其他元素的动画效果 动画场景分析 从效果图可以看出需要实现此动画的话&#xff0c;需要position属性控制元素…...

6_相机坐标系_相机4个坐标系详述

相机系列文章是用来记录使用opencv3来完成单目相机和6轴机械臂手眼标定。本人吃饭的主职是linux下6轴机械臂相关应用开发。但对于机械臂运动学、相机应用等都非常感兴趣&#xff0c;所以对一些线性代数基础薄弱又想深入了解机械臂内部运算的同志比较有体会。由于是探索性学习&a…...

软考 - 系统架构设计师 - 敏捷开发方法

前言 敏捷开发方法是一种以人为核心、迭代、循序渐进的软件开发方法。它强调团队合作、客户需求和适应变化&#xff0c;旨在通过快速迭代和反馈来快速交付高质量的软件产品。 敏捷开发方法的优势在于能够快速响应变化、提高开发效率和质量、增强团队协作和沟通&#xff0c;并降…...

Django 仿博客园练习

数据库搭建 部分功能介绍 【一】注册 &#xff08;1&#xff09;效果显示、简单简介 主要亮点 结合了layui和forms组件默认头像可以随着性别的选择发生改变自定义头像可以实时更新显示forms组件报错信息可以局部刷新显示在对应框体下面 没有直接使用layui的前端验证后端验证…...

MySQL(常用函数、多表查询)

文章目录 1.数据库函数1.count函数案例答案count&#xff08;*&#xff09;与count&#xff08;列&#xff09;的区别 2.sum函数案例答案 3.avg函数案例答案 4.max/min函数案例答案 5.group by 分组统计案例答案 6.字符串相关函数演示练习 7.数学相关函数演示 8.日期相关函数演…...

【Pt】马灯贴图绘制过程 01-制作基础色

目录 一、导入模型并烘焙 二、制作基础底漆 &#xff08;1&#xff09;底漆层 &#xff08;2&#xff09;水痕层 &#xff08;3&#xff09;指纹层 一、导入模型并烘焙 1. 导入模型&#xff0c;马灯模型如下所示 2. 在纹理集设置中点击“烘焙模型贴图” 设置输出大小为…...

TransmittableThreadLocal 问题杂记

0、前言 TransmittableThreadLocal&#xff0c;简称 TTL&#xff0c;是阿里巴巴开源的一个Java库&#xff0c;它能够实现ThreadLocal在多线程间的值传递&#xff0c;适用于使用线程池、异步调用等需要线程切换的场景&#xff0c;解决了ThreadLocal在使用父子线程、线程池时不能…...

Linux之 线程池 | 单例模式的线程安全问题 | 其他锁

目录 一、线程池 1、线程池 2、线程池代码 3、线程池的应用场景 二、单例模式的线程安全问题 1、线程池的单例模式 2、线程安全问题 三、其他锁 一、线程池 1、线程池 线程池是一种线程使用模式。线程池里面可以维护一些线程。 为什么要有线程池&#xff1f; 因为在…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...