怎么创建 SpringBoot 示例项目
步骤
初始化空项目

添加依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--使用postgresql时引入 -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.5</version>
</dependency>
<!--knife4j 接口文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.9</version>
</dependency>
|
配置文件
配置文件名建议为:application.yaml。放置在 resources 文件夹下。
针对不同环境可配置为 application-dev.yaml, application-prod.yaml…并在 application.yaml 中设置激活的环境。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
spring:
profiles:
active: dev
servlet:
multipart:
max-file-size: 200MB
# postgres driver
datasource:
driver-class-name: org.postgresql.Driver
type: com.alibaba.druid.pool.DruidDataSource
# Druid的其他属性配置
druid:
url: jdbc:postgresql://192.168.10.96:5432/tdap_test?stringtype=unspecified
username: docker
password: docker
initial-size: 1
min-idle: 1
max-active: 20
max-wait: 60000
test-while-idle: true
test-on-borrow: false
test-on-return: false
filters: stat,slf4j
use-global-data-source-stat: true
connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
web-stat-filter:
enabled: true
url-pattern: /*
exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico
stat-view-servlet:
enabled: true
url-pattern: /druid/*
reset-enable: false
login-username: druid
login-password: druid
allow: 192.168.0.0/16,127.0.0.1
deny:
mvc:
pathmatch:
# knife4j 必须的配置
matching-strategy: ant_path_matcher
jackson:
date-format: yyyy-MM-dd HH:mm:ss
# 时区(需根据实际位置修改)
time-zone: GMT+8
mybatis-plus:
type-handlers-package: com.xag.ai.train.common.config.mybatis
global-config:
db-config:
id-type: auto
logging:
config: classpath:logback-spring.xml
|
日志配置
logback.xml 放置在和 application.xml 同层级位置。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
<?xml version="1.0" encoding="UTF-8"?>
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
<configuration scan="true" scanPeriod="10 seconds">
<!--<include resource="org/springframework/boot/logging/logback/base.xml"
/> -->
<contextName>Logback For Boss</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="./locakback"/>
<!-- 定义日志文件 输入位置 -->
<property name="logDir" value="./logback"/>
<!-- 日志最大的历史 7天 -->
<property name="maxHistory" value="7"/>
<!-- 控制台输出日志 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
</appender>
<!-- ERROR级别日志 -->
<appender name="ERROR"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logDir}\%d{yyyyMMdd}\error.log</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger -
%msg%n
</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<append>false</append>
<prudent>false</prudent>
</appender>
<!-- WARN级别日志 -->
<appender name="WARN"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>WARN</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logDir}\%d{yyyyMMdd}\warn.log</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<append>false</append>
<prudent>false</prudent>
</appender>
<!-- INFO级别日志 -->
<appender name="INFO"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logDir}\%d{yyyyMMdd}\info.log</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<append>false</append>
<prudent>false</prudent>
</appender>
<!-- DEBUG级别日志 -->
<appender name="DEBUG"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${logDir}\%d{yyyyMMdd}\debug.log</fileNamePattern>
<maxHistory>${maxHistory}</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger-%msg%n</pattern>
<charset class="java.nio.charset.Charset">UTF-8</charset>
</encoder>
<append>false</append>
<prudent>false</prudent>
</appender>
<!--文件日志, 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${logDir}/%d{yyyyMMdd}/boss.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 异步输出 -->
<appender name="dayLogAsyncAppender" class="ch.qos.logback.classic.AsyncAppender">
<includeCallerData>true</includeCallerData>
<!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
<discardingThreshold>0</discardingThreshold>
<!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
<queueSize>512</queueSize>
<appender-ref ref="FILE"/>
</appender>
<!--专为 spring 定制
-->
<logger name="org.springframework" level="info"/>
<!-- show parameters for hibernate sql 专为 Hibernate 定制 -->
<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="TRACE"/>
<logger name="org.hibernate.type.descriptor.sql.BasicExtractor" level="DEBUG"/>
<logger name="org.hibernate.SQL" level="DEBUG"/>
<logger name="org.hibernate.engine.QueryParameters" level="DEBUG"/>
<logger name="org.hibernate.engine.query.HQLQueryPlan" level="DEBUG"/>
<logger name="org.apache.kafka" level="off"/>
<!--myibatis log configure-->
<!--
<logger name="com.apache.ibatis" level="TRACE"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
-->
<!-- root级别 DEBUG -->
<root level="INFO">
<!-- 控制台输出 -->
<appender-ref ref="STDOUT"/>
<!-- 文件输出 -->
<appender-ref ref="ERROR"/>
<appender-ref ref="INFO"/>
<appender-ref ref="WARN"/>
<appender-ref ref="DEBUG"/>
</root>
</configuration>
|
配置全局处理
MybatisPlus 分页插件配置
1
2
3
4
5
6
7
8
9
10
11
|
@Configuration
public class MybatisPlusConfig {
// 最新版分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
return interceptor;
}
}
|
Knife4J 在线接口文档配置
1
2
3
4
5
6
7
8
9
10
|
@Configuration
public class MybatisPlusConfig {
// 最新版分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.POSTGRE_SQL));
return interceptor;
}
}
|
Long 序列化配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
/**
* 全局序列化配置类
*
* @author GuoYingdong
* @date 2023/02/02
*/
@Configuration
public class JsonConfig {
/**
* 创建Jackson对象映射器
*
* @param builder Jackson对象映射器构建器
* @return ObjectMapper
*/
@Bean
public ObjectMapper getJacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
this.registerLongSerializer(objectMapper);
//反序列化的时候如果多了其他属性,不抛出异常
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//日期格式处理
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
return objectMapper;
}
/**
* 注册 Long 类型的序列化器
*
* @param objectMapper
*/
private void registerLongSerializer(ObjectMapper objectMapper) {
//序列换成json时,将所有的long变成string.因为js中得数字类型不能包含所有的java long值,超过16位后会出现精度丢失
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
simpleModule.addSerializer(Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
objectMapper.registerModule(simpleModule);
}
}
|
返回内容 Result 配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/**
* 返回结果定义
*
* @author guoyd
* @version 1.0.0
* @date 2021/01/25
*/
public class ResultBody<T> {
/**
* 响应代码
*/
private String code;
/**
* 响应消息
*/
private String message;
/**
* 响应结果
*/
private T result;
public ResultBody() {
}
/**
* 结果
*
* @param errorInfo 错误信息
* @return {@link }
*/
public ResultBody(BaseErrorInfoInterface errorInfo) {
this.code = errorInfo.getResultCode();
this.message = errorInfo.getResultMsg();
}
/**
* 成功
*
* @return {@link ResultBody }
*/
public static <T> ResultBody<T> success() {
return success(null);
}
/**
* 成功
*
* @param data 数据
* @return {@link ResultBody }
*/
public static <T> ResultBody<T> success(T data) {
ResultBody<T> rb = new ResultBody<T>();
rb.setCode(CommonEnum.SUCCESS.getResultCode());
rb.setMessage(CommonEnum.SUCCESS.getResultMsg());
rb.setResult(data);
return rb;
}
/**
* 失败
*/
public static <T> ResultBody<T> error(BaseErrorInfoInterface errorInfo) {
ResultBody<T> rb = new ResultBody<T>();
rb.setCode(errorInfo.getResultCode());
rb.setMessage(errorInfo.getResultMsg());
rb.setResult(null);
return rb;
}
/**
* 失败
*/
public static <T> ResultBody<T> error(String status, String message) {
ResultBody<T> rb = new ResultBody<T>();
rb.setCode(status);
rb.setMessage(message);
rb.setResult(null);
return rb;
}
/**
* 失败
*/
public static <T> ResultBody<T> error(String message) {
ResultBody<T> rb = new ResultBody<T>();
rb.setCode("500");
rb.setMessage(message);
rb.setResult(null);
return rb;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
@Override
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
}
}
|
全局异常捕捉
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/**
* 基本错误信息界面
*
* @author guoyd
* @version 1.0.0
* @date 2021/01/25
*/
public interface BaseErrorInfoInterface {
/**
* 获取的结果状态码
*
* @return {@link String }
*/
String getResultCode();
/**
* 获取结果信息
*
* @return {@link String }
*/
String getResultMsg();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
/**
* 业务异常
*
* @author guoyd
* @version 1.0.0
* @date 2021/01/25
*/
public class BizException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
protected String errorCode = "500";
/**
* 错误信息
*/
protected String errorMsg;
public BizException() {
super();
}
public BizException(BaseErrorInfoInterface errorInfoInterface) {
super(errorInfoInterface.getResultCode());
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(BaseErrorInfoInterface errorInfoInterface, Throwable cause) {
super(errorInfoInterface.getResultCode(), cause);
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
@Override
public String getMessage() {
return errorMsg;
}
@Override
public Throwable fillInStackTrace() {
return this;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
/**
* 常见的枚举
*
* @author guoyd
* @version 1.0.0
* @date 2021/01/25
*/
public enum CommonEnum implements BaseErrorInfoInterface {
// 数据操作错误定义
SUCCESS("200", "成功!"),
BODY_NOT_MATCH("400", "请求的数据格式不符!"),
SIGNATURE_NOT_MATCH("401", "token 无效!"),
NOT_FOUND("404", "未找到该资源!"),
INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),
SERVER_BUSY("503", "服务器正忙,请稍后再试!");
/**
* 错误码
*/
private final String resultCode;
/**
* 错误描述
*/
private final String resultMsg;
CommonEnum(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
@Override
public String getResultCode() {
return resultCode;
}
@Override
public String getResultMsg() {
return resultMsg;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
|
/**
* 全局异常处理
*
* @author guoyd
* @version 1.0.0
* @date 2021/01/25
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 处理自定义的业务异常
*
* @param req 要求的事情
* @param e e
* @return {@link ResultBody }
*/
@ExceptionHandler(value = BizException.class)
@ResponseBody
public ResultBody bizExceptionHandler(HttpServletRequest req, BizException e) {
logger.error("业务异常!原因:{}", e.getErrorMsg());
return ResultBody.error(e.getErrorCode(), e.getErrorMsg());
}
/**
* 处理空指针的异常
*
* @param req 要求的事情
* @param e e
* @return {@link ResultBody }
*/
@ExceptionHandler(value = {NullPointerException.class})
@ResponseBody
public ResultBody exceptionHandler(HttpServletRequest req, NullPointerException e) {
logger.error("空指针异常!原因:", e);
return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
}
/**
* 处理参数异常
*
* @param req 要求的事情
* @param e e
* @return {@link ResultBody}
*/
@ExceptionHandler(value = MissingRequestValueException.class)
@ResponseBody
public ResultBody exceptionHandler(HttpServletRequest req,
MissingRequestValueException e) {
logger.error("参数异常!原因:", e);
return ResultBody.error(CommonEnum.BODY_NOT_MATCH);
}
/**
* 处理参数异常
*
* @param req 要求的事情
* @param e e
* @return {@link ResultBody}
*/
@ExceptionHandler(value = HttpMessageNotReadableException.class)
@ResponseBody
public ResultBody exceptionHandler(HttpServletRequest req,
HttpMessageNotReadableException e) {
logger.error("参数异常!原因:", e);
return ResultBody.error(CommonEnum.BODY_NOT_MATCH);
}
/**
* 处理其他异常
*
* @param req 要求的事情
* @param e e
* @return {@link ResultBody }
*/
@ExceptionHandler(value = Exception.class)
@ResponseBody
public ResultBody exceptionHandler(HttpServletRequest req, Exception e) {
logger.error("未知异常!原因:", e);
return ResultBody.error(CommonEnum.INTERNAL_SERVER_ERROR);
}
}
|
业务代码
业务代码中 try-catch 到异常后,以 new BizException("error msg") 的形式跑出来,方便定位问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/**
* 系统信息控制器
*
* @author GuoYingdong
* @date 2023/02/01
*/
@Slf4j
@Api("服务信息")
@RestController
@RequestMapping("/sysInfo")
@RequiredArgsConstructor
public class SysInfoController {
/**
* 获取服务信息
*
* @return {@link ResultBody}<{@link Map}<{@link String}, {@link String}>>
* @throws JsonProcessingException json处理异常
*/
@GetMapping("/info")
public ResultBody<Map<String, String>> info() {
Map<String, String> map = new HashMap<>();
map.put("name", "");
map.put("description", "");
return ResultBody.success(map);
}
@GetMapping("/health")
public ResultBody<Boolean> health() {
return ResultBody.success(true);
}
}
|