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

Swagge详解,SpringBoot项目集成Swagger

介绍

        相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。其实无论是前端调用后端,还是后端调用后端,都期望有一个好的接口文档。但是这个接口文档对于程序员来说,就跟注释一样,经常会抱怨别人写的代码没有写注释,然而自己写起代码起来,最讨厌的,也是写注释。所以仅仅只通过强制来规范大家是不够的,随着时间推移,版本迭代,接口文档往往很容易就跟不上代码了。

        发现了痛点就要去找解决方案。解决方案用的人多了,就成了标准的规范,这就是Swagger的由来。通过这套规范,你只需要按照它的规范去定义接口及接口相关的信息。再通过Swagger衍生出来的一系列项目和工具,就可以做到生成各种格式的接口文档,生成多种语言的客户端和服务端的代码,以及在线接口调试页面等等。这样,如果按照新的开发模式,在开发新版本或者迭代版本的时候,只需要更新Swagger描述文件,就可以自动生成接口文档和客户端服务端代码,做到调用端代码、服务端代码以及接口文档的一致性。

Swagger官网:https://swagger.io/

框架说明

        现在SWAGGER官网主要提供了几种开源工具,提供相应的功能。可以通过配置甚至是修改源码以达到你想要的效果

Swagger Codegen: 通过Codegen 可以将描述文件生成html格式和cwiki形式的接口文档,同时也能生成多钟语言的服务端和客户端的代码。支持通过jar包,docker,node等方式在本地化执行生成。也可以在后面的Swagger Editor中在线生成。

Swagger UI:提供了一个可视化的UI页面展示描述文件。接口的调用方、测试、项目经理等都可以在该页面中对相关接口进行查阅和做一些简单的接口请求。该项目支持在线导入描述文件和本地部署UI项目。

Swagger Editor: 类似于markendown编辑器的编辑Swagger描述文件的编辑器,该编辑支持实时预览描述文件的更新效果。也提供了在线编辑器和本地部署编辑器两种方式。

Swagger Hub:集成了上面所有项目的各个功能,你可以以项目和版本为单位,将你的描述文件上传到Swagger Hub中。在Swagger Hub中可以完成上面项目的所有工作,需要注册账号,分免费版和收费版。

PS:

Springfox Swagger: Spring 基于swagger规范,可以将基于SpringMVC和Spring Boot项目的项目代码,自动生成JSON格式的描述文件。本身不是属于Swagger官网提供的,在这里列出来做个说明,方便后面作一个使用的展开。其实swagger是有两个版本的,区别还挺大的,一个是swagger-ui也就是swagger1;还有一个是springfox-swagger也就是swagger2;

总结:

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。使用Swagger,就是把相关的信息存储在它定义的描述文件里面(yml或json格式),再通过维护这个描述文件可以去更新接口文档,以及生成各端代码。而Springfox-swagger,则可以通过扫描代码去生成这个描述文件,连描述文件都不需要再去维护了。所有的信息,都在代码里面了。代码即接口文档,接口文档即代码。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。文件的方法,参数和模型紧密集成到服务器端的代码,允许API来始终保持同步。

作用:
  1. 接口的文档在线自动生成
  2. 功能测试

SpringBoot集成Swagger

初始实现步骤

1. 添加Maven依赖

<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version>
</dependency>
<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
</dependency>

2. 编写HelloController,测试确保运行成功

@RestController
public class SwapperControllerTest {@GetMapping("/swapperTest")public String swapperTest(String name){return name;}
}

3. 编写一个配置类-SwaggerConfig(或者通过在项目启动类上加@EnableSwagger2注解)来配置 Swagger

@Configuration //配置类
@EnableSwagger2// 开启Swagger2的自动配置
public class SwaggerConfig {}

启动类加注解

以上方法2选1即可

4. 访问测试 :http://localhost:8080/swagger-ui.html ,可以看到swagger的主界面

注意:

