【JavaEE】 spring boot的配置文件详解

spring boot的配置文件详解

文章目录

  • spring boot的配置文件详解
    • 常用配置
    • spring boot的配置文件
      • 1. properties 文件
      • 2. YAML 文件
      • 3. 多环境配置
      • 4. 配置文件优先级
      • 5. 配置属性注入
      • 特殊说明
    • properties配置文件
      • 基本语法
    • 例子
      • peoperties文件的缺点
    • YML配置文件
    • YML使用
      • yml 配置不同数据类型及 null
        • 注意事项
      • 配置对象
      • 配置集合
      • 配置map
      • YML 的优缺点
        • 优点
        • 缺点

常用配置

spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Drivermvc:favicon:enable: falseprofiles:  #多平台配置active: dev
# 设置 Mybatis 的 xml 保存路径
mybatis:mapper-locations: classpath:mapper/*Mapper.xmlconfiguration: # 配置打印 MyBatis 执行的 SQLlog-impl: org.apache.ibatis.logging.stdout.StdOutImplmap-underscore-to-camel-case: true  #自动驼峰转换
# 配置打印 MyBatis 执行的 SQL
logging:file:name: logs/springboot.loglogback:rollingpolicy:max-file-size: 1KBfile-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%ilevel:com:example:demo: debug

spring boot的配置文件

SpringBoot⽀持并定义了配置⽂件的格式, 也在另⼀个层⾯达到了规范其他框架集成到SpringBoot的

⽬的.

很多项⽬或者框架的配置信息也放在配置⽂件中, ⽐如:

  • 项⽬的启动端⼝
  • 数据库的连接信息(包含⽤⼾名和密码的设置)
  • 第三⽅系统的调⽤密钥等信息
  • ⽤于发现和定位问题的普通⽇志和异常⽇志等.

在idea中我们修改 application.properties ⽂件即可。

Spring Boot 配置文件详解

在 Spring Boot 中,配置文件是管理应用程序配置的重要组成部分。它可以用来配置应用程序的各种属性,包括数据库连接、日志级别、端口号等。Spring Boot 支持多种类型的配置文件,包括 properties 文件、YAML 文件等。本文将详细介绍 Spring Boot 配置文件的使用方法和常见配置项。

1. properties 文件

示例:application.properties

# 设置应用程序端口号
server.port=8080# 配置数据库连接
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username=root
spring.datasource.password=root# 配置日志级别
logging.level.org.springframework=INFO

2. YAML 文件

YAML和YML文件是一样的。

示例:application.yaml

# 设置应用程序端口号
server:port: 8080# 配置数据库连接
spring:datasource:url: jdbc:mysql://localhost:3306/mydatabaseusername: rootpassword: root# 配置日志级别
logging:level:org:springframework: INFO

3. 多环境配置

示例:application-{profile}.properties 或 application-{profile}.yaml

# 开发环境配置
# application-dev.propertiesserver.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/dev_database
spring.datasource.username=root
spring.datasource.password=root
# 生产环境配置
# application-prod.propertiesserver.port=80
spring.datasource.url=jdbc:mysql://localhost:3306/prod_database
spring.datasource.username=admin
spring.datasource.password=admin

4. 配置文件优先级

Spring Boot 配置文件的优先级顺序如下:

  1. 命令行参数:使用命令行参数可以覆盖配置文件中的属性。
  2. 内置默认值:Spring Boot 内置了许多默认属性,如果没有在配置文件中指定,则会使用这些默认值。
  3. 当前目录下的 config 文件夹:Spring Boot 会在当前目录下的 config 文件夹中查找配置文件。
  4. 当前目录:Spring Boot 会在当前目录中查找配置文件。
  5. classpath 下的 /config 文件夹:Spring Boot 会在类路径下的 /config 文件夹中查找配置文件。
  6. classpath 根目录:Spring Boot 会在类路径的根目录下查找配置文件。
  7. 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5. 配置属性注入

Spring Boot 支持在配置文件中定义属性,并使用 @Value 注解将属性值注入到 Java 类中。

示例:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class MyComponent {@Value("${myapp.message}")private String message;public void displayMessage() {System.out.println("Message from properties file: " + message);}
}

在配置文件中设置 myapp.message=Hello, World!,则 message 属性的值会被注入为 “Hello, World!”。

特殊说明

  1. 理论上讲 .properties.yml 可以并存在于⼀个项⽬中,当 .properties.yml

并存时,两个配置都会加载. 如果配置⽂件内容有冲突, 则以 .properties 为主, 也就是.properties 优先级更⾼.

  1. 虽然理论上来讲 .properties 可以和 .yml 共存,但实际的业务当中,我们通常会采取⼀种

统⼀的配置⽂件格式,这样可以更好的维护 (降低故障率)

properties配置文件

配置文件官网可参考学习

基本语法

Properties 文件是一种常见的配置文件格式,用于存储键值对形式的配置信息。它通常用于配置应用程序的参数、属性、设置等。下面是 Properties 文件的语法:

  1. 键值对:Properties 文件由多个键值对组成,每个键值对由键和值组成,中间用等号连接,如:key=value

  2. 注释:可以在 Properties 文件中添加注释,以 #! 开头的行被视为注释,不会被解析。

  3. 空行:空行会被忽略,不会被解析。

  4. 转义字符:可以使用反斜杠 \ 进行转义,表示特殊字符的转义,如 \n 表示换行符。

  5. Unicode 编码:可以使用 Unicode 编码表示非 ASCII 字符。

下面是一个简单的 Properties 文件示例:

# This is a sample properties file# Database configuration
db.url=jdbc:mysql://localhost:3306/mydatabase
db.username=admin
db.password=123456# Server configuration
server.port=8080
server.host=localhost

在这个示例中,我们定义了数据库和服务器的配置信息,每个键值对代表一个配置项,键表示配置项的名称,值表示配置项的值。注释以 # 开头,表示注释内容。

例子

# 项目常用端口号
server.port=8080
# 配置数据库连接信息
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root# 自定义一些配置
ben.key1=ben666
ben.key2=789
package org.haobin.ioc.demo.Controller;import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author 刘浩彬* @date 2024/2/25*/@RestController
@RequestMapping("/prop")
public class PropertiesController {@Value("${ben.key1}")private String key1;@Value("${ben.key2}")private Integer key2;@RequestMapping("/readValue")public String readValue(){return "从Properties读取配置文件,key1:"+key1;}@RequestMapping("/readValue2")public String readValue2(){return "从Properties读取配置文件,key2:"+key2;}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

peoperties文件的缺点

虽然 Properties 文件在很多情况下都是一种方便的配置方式,但也存在一些缺点,包括:

  1. 扩展性差:Properties 文件的结构简单,只支持键值对形式的配置,无法表示复杂的数据结构,如列表、嵌套对象等,因此在需要表示复杂配置信息时,会显得不够灵活。

  2. 类型转换不方便:Properties 文件中的值都是字符串形式,无法直接表示其他类型的数据,比如整数、浮点数、布尔值等。在读取配置时,需要手动进行类型转换,增加了开发的复杂度和出错的可能性。

  3. 不支持注释嵌套:Properties 文件的注释只能位于行首,无法在行内或值之后添加注释。这样的限制可能会导致注释和配置项的关系不够清晰,不利于代码的维护和阅读。

  4. 不支持环境变量替换:Properties 文件无法直接引用环境变量,需要借助外部工具或框架来实现环境变量的替换,增加了配置的复杂度。

  5. 不支持多语言:Properties 文件中的配置项只能使用一种语言表示,无法方便地支持多语言配置,这在国际化的应用程序中可能会造成不便。

YML配置文件

yml 是树形结构的配置⽂件,它的基础语法是"key: value".

key 和 value 之间使⽤英⽂冒号加空格的⽅式组成,空格不可省略YAML(YAML Ain’t Markup Language)是一种人类友好的数据序列化格式,常用于配置文件和数据交换。YAML 文件采用缩进和空格来表示层次结构,具有清晰简洁、易读易写的特点。下面是 YAML 配置文件的主要语法:

  1. 基本规则

    • YAML 文件以 .yml.yaml 扩展名结尾。
    • 使用缩进表示层次结构,缩进时只能使用空格,不能使用制表符。
    • 使用 # 符号表示注释,注释可以单独一行或在行尾。
  2. 键值对

    • 使用冒号 : 将键和值分隔开。
    • 键值对可以写在同一行,也可以换行写,但冒号后必须跟一个空格。
  3. 列表

    • 使用连字符 - 表示列表项。
    • 列表项可以是简单值,也可以是对象或其他列表。
  4. 对象

    • 对象使用缩进表示层次结构,每个属性都是键值对形式。
    • 对象的属性可以是简单值,也可以是嵌套的对象或列表。
  5. 引号

    • 字符串值可以使用单引号 ' ' 或双引号 " " 包裹,也可以省略引号。
    • 使用引号可以保留字符串的空白字符或特殊字符。
  6. 多行字符串

