MyBatis Generator系列(二)----自定义CommentGenerator实现中文注释

本文主要是介绍MyBatis Generator系列(二)----自定义CommentGenerator实现中文注释,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、简介


由于MyBatis Generator自带了生成注释的功能,但是,是英文的而且生成的根本无法理解,所以可以通过,修改他的源码来实现生成中文的注释,具体方式有以下几种:


1) 自定义CommentGenerator

2) 修改源码

3) PluginAdapter插件的形式


二、自定义CommentGenerator实现中文注释


2.1、先创建Maven项目




然后右键项目->new->source folder,输入src/main/resources,建好resources目录




然后在POM.XML中加入以下依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fendo</groupId><artifactId>mybatis-generator-plus</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><name>mybatis-generator-plus</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.5</version></dependency><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</artifactId><version>6.0</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.9</version></dependency></dependencies><build><finalName>mybatis-generator-plus</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build></project>


引入了mybatis-generator-core1.3.5和mysql,oracle。


注意: 


ojdbc6需要自己手动进行安装,下载ojdbc6之后,通过以下命令进行安装:


mvn install:install-file -Dfile=C:/Users/fendo/Downloads/ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=6.0 -Dpackaging=jar -DgeneratePom=true


2.2、创建MyCommentGenerator类实现CommentGenerator接口


