全局异常处理
全局异常处理可以通过使用 @ControllerAdvice 或 @RestControllerAdvice 结合 @ExceptionHandler 实现。它是一个优雅的方式,用来集中处理应用程序中的异常,避免在每个控制器中重复处理异常逻辑。
核心注解介绍
@ControllerAdvice:- 作用:定义全局范围的异常处理器,适用于所有的
Controller。 - 处理异常后可以返回视图或 JSON,取决于控制器的返回类型。
- 作用:定义全局范围的异常处理器,适用于所有的
@RestControllerAdvice:- 是
@ControllerAdvice的扩展,默认将异常处理结果返回为 JSON 或其他对象格式(基于@ResponseBody)。
- 是
@ExceptionHandler:- 作用:指定要处理的异常类型,可以用于单个控制器或全局异常处理器中。
统一返回实体
java
package local.ateng.java.exception.utils;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 统一 API 响应结果封装类,支持链式调用和额外数据存储。
* <p>
* 该类是 **不可变对象(Immutable Object)**,以保证线程安全。
* 每次修改操作都会创建一个新的 `Result<T>` 实例,避免并发环境下的数据竞争问题。
* </p>
*
* @param <T> 业务数据的类型
* @author 孔余
* @email 2385569970@qq.com
* @since 2025-03-05
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 默认成功状态码
*/
private static final String DEFAULT_SUCCESS_CODE = "0";
/**
* 默认成功消息
*/
private static final String DEFAULT_SUCCESS_MESSAGE = "请求成功";
/**
* 默认失败状态码
*/
private static final String DEFAULT_ERROR_CODE = "-1";
/**
* 默认失败消息
*/
private static final String DEFAULT_ERROR_MESSAGE = "服务器异常,请稍后再试";
/**
* 状态码
*/
private final String code;
/**
* 提示信息
*/
private final String msg;
/**
* 业务数据
*/
private final T data;
/**
* 响应时间戳(不可变)
*/
private final LocalDateTime timestamp;
/**
* 额外信息存储(使用不可变 Map,保证线程安全)
*/
private final Map<String, Object> extra;
/**
* 私有构造方法,默认初始化成功状态,extra 为空 Map。
*/
private Result() {
this.code = DEFAULT_SUCCESS_CODE;
this.msg = DEFAULT_SUCCESS_MESSAGE;
this.data = null;
this.timestamp = LocalDateTime.now();
this.extra = Collections.emptyMap();
}
/**
* 统一构造方法,确保 extra 是不可变的,防止并发修改问题。
*
* @param code 状态码
* @param msg 提示信息
* @param data 业务数据
* @param extra 额外信息 Map
*/
private Result(String code, String msg, T data, Map<String, Object> extra) {
this.code = code;
this.msg = msg;
this.data = data;
this.timestamp = LocalDateTime.now();
// 使用不可变 Map 防止外部修改
this.extra = (extra == null) ? Collections.emptyMap() : Collections.unmodifiableMap(extra);
}
// ==============================
// 静态工厂方法(标准 API 响应)
// ==============================
/**
* 生成一个成功的响应(无数据)。
*
* @param <T> 泛型类型
* @return 成功的 Result 实例
*/
public static <T> Result<T> success() {
return new Result<>(DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, null, null);
}
/**
* 生成一个成功的响应,包含数据。
*
* @param <T> 业务数据类型
* @param data 业务数据
* @return 成功的 Result 实例
*/
public static <T> Result<T> success(T data) {
return new Result<>(DEFAULT_SUCCESS_CODE, DEFAULT_SUCCESS_MESSAGE, data, null);
}
/**
* 生成一个成功的响应,包含自定义消息和数据。
*
* @param <T> 业务数据类型
* @param msg 自定义成功消息
* @param data 业务数据
* @return 成功的 Result 实例
*/
public static <T> Result<T> success(String msg, T data) {
return new Result<>(DEFAULT_SUCCESS_CODE, msg, data, null);
}
/**
* 生成一个成功的响应,包含自定义状态码、消息和数据。
*
* @param <T> 业务数据类型
* @param code 自定义状态码
* @param msg 自定义成功消息
* @param data 业务数据
* @return 返回标准成功响应
*/
public static <T> Result<T> success(String code, String msg, T data) {
return new Result<>(code, msg, data, null);
}
/**
* 生成一个失败的响应(无数据)。
*
* @param <T> 业务数据类型
* @return 失败的 Result 实例
*/
public static <T> Result<T> failure() {
return new Result<>(DEFAULT_ERROR_CODE, DEFAULT_ERROR_MESSAGE, null, null);
}
/**
* 生成一个失败的响应,包含自定义错误消息。
*
* @param <T> 业务数据类型
* @param msg 自定义失败消息
* @return 失败的 Result 实例
*/
public static <T> Result<T> failure(String msg) {
return new Result<>(DEFAULT_ERROR_CODE, msg, null, null);
}
/**
* 生成一个失败的响应,包含自定义状态码和消息(无业务数据)。
*
* @param <T> 业务数据类型
* @param code 自定义状态码
* @param msg 自定义失败消息
* @return 返回标准失败响应
*/
public static <T> Result<T> failure(String code, String msg) {
return new Result<>(code, msg, null, null);
}
/**
* 生成一个失败的响应,包含自定义状态码、消息和数据。
*
* @param <T> 业务数据类型
* @param code 自定义状态码
* @param msg 自定义失败消息
* @param data 业务数据
* @return 返回标准失败响应
*/
public static <T> Result<T> failure(String code, String msg, T data) {
return new Result<>(code, msg, data, null);
}
// ==============================
// 生成新实例的方法(不可变对象)
// ==============================
/**
* 生成新的 `Result<T>`,修改状态码。
*
* @param code 新的状态码
* @return 新的 `Result<T>` 实例
*/
public Result<T> withCode(String code) {
return new Result<>(code, this.msg, this.data, this.extra);
}
/**
* 生成新的 `Result<T>`,修改提示信息。
*
* @param msg 新的提示信息
* @return 新的 `Result<T>` 实例
*/
public Result<T> withMsg(String msg) {
return new Result<>(this.code, msg, this.data, this.extra);
}
/**
* 生成新的 `Result<U>`,修改业务数据类型。
*
* @param <U> 新的泛型类型
* @param data 业务数据
* @return 新的 `Result<U>` 实例
*/
public <U> Result<U> withData(U data) {
return new Result<>(this.code, this.msg, data, this.extra);
}
/**
* 生成新的 `Result<T>`,添加单个额外信息。
*
* @param key 额外信息的键
* @param value 额外信息的值
* @return 新的 `Result<T>` 实例
*/
public Result<T> withExtra(String key, Object value) {
Map<String, Object> newExtra = new ConcurrentHashMap<>(this.extra);
newExtra.put(key, value);
return new Result<>(this.code, this.msg, this.data, newExtra);
}
/**
* 生成新的 `Result<T>`,添加多个额外信息。
*
* @param extraData 额外信息的 Map
* @return 新的 `Result<T>` 实例
*/
public Result<T> withExtra(Map<String, Object> extraData) {
if (extraData == null || extraData.isEmpty()) {
return this;
}
Map<String, Object> newExtra = new ConcurrentHashMap<>(this.extra);
newExtra.putAll(extraData);
return new Result<>(this.code, this.msg, this.data, newExtra);
}
// ==============================
// Getter 方法(保持不可变性)
// ==============================
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
public T getData() {
return data;
}
public LocalDateTime getTimestamp() {
return timestamp;
}
public Map<String, Object> getExtra() {
return extra;
}
// ==============================
// toString 方法
// ==============================
@Override
public String toString() {
return "Result{" +
"code='" + code + '\'' +
", msg='" + msg + '\'' +
", data=" + data +
", timestamp=" + timestamp +
", extra=" + extra +
'}';
}
}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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
全局异常拦截器
这里只给出关键的ExceptionHandler类,其他涉及到的代码自行去源码中查找
java
package local.ateng.java.exception.handler;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import local.ateng.java.exception.enums.AppCodeEnum;
import local.ateng.java.exception.exception.ServiceException;
import local.ateng.java.exception.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.resource.NoResourceFoundException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 全局异常处理器
*
* <p>该类通过 {@link RestControllerAdvice} 注解实现 Spring Boot 统一异常处理,
* 能够捕获控制层抛出的不同类型的异常,并统一转换为标准化的 {@link Result} 响应对象。</p>
*
* <p>主要功能包括:</p>
* <ul>
* <li>处理 POST 请求参数校验异常({@link MethodArgumentNotValidException})</li>
* <li>处理 GET 请求参数校验异常({@link ConstraintViolationException})</li>
* <li>处理自定义业务异常({@link ServiceException})</li>
* <li>处理未捕获的系统异常,返回统一的错误响应</li>
* </ul>
*
* <p>日志中会打印异常发生时的请求路径和详细堆栈,便于排查问题。</p>
*
* @author 孔余
* @since 2025-01-09
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 处理 POST 请求参数校验异常
*
* <p>当请求体参数校验失败(例如字段缺失、格式不正确等)时,
* Spring 会抛出 {@link MethodArgumentNotValidException},
* 本方法捕获该异常并提取所有字段的错误信息。</p>
*
* @param request 当前 HTTP 请求对象
* @param ex 参数校验异常
* @return 标准化错误响应,包含首个错误提示及所有字段错误详情
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidationExceptions(HttpServletRequest request, HttpServletResponse response, MethodArgumentNotValidException ex) {
// 获取所有参数校验失败的异常
Map<String, String> errors = new HashMap<>();
String firstFieldName = null;
String firstErrorMessage = null;
for (FieldError error : ex.getBindingResult().getFieldErrors()) {
if (firstFieldName == null && firstErrorMessage == null) {
firstFieldName = error.getField();
firstErrorMessage = error.getDefaultMessage();
}
errors.put(error.getField(), error.getDefaultMessage());
}
// 打印异常日志
log.error("请求 [{}] 参数校验失败: {}", request.getRequestURI(), ex.getMessage(), ex);
// 设置状态码
response.setStatus(AppCodeEnum.PARAM_DATA_VALIDATION_FAILED.getHttpStatus());
// 构建返回结果
return Result.failure(AppCodeEnum.PARAM_DATA_VALIDATION_FAILED.getCode(), firstErrorMessage)
.withData(errors);
}
/**
* 处理 GET 请求参数校验异常
*
* <p>当 URL 查询参数校验失败时(例如 @RequestParam 或 @PathVariable 校验失败),
* Spring 会抛出 {@link ConstraintViolationException},
* 本方法捕获该异常并提取所有字段的错误信息。</p>
*
* @param request 当前 HTTP 请求对象
* @param ex 参数校验异常
* @return 标准化错误响应,包含首个错误提示及所有字段错误详情
*/
@ExceptionHandler(ConstraintViolationException.class)
public Result handleConstraintViolationException(HttpServletRequest request, HttpServletResponse response, ConstraintViolationException ex) {
// 获取所有参数校验失败的异常
Map<String, String> errors = new HashMap<>();
String firstFieldName = null;
String firstErrorMessage = null;
for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
String propertyPath = violation.getPropertyPath().toString();
// 只保留参数名称
String fieldName = propertyPath.split("\\.")[1];
String errorMessage = violation.getMessage();
if (firstFieldName == null && firstErrorMessage == null) {
firstFieldName = fieldName;
firstErrorMessage = errorMessage;
}
errors.put(fieldName, errorMessage);
}
// 打印异常日志
log.error("请求 [{}] 参数校验失败: {}", request.getRequestURI(), ex.getMessage(), ex);
// 设置状态码
response.setStatus(AppCodeEnum.PARAM_DATA_VALIDATION_FAILED.getHttpStatus());
// 构建返回结果
return Result.failure(AppCodeEnum.PARAM_DATA_VALIDATION_FAILED.getCode(), firstErrorMessage)
.withData(errors);
}
/**
* 处理业务异常
*
* <p>当业务逻辑中主动抛出 {@link ServiceException} 时,
* 本方法捕获异常并返回自定义的错误码和错误信息。</p>
*
* @param request 当前 HTTP 请求对象
* @param ex 自定义业务异常
* @return 标准化错误响应,包含业务定义的错误码、错误信息及详细描述
*/
@ExceptionHandler(ServiceException.class)
public final Result handleServiceException(HttpServletRequest request, HttpServletResponse response, ServiceException ex) {
String message = ex.getMessage();
String code = ex.getCode();
HashMap<String, String> data = new HashMap<>();
data.put("detailMessage", ex.getDetailMessage());
// 打印异常日志
log.error("请求 [{}] 业务异常: {}", request.getRequestURI(), ex.getMessage(), ex);
// 设置状态码
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
// 构建返回结果
return Result.failure(code, message).withData(data);
}
/**
* 兜底系统异常处理
*
* <p>
* 捕获所有未显式声明的异常类型,根据异常类别返回对应的枚举错误码和提示信息。
* 确保系统不会因未捕获异常而暴露堆栈或返回非标准响应。
* </p>
*
* @param request 当前 HTTP 请求对象
* @param response 当前 HTTP 响应对象
* @param ex 未捕获的异常
* @return {@link Result} 标准化失败结果,包含错误码与提示信息
*/
@ExceptionHandler(Exception.class)
public Result handleAllExceptions(HttpServletRequest request,
HttpServletResponse response,
Exception ex) {
AppCodeEnum errorCode;
// 分批处理异常类型
if (ex instanceof HttpRequestMethodNotSupportedException) {
errorCode = AppCodeEnum.REQUEST_METHOD_NOT_SUPPORTED;
} else if (ex instanceof NoHandlerFoundException || ex instanceof NoResourceFoundException) {
errorCode = AppCodeEnum.RESOURCE_NOT_FOUND;
} else if (ex instanceof MissingServletRequestParameterException) {
errorCode = AppCodeEnum.PARAM_MISSING_REQUIRED;
} else if (ex instanceof IllegalArgumentException
|| ex instanceof MethodArgumentTypeMismatchException
|| ex instanceof NumberFormatException) {
errorCode = AppCodeEnum.PARAM_REQUEST_PARAMETER_TYPE_ERROR;
} else if (ex instanceof FileNotFoundException || ex instanceof IOException) {
errorCode = AppCodeEnum.FILE_NOT_FOUND;
} else if (ex instanceof NullPointerException) {
errorCode = AppCodeEnum.NULL_POINTER_ERROR;
} else if (ex instanceof UnsupportedOperationException) {
errorCode = AppCodeEnum.INVALID_OPERATION_TYPE;
} else {
errorCode = AppCodeEnum.ERROR;
}
// 打印异常日志
log.error("请求 [{}] 系统异常: {}", request.getRequestURI(), ex.getMessage(), ex);
// 设置状态码
response.setStatus(errorCode.getHttpStatus());
// 构建返回结果
return Result.failure(errorCode.getCode(), errorCode.getMessage());
}
}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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
接口测试
创建接口
创建一个测试接口,查看全局异常处理的结果
java
package local.ateng.java.exception.controller;
import local.ateng.java.exception.constant.AppCodeEnum;
import local.ateng.java.exception.utils.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
/**
* 测试接口
*
* @author 孔余
* @email 2385569970@qq.com
* @since 2025-01-09
*/
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/exception")
public Result exception(@RequestParam(name = "id", required = false, defaultValue = "0") Long id) {
long result = 1 / id;
HashMap<String, Long> map = new HashMap<>() {{
put("result", result);
put("null", null);
}};
return Result.success(AppCodeEnum.SUCCESS.getCode(), AppCodeEnum.SUCCESS.getDescription()).withData(map);
}
}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
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
正确使用
C:\Users\admin>curl http://localhost:12006/test/exception?id=1
{"code":"0","msg":"请求成功","data":{"result":1,"null":null}}1
2
2
异常使用
由此可以看到全局异常生效
C:\Users\admin>curl http://localhost:12006/test/exception?id=0
{"code":"-1","msg":"数据计算异常","data":null}
C:\Users\admin>curl http://localhost:12006/test/exception
{"code":"-1","msg":"数据计算异常","data":null}
C:\Users\admin>curl http://localhost:12006/test/exception?id=null
{"code":"-1","msg":"数据类型不匹配异常","data":null}1
2
3
4
5
6
2
3
4
5
6
关于统一返回的使用
使用 Result<T>
java
package local.ateng.java.controller;
import local.ateng.java.serialize.utils.Result;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
/**
* 示例 Controller,展示如何在 Spring Boot 中使用 Result<T> 封装统一的 API 响应。
*/
@RestController
@RequestMapping("/api")
public class ExampleController {
/**
* 获取成功响应的示例,无业务数据。
*
* @return 返回标准成功响应
*/
@GetMapping("/success/no-data")
public Result<String> successNoData() {
return Result.success();
}
/**
* 获取成功响应的示例,包含业务数据。
*
* @return 返回成功响应,包含业务数据
*/
@GetMapping("/success/with-data")
public Result<Map<String, String>> successWithData() {
Map<String, String> data = new HashMap<>();
data.put("message", "Hello, World!");
data.put("status", "success");
return Result.success(data);
}
/**
* 获取成功响应的示例,包含自定义消息和数据。
*
* @return 返回成功响应,包含自定义消息和数据
*/
@GetMapping("/success/custom-msg")
public Result<String> successCustomMsg() {
return Result.success("Custom success message", "This is some business data");
}
/**
* 获取失败响应的示例,包含自定义错误消息。
*
* @return 返回失败响应,包含自定义错误消息
*/
@GetMapping("/failure/custom-msg")
public Result<String> failureCustomMsg() {
return Result.failure("Custom failure message");
}
/**
* 获取失败响应的示例,包含自定义错误码和消息。
*
* @return 返回失败响应,包含自定义错误码和消息
*/
@GetMapping("/failure/custom-code-msg")
public Result<String> failureCustomCodeMsg() {
return Result.failure("1001", "Custom error code and message");
}
/**
* 获取包含额外信息的成功响应示例。
*
* @return 返回成功响应,包含额外信息
*/
@GetMapping("/success/with-extra")
public Result<Map<String, String>> successWithExtra() {
Map<String, String> data = new HashMap<>();
data.put("message", "Operation was successful");
return Result.success(data)
.extra("timestamp", System.currentTimeMillis()) // 添加额外信息
.extra("source", "example-controller");
}
/**
* 获取失败响应的示例,包含自定义状态码、消息和数据。
*
* @return 返回失败响应,包含自定义状态码、消息和数据
*/
@GetMapping("/failure/with-data")
public Result<String> failureWithData() {
return Result.failure("500", "Server error", "Failed to process the request");
}
}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
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
解释:
successNoData():示范返回一个成功的响应,且没有业务数据。successWithData():示范返回一个成功的响应,包含一些业务数据(如Map<String, String>)。successCustomMsg():示范返回一个成功的响应,包含自定义消息和数据。failureCustomMsg():示范返回一个失败的响应,包含自定义失败消息(没有业务数据)。failureCustomCodeMsg():示范返回一个失败的响应,包含自定义状态码和失败消息。successWithExtra():示范返回一个成功的响应,并且在返回中包含额外信息(通过extra()方法添加的)。failureWithData():示范返回一个失败的响应,包含自定义状态码、消息以及业务数据。
API 响应示例
成功响应:
/api/success/no-datajson{ "code": "0", "msg": "请求成功", "data": null, "timestamp": "2025-03-05T10:20:30", "extra": {} }1
2
3
4
5
6
7/api/success/with-datajson{ "code": "0", "msg": "请求成功", "data": { "message": "Hello, World!", "status": "success" }, "timestamp": "2025-03-05T10:20:30", "extra": {} }1
2
3
4
5
6
7
8
9
10
失败响应:
/api/failure/custom-msgjson{ "code": "-1", "msg": "Custom failure message", "data": null, "timestamp": "2025-03-05T10:20:30", "extra": {} }1
2
3
4
5
6
7/api/failure/custom-code-msgjson{ "code": "1001", "msg": "Custom error code and message", "data": null, "timestamp": "2025-03-05T10:20:30", "extra": {} }1
2
3
4
5
6
7
带额外信息的成功响应:
/api/success/with-extra1json{ "code": "0", "msg": "请求成功", "data": { "message": "Operation was successful" }, "timestamp": "2025-03-05T10:20:30", "extra": { "timestamp": 1678013430000, "source": "example-controller" } }1
2
3
4
5
6
7
8
9
10
11
12