    • 使用 | 符号表示多行字符串,保留换行符和缩进。
    • 使用 > 符号表示多行字符串,忽略换行符,但保留缩进。
  7. 特殊值

    • truefalsenull 分别表示布尔值 true、false 和空值。

下面是一个简单的 YAML 示例:

# YAML 示例配置文件server:port: 8080hostname: localhostdatabase:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: passwordlogging:level:root: infocom.example: debugprofiles:- dev- test- prod
server:port: 9090spring:datasource:url: jdbc:mysql://127.0.0.0:3306/dbname?characterEncoding=utf8&useSSL=falseusername: rootpassword: root

YML使用

yml 配置不同数据类型及 null

server:port: 9090spring:datasource:url: jdbc:mysql://127.0.0.0:3306/dbname?characterEncoding=utf8&useSSL=falseusername: rootpassword: root# 自定义配置项
string.value: ben666
string:value2: ben22222222
package org.haobin.ioc.demo.Controller;import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/yml")
public class ymlController {@Value("${string.value}")private String value;@Value("${string.value2}")private String key2;@Value("${spring.datasource.url}")private String url;@RequestMapping("/readValue")public String readValue() {return "从yml读取配置文件,value:" + value;}@RequestMapping("/readValue2")public String readValue2() {return "从yml读取配置文件,key2:" + key2;}@RequestMapping("/url")public String readUrl() {return "从yml读取配置文件,url:" + url;}
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

# 字符串
string.value: Hello
# 布尔值,true或false
boolean.value: true
boolean.value1: false
# 整数
int.value: 10
# 浮点数
float.value: 3.14159
# Null,~代表null
null.value: ~
# 如果使用字符串接收,字符串的值是 ~# "" 空字符串
#, 直接后⾯什么都不加就可以了, 但这种⽅式不直观, 更多的表⽰是使⽤引号括起来
empty.value:
注意事项

value 值加单双引号

字符串默认不⽤加上单引号或者双引号,如果加英⽂的单双引号可以表⽰特殊的含义。

尝试在 application.yml 中配置如下信息

string:str1: Hello \n Spring Boot.str2: 'Hello \n Spring Boot.'str3: "Hello \n Spring Boot."
@Value("${string.str1}")private String str1;@Value("${string.str2}")private String str2;@Value("${string.str3}")private String str3;@RequestMapping("/yml")public String readYml(){System.out.println(str1);System.out.println(str2);System.out.println(str3);return "yml";}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上述结果可以看出:

  • 字符串默认不⽤加上单引号或者双引号。
  • 单引号会转义特殊字符,使其失去特殊功能, 始终是⼀个普通的字符串.
  • 双引号不会转义字符串⾥⾯的特殊字符, 特殊字符会表⽰本⾝的含义.

此处的转义理解起来会有些拗⼝, \n 本意表⽰的是换⾏

使⽤单引号会转义, 就是说, \n 不再表⽰换⾏了, ⽽是表⽰⼀个普通的字符串

使⽤双引号不会转义, 表⽰ \n 表⽰的是它本⾝的含义, 就是换⾏


配置对象

@Autowired
private Student student;@RequestMapping("/stu")
public String readStu(){return student.toString();
}
package org.haobin.ioc.demo.model;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "student")
@Data
public class Student {private Integer id;private Integer age;private String name;
}
student:id: 1name: javaage: 18

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


配置集合

配置⽂件也可以配置 list 集合,如下所⽰:

dbtypes:name:- mysql- sqlserver- db2

注意点

dbtypes:name:- mysql- sqlserver- db2

如果- mysql中的空格省略了,不会报错。但是含义是变了的,这几个元素就会被当做一个元素来处理

集合的读取和对象⼀样,也是使⽤ @ConfigurationProperties 来读取的,具体实现如下:

@Component
@Data
@ConfigurationProperties("dbtypes")
public class Dbtypes {private List<String> name;
}

访问集合的实现如下:

@Autowired
private Dbtypes dbtypes;@RequestMapping("/list")
public String readList(){return dbtypes.toString();
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

配置map

道理和配置list一样

不做解释,给示例代码如下:

maptypes:map:k1: kk1k2: kk2k3: kk3
@Component
@Data
@ConfigurationProperties("maptypes")
public class Maptypes {private HashMap<String, String> map;
}
@Autowired
private Maptypes maptypes;@RequestMapping("/map")
public String readMap(){return maptypes.toString();
}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

YML 的优缺点

优点
  1. 易读性高

    • YML 使用缩进和空格来表示层次结构,与传统的大括号和逗号相比,更接近自然语言,更易于理解和阅读。
    • YML 文件结构清晰简洁,注重可读性,适合人类阅读和编辑。
  2. 简洁清晰

    • YML 使用简洁的语法,可以轻松地表示复杂的数据结构,如列表、对象和多行字符串,使配置文件更加简洁明了。
  3. 可扩展性

    • YML 具有灵活的语法和结构,可以轻松地扩展和调整配置文件的内容,适用于各种类型的应用场景和需求。
  4. 与多种编程语言兼容

    • YML 格式与多种编程语言兼容,包括 Java、Python、JavaScript 等,可以方便地在不同语言环境中使用和解析。
缺点
  1. 空格敏感

    • YML 的语法对空格敏感,缩进和空格的使用必须严格遵循规范,否则可能会导致解析错误或意外结果。
  2. 复杂性

    • 随着配置文件的复杂度增加,YML 文件的结构也可能变得复杂,不易于管理和维护,尤其是对于大型项目。
  3. 不适合所有场景

    • 尽管 YML 在配置文件和数据交换方面表现良好,但并不适合所有场景。对于某些特定需求或环境,可能存在更合适的选择。
  4. 缺乏严格的规范

    • YML 并没有像 JSON 那样严格的规范,不同的实现可能存在细微差异,可能会导致不同解析器之间的兼容性问题。

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

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

相关文章

Android学习笔记 service启动方式

在Android系统中&#xff0c;Service的启动方式主要有两种&#xff1a; ## 1. startService 这种方式用于启动一个服务执行后台任务&#xff0c;不进行通信。当你调用startService()方法启动服务后&#xff0c;服务会一直无限期运行下去&#xff0c;只有在外部调用了stopServi…

关于Sora的基本情况

Sora 是一种由 OpenAI 开发的 AI 模型&#xff0c;它能够根据文本指令创建逼真的、富有想象力的视频场景。它使用一种称为“扩散模型”的技术来生成视频&#xff0c;该技术从随机噪声开始&#xff0c;并逐渐将其转化为具有所需特征的图像或视频帧。 功能 Sora 的主要功能包括…

守护绿色屏障:智能高压森林应急消防泵|恒峰智慧科技

在茂密的森林中&#xff0c;树木蓊郁&#xff0c;绿意盎然。这里是大自然赋予我们的宝贵财富&#xff0c;是我们人类赖以生存的重要资源。然而&#xff0c;随着人类活动的增加&#xff0c;森林火灾频发&#xff0c;给我们的生活带来了极大的威胁。为了保护这片绿色屏障&#xf…

springstarter

starter 例如我想要在SpringBoot项目中集成Redis&#xff0c;那么我只需要加入spring-data-redis-starter的依赖&#xff0c;并简单配置一下连接信息以及Jedis连接池配置就可以。这为我们省去了之前很多的配置操作。甚至有些功能的开启只需要在启动类或配置类上增加一个注解即…

HUAWEI Programming Contest 2024(AtCoder Beginner Contest 342)

D - Square Pair 题目大意 给一长为的数组&#xff0c;问有多少对&#xff0c;两者相乘为非负整数完全平方数 解题思路 一个数除以其能整除的最大的完全平方数&#xff0c;看前面有多少个与其余数相同的数&#xff0c;两者乘积满足条件&#xff08;已经是完全平方数的部分无…

Linux系统前后端分离项目

目录 一.jdk安装 二.tomcat安装 三.MySQL安装 四.nginx安装 五.Nginx负载均衡tomcat 六.前端部署 一.jdk安装 1. 上传jdk安装包 jdk-8u151-linux-x64.tar.gz 进入opt目录&#xff0c;将安装包拖进去 2. 解压安装包 这里需要解压到usr/local目录下&#xff0c;在这里新建一个…

LINUX ntp时间服务器编译

下载 Index of /~ntp/ntp_spool/ntp4 https://www.eecis.udel.edu/~ntp/ntp_spool/ntp4/ntp-4.2.8p17.tar.gz 编译openssl LINUX下载编译OpenSSL_openssl-1.0.2u编译-CSDN博客 编译 DEST_DIR/home/toybrick/ntp_serverif [ -d ${DEST_DIR} ]; thenrm -rf ${DEST_DIR} fi.…

Python in Excel的一些使用心得

获得Python in Excel的preview之后, 就在任意的Excel单元格里可以敲py(来写Python代码了。不过Python in Excel并没有什么专门的文档, 只有一些_Get Started_教程, 比如link 1, link 2, 剩下的就是pandas, matplotlib, seaborn等lib的文章&#xff0c;和Python in Excel并没有什…

Python算法题集_实现 Trie [前缀树]

Python算法题集_实现 Trie [前缀树] 题208&#xff1a;实现 Trie (前缀树)1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【定义数据类默认字典】2) 改进版一【初始化字典无额外类】3) 改进版二【字典保存结尾信息无额外类】 4. 最优算法5. 相关…

OpenGL-ES 学习(5)---- GPU 基础知识

目录 Arm GPU 架构说明移动系统的特点渲染管线渲染管线简介几何处理像素处理 渲染管线的硬件IMR(立即渲染)TBR(Tile Based Rendering) 渲染硬件的实现CPUGPU 设计 Mali Shadercore重要补充 Arm GPU 架构说明 UtGard: 比较早的架构,支持到 OpenGL-ES 2.0&#xff0c;VertexShad…

【小尘送书-第十四期】《高效使用Redis:一书学透数据存储与高可用集群》

大家好&#xff0c;我是小尘&#xff0c;欢迎你的关注&#xff01;大家可以一起交流学习&#xff01;欢迎大家在CSDN后台私信我&#xff01;一起讨论学习&#xff0c;讨论如何找到满意的工作&#xff01; &#x1f468;‍&#x1f4bb;博主主页&#xff1a;小尘要自信 &#x1…

Vue组件间的通信详解

在Vue中&#xff0c;组件之间的通信可以有多种方式实现&#xff1a; Props 和 $emit Props&#xff1a;父组件向子组件传递数据时&#xff0c;通过属性绑定&#xff08;v-bind 或 :&#xff09;将数据作为属性传给子组件。子组件需要在props选项中声明它接收的属性列表。**emit…

Base64 编码 lua

Base64 编码 -- Base64 字符表 local base64_chars { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,…

文献阅读:Large Language Models are Null-Shot Learners

文献阅读&#xff1a;Large Language Models are Null-Shot Learners 1. 文章简介2. 方法介绍3. 实验考察 & 结论 1. 基础实验 1. 实验设计2. 实验结果 2. 消融实验 1. 小模型上的有效性2. ∅CoT Prompting3. 位置影响4. 组成内容 4. 总结 & 思考 文献链接&#xff1…

gitlab 忘记root密码,修改root密码

1.使用root用户登录服务器 2.进入GitLab的安装目录&#xff0c;一般是 /opt/gitlab/ 3.执行以下命令重置密码&#xff1a; sudo gitlab-rails consoleuser User.where(id: 1).first user.password new password user.password_confirmation new password user.save! 退出…

openEuler22.03 LTS中配置vsftp服务器

一、说明 配置环境&#xff1a;VMware虚拟机中安装openEuler 22.03 LTS系统&#xff0c;并确保该Linux服务器能访问Internet。 FTP服务器的身份认证模式 vsftpd服务提供以下3种身份认证模式&#xff0c;前两种模式比较常见&#xff0c;第3种模式是vsftpd的特有的服务模式。 …

代码随想录算法刷题训练营day23

代码随想录算法刷题训练营day23&#xff1a;LeetCode(669)修剪二叉搜索树、LeetCode(108)将有序数组转换为二叉搜索树、LeetCode(538)把二叉树转化为累加树 LeetCode(669)修剪二叉搜索树 题目 代码 /*** Definition for a binary tree node.* public class TreeNode {* …

【Vue】Vue双向绑定原理

【Vue】Vue双向绑定原理 定义&#xff1a;数据变化视图会自动更新&#xff0c;视图变化数据也会更新原理&#xff1a;通过数据劫持和发布订阅模式实现的实现 定义&#xff1a;数据变化视图会自动更新&#xff0c;视图变化数据也会更新 比如说&#xff0c;当在输入框输入文字时…

SocketWeb实现小小聊天室

SocketWeb实现小小聊天室 消息推送的常见方式轮询长轮询SSE&#xff08;server-sent event&#xff09;&#xff1a;服务器发送事件WebSocketWebSocket简介WebSocket API 实现小小聊天室实现流程消息格式客户端-->服务端服务端-->客户端 消息推送的常见方式 轮询 浏览器…

图书推荐|Windows Server 2022 Active Directory配置实战

十几年磨一剑&#xff0c;畅销书第10次升级 本书简介 《Windows Server 2022 Active Directory配置实战》是微软技术专家最新推出的Windows Server 2022两卷力作中的Active Directory配置实战篇。 《Windows Server 2022 Active Directory配置实战》延续了作者一贯的写作风格…