package org.mybatis.generator;import static org.mybatis.generator.internal.util.StringUtility.isTrue;import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;import org.mybatis.generator.api.CommentGenerator;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.CompilationUnit;
import org.mybatis.generator.api.dom.java.Field;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.InnerEnum;
import org.mybatis.generator.api.dom.java.JavaElement;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.config.MergeConstants;
import org.mybatis.generator.config.PropertyRegistry;/**   * @Title: MyCommentGenerator.java * @Package com.fendo.mybatis_generator_plus * @Description:  mybatis generator 自定义comment生成器.*                基于MBG 1.3.5* @author fendo* @date 2017年10月5日 下午3:07:26 * @version V1.0   
*/
public class MyCommentGenerator implements CommentGenerator{/*** properties配置文件*/private Properties properties;/*** properties配置文件*/private Properties systemPro;/** 父类时间*/private boolean suppressDate;/*** 父类所有注释*/private boolean suppressAllComments;/*** 当前时间*/private String currentDateStr;public MyCommentGenerator() {super();properties = new Properties();systemPro = System.getProperties();suppressDate = false;suppressAllComments = false;currentDateStr = (new SimpleDateFormat("yyyy-MM-dd")).format(new Date());}/*** Java类的类注释*/@Overridepublic void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable) {if (suppressAllComments) {return;}StringBuilder sb = new StringBuilder();innerClass.addJavaDocLine("/**");sb.append(" * ");sb.append(introspectedTable.getFullyQualifiedTable());sb.append(" ");sb.append(getDateString());innerClass.addJavaDocLine(sb.toString().replace("\n", " "));innerClass.addJavaDocLine(" */");}/*** 为类添加注释*/@Overridepublic void addClassComment(InnerClass innerClass, IntrospectedTable introspectedTable, boolean markAsDoNotDelete) {if (suppressAllComments) {return;}StringBuilder sb = new StringBuilder();innerClass.addJavaDocLine("/**");sb.append(" * ");sb.append(" * ");sb.append(introspectedTable.getFullyQualifiedTable());innerClass.addJavaDocLine(sb.toString().replace("\n", " "));sb.setLength(0);sb.append(" * @author ");sb.append(systemPro.getProperty("user.name"));sb.append(" ");sb.append(currentDateStr);innerClass.addJavaDocLine(" */");}/*** Mybatis的Mapper.xml文件里面的注释*/@Overridepublic void addComment(XmlElement xmlElement) {}/*** *@Title addConfigurationProperties *@Description: 从该配置中的任何属性添加此实例的属性CommentGenerator配置。*              这个方法将在任何其他方法之前被调用。*@Author fendo*@Date 2017年10月5日 下午3:45:58*@return*@throws*/@Overridepublic void addConfigurationProperties(Properties properties) {this.properties.putAll(properties);suppressDate = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_DATE));suppressAllComments = isTrue(properties.getProperty(PropertyRegistry.COMMENT_GENERATOR_SUPPRESS_ALL_COMMENTS));}/*** *@Title getDateString *@Description: 此方法返回格式化的日期字符串以包含在Javadoc标记中和XML注释。 如果您不想要日期,则可以返回null在这些文档元素中。*@Author fendo*@Date 2017年10月5日 下午3:45:58*@return*@throws*/protected String getDateString() {String result = null;if (!suppressDate) {result = currentDateStr;}return result;}/*** *@Title addJavadocTag *@Description: 此方法为其添加了自定义javadoc标签。*@Author fendo*@Date 2017年10月5日 下午3:49:05*@param javaElement*@param markAsDoNotDelete*@throws*/protected void addJavadocTag(JavaElement javaElement, boolean markAsDoNotDelete) {javaElement.addJavaDocLine(" *");StringBuilder sb = new StringBuilder();sb.append(" * ");sb.append(MergeConstants.NEW_ELEMENT_TAG);if (markAsDoNotDelete) {sb.append(" do_not_delete_during_merge");}String s = getDateString();if (s != null) {sb.append(' ');sb.append(s);}javaElement.addJavaDocLine(sb.toString());}/*** 为枚举添加注释*/@Overridepublic void addEnumComment(InnerEnum innerEnum, IntrospectedTable introspectedTable) {if (suppressAllComments) {return;}StringBuilder sb = new StringBuilder();innerEnum.addJavaDocLine("/**");sb.append(" * ");sb.append(introspectedTable.getFullyQualifiedTable());innerEnum.addJavaDocLine(sb.toString().replace("\n", " "));innerEnum.addJavaDocLine(" */");}/*** Java属性注释*/@Overridepublic void addFieldComment(Field field, IntrospectedTable introspectedTable) {if (suppressAllComments) {return;}StringBuilder sb = new StringBuilder();field.addJavaDocLine("/**");sb.append(" * ");sb.append(introspectedTable.getFullyQualifiedTable());field.addJavaDocLine(sb.toString().replace("\n", " "));field.addJavaDocLine(" */");}/*** 为字段添加注释*/@Overridepublic void addFieldComment(Field field, IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn) {if (suppressAllComments) {return;}StringBuilder sb = new StringBuilder();field.addJavaDocLine("/**");sb.append(" * ");sb.append(introspectedColumn.getRemarks());field.addJavaDocLine(sb.toString().replace("\n", " "));field.addJavaDocLine(" */");}/*** 普通方法的注释,这里主要是XXXMapper.java里面的接口方法的注释*/@Overridepublic void addGeneralMethodComment(Method method, IntrospectedTable introspectedTable) {if (suppressAllComments) {return;}method.addJavaDocLine("/**");addJavadocTag(method, false);method.addJavaDocLine(" */");}/*** 给getter方法加注释*/@Overridepublic void addGetterComment(Method method, IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn) {if (suppressAllComments) {return;}method.addJavaDocLine("/**");StringBuilder sb = new StringBuilder();sb.append(" * ");sb.append(introspectedColumn.getRemarks());method.addJavaDocLine(sb.toString().replace("\n", " "));sb.setLength(0);sb.append(" * @return ");sb.append(introspectedColumn.getActualColumnName());sb.append(" ");sb.append(introspectedColumn.getRemarks());method.addJavaDocLine(sb.toString().replace("\n", " "));method.addJavaDocLine(" */");}/*** 给Java文件加注释,这个注释是在文件的顶部,也就是package上面。*/@Overridepublic void addJavaFileComment(CompilationUnit compilationUnit) {SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");compilationUnit.addFileCommentLine("/*");compilationUnit.addFileCommentLine("*");compilationUnit.addFileCommentLine("* "+compilationUnit.getType().getShortName()+".java");compilationUnit.addFileCommentLine("* Copyright(C) 2017-2020 fendo公司");compilationUnit.addFileCommentLine("* @date "+sdf.format(new Date())+"");compilationUnit.addFileCommentLine("*/");}/*** 为模型类添加注释*/@Overridepublic void addModelClassComment(TopLevelClass arg0, IntrospectedTable arg1) {}/*** 为调用此方法作为根元素的第一个子节点添加注释。*/@Overridepublic void addRootComment(XmlElement arg0) {}/*** 给setter方法加注释*/@Overridepublic void addSetterComment(Method method, IntrospectedTable introspectedTable,IntrospectedColumn introspectedColumn) {if (suppressAllComments) {return;}method.addJavaDocLine("/**");StringBuilder sb = new StringBuilder();sb.append(" * ");sb.append(introspectedColumn.getRemarks());method.addJavaDocLine(sb.toString().replace("\n", " "));Parameter parm = method.getParameters().get(0);sb.setLength(0);sb.append(" * @param ");sb.append(parm.getName());sb.append(" ");sb.append(introspectedColumn.getRemarks());method.addJavaDocLine(sb.toString().replace("\n", " "));method.addJavaDocLine(" */");}}

配置generator.xml,修改其中的<commentGenerator>为如下形式:


<commentGenerator type="package org.mybatis.generator.MyCommentGenerator">
</commentGenerator>

注意type的值为MyCommentGenerator类的全路径,完整文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>  
<!-- 数据库驱动-->  <classPathEntry  location="D:\MavenRepository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar"/>  <context id="DB2Tables"  targetRuntime="MyBatis3">  <!-- 指定生成的java文件的编码,没有直接生成到项目时中文可能会乱码 --><property name="javaFileEncoding" value="UTF-8"/><!-- 这里的type里写的是你的实现类的类全路径 --><commentGenerator type="com.fendo.generatorplus.MyCommentGenerator"></commentGenerator><!--数据库链接URL,用户名、密码 -->   <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="root" password="root">  </jdbcConnection>  <javaTypeResolver>  <property name="forceBigDecimals" value="false"/>  </javaTypeResolver>  <!-- 生成模型的包名和位置-->  <javaModelGenerator targetPackage="com.fendo.generatorplus.entity" targetProject="src/main/java">  <property name="enableSubPackages" value="true"/>  <property name="trimStrings" value="true"/>  </javaModelGenerator>  <!-- 生成映射文件的包名和位置-->  <sqlMapGenerator targetPackage="com.fendo.generatorplus.dao" targetProject="src/main/java">  <property name="enableSubPackages" value="true"/>  </sqlMapGenerator>  <!-- 生成DAO的包名和位置-->  <javaClientGenerator type="XMLMAPPER" targetPackage="com.fendo.generatorplus.dao" targetProject="src/main/java">  <property name="enableSubPackages" value="true"/>  </javaClientGenerator>  <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->  <table tableName="test" domainObjectName="Test" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table></context>  
</generatorConfiguration>  


2.3、测试代码生成


新建StartUp测试类

package org.mybatis.generator;import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.exception.XMLParserException;
import org.mybatis.generator.internal.DefaultShellCallback;/**   * @Title: StartUp.java * @Package com.fendo.mybatis_generator_plus * @Description: TODO* @author fendo* @date 2017年10月5日 下午3:53:17 * @version V1.0   
*/
public class StartUp {public static void main(String[] args) throws URISyntaxException {try {System.out.println("--------------------start generator-------------------");List<String> warnings = new ArrayList<String>();boolean overwrite = true;ClassLoader classloader = Thread.currentThread().getContextClassLoader();InputStream is = classloader.getResourceAsStream("generatorConfig.xml");ConfigurationParser cp = new ConfigurationParser(warnings);Configuration config = cp.parseConfiguration(is);DefaultShellCallback callback = new DefaultShellCallback(overwrite);MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);myBatisGenerator.generate(null);System.out.println("--------------------end generator-------------------");} catch (SQLException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();} catch (InvalidConfigurationException e) {e.printStackTrace();} catch (XMLParserException e) {e.printStackTrace();}}
}