如果启动报错空指针是因为springboot2.6.0中将SpringMVC 默认路径匹配策略从AntPathMatcher 更改为PathPatternParser,导致出错,可以在启动类上加上@EnableWebMvc注解或者在配置中切换为原先的AntPathMatcherspring.mvc.pathmatch.matching-strategy=ant_path_matcher

配置Swagger

1. Swagger实例Bean是Docket,所以通过配置Docket实例来配置Swagger

@Bean //配置docket以配置Swagger具体参数
public Docket docket() {return new Docket(DocumentationType.SWAGGER_2);
}

2. 可以通过apiInfo()属性配置文档信息

private ApiInfo createApiInfo(){Contact contact = new Contact("testName","www.baidu.com","277277727727@163.com");return new ApiInfo("Swagger学习", // 标题"学习演示如何配置Swagger", // 描述"v1.0", // 版本"http://ape.com", // 组织链接contact, // 联系人信息"Apach 2.0 许可", // 许可"许可链接", // 许可连接new ArrayList<>()// 扩展);

3. Docket 实例关联上 apiInfo()

@Bean
public Docket docket() {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
}

4. 重启项目,访问测试 http://localhost:8080/swagger-ui.html 看下效果;

配置扫描接口

1. 构建Docket时通过select()方法配置怎么扫描接口

//配置swapper主页信息@Beanpublic Docket docket(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(createApiInfo()).select()// 通过.select()方法,去配置扫描接口,RequestHandlerSelectors配置如何扫描接口.apis(RequestHandlerSelectors.basePackage("com.ape.springboot_swapper.controller")).build();}

2. 重启项目测试,由于我们配置根据包的路径扫描接口,所以我们只能看到一个类

3. 除了通过包路径配置扫描接口外,还可以通过配置其他方式扫描接口,这里注释一下所有的配置方式

any() // 扫描所有,项目中的所有接口都会被扫描到
none() // 不扫描接口
// 通过方法上的注解扫描,如withMethodAnnotation(GetMapping.class)只扫描get请求
withMethodAnnotation(final Class<? extends Annotation> annotation)
// 通过类上的注解扫描,如.withClassAnnotation(Controller.class)只扫描有controller注解的类中的接口
withClassAnnotation(final Class<? extends Annotation> annotation)
basePackage(final String basePackage) // 根据包路径扫描接口

4. 除此之外,我们还可以配置接口扫描过滤

// 配置如何通过path过滤,即这里只扫描请求以/apesource开头的接口
.paths(PathSelectors.ant("/apesource/**"))

5. 这里的可选值还有

any() // 任何请求都扫描
none() // 任何请求都不扫描
regex(final String pathRegex) // 通过正则表达式控制
ant(final String antPattern) // 通过ant()控制

配置API分组

1. 如果没有配置分组,默认是default。通过groupName()方法即可配置分组

@Bean
public Docket docket(Environment environment) {return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).groupName("hello") // 配置分组// 省略配置....
}

2. 重启项目查看分组

3. 如何配置多个分组?配置多个分组只需要配置多个docket即可

//    多个分组@Bean Docket docket2(){return new Docket(DocumentationType.SWAGGER_2).groupName("test2");}@Bean Docket docket3(){return new Docket(DocumentationType.SWAGGER_2).groupName("test3");}@Bean Docket docket4(){return new Docket(DocumentationType.SWAGGER_2).groupName("test4");}@Bean Docket docket5(){return new Docket(DocumentationType.SWAGGER_2).groupName("test5");}

拓展:其他皮肤

我们可以导入不同的包实现不同的皮肤定义

1.默认的访问 http://localhost:8080/swagger-ui.html

<dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version>
</dependency>

bootstrap-ui 访问 http://localhost:8080/doc.html

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.1</version>
</dependency>

常用注解

swagger通过注解生成接口文档,包括接口名、请求方法、参数、返回信息的等等。

1. @Api:修饰整个类,描述Controller的作用

语法:@Api(tags="说明该类的作用,可以在UI界面上看到的注解",value = "/类的访问路径",

description = "类的文字描述")

2. @ApiOperation:描述一个类的一个方法,说明方法的作用

语法:@ApiOperation(value = “接口说明”, httpMethod = “接口请求方式”, response = “接口返回参数类型”, notes = “接口发布说明”)

3. @ApiImplicitParam:一个请求参数

语法:@ApiImplicitParam(required = “是否必须参数”, name = “参数名称”, value = “参数具体描述”,dateType="变量类型”,paramType="请求方式”

· header --> 请求参数的获取:@RequestHeader

· query --> 请求参数的获取:@RequestParam

· path(用于restful接口)--> 请求参数的获取:

@PathVariable

· body(不常用)

· form(不常用)

4. @ApiImplicitParams: 多个请求参数

5. @ApiParam:单个参数描述

语法:@ApiParam(required = “是否必须参数”, name = “参数名称”, value = “参数具体描

述”,dateType="变量类型”,paramType="请求方式”)

6. @ApiResponse:HTTP响应其中1个描述,响应配置

语法:@ApiResponse(code = 400, message = "Invalid user supplied")

7. @ApiResponses:HTTP响应整体描述

语法:@ApiResponses({ @ApiResponse(code = 400, message = "Invalid Order") })

8. @ApiModel:用对象实体来作为入参

9. @ApiProperty:用对象接实体收参数时,描述对象的一个字段

10. @ApiIgnore:使用该注解忽略这个API

11. @ApiError :发生错误返回的信息

测试

创建实体类与测试类并使用注解

@NoArgsConstructor
@AllArgsConstructor
@Data
@ApiModel(value = "控制器方法返回值",description = "自定义结果集")
public class Result {@ApiModelProperty(name = "state",value = "结果集状态",example = "true")private boolean state;@ApiModelProperty(name = "message",value = "消息",example = "abc")private String message;@ApiModelProperty(name = "date",value = "数据集")private Object date;
}
@RestController
@Api
@RequestMapping("/user")
public class SwapperControllerTest02 {@GetMapping("/findByName")@ApiOperation(value = "根据用户名查询")public Result findByName(String name){if(name.equals("aaa")){return new Result(true,"成功","aaa");}else {return new Result(false,"失败","bbb");}}
}

使用注解后效果如下

Swagger会自动识别接口请求方式,参数类型,个数,返回结果等信息

点击Try it out测试接口

输入对应参数点击执行、

成功后返回相关信息

相关文章:

Swagge详解,SpringBoot项目集成Swagger

介绍 相信无论是前端还是后端开发&#xff0c;都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力&#xff0c;经常来不及更新。其实无论是前端调用后端&#xff0c;还是后端调用后端&#xff0c;都期望…...

docker搭建etcd集群环境方式

docker搭建etcd集群环境方式 from: etcd 虚拟机与docker搭建etcd集群环境方式_docker部署etcd集群-CSDN博客 windows系统下 1: “\”要换成&#xff1a;“^” 2: 不能在windows powershell下执行...

重装ubuntu系统后配置

零、我的电脑硬件 1、购买型号 2021年12月25日在京东下单 7196元 联想拯救者15.6英寸 R7000P 2021游戏本 2、运行内存 内存 16 3、显卡型号 GPU nvidia RTX 3050Ti 4GB 一、安装终端 虽然自带的有&#xff0c;但是更方便 sudo apt install terminator 二、两个系统…...

Java基于数据库的分布式可重入锁(带等待时间和过期时间)

文章目录 技术背景介绍代码实现数据库表结构尝试获取锁续约阻塞式获取锁解锁检查锁是否过期或者释放 使用示例优化方案 项目代码 技术背景介绍 一般分布式锁使用最方便的就是使用redis实现&#xff0c;因为他自带超时过期机制、发布订阅模式、高吞吐高性能的优势&#xff0c;…...

国家信息安全水平考试(NISP一级)最新题库-第十七章

目录 另外免费为大家准备了刷题小程序和docx文档&#xff0c;有需要的可以私信获取 1 受到了ARP欺骗的计算机&#xff0c;发出的数据包&#xff0c;     地址是错误的&#xff08;&#xff09; A.源IP&#xff1b;B.目的IP&#xff1b;C.源MAC&#xff1b;D.目的MAC 正…...

Java 8 新特性概览

Java 8 是 Java 语言发展史上的一个重要里程碑&#xff0c;它引入了许多革命性的特性&#xff0c;极大地提高了开发效率和程序性能。以下是 Java 8 的一些关键新特性&#xff1a; 1. Lambda 表达式 Lambda 表达式是 Java 8 中最引人注目的特性之一。它允许你以简洁的语法编写…...

pyspark==堆叠

安装环境 docker pull jupyter/all-spark-notebook 方式一 from pyspark.sql import SparkSession from pyspark.sql.functions import expr, col# 创建SparkSession spark SparkSession.builder.appName("StudentScores").getOrCreate()# 创建示例数据 data [(…...

Zypher Network Layer3 主网上线,不容错过的“宝藏方舟”活动

前言 随着 Zytron Layer3 主网的上线&#xff0c;Zypher Network 联合 Linea 共同推出了“宝藏方舟”活动&#xff0c;用户可通过参与活动&#xff0c;获得包括代币、积分、SBT 等系列奖励。 Zypher Network 是一个以 ZK 方案为核心的游戏底层堆栈&#xff0c;其提供了一个具备…...

【小白学机器学习21】 理解假设检验的关键:反证法

目录 理解假设检验的关键&#xff1a;反证法 1 假设的检验的出发点&#xff1a;H1假设&#xff0c; 1.1 为什么我们不去直接证明H1是否正确&#xff1f; 2 故意设立一个假设H1的否命题为H0 3 设定显著度α 4 总结假设检验的整个思路就是反证法 5 两类错误的关系 理解假…...

鸿蒙中富文本编辑与展示

富文本在鸿蒙系统如何展示和编辑的&#xff1f;在文章开头我们提出这个疑问&#xff0c;带着疑问来阅读这篇文章。 富文本用途可以展示图文混排的内容&#xff0c;在日常App 中非常常见&#xff0c;比如微博的发布与展示&#xff0c;朋友圈的发布与展示&#xff0c;都在使用富文…...

Python Q-learning 算法详解与应用案例

目录 Python Q-learning 算法详解与应用案例引言一、Q-learning 的基本原理1.1 强化学习基础1.2 Q值及其更新1.3 Q-learning 的特性 二、Python 中 Q-learning 的面向对象实现2.1 QTable 类的实现2.2 Environment 类的实现2.3 Agent 类的实现 三、案例分析3.1 简单环境中的 Q-l…...

解决:如何在opencv中得到与matlab立体标定一样的矫正图?(python版opencv)

目的&#xff1a;采用一样的标定参数&#xff0c;matlab中和opencv中的立体矫正图像是一样的吗&#xff1f;不一样的话怎么让它们一样&#xff1f; 结论&#xff1a;不一样。后文为解决方案。 原因&#xff1a;注意matlab的标定结果在matlab中的用法和在opencv中的用法不一样&a…...

gin入门教程(4):路由与处理器

路由与处理器 在 Gin 框架中&#xff0c;路由和处理器是核心组成部分&#xff0c;负责将 HTTP 请求映射到相应的处理逻辑。 1. 定义路由 在 cmd/main.go 中&#xff0c;您可以定义不同的路由&#xff0c;例如&#xff1a; r.GET("/ping", func(c *gin.Context) {…...

【python+Redis】hash修改

文章目录 前请详解一、关于Update1. 语法2. 代码示例 二、完整代码 前请详解 Redis库数据 keyvalue1{“id”: 1, “name”: “xxx”, “age”: “18”, “sex”: “\u7537”}2{“id”: 2, “name”: “xxx”, “age”: “18”, “sex”: “\u5973”}3{“id”: 3, “name”: “…...

MAVlink协议 部分通用消息集解析

文章目录 MAVLink是一种非常轻量级的消息传输协议, 用于地面控制终端&#xff08;地面站&#xff09;与无人机之间 (以及机载无人机组件之间) 进行通信&#xff0c; 为一种设计用于资源受限系统及带宽受限链路的二进制遥测协议。 HEARTBEAT 检测信号消息显示系统或组件存在并正…...

c++实现跳表

原理 跳表&#xff08;Skip List&#xff09; 是一种随机化数据结构&#xff0c;用于高效查找、插入和删除&#xff0c;尤其适用于有序数据集合。相比链表&#xff0c;跳表通过多层索引结构加速查找&#xff0c;期望时间复杂度接近 O(log⁡n)。跳表的主要思想是&#xff1a; …...

新探索研究生英语读写教程pdf答案(基础级)

《新探索研究生英语读写教程》的设计和编写充分考虑国内研究生人才培养目标和研究生公共英语的教学需求&#xff0c; 教学内容符合研究生认知水平&#xff0c; 学术特征突出&#xff1b;教学设计紧密围绕学术阅读、学术写作和学术研究能力培养&#xff1b;教学资源立体多元&…...

管道与共享内存

一&#xff0c;命名管道 管道的限制就是他只能在有血缘关系&#xff08;父子进程&#xff09;的进程中&#xff0c;允许互相访问&#xff0c;这是有局限性的&#xff0c;所以我们想在毫无关系的进程中允许他们相互访问&#xff0c;这就是命名管道的定义。 总结&#xff1a;命名…...

ES 自定义排序方式

es默认score是根据query的相关度进行打分的&#xff0c;具体打分机制可以参见&#xff1a;官方文档。如果召回时既希望有相关性又能根据其他信息进行排序。 例如小红书搜索的时候&#xff0c;可能既希望有召回相关度又能根据热度信息&#xff08;如果喜欢、收藏等等参数去进行召…...

在vue中,编写一个li标签同时使用v-for和v-if,谁的优先级更高

在 Vue 中&#xff0c;v-if 和 v-for 是两个常用的指令&#xff0c;但它们的优先级不同。当二者一起使用时&#xff0c;v-for 的优先级高于 v-if。这意味着&#xff0c;v-for 会先执行&#xff0c;即使列表中的某些元素不满足 v-if 条件&#xff0c;它们仍会被遍历和渲染。 由…...

Java 后端开发面试题及其答案

以下是一些常见的 Java 后端开发面试题及其答案&#xff0c;涵盖了 Java 基础、面向对象、并发、多线程、框架等多个方面&#xff1a; 1. Java 中的基本数据类型有哪些&#xff1f; 答案&#xff1a; Java 中的基本数据类型有 8 种&#xff1a; int&#xff1a;32 位整数lon…...

C++,STL 045(24.10.24)

内容 1.对set容器的大小进行操作。 2.set容器的交换操作。 运行代码 #include <iostream> #include <set>using namespace std;void printSet(set<int> &s) {for (set<int>::iterator it s.begin(); it ! s.end(); it){cout << *it <…...

二叉树习题其五【力扣】【算法学习day.12】

前言 书接上篇文章二叉树习题其四&#xff0c;这篇文章我们将基础拓展 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一…...

【数据库】Mysql的锁类型

Mysql中的锁机制主要是为了保证数据的一致性和完整性&#xff0c;在并发的情况下起着至关重要的作用。其中锁的类型主要是分为以下几种&#xff1a; 按照粒度分类 全局锁&#xff1a;对于整个数据库实例进行枷锁&#xff0c;加锁后整个实例就处于只读的状态。局锁通常用于需要…...

自媒体短视频制作素材下载网站推荐,让创作更简单

随着自媒体行业的火爆&#xff0c;视频质量要求也越来越高。想要找到无版权的高清视频素材并不容易&#xff0c;但别担心&#xff01;今天为大家整理了5个国内外高质量的素材网站&#xff0c;让你轻松获取自媒体短视频素材&#xff0c;快收藏起来吧&#xff01; 蛙学网 蛙学网是…...

Altium Designer 入门基础教程(五)

本文章继续接着《Altium Designer 入门基础教程&#xff08;四&#xff09;》的内容往下介绍&#xff1a; 七、AD画板的整个流程步骤 I.集成库的制作 AD元件库有2种&#xff1a;1、原理图元件库SCH.LIB 2、印刷电路板&#xff08;PCB&#xff09;元件库 PCB.LIB 印刷电路…...

Java题集练习3

Java题集练习3 1 什么时候用instanceof instanceOf关键字主要用于判断一个对象是否为某个类的子类或是接口的实例&#xff0c;通常用于类型转换和运行时类型判断的场景&#xff0c;比如继承和多态中。比如&#xff0c;创建一个Animal类及其子类Cat和Cat子类Hat&#xff0c;可…...

【部署篇】Haproxy-01安装部署(源码方式安装)

‌一、HAProxy概述‌ HAProxy是一款免费、快速且可靠的代理软件&#xff0c;提供高可用性、负载均衡&#xff0c;支持TCP和HTTP应用代理&#xff0c;HAProxy凭借其卓越的性能和灵活性&#xff0c;成为众多知名网站和系统的首选代理软件。‌ ‌核心特点‌&#xff1a; ‌高性能…...

开拓鸿蒙测试新境界,龙测科技引领自动化测试未来

在当今科技舞台上&#xff0c;鸿蒙 OS 以非凡先进性强势登场&#xff0c;打破传统操作系统格局&#xff0c;为软件测试领域带来全新机遇与艰巨挑战。 一、鸿蒙 OS 的辉煌崛起 &#xff08;一&#xff09;壮丽发展历程与卓越市场地位 鸿蒙 OS 的发展如波澜壮阔的史诗。2023 年…...

Java项目-基于springboot框架的自习室预订系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…...

备案价网站/短视频询盘获客系统

添加和删除主题&#xff08;Topic&#xff09;你可能使用过手动创建主题或发送消息时自动创建主题这样的操作。但是你并不了解其中的详情。Kafka中的主题可以在主题配置中配置为自动创建的。./kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 2 --p…...

html5单页模板/seo关键词优化推广外包

hive数据类型 基本数据类型&#xff1a; 数据类型长度例子TINYINT1byte有符号整数20SMALLINT2byte有符号整数20INT4byte有符号整数20BIGINT8byte有符号整数20BOOLEAN布尔类型TRUEFLOAT单精度浮点数3.1419DOUBLE双精度浮点数3.14159STRING字符序列。可以指定字符集。可以使用单…...

怎么网站/关键词优化推广

使用Visual Studio .NET 2003的问题 尝试创建Web项目或打开位于URL "" 的Web项目时&#xff0c;Web服务器报告了以下错误。“HTTP/1.1 500 Internal Server Error” 原因&#xff1a;ASP.NET帐号对网站根目录没有访问权限。 解决方法&#xff1a;在根目录文件夹的安全…...

中国印花图案设计网站/完善的seo网站

node *proot;stack<node*>st;node *rNULL;while(p||!st.empty()){if(p){st.push(p);pp->l;}else{pst.top();if(p->r&&p->r!r){pp->r;}else{cout<<st.top()->data<<endl;st.pop();rp;pNULL;}}}...

软件应用下载安装/seo优化的主要内容

1.1 案例四&#xff1a;使用JS完成后台数据展示的隔行换色的表格&#xff1a;1.1.1 需求&#xff1a;在后台展示数据的页面上&#xff0c;通常使用表格标签进行数据的展示.没有背景的表格比较难看的&#xff0c;可以使用JS控制表格的隔行换色.1.1.2 分析&#xff1a;1.1.2.1 技…...

网站源码大全免费/网课培训机构排名前十

关注 M r . m a t e r i a l , \color{Violet} \rm Mr.material\ , Mr.material ,...