第237集SpringBoot接口命名规范架构实战:DTO/VO标准化、接口分层、命名约定的企业级解决方案

前言

在大型企业级项目中,随着业务复杂度不断增加,接口数量呈指数级增长,各种DTO、VO、BO等数据传输对象不计其数。缺乏统一的命名规范导致代码可读性差、维护困难、团队协作效率低下。基于SpringBoot的接口命名规范架构,不仅能够建立标准化的命名体系,还能实现接口分层、自动生成和规范检查。随着微服务架构和团队协作的普及,构建可维护、可扩展的命名规范框架,已成为企业级架构师必须掌握的核心技能。

本文将深入探讨SpringBoot中接口和DTO/VO的命名规范架构设计与实战应用,从标准化命名到接口分层,从命名约定到代码生成,为企业构建规范、高效的接口命名解决方案提供全面的技术指导。

一、SpringBoot接口命名规范架构概述与核心原理

1.1 接口命名规范架构设计

SpringBoot接口命名规范系统采用分层架构设计,通过命名约定、代码生成、规范检查等技术,实现高效的接口和DTO/VO管理能力。

1.2 核心组件架构

二、企业级接口命名规范框架设计

2.1 命名规范核心引擎

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
/**
* 企业级命名规范引擎
* 提供统一的命名规范管理和代码生成能力
*/
@Component
@Slf4j
public class NamingConventionEngine {

private final InterfaceNamingService interfaceNamingService;
private final DTOVONamingService dtoVONamingService;
private final CodeGenerationService codeGenerationService;
private final NamingValidationService namingValidationService;

/**
* 生成标准化的接口命名
*/
public InterfaceNamingResult generateInterfaceNaming(InterfaceNamingRequest request) {
try {
// 验证命名规范
NamingValidationResult validation = namingValidationService.validateNaming(request);
if (!validation.isValid()) {
throw new NamingConventionException("命名规范验证失败: " + validation.getErrorMessage());
}

// 生成接口命名
InterfaceNamingResult result = interfaceNamingService.generateNaming(request);

// 生成代码
if (request.isGenerateCode()) {
CodeGenerationResult codeResult = codeGenerationService.generateInterfaceCode(result);
result.setGeneratedCode(codeResult.getCode());
}

log.info("接口命名生成成功: {}", result.getInterfaceName());
return result;

} catch (Exception e) {
log.error("接口命名生成失败", e);
throw new NamingConventionException("接口命名生成失败: " + e.getMessage());
}
}

/**
* 生成DTO/VO命名
*/
public DTOVONamingResult generateDTOVONaming(DTOVONamingRequest request) {
try {
// 根据业务类型确定命名规范
NamingConvention convention = determineConvention(request.getBusinessType());

// 生成DTO/VO命名
DTOVONamingResult result = dtoVONamingService.generateNaming(request, convention);

// 生成代码模板
if (request.isGenerateTemplate()) {
CodeTemplate template = codeGenerationService.generateDTOVOTemplate(result);
result.setCodeTemplate(template);
}

log.info("DTO/VO命名生成成功: {}", result.getClassName());
return result;

} catch (Exception e) {
log.error("DTO/VO命名生成失败", e);
throw new NamingConventionException("DTO/VO命名生成失败: " + e.getMessage());
}
}

/**
* 批量生成命名规范
*/
public BatchNamingResult batchGenerateNaming(BatchNamingRequest request) {
List<NamingResult> results = new ArrayList<>();
List<String> errors = new ArrayList<>();

for (NamingRequest namingRequest : request.getNamingRequests()) {
try {
NamingResult result = generateNaming(namingRequest);
results.add(result);
} catch (Exception e) {
errors.add(namingRequest.getBusinessName() + ": " + e.getMessage());
}
}

return BatchNamingResult.builder()
.results(results)
.errors(errors)
.successCount(results.size())
.failureCount(errors.size())
.build();
}

private NamingConvention determineConvention(BusinessType businessType) {
return NamingConventionFactory.getConvention(businessType);
}
}