然后运行StartUp文件,就会自动生成代码了,生成的bean代码如下:




生成的Mapper如下




能生成中文注释了,但是好像类的注释并没有生成,而且mapper中的注释生成的有点无视。。。这些问题,在修改源码实现中文注释中,得以解决,下一步,就是,把这个项目,打包成JAR,这样才好使用,要使依赖包被打包到最后的jar包中,要在pom.xml中进行相应的配置:


	    <plugin><!-- 因为项目中使用了依赖包,所以要使用maven-assembly-plugin来构建,会把依赖包同时打进jar包中 --><artifactId>maven-assembly-plugin</artifactId><version>2.6</version><configuration><!-- 这里不指定为false打包会生成两个jar包,我们要用的那个jar包命名很乱,后面加了jar-with-dependencies,不喜欢,直接禁用掉 --><appendAssemblyId>false</appendAssemblyId><archive><manifest><!-- 指定类的全路径  否则运行会报找不到main class的错误--><mainClass>org.mybatis.generator.api.ShellRunner</mainClass></manifest></archive><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin>


由于使用了Generator的ShellRunner,所以在打包JAR的时候,可以删了StartUp和generatorConfig.xml文件,然后在项目根路径使用打包命令


mvn clean package


来打包成jar文件,生成如下的jar包



然后把mybatis-generator-plus.jar复制到一个目录下,同时新建一个generatorConfig.xml配置文件,以及一个cmd文件




generatorConfig.xml配置文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>  
<!-- 数据库驱动-->  <classPathEntry  location="D:\MavenRepository\mysql\mysql-connector-java\5.1.38\mysql-connector-java-5.1.38.jar"/>  <context id="DB2Tables"  targetRuntime="MyBatis3">  <!-- 指定生成的java文件的编码,没有直接生成到项目时中文可能会乱码 --><property name="javaFileEncoding" value="UTF-8"/><!-- 这里的type里写的是你的实现类的类全路径 --><commentGenerator type="org.mybatis.generator.MyCommentGenerator"></commentGenerator><!--数据库链接URL,用户名、密码 -->   <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="root" password="root">  </jdbcConnection>  <javaTypeResolver>  <property name="forceBigDecimals" value="false"/>  </javaTypeResolver>  <!-- 生成模型的包名和位置-->  <javaModelGenerator targetPackage="com.fendo.generatorplus.entity" targetProject="src/main/java">  <property name="enableSubPackages" value="true"/>  <property name="trimStrings" value="true"/>  </javaModelGenerator>  <!-- 生成映射文件的包名和位置-->  <sqlMapGenerator targetPackage="com.fendo.generatorplus.dao" targetProject="src/main/java">  <property name="enableSubPackages" value="true"/>  </sqlMapGenerator>  <!-- 生成DAO的包名和位置-->  <javaClientGenerator type="XMLMAPPER" targetPackage="com.fendo.generatorplus.dao" targetProject="src/main/java">  <property name="enableSubPackages" value="true"/>  </javaClientGenerator>  <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->  <table tableName="test" domainObjectName="Test" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table></context>  
</generatorConfiguration>  

cmd内容如下:

echo off
set JAVA_HOME=C:\work\java\jdk1.8.0_102
set M2_HOME=C:\work\Java\apache-maven-3.0.3set PATHP=%PATH%
set PATH=%PATH%;%M2_HOME%\bin;%ANT_HOME%\binJava -jar mybatis-generator-plus.jar -configfile generatorConfig.xml -overwriteset PATHP=%PATH%

然后一运行就cmd文件就会自动生成代码了。


完整项目:http://download.csdn.net/download/u011781521/10008156

这篇关于MyBatis Generator系列(二)----自定义CommentGenerator实现中文注释的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1068614

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

2024.6.24 IDEA中文乱码问题(服务器 控制台 TOMcat)实测已解决

1.问题产生原因: 1.文件编码不一致:如果文件的编码方式与IDEA设置的编码方式不一致,就会产生乱码。确保文件和IDEA使用相同的编码,通常是UTF-8。2.IDEA设置问题:检查IDEA的全局编码设置和项目编码设置是否正确。3.终端或控制台编码问题:如果你在终端或控制台看到乱码,可能是终端的编码设置问题。确保终端使用的是支持你的文件的编码方式。 2.解决方案: 1.File -> S

持久层 技术选型如何决策?JPA,Hibernate,ibatis(mybatis)

转自:http://t.51jdy.cn/thread-259-1-1.html 持久层 是一个项目 后台 最重要的部分。他直接 决定了 数据读写的性能,业务编写的复杂度,数据结构(对象结构)等问题。 因此 架构师在考虑 使用那个持久层框架的时候 要考虑清楚。 选择的 标准: 1,项目的场景。 2,团队的技能掌握情况。 3,开发周期(开发效率)。 传统的 业务系统,通常业

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

ROS话题通信流程自定义数据格式

ROS话题通信流程自定义数据格式 需求流程实现步骤定义msg文件编辑配置文件编译 在 ROS 通信协议中,数据载体是一个较为重要组成部分,ROS 中通过 std_msgs 封装了一些原生的数据类型,比如:String、Int32、Int64、Char、Bool、Empty… 但是,这些数据一般只包含一个 data 字段,结构的单一意味着功能上的局限性,当传输一些复杂的数据,比如:

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议