2.2 接口命名服务

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
/**
* 接口命名服务
* 负责各种接口的标准化命名
*/
@Service
@Slf4j
public class InterfaceNamingService {

private final NamingRuleEngine namingRuleEngine;
private final InterfaceTemplateEngine templateEngine;

/**
* 生成Controller接口命名
*/
public InterfaceNamingResult generateControllerNaming(ControllerNamingRequest request) {
try {
// 构建命名规则
NamingRule rule = NamingRule.builder()
.prefix("")
.suffix("Controller")
.businessName(request.getBusinessName())
.moduleName(request.getModuleName())
.version(request.getVersion())
.build();

// 生成接口名称
String interfaceName = namingRuleEngine.generateName(rule);

// 生成方法命名
List<MethodNaming> methodNamings = generateMethodNamings(request.getOperations());

// 生成URL路径
String basePath = generateBasePath(request.getModuleName(), request.getBusinessName());

InterfaceNamingResult result = InterfaceNamingResult.builder()
.interfaceName(interfaceName)
.className(interfaceName)
.packageName(generatePackageName(request.getModuleName()))
.basePath(basePath)
.methodNamings(methodNamings)
.build();

log.info("Controller命名生成成功: {}", interfaceName);
return result;

} catch (Exception e) {
log.error("Controller命名生成失败", e);
throw new InterfaceNamingException("Controller命名生成失败: " + e.getMessage());
}
}

/**
* 生成Service接口命名
*/
public InterfaceNamingResult generateServiceNaming(ServiceNamingRequest request) {
try {
// 构建命名规则
NamingRule rule = NamingRule.builder()
.prefix("")
.suffix("Service")
.businessName(request.getBusinessName())
.moduleName(request.getModuleName())
.version(request.getVersion())
.build();

// 生成接口名称
String interfaceName = namingRuleEngine.generateName(rule);

// 生成实现类名称
String implClassName = interfaceName + "Impl";

// 生成方法命名
List<MethodNaming> methodNamings = generateServiceMethodNamings(request.getOperations());

InterfaceNamingResult result = InterfaceNamingResult.builder()
.interfaceName(interfaceName)
.className(implClassName)
.packageName(generateServicePackageName(request.getModuleName()))
.methodNamings(methodNamings)
.build();

log.info("Service命名生成成功: {}", interfaceName);
return result;

} catch (Exception e) {
log.error("Service命名生成失败", e);
throw new InterfaceNamingException("Service命名生成失败: " + e.getMessage());
}
}

/**
* 生成Repository接口命名
*/
public InterfaceNamingResult generateRepositoryNaming(RepositoryNamingRequest request) {
try {
// 构建命名规则
NamingRule rule = NamingRule.builder()
.prefix("")
.suffix("Repository")
.businessName(request.getEntityName())
.moduleName(request.getModuleName())
.version(request.getVersion())
.build();

// 生成接口名称
String interfaceName = namingRuleEngine.generateName(rule);

// 生成方法命名
List<MethodNaming> methodNamings = generateRepositoryMethodNamings(request.getOperations());

InterfaceNamingResult result = InterfaceNamingResult.builder()
.interfaceName(interfaceName)
.className(interfaceName)
.packageName(generateRepositoryPackageName(request.getModuleName()))
.methodNamings(methodNamings)
.build();

log.info("Repository命名生成成功: {}", interfaceName);
return result;

} catch (Exception e) {
log.error("Repository命名生成失败", e);
throw new InterfaceNamingException("Repository命名生成失败: " + e.getMessage());
}
}

private List<MethodNaming> generateMethodNamings(List<Operation> operations) {
return operations.stream()
.map(this::generateMethodNaming)
.collect(Collectors.toList());
}

private MethodNaming generateMethodNaming(Operation operation) {
String methodName = generateMethodName(operation);
String urlPath = generateUrlPath(operation);
HttpMethod httpMethod = operation.getHttpMethod();

return MethodNaming.builder()
.methodName(methodName)
.urlPath(urlPath)
.httpMethod(httpMethod)
.operation(operation)
.build();
}

private String generateMethodName(Operation operation) {
OperationType type = operation.getType();
String businessName = operation.getBusinessName();

switch (type) {
case CREATE:
return "create" + capitalize(businessName);
case READ:
return "get" + capitalize(businessName);
case UPDATE:
return "update" + capitalize(businessName);
case DELETE:
return "delete" + capitalize(businessName);
case LIST:
return "list" + capitalize(businessName) + "s";
case SEARCH:
return "search" + capitalize(businessName) + "s";
default:
return operation.getName();
}
}

private String generateUrlPath(Operation operation) {
OperationType type = operation.getType();
String businessName = operation.getBusinessName().toLowerCase();

switch (type) {
case CREATE:
return "/" + businessName;
case READ:
return "/" + businessName + "/{id}";
case UPDATE:
return "/" + businessName + "/{id}";
case DELETE:
return "/" + businessName + "/{id}";
case LIST:
return "/" + businessName + "s";
case SEARCH:
return "/" + businessName + "s/search";
default:
return "/" + businessName;
}
}

private String generateBasePath(String moduleName, String businessName) {
return "/api/" + moduleName.toLowerCase() + "/" + businessName.toLowerCase();
}

private String generatePackageName(String moduleName) {
return "com.company." + moduleName.toLowerCase() + ".controller";
}

private String generateServicePackageName(String moduleName) {
return "com.company." + moduleName.toLowerCase() + ".service";
}

private String generateRepositoryPackageName(String moduleName) {
return "com.company." + moduleName.toLowerCase() + ".repository";
}

private String capitalize(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}

2.3 DTO/VO命名服务

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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/**
* DTO/VO命名服务
* 负责各种数据传输对象的标准化命名
*/
@Service
@Slf4j
public class DTOVONamingService {

private final NamingRuleEngine namingRuleEngine;
private final DTOVOTemplateEngine templateEngine;

/**
* 生成请求DTO命名
*/
public DTOVONamingResult generateRequestDTONaming(RequestDTONamingRequest request) {
try {
// 构建命名规则
NamingRule rule = NamingRule.builder()
.prefix("")
.suffix("RequestDTO")
.businessName(request.getBusinessName())
.moduleName(request.getModuleName())
.operation(request.getOperation())
.build();

// 生成类名
String className = namingRuleEngine.generateName(rule);

// 生成字段命名
List<FieldNaming> fieldNamings = generateFieldNamings(request.getFields());

// 生成验证规则
List<ValidationRule> validationRules = generateValidationRules(request.getFields());

DTOVONamingResult result = DTOVONamingResult.builder()
.className(className)
.packageName(generateDTOPackageName(request.getModuleName()))
.fieldNamings(fieldNamings)
.validationRules(validationRules)
.type(DTOVOType.REQUEST_DTO)
.build();

log.info("请求DTO命名生成成功: {}", className);
return result;

} catch (Exception e) {
log.error("请求DTO命名生成失败", e);
throw new DTOVONamingException("请求DTO命名生成失败: " + e.getMessage());
}
}

/**
* 生成响应VO命名
*/
public DTOVONamingResult generateResponseVONaming(ResponseVONamingRequest request) {
try {
// 构建命名规则
NamingRule rule = NamingRule.builder()
.prefix("")
.suffix("ResponseVO")
.businessName(request.getBusinessName())
.moduleName(request.getModuleName())
.operation(request.getOperation())
.build();

// 生成类名
String className = namingRuleEngine.generateName(rule);

// 生成字段命名
List<FieldNaming> fieldNamings = generateFieldNamings(request.getFields());

// 生成序列化规则
List<SerializationRule> serializationRules = generateSerializationRules(request.getFields());

DTOVONamingResult result = DTOVONamingResult.builder()
.className(className)
.packageName(generateVOPackageName(request.getModuleName()))
.fieldNamings(fieldNamings)
.serializationRules(serializationRules)
.type(DTOVOType.RESPONSE_VO)
.build();

log.info("响应VO命名生成成功: {}", className);
return result;

} catch (Exception e) {
log.error("响应VO命名生成失败", e);
throw new DTOVONamingException("响应VO命名生成失败: " + e.getMessage());
}
}

/**
* 生成业务BO命名
*/
public DTOVONamingResult generateBusinessBONaming(BusinessBONamingRequest request) {
try {
// 构建命名规则
NamingRule rule = NamingRule.builder()
.prefix("")
.suffix("BO")
.businessName(request.getBusinessName())
.moduleName(request.getModuleName())
.build();

// 生成类名
String className = namingRuleEngine.generateName(rule);

// 生成字段命名
List<FieldNaming> fieldNamings = generateFieldNamings(request.getFields());

// 生成业务规则
List<BusinessRule> businessRules = generateBusinessRules(request.getFields());

DTOVONamingResult result = DTOVONamingResult.builder()
.className(className)
.packageName(generateBOPackageName(request.getModuleName()))
.fieldNamings(fieldNamings)
.businessRules(businessRules)
.type(DTOVOType.BUSINESS_BO)
.build();

log.info("业务BO命名生成成功: {}", className);
return result;

} catch (Exception e) {
log.error("业务BO命名生成失败", e);
throw new DTOVONamingException("业务BO命名生成失败: " + e.getMessage());
}
}

/**
* 生成查询QO命名
*/
public DTOVONamingResult generateQueryQONaming(QueryQONamingRequest request) {
try {
// 构建命名规则
NamingRule rule = NamingRule.builder()
.prefix("")
.suffix("QueryQO")
.businessName(request.getBusinessName())
.moduleName(request.getModuleName())
.build();

// 生成类名
String className = namingRuleEngine.generateName(rule);

// 生成查询字段
List<FieldNaming> fieldNamings = generateQueryFieldNamings(request.getQueryFields());

// 生成分页字段
List<FieldNaming> pageFieldNamings = generatePageFieldNamings();

// 合并字段
List<FieldNaming> allFieldNamings = new ArrayList<>();
allFieldNamings.addAll(fieldNamings);
allFieldNamings.addAll(pageFieldNamings);

DTOVONamingResult result = DTOVONamingResult.builder()
.className(className)
.packageName(generateQOPackageName(request.getModuleName()))
.fieldNamings(allFieldNamings)
.type(DTOVOType.QUERY_QO)
.build();

log.info("查询QO命名生成成功: {}", className);
return result;

} catch (Exception e) {
log.error("查询QO命名生成失败", e);
throw new DTOVONamingException("查询QO命名生成失败: " + e.getMessage());
}
}

private List<FieldNaming> generateFieldNamings(List<FieldDefinition> fields) {
return fields.stream()
.map(this::generateFieldNaming)
.collect(Collectors.toList());
}

private FieldNaming generateFieldNaming(FieldDefinition field) {
String fieldName = generateFieldName(field);
String fieldType = field.getType();
String comment = field.getComment();

return FieldNaming.builder()
.fieldName(fieldName)
.fieldType(fieldType)
.comment(comment)
.isRequired(field.isRequired())
.defaultValue(field.getDefaultValue())
.build();
}

private String generateFieldName(FieldDefinition field) {
String name = field.getName();

// 转换为驼峰命名
return convertToCamelCase(name);
}

private String convertToCamelCase(String str) {
if (str == null || str.isEmpty()) {
return str;
}

// 处理下划线命名
if (str.contains("_")) {
String[] parts = str.split("_");
StringBuilder result = new StringBuilder(parts[0].toLowerCase());
for (int i = 1; i < parts.length; i++) {
result.append(capitalize(parts[i].toLowerCase()));
}
return result.toString();
}

// 处理连字符命名
if (str.contains("-")) {
String[] parts = str.split("-");
StringBuilder result = new StringBuilder(parts[0].toLowerCase());
for (int i = 1; i < parts.length; i++) {
result.append(capitalize(parts[i].toLowerCase()));
}
return result.toString();
}

return str.substring(0, 1).toLowerCase() + str.substring(1);
}

private List<FieldNaming> generateQueryFieldNamings(List<QueryField> queryFields) {
return queryFields.stream()
.map(this::generateQueryFieldNaming)
.collect(Collectors.toList());
}

private FieldNaming generateQueryFieldNaming(QueryField queryField) {
String fieldName = generateFieldName(queryField.getName());
String fieldType = determineQueryFieldType(queryField);

return FieldNaming.builder()
.fieldName(fieldName)
.fieldType(fieldType)
.comment(queryField.getComment())
.isRequired(false)
.build();
}

private List<FieldNaming> generatePageFieldNamings() {
List<FieldNaming> pageFields = new ArrayList<>();

// 页码字段
pageFields.add(FieldNaming.builder()
.fieldName("pageNum")
.fieldType("Integer")
.comment("页码")
.isRequired(false)
.defaultValue("1")
.build());

// 页大小字段
pageFields.add(FieldNaming.builder()
.fieldName("pageSize")
.fieldType("Integer")
.comment("页大小")
.isRequired(false)
.defaultValue("10")
.build());

// 排序字段
pageFields.add(FieldNaming.builder()
.fieldName("orderBy")
.fieldType("String")
.comment("排序字段")
.isRequired(false)
.build());

// 排序方向
pageFields.add(FieldNaming.builder()
.fieldName("orderDirection")
.fieldType("String")
.comment("排序方向")
.isRequired(false)
.defaultValue("ASC")
.build());

return pageFields;
}

private String determineQueryFieldType(QueryField queryField) {
QueryFieldType type = queryField.getType();

switch (type) {
case STRING:
return "String";
case INTEGER:
return "Integer";
case LONG:
return "Long";
case DATE:
return "Date";
case DATE_TIME:
return "LocalDateTime";
case BOOLEAN:
return "Boolean";
case DECIMAL:
return "BigDecimal";
default:
return "String";
}
}

private String generateDTOPackageName(String moduleName) {
return "com.company." + moduleName.toLowerCase() + ".dto";
}

private String generateVOPackageName(String moduleName) {
return "com.company." + moduleName.toLowerCase() + ".vo";
}

private String generateBOPackageName(String moduleName) {
return "com.company." + moduleName.toLowerCase() + ".bo";
}

private String generateQOPackageName(String moduleName) {
return "com.company." + moduleName.toLowerCase() + ".qo";
}

private String capitalize(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}

三、命名规范验证与检查框架

3.1 命名规范验证服务

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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
/**
* 命名规范验证服务
* 负责验证各种命名是否符合规范
*/
@Service
@Slf4j
public class NamingValidationService {

private final NamingRuleRepository namingRuleRepository;
private final ValidationRuleEngine validationRuleEngine;

/**
* 验证接口命名
*/
public NamingValidationResult validateInterfaceNaming(InterfaceNamingRequest request) {
try {
List<ValidationError> errors = new ArrayList<>();

// 验证类名规范
ValidationResult classNameResult = validateClassName(request.getBusinessName());
if (!classNameResult.isValid()) {
errors.addAll(classNameResult.getErrors());
}

// 验证包名规范
ValidationResult packageNameResult = validatePackageName(request.getModuleName());
if (!packageNameResult.isValid()) {
errors.addAll(packageNameResult.getErrors());
}

// 验证方法名规范
for (Operation operation : request.getOperations()) {
ValidationResult methodNameResult = validateMethodName(operation);
if (!methodNameResult.isValid()) {
errors.addAll(methodNameResult.getErrors());
}
}

// 验证URL路径规范
ValidationResult urlPathResult = validateUrlPath(request.getModuleName(), request.getBusinessName());
if (!urlPathResult.isValid()) {
errors.addAll(urlPathResult.getErrors());
}

boolean isValid = errors.isEmpty();
String errorMessage = isValid ? null : errors.stream()
.map(ValidationError::getMessage)
.collect(Collectors.joining("; "));

return NamingValidationResult.builder()
.isValid(isValid)
.errors(errors)
.errorMessage(errorMessage)
.build();

} catch (Exception e) {
log.error("接口命名验证失败", e);
throw new NamingValidationException("接口命名验证失败: " + e.getMessage());
}
}

/**
* 验证DTO/VO命名
*/
public NamingValidationResult validateDTOVONaming(DTOVONamingRequest request) {
try {
List<ValidationError> errors = new ArrayList<>();

// 验证类名规范
ValidationResult classNameResult = validateClassName(request.getBusinessName());
if (!classNameResult.isValid()) {
errors.addAll(classNameResult.getErrors());
}

// 验证字段名规范
for (FieldDefinition field : request.getFields()) {
ValidationResult fieldNameResult = validateFieldName(field.getName());
if (!fieldNameResult.isValid()) {
errors.addAll(fieldNameResult.getErrors());
}
}

// 验证命名冲突
ValidationResult conflictResult = validateNamingConflict(request);
if (!conflictResult.isValid()) {
errors.addAll(conflictResult.getErrors());
}

boolean isValid = errors.isEmpty();
String errorMessage = isValid ? null : errors.stream()
.map(ValidationError::getMessage)
.collect(Collectors.joining("; "));

return NamingValidationResult.builder()
.isValid(isValid)
.errors(errors)
.errorMessage(errorMessage)
.build();

} catch (Exception e) {
log.error("DTO/VO命名验证失败", e);
throw new NamingValidationException("DTO/VO命名验证失败: " + e.getMessage());
}
}

/**
* 验证类名规范
*/
private ValidationResult validateClassName(String className) {
List<ValidationError> errors = new ArrayList<>();

// 检查是否为空
if (className == null || className.trim().isEmpty()) {
errors.add(ValidationError.builder()
.field("className")
.message("类名不能为空")
.build());
return ValidationResult.builder().isValid(false).errors(errors).build();
}

// 检查长度
if (className.length() > 50) {
errors.add(ValidationError.builder()
.field("className")
.message("类名长度不能超过50个字符")
.build());
}

// 检查格式
if (!className.matches("^[A-Z][a-zA-Z0-9]*$")) {
errors.add(ValidationError.builder()
.field("className")
.message("类名必须以大写字母开头,只能包含字母和数字")
.build());
}

// 检查关键字冲突
if (isJavaKeyword(className)) {
errors.add(ValidationError.builder()
.field("className")
.message("类名不能使用Java关键字: " + className)
.build());
}

// 检查保留字冲突
if (isReservedWord(className)) {
errors.add(ValidationError.builder()
.field("className")
.message("类名不能使用保留字: " + className)
.build());
}

return ValidationResult.builder()
.isValid(errors.isEmpty())
.errors(errors)
.build();
}

/**
* 验证方法名规范
*/
private ValidationResult validateMethodName(Operation operation) {
List<ValidationError> errors = new ArrayList<>();
String methodName = operation.getName();

// 检查是否为空
if (methodName == null || methodName.trim().isEmpty()) {
errors.add(ValidationError.builder()
.field("methodName")
.message("方法名不能为空")
.build());
return ValidationResult.builder().isValid(false).errors(errors).build();
}

// 检查长度
if (methodName.length() > 30) {
errors.add(ValidationError.builder()
.field("methodName")
.message("方法名长度不能超过30个字符")
.build());
}

// 检查格式
if (!methodName.matches("^[a-z][a-zA-Z0-9]*$")) {
errors.add(ValidationError.builder()
.field("methodName")
.message("方法名必须以小写字母开头,只能包含字母和数字")
.build());
}

// 检查关键字冲突
if (isJavaKeyword(methodName)) {
errors.add(ValidationError.builder()
.field("methodName")
.message("方法名不能使用Java关键字: " + methodName)
.build());
}

// 检查命名约定
ValidationResult conventionResult = validateMethodNamingConvention(operation);
if (!conventionResult.isValid()) {
errors.addAll(conventionResult.getErrors());
}

return ValidationResult.builder()
.isValid(errors.isEmpty())
.errors(errors)
.build();
}

/**
* 验证字段名规范
*/
private ValidationResult validateFieldName(String fieldName) {
List<ValidationError> errors = new ArrayList<>();

// 检查是否为空
if (fieldName == null || fieldName.trim().isEmpty()) {
errors.add(ValidationError.builder()
.field("fieldName")
.message("字段名不能为空")
.build());
return ValidationResult.builder().isValid(false).errors(errors).build();
}

// 检查长度
if (fieldName.length() > 30) {
errors.add(ValidationError.builder()
.field("fieldName")
.message("字段名长度不能超过30个字符")
.build());
}

// 检查格式
if (!fieldName.matches("^[a-z][a-zA-Z0-9]*$")) {
errors.add(ValidationError.builder()
.field("fieldName")
.message("字段名必须以小写字母开头,只能包含字母和数字")
.build());
}

// 检查关键字冲突
if (isJavaKeyword(fieldName)) {
errors.add(ValidationError.builder()
.field("fieldName")
.message("字段名不能使用Java关键字: " + fieldName)
.build());
}

return ValidationResult.builder()
.isValid(errors.isEmpty())
.errors(errors)
.build();
}

/**
* 验证包名规范
*/
private ValidationResult validatePackageName(String packageName) {
List<ValidationError> errors = new ArrayList<>();

// 检查是否为空
if (packageName == null || packageName.trim().isEmpty()) {
errors.add(ValidationError.builder()
.field("packageName")
.message("包名不能为空")
.build());
return ValidationResult.builder().isValid(false).errors(errors).build();
}

// 检查格式
if (!packageName.matches("^[a-z][a-z0-9]*$")) {
errors.add(ValidationError.builder()
.field("packageName")
.message("包名只能包含小写字母和数字,且必须以字母开头")
.build());
}

// 检查长度
if (packageName.length() > 20) {
errors.add(ValidationError.builder()
.field("packageName")
.message("包名长度不能超过20个字符")
.build());
}

return ValidationResult.builder()
.isValid(errors.isEmpty())
.errors(errors)
.build();
}

/**
* 验证URL路径规范
*/
private ValidationResult validateUrlPath(String moduleName, String businessName) {
List<ValidationError> errors = new ArrayList<>();

String urlPath = "/api/" + moduleName.toLowerCase() + "/" + businessName.toLowerCase();

// 检查长度
if (urlPath.length() > 100) {
errors.add(ValidationError.builder()
.field("urlPath")
.message("URL路径长度不能超过100个字符")
.build());
}

// 检查格式
if (!urlPath.matches("^/[a-z0-9/]*$")) {
errors.add(ValidationError.builder()
.field("urlPath")
.message("URL路径只能包含小写字母、数字和斜杠")
.build());
}

return ValidationResult.builder()
.isValid(errors.isEmpty())
.errors(errors)
.build();
}

/**
* 验证命名冲突
*/
private ValidationResult validateNamingConflict(DTOVONamingRequest request) {
List<ValidationError> errors = new ArrayList<>();

// 检查类名冲突
String className = request.getBusinessName() + request.getType().getSuffix();
if (namingRuleRepository.existsByClassName(className)) {
errors.add(ValidationError.builder()
.field("className")
.message("类名已存在: " + className)
.build());
}

// 检查字段名冲突
Set<String> fieldNames = new HashSet<>();
for (FieldDefinition field : request.getFields()) {
String fieldName = convertToCamelCase(field.getName());
if (fieldNames.contains(fieldName)) {
errors.add(ValidationError.builder()
.field("fieldName")
.message("字段名重复: " + fieldName)
.build());
}
fieldNames.add(fieldName);
}

return ValidationResult.builder()
.isValid(errors.isEmpty())
.errors(errors)
.build();
}

/**
* 验证方法命名约定
*/
private ValidationResult validateMethodNamingConvention(Operation operation) {
List<ValidationError> errors = new ArrayList<>();
String methodName = operation.getName();
OperationType type = operation.getType();

// 根据操作类型验证命名约定
switch (type) {
case CREATE:
if (!methodName.startsWith("create") && !methodName.startsWith("add")) {
errors.add(ValidationError.builder()
.field("methodName")
.message("创建操作的方法名应以create或add开头")
.build());
}
break;
case READ:
if (!methodName.startsWith("get") && !methodName.startsWith("find") && !methodName.startsWith("query")) {
errors.add(ValidationError.builder()
.field("methodName")
.message("查询操作的方法名应以get、find或query开头")
.build());
}
break;
case UPDATE:
if (!methodName.startsWith("update") && !methodName.startsWith("modify")) {
errors.add(ValidationError.builder()
.field("methodName")
.message("更新操作的方法名应以update或modify开头")
.build());
}
break;
case DELETE:
if (!methodName.startsWith("delete") && !methodName.startsWith("remove")) {
errors.add(ValidationError.builder()
.field("methodName")
.message("删除操作的方法名应以delete或remove开头")
.build());
}
break;
}

return ValidationResult.builder()
.isValid(errors.isEmpty())
.errors(errors)
.build();
}

private boolean isJavaKeyword(String name) {
Set<String> keywords = Set.of(
"abstract", "assert", "boolean", "break", "byte", "case", "catch", "char",
"class", "const", "continue", "default", "do", "double", "else", "enum",
"extends", "final", "finally", "float", "for", "goto", "if", "implements",
"import", "instanceof", "int", "interface", "long", "native", "new",
"package", "private", "protected", "public", "return", "short", "static",
"strictfp", "super", "switch", "synchronized", "this", "throw", "throws",
"transient", "try", "void", "volatile", "while"
);
return keywords.contains(name.toLowerCase());
}

private boolean isReservedWord(String name) {
Set<String> reservedWords = Set.of(
"true", "false", "null", "var", "record", "sealed", "permits", "non-sealed"
);
return reservedWords.contains(name.toLowerCase());
}

private String convertToCamelCase(String str) {
if (str == null || str.isEmpty()) {
return str;
}

if (str.contains("_")) {
String[] parts = str.split("_");
StringBuilder result = new StringBuilder(parts[0].toLowerCase());
for (int i = 1; i < parts.length; i++) {
result.append(capitalize(parts[i].toLowerCase()));
}
return result.toString();
}

return str.substring(0, 1).toLowerCase() + str.substring(1);
}

private String capitalize(String str) {
if (str == null || str.isEmpty()) {
return str;
}
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}

四、代码生成与模板引擎

4.1 代码生成服务

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
/**
* 代码生成服务
* 负责根据命名规范生成标准化的代码
*/
@Service
@Slf4j
public class CodeGenerationService {

private final TemplateEngine templateEngine;
private final CodeTemplateRepository templateRepository;

/**
* 生成接口代码
*/
public CodeGenerationResult generateInterfaceCode(InterfaceNamingResult namingResult) {
try {
// 获取模板
CodeTemplate template = templateRepository.findByType(TemplateType.INTERFACE);

// 准备模板数据
Map<String, Object> templateData = prepareInterfaceTemplateData(namingResult);

// 生成代码
String generatedCode = templateEngine.process(template.getContent(), templateData);

// 生成文件路径
String filePath = generateFilePath(namingResult);

CodeGenerationResult result = CodeGenerationResult.builder()
.code(generatedCode)
.filePath(filePath)
.templateType(TemplateType.INTERFACE)
.generatedAt(LocalDateTime.now())
.build();

log.info("接口代码生成成功: {}", filePath);
return result;

} catch (Exception e) {
log.error("接口代码生成失败", e);
throw new CodeGenerationException("接口代码生成失败: " + e.getMessage());
}
}

/**
* 生成DTO/VO代码模板
*/
public CodeTemplate generateDTOVOTemplate(DTOVONamingResult namingResult) {
try {
// 获取模板
CodeTemplate template = templateRepository.findByType(namingResult.getType().getTemplateType());

// 准备模板数据
Map<String, Object> templateData = prepareDTOVOTemplateData(namingResult);

// 生成代码
String generatedCode = templateEngine.process(template.getContent(), templateData);

// 生成文件路径
String filePath = generateDTOVOFilePath(namingResult);

CodeTemplate result = CodeTemplate.builder()
.content(generatedCode)
.filePath(filePath)
.templateType(namingResult.getType().getTemplateType())
.generatedAt(LocalDateTime.now())
.build();

log.info("DTO/VO代码模板生成成功: {}", filePath);
return result;

} catch (Exception e) {
log.error("DTO/VO代码模板生成失败", e);
throw new CodeGenerationException("DTO/VO代码模板生成失败: " + e.getMessage());
}
}

/**
* 批量生成代码
*/
public BatchCodeGenerationResult batchGenerateCode(BatchCodeGenerationRequest request) {
List<CodeGenerationResult> results = new ArrayList<>();
List<String> errors = new ArrayList<>();

for (CodeGenerationRequest codeRequest : request.getCodeRequests()) {
try {
CodeGenerationResult result = generateCode(codeRequest);
results.add(result);
} catch (Exception e) {
errors.add(codeRequest.getBusinessName() + ": " + e.getMessage());
}
}

return BatchCodeGenerationResult.builder()
.results(results)
.errors(errors)
.successCount(results.size())
.failureCount(errors.size())
.build();
}

private Map<String, Object> prepareInterfaceTemplateData(InterfaceNamingResult namingResult) {
Map<String, Object> data = new HashMap<>();

data.put("interfaceName", namingResult.getInterfaceName());
data.put("className", namingResult.getClassName());
data.put("packageName", namingResult.getPackageName());
data.put("basePath", namingResult.getBasePath());
data.put("methodNamings", namingResult.getMethodNamings());
data.put("imports", generateImports(namingResult));
data.put("annotations", generateAnnotations(namingResult));

return data;
}

private Map<String, Object> prepareDTOVOTemplateData(DTOVONamingResult namingResult) {
Map<String, Object> data = new HashMap<>();

data.put("className", namingResult.getClassName());
data.put("packageName", namingResult.getPackageName());
data.put("fieldNamings", namingResult.getFieldNamings());
data.put("validationRules", namingResult.getValidationRules());
data.put("serializationRules", namingResult.getSerializationRules());
data.put("businessRules", namingResult.getBusinessRules());
data.put("imports", generateDTOVOImports(namingResult));
data.put("annotations", generateDTOVOAnnotations(namingResult));

return data;
}

private List<String> generateImports(InterfaceNamingResult namingResult) {
List<String> imports = new ArrayList<>();

// 基础导入
imports.add("import org.springframework.web.bind.annotation.*;");
imports.add("import org.springframework.http.ResponseEntity;");
imports.add("import javax.validation.Valid;");

// 根据方法类型添加导入
for (MethodNaming methodNaming : namingResult.getMethodNamings()) {
HttpMethod httpMethod = methodNaming.getHttpMethod();
switch (httpMethod) {
case GET:
imports.add("import org.springframework.web.bind.annotation.GetMapping;");
break;
case POST:
imports.add("import org.springframework.web.bind.annotation.PostMapping;");
break;
case PUT:
imports.add("import org.springframework.web.bind.annotation.PutMapping;");
break;
case DELETE:
imports.add("import org.springframework.web.bind.annotation.DeleteMapping;");
break;
}
}

return imports.stream().distinct().collect(Collectors.toList());
}

private List<String> generateDTOVOImports(DTOVONamingResult namingResult) {
List<String> imports = new ArrayList<>();

// 基础导入
imports.add("import lombok.Data;");
imports.add("import lombok.Builder;");
imports.add("import lombok.NoArgsConstructor;");
imports.add("import lombok.AllArgsConstructor;");

// 验证注解导入
if (namingResult.getValidationRules() != null && !namingResult.getValidationRules().isEmpty()) {
imports.add("import javax.validation.constraints.*;");
}

// 序列化注解导入
if (namingResult.getSerializationRules() != null && !namingResult.getSerializationRules().isEmpty()) {
imports.add("import com.fasterxml.jackson.annotation.*;");
}

// 根据字段类型添加导入
Set<String> fieldTypes = namingResult.getFieldNamings().stream()
.map(FieldNaming::getFieldType)
.collect(Collectors.toSet());

if (fieldTypes.contains("Date")) {
imports.add("import java.util.Date;");
}
if (fieldTypes.contains("LocalDateTime")) {
imports.add("import java.time.LocalDateTime;");
}
if (fieldTypes.contains("BigDecimal")) {
imports.add("import java.math.BigDecimal;");
}

return imports.stream().distinct().collect(Collectors.toList());
}

private List<String> generateAnnotations(InterfaceNamingResult namingResult) {
List<String> annotations = new ArrayList<>();

annotations.add("@RestController");
annotations.add("@RequestMapping(\"" + namingResult.getBasePath() + "\")");
annotations.add("@Slf4j");

return annotations;
}

private List<String> generateDTOVOAnnotations(DTOVONamingResult namingResult) {
List<String> annotations = new ArrayList<>();

annotations.add("@Data");
annotations.add("@Builder");
annotations.add("@NoArgsConstructor");
annotations.add("@AllArgsConstructor");

return annotations;
}

private String generateFilePath(InterfaceNamingResult namingResult) {
String packagePath = namingResult.getPackageName().replace(".", "/");
return "src/main/java/" + packagePath + "/" + namingResult.getClassName() + ".java";
}

private String generateDTOVOFilePath(DTOVONamingResult namingResult) {
String packagePath = namingResult.getPackageName().replace(".", "/");
return "src/main/java/" + packagePath + "/" + namingResult.getClassName() + ".java";
}
}

五、命名规范配置与管理

5.1 命名规范配置

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
/**
* 命名规范配置
* 提供灵活的命名规范配置管理
*/
@Configuration
@EnableConfigurationProperties(NamingConventionProperties.class)
@Slf4j
public class NamingConventionConfiguration {

private final NamingConventionProperties properties;

/**
* 命名规范引擎
*/
@Bean
@ConditionalOnMissingBean
public NamingConventionEngine namingConventionEngine(
InterfaceNamingService interfaceNamingService,
DTOVONamingService dtoVONamingService,
CodeGenerationService codeGenerationService,
NamingValidationService namingValidationService) {

return new NamingConventionEngine(
interfaceNamingService,
dtoVONamingService,
codeGenerationService,
namingValidationService
);
}

/**
* 接口命名服务
*/
@Bean
@ConditionalOnMissingBean
public InterfaceNamingService interfaceNamingService(
NamingRuleEngine namingRuleEngine,
InterfaceTemplateEngine templateEngine) {

return new InterfaceNamingService(namingRuleEngine, templateEngine);
}

/**
* DTO/VO命名服务
*/
@Bean
@ConditionalOnMissingBean
public DTOVONamingService dtoVONamingService(
NamingRuleEngine namingRuleEngine,
DTOVOTemplateEngine templateEngine) {

return new DTOVONamingService(namingRuleEngine, templateEngine);
}

/**
* 代码生成服务
*/
@Bean
@ConditionalOnMissingBean
public CodeGenerationService codeGenerationService(
TemplateEngine templateEngine,
CodeTemplateRepository templateRepository) {

return new CodeGenerationService(templateEngine, templateRepository);
}

/**
* 命名验证服务
*/
@Bean
@ConditionalOnMissingBean
public NamingValidationService namingValidationService(
NamingRuleRepository namingRuleRepository,
ValidationRuleEngine validationRuleEngine) {

return new NamingValidationService(namingRuleRepository, validationRuleEngine);
}

/**
* 命名规则引擎
*/
@Bean
@ConditionalOnMissingBean
public NamingRuleEngine namingRuleEngine() {
return new NamingRuleEngine();
}

/**
* 验证规则引擎
*/
@Bean
@ConditionalOnMissingBean
public ValidationRuleEngine validationRuleEngine() {
return new ValidationRuleEngine();
}

/**
* 模板引擎
*/
@Bean
@ConditionalOnMissingBean
public TemplateEngine templateEngine() {
return new TemplateEngine();
}

/**
* 接口模板引擎
*/
@Bean
@ConditionalOnMissingBean
public InterfaceTemplateEngine interfaceTemplateEngine() {
return new InterfaceTemplateEngine();
}

/**
* DTO/VO模板引擎
*/
@Bean
@ConditionalOnMissingBean
public DTOVOTemplateEngine dtoVOTemplateEngine() {
return new DTOVOTemplateEngine();
}

/**
* 命名规则仓库
*/
@Bean
@ConditionalOnMissingBean
public NamingRuleRepository namingRuleRepository() {
return new NamingRuleRepository();
}

/**
* 代码模板仓库
*/
@Bean
@ConditionalOnMissingBean
public CodeTemplateRepository codeTemplateRepository() {
return new CodeTemplateRepository();
}

/**
* 命名规范管理端点
*/
@Bean
@ConditionalOnProperty(name = "naming-convention.management.endpoints.enabled", havingValue = "true", matchIfMissing = true)
public NamingConventionManagementEndpoint namingConventionManagementEndpoint(
NamingConventionEngine namingConventionEngine) {

return new NamingConventionManagementEndpoint(namingConventionEngine);
}
}

5.2 命名规范属性配置

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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/**
* 命名规范属性配置
*/
@ConfigurationProperties(prefix = "naming-convention")
@Data
@Slf4j
public class NamingConventionProperties {

/**
* 是否启用命名规范
*/
private boolean enabled = true;

/**
* 是否启用自动代码生成
*/
private boolean autoGenerateCode = true;

/**
* 是否启用命名验证
*/
private boolean enableValidation = true;

/**
* 是否启用命名冲突检查
*/
private boolean enableConflictCheck = true;

/**
* 类名配置
*/
private ClassNameConfig className = new ClassNameConfig();

/**
* 方法名配置
*/
private MethodNameConfig methodName = new MethodNameConfig();

/**
* 字段名配置
*/
private FieldNameConfig fieldName = new FieldNameConfig();

/**
* 包名配置
*/
private PackageNameConfig packageName = new PackageNameConfig();

/**
* URL路径配置
*/
private UrlPathConfig urlPath = new UrlPathConfig();

/**
* 代码生成配置
*/
private CodeGenerationConfig codeGeneration = new CodeGenerationConfig();

/**
* 模板配置
*/
private TemplateConfig template = new TemplateConfig();

/**
* 类名配置
*/
@Data
public static class ClassNameConfig {
/**
* 最大长度
*/
private int maxLength = 50;

/**
* 最小长度
*/
private int minLength = 2;

/**
* 是否允许数字
*/
private boolean allowNumbers = true;

/**
* 是否允许下划线
*/
private boolean allowUnderscore = false;

/**
* 是否允许连字符
*/
private boolean allowHyphen = false;

/**
* 前缀规则
*/
private List<String> prefixes = new ArrayList<>();

/**
* 后缀规则
*/
private List<String> suffixes = new ArrayList<>();

/**
* 禁止使用的词
*/
private List<String> forbiddenWords = new ArrayList<>();
}

/**
* 方法名配置
*/
@Data
public static class MethodNameConfig {
/**
* 最大长度
*/
private int maxLength = 30;

/**
* 最小长度
*/
private int minLength = 2;

/**
* 是否允许数字
*/
private boolean allowNumbers = true;

/**
* 是否允许下划线
*/
private boolean allowUnderscore = false;

/**
* 是否允许连字符
*/
private boolean allowHyphen = false;

/**
* 操作类型前缀映射
*/
private Map<OperationType, List<String>> operationPrefixes = new HashMap<>();

/**
* 禁止使用的方法名
*/
private List<String> forbiddenNames = new ArrayList<>();
}

/**
* 字段名配置
*/
@Data
public static class FieldNameConfig {
/**
* 最大长度
*/
private int maxLength = 30;

/**
* 最小长度
*/
private int minLength = 2;

/**
* 是否允许数字
*/
private boolean allowNumbers = true;

/**
* 是否允许下划线
*/
private boolean allowUnderscore = false;

/**
* 是否允许连字符
*/
private boolean allowHyphen = false;

/**
* 禁止使用的字段名
*/
private List<String> forbiddenNames = new ArrayList<>();

/**
* 保留字段名
*/
private List<String> reservedNames = new ArrayList<>();
}

/**
* 包名配置
*/
@Data
public static class PackageNameConfig {
/**
* 最大长度
*/
private int maxLength = 20;

/**
* 最小长度
*/
private int minLength = 2;

/**
* 是否允许数字
*/
private boolean allowNumbers = true;

/**
* 基础包名
*/
private String basePackage = "com.company";

/**
* 模块包名映射
*/
private Map<String, String> modulePackages = new HashMap<>();
}

/**
* URL路径配置
*/
@Data
public static class UrlPathConfig {
/**
* 最大长度
*/
private int maxLength = 100;

/**
* 基础路径
*/
private String basePath = "/api";

/**
* 版本路径
*/
private String versionPath = "/v1";

/**
* 是否启用版本控制
*/
private boolean enableVersioning = true;

/**
* 路径分隔符
*/
private String separator = "/";
}

/**
* 代码生成配置
*/
@Data
public static class CodeGenerationConfig {
/**
* 是否启用代码生成
*/
private boolean enabled = true;

/**
* 生成目录
*/
private String outputDirectory = "src/main/java";

/**
* 是否覆盖已存在的文件
*/
private boolean overwriteExisting = false;

/**
* 是否生成注释
*/
private boolean generateComments = true;

/**
* 是否生成测试代码
*/
private boolean generateTests = false;

/**
* 是否生成文档
*/
private boolean generateDocumentation = true;
}

/**
* 模板配置
*/
@Data
public static class TemplateConfig {
/**
* 模板目录
*/
private String templateDirectory = "templates";

/**
* 模板文件扩展名
*/
private String templateExtension = ".ftl";

/**
* 是否启用模板缓存
*/
private boolean enableCache = true;

/**
* 模板缓存时间(秒)
*/
private int cacheTime = 3600;
}
}

六、命名规范管理端点

6.1 管理端点实现

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
/**
* 命名规范管理端点
* 提供RESTful API进行命名规范管理
*/
@RestController
@RequestMapping("/api/naming-convention")
@Slf4j
public class NamingConventionManagementEndpoint {

private final NamingConventionEngine namingConventionEngine;

/**
* 生成接口命名
*/
@PostMapping("/interface")
public ResponseEntity<InterfaceNamingResult> generateInterfaceNaming(
@Valid @RequestBody InterfaceNamingRequest request) {

try {
InterfaceNamingResult result = namingConventionEngine.generateInterfaceNaming(request);
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("生成接口命名失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 生成DTO/VO命名
*/
@PostMapping("/dto-vo")
public ResponseEntity<DTOVONamingResult> generateDTOVONaming(
@Valid @RequestBody DTOVONamingRequest request) {

try {
DTOVONamingResult result = namingConventionEngine.generateDTOVONaming(request);
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("生成DTO/VO命名失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 批量生成命名
*/
@PostMapping("/batch")
public ResponseEntity<BatchNamingResult> batchGenerateNaming(
@Valid @RequestBody BatchNamingRequest request) {

try {
BatchNamingResult result = namingConventionEngine.batchGenerateNaming(request);
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("批量生成命名失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 验证命名规范
*/
@PostMapping("/validate")
public ResponseEntity<NamingValidationResult> validateNaming(
@Valid @RequestBody NamingValidationRequest request) {

try {
NamingValidationResult result = namingConventionEngine.validateNaming(request);
return ResponseEntity.ok(result);
} catch (Exception e) {
log.error("验证命名规范失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 获取命名规范配置
*/
@GetMapping("/config")
public ResponseEntity<NamingConventionProperties> getNamingConventionConfig() {
try {
NamingConventionProperties config = namingConventionEngine.getNamingConventionConfig();
return ResponseEntity.ok(config);
} catch (Exception e) {
log.error("获取命名规范配置失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 更新命名规范配置
*/
@PutMapping("/config")
public ResponseEntity<Void> updateNamingConventionConfig(
@Valid @RequestBody NamingConventionProperties config) {

try {
namingConventionEngine.updateNamingConventionConfig(config);
return ResponseEntity.ok().build();
} catch (Exception e) {
log.error("更新命名规范配置失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 获取命名规范统计
*/
@GetMapping("/statistics")
public ResponseEntity<NamingConventionStatistics> getNamingConventionStatistics() {
try {
NamingConventionStatistics statistics = namingConventionEngine.getNamingConventionStatistics();
return ResponseEntity.ok(statistics);
} catch (Exception e) {
log.error("获取命名规范统计失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 导出命名规范报告
*/
@GetMapping("/export")
public ResponseEntity<byte[]> exportNamingConventionReport(
@RequestParam(defaultValue = "pdf") String format) {

try {
byte[] report = namingConventionEngine.exportNamingConventionReport(format);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.setContentDispositionFormData("attachment", "naming-convention-report." + format);
return ResponseEntity.ok().headers(headers).body(report);
} catch (Exception e) {
log.error("导出命名规范报告失败", e);
return ResponseEntity.badRequest().build();
}
}
}

七、实战应用与最佳实践

7.1 用户管理模块命名规范实战

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
/**
* 用户管理模块命名规范实战示例
*/
@RestController
@RequestMapping("/api/user")
@Slf4j
public class UserManagementNamingExample {

private final NamingConventionEngine namingConventionEngine;

/**
* 生成用户管理接口命名
*/
@PostMapping("/generate-interface")
public ResponseEntity<InterfaceNamingResult> generateUserInterfaceNaming() {
try {
// 构建接口命名请求
InterfaceNamingRequest request = InterfaceNamingRequest.builder()
.businessName("User")
.moduleName("UserManagement")
.version("v1")
.operations(Arrays.asList(
Operation.builder()
.name("createUser")
.type(OperationType.CREATE)
.businessName("User")
.httpMethod(HttpMethod.POST)
.build(),
Operation.builder()
.name("getUser")
.type(OperationType.READ)
.businessName("User")
.httpMethod(HttpMethod.GET)
.build(),
Operation.builder()
.name("updateUser")
.type(OperationType.UPDATE)
.businessName("User")
.httpMethod(HttpMethod.PUT)
.build(),
Operation.builder()
.name("deleteUser")
.type(OperationType.DELETE)
.businessName("User")
.httpMethod(HttpMethod.DELETE)
.build(),
Operation.builder()
.name("listUsers")
.type(OperationType.LIST)
.businessName("User")
.httpMethod(HttpMethod.GET)
.build()
))
.generateCode(true)
.build();

// 生成接口命名
InterfaceNamingResult result = namingConventionEngine.generateInterfaceNaming(request);

log.info("用户管理接口命名生成成功: {}", result.getInterfaceName());
return ResponseEntity.ok(result);

} catch (Exception e) {
log.error("用户管理接口命名生成失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 生成用户DTO/VO命名
*/
@PostMapping("/generate-dto-vo")
public ResponseEntity<DTOVONamingResult> generateUserDTOVONaming() {
try {
// 构建DTO/VO命名请求
DTOVONamingRequest request = DTOVONamingRequest.builder()
.businessName("User")
.moduleName("UserManagement")
.type(DTOVOType.REQUEST_DTO)
.operation("Create")
.fields(Arrays.asList(
FieldDefinition.builder()
.name("username")
.type("String")
.comment("用户名")
.required(true)
.build(),
FieldDefinition.builder()
.name("email")
.type("String")
.comment("邮箱")
.required(true)
.build(),
FieldDefinition.builder()
.name("phone")
.type("String")
.comment("手机号")
.required(false)
.build(),
FieldDefinition.builder()
.name("age")
.type("Integer")
.comment("年龄")
.required(false)
.build()
))
.generateTemplate(true)
.build();

// 生成DTO/VO命名
DTOVONamingResult result = namingConventionEngine.generateDTOVONaming(request);

log.info("用户DTO/VO命名生成成功: {}", result.getClassName());
return ResponseEntity.ok(result);

} catch (Exception e) {
log.error("用户DTO/VO命名生成失败", e);
return ResponseEntity.badRequest().build();
}
}

/**
* 批量生成用户管理命名
*/
@PostMapping("/batch-generate")
public ResponseEntity<BatchNamingResult> batchGenerateUserNaming() {
try {
// 构建批量命名请求
List<NamingRequest> namingRequests = Arrays.asList(
NamingRequest.builder()
.businessName("User")
.moduleName("UserManagement")
.type(NamingType.INTERFACE)
.build(),
NamingRequest.builder()
.businessName("User")
.moduleName("UserManagement")
.type(NamingType.REQUEST_DTO)
.build(),
NamingRequest.builder()
.businessName("User")
.moduleName("UserManagement")
.type(NamingType.RESPONSE_VO)
.build(),
NamingRequest.builder()
.businessName("User")
.moduleName("UserManagement")
.type(NamingType.BUSINESS_BO)
.build(),
NamingRequest.builder()
.businessName("User")
.moduleName("UserManagement")
.type(NamingType.QUERY_QO)
.build()
);

BatchNamingRequest request = BatchNamingRequest.builder()
.namingRequests(namingRequests)
.build();

// 批量生成命名
BatchNamingResult result = namingConventionEngine.batchGenerateNaming(request);

log.info("用户管理批量命名生成成功,成功: {}, 失败: {}",
result.getSuccessCount(), result.getFailureCount());
return ResponseEntity.ok(result);

} catch (Exception e) {
log.error("用户管理批量命名生成失败", e);
return ResponseEntity.badRequest().build();
}
}
}

7.2 命名规范最佳实践

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
/**
* 命名规范最佳实践
*/
@Component
@Slf4j
public class NamingConventionBestPractices {

private final NamingConventionEngine namingConventionEngine;

/**
* 命名规范最佳实践指南
*/
public void demonstrateBestPractices() {
log.info("=== 命名规范最佳实践指南 ===");

// 1. 接口命名最佳实践
demonstrateInterfaceNamingBestPractices();

// 2. DTO/VO命名最佳实践
demonstrateDTOVONamingBestPractices();

// 3. 方法命名最佳实践
demonstrateMethodNamingBestPractices();

// 4. 字段命名最佳实践
demonstrateFieldNamingBestPractices();

// 5. 包命名最佳实践
demonstratePackageNamingBestPractices();
}

/**
* 接口命名最佳实践
*/
private void demonstrateInterfaceNamingBestPractices() {
log.info("--- 接口命名最佳实践 ---");

// 好的命名示例
List<String> goodInterfaceNames = Arrays.asList(
"UserController", // 清晰表达业务含义
"OrderService", // 简洁明了
"ProductRepository", // 符合分层架构
"PaymentGateway", // 表达技术含义
"NotificationHandler" // 表达处理逻辑
);

// 不好的命名示例
List<String> badInterfaceNames = Arrays.asList(
"Controller1", // 缺乏业务含义
"Service", // 过于通用
"Data", // 含义不明确
"Manager", // 过于宽泛
"Util" // 工具类命名不当
);

log.info("好的接口命名示例: {}", goodInterfaceNames);
log.info("不好的接口命名示例: {}", badInterfaceNames);

// 命名规范建议
log.info("接口命名规范建议:");
log.info("1. 使用业务领域名称 + 技术角色后缀");
log.info("2. 避免使用数字、下划线、连字符");
log.info("3. 保持名称简洁但含义明确");
log.info("4. 遵循驼峰命名法");
log.info("5. 避免使用过于通用的词汇");
}

/**
* DTO/VO命名最佳实践
*/
private void demonstrateDTOVONamingBestPractices() {
log.info("--- DTO/VO命名最佳实践 ---");

// 好的DTO/VO命名示例
Map<String, List<String>> goodDTOVONames = new HashMap<>();
goodDTOVONames.put("RequestDTO", Arrays.asList(
"CreateUserRequestDTO",
"UpdateProductRequestDTO",
"SearchOrderRequestDTO"
));
goodDTOVONames.put("ResponseVO", Arrays.asList(
"UserResponseVO",
"ProductListResponseVO",
"OrderDetailResponseVO"
));
goodDTOVONames.put("BusinessBO", Arrays.asList(
"UserBO",
"ProductBO",
"OrderBO"
));
goodDTOVONames.put("QueryQO", Arrays.asList(
"UserQueryQO",
"ProductQueryQO",
"OrderQueryQO"
));

// 不好的DTO/VO命名示例
List<String> badDTOVONames = Arrays.asList(
"DTO", // 缺乏业务含义
"VO", // 过于通用
"Data", // 含义不明确
"Request", // 缺乏类型区分
"Response" // 缺乏类型区分
);

log.info("好的DTO/VO命名示例: {}", goodDTOVONames);
log.info("不好的DTO/VO命名示例: {}", badDTOVONames);

// 命名规范建议
log.info("DTO/VO命名规范建议:");
log.info("1. 使用业务名称 + 类型后缀");
log.info("2. RequestDTO用于接收请求数据");
log.info("3. ResponseVO用于返回响应数据");
log.info("4. BO用于业务逻辑处理");
log.info("5. QO用于查询条件封装");
}

/**
* 方法命名最佳实践
*/
private void demonstrateMethodNamingBestPractices() {
log.info("--- 方法命名最佳实践 ---");

// 好的方法命名示例
Map<OperationType, List<String>> goodMethodNames = new HashMap<>();
goodMethodNames.put(OperationType.CREATE, Arrays.asList(
"createUser",
"addProduct",
"registerAccount"
));
goodMethodNames.put(OperationType.READ, Arrays.asList(
"getUser",
"findProduct",
"queryOrder"
));
goodMethodNames.put(OperationType.UPDATE, Arrays.asList(
"updateUser",
"modifyProduct",
"changeOrderStatus"
));
goodMethodNames.put(OperationType.DELETE, Arrays.asList(
"deleteUser",
"removeProduct",
"cancelOrder"
));

// 不好的方法命名示例
List<String> badMethodNames = Arrays.asList(
"do", // 过于通用
"process", // 含义不明确
"handle", // 过于宽泛
"execute", // 缺乏业务含义
"run" // 过于通用
);

log.info("好的方法命名示例: {}", goodMethodNames);
log.info("不好的方法命名示例: {}", badMethodNames);

// 命名规范建议
log.info("方法命名规范建议:");
log.info("1. 使用动词 + 名词的组合");
log.info("2. 动词要准确表达操作类型");
log.info("3. 名词要清晰表达操作对象");
log.info("4. 避免使用过于通用的动词");
log.info("5. 保持方法名简洁但含义明确");
}

/**
* 字段命名最佳实践
*/
private void demonstrateFieldNamingBestPractices() {
log.info("--- 字段命名最佳实践 ---");

// 好的字段命名示例
List<String> goodFieldNames = Arrays.asList(
"userId", // 清晰表达含义
"userName", // 符合驼峰命名
"emailAddress", // 含义明确
"createTime", // 时间字段命名
"isActive" // 布尔字段命名
);

// 不好的字段命名示例
List<String> badFieldNames = Arrays.asList(
"id", // 过于通用
"name", // 含义不明确
"data", // 过于宽泛
"flag", // 含义不明确
"temp" // 临时字段命名不当
);

log.info("好的字段命名示例: {}", goodFieldNames);
log.info("不好的字段命名示例: {}", badFieldNames);

// 命名规范建议
log.info("字段命名规范建议:");
log.info("1. 使用有意义的名称");
log.info("2. 避免使用缩写");
log.info("3. 布尔字段使用is/has/can等前缀");
log.info("4. 时间字段使用Time/Date后缀");
log.info("5. 保持字段名简洁但含义明确");
}

/**
* 包命名最佳实践
*/
private void demonstratePackageNamingBestPractices() {
log.info("--- 包命名最佳实践 ---");

// 好的包命名示例
List<String> goodPackageNames = Arrays.asList(
"com.company.user.controller", // 清晰的分层结构
"com.company.user.service", // 符合业务模块
"com.company.user.repository", // 技术分层明确
"com.company.user.dto", // 数据传输对象
"com.company.user.vo" // 视图对象
);

// 不好的包命名示例
List<String> badPackageNames = Arrays.asList(
"com.company.controller", // 缺乏业务模块
"com.company.service", // 过于通用
"com.company.data", // 含义不明确
"com.company.util", // 工具类包命名不当
"com.company.common" // 过于宽泛
);

log.info("好的包命名示例: {}", goodPackageNames);
log.info("不好的包命名示例: {}", badPackageNames);

// 命名规范建议
log.info("包命名规范建议:");
log.info("1. 使用反向域名命名");
log.info("2. 按业务模块组织包结构");
log.info("3. 按技术分层组织包结构");
log.info("4. 避免使用过于通用的包名");
log.info("5. 保持包名简洁但含义明确");
}
}

八、总结

本文深入探讨了SpringBoot中接口和DTO/VO的命名规范架构设计与实战应用。通过构建标准化的命名规范框架,我们实现了:

  1. 统一的命名规范体系:建立了完整的接口、DTO/VO命名规范,确保代码的一致性和可读性
  2. 智能的代码生成能力:基于命名规范自动生成标准化的代码模板,提高开发效率
  3. 完善的验证检查机制:提供命名规范验证和冲突检查,确保代码质量
  4. 灵活的配置管理:支持灵活的命名规范配置,适应不同项目的需求
  5. 全面的管理端点:提供RESTful API进行命名规范管理,支持批量操作和报告导出

通过这套企业级的接口命名规范架构,我们能够有效解决大型项目中接口和DTO/VO命名混乱的问题,提升代码的可维护性和团队协作效率。随着微服务架构和团队协作的不断发展,构建规范、高效的命名体系将成为企业级架构师必须掌握的核心技能。

在实际应用中,建议根据项目特点和团队习惯,制定适合的命名规范,并通过代码审查和自动化检查确保规范的执行。只有这样,才能真正发挥命名规范的价值,构建高质量的企业级应用系统。