1. 微服务架构概述

微服务架构是一种将单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,并通过轻量级机制(通常是HTTP API)进行通信。本文将详细介绍用户服务、API网关、设备服务、订单服务、接入服务等核心微服务的设计与实现,以及微服务架构的最佳实践。

1.1 微服务架构的优势

  1. 技术多样性: 每个服务可以使用不同的技术栈
  2. 独立部署: 服务可以独立开发、测试和部署
  3. 可扩展性: 可以针对特定服务进行水平扩展
  4. 故障隔离: 单个服务的故障不会影响整个系统
  5. 团队自治: 不同团队可以独立开发不同的服务

1.2 微服务架构挑战

  1. 分布式复杂性: 网络延迟、故障处理、数据一致性
  2. 服务治理: 服务发现、负载均衡、熔断降级
  3. 数据管理: 分布式事务、数据一致性
  4. 监控运维: 分布式链路追踪、日志聚合
  5. 安全管控: 服务间认证、授权、数据加密

1.3 微服务架构设计原则

1
2
3
4
5
6
7
8
9
10
11
12
13
┌─────────────────────────────────────────┐
│ 客户端层 │
│ (Web应用、移动应用、第三方系统) │
├─────────────────────────────────────────┤
│ API网关层 │
│ (路由、认证、限流、监控、日志) │
├─────────────────────────────────────────┤
│ 业务服务层 │
│ (用户服务、设备服务、订单服务、接入服务) │
├─────────────────────────────────────────┤
│ 基础设施层 │
│ (服务注册、配置中心、消息队列、数据库) │
└─────────────────────────────────────────┘

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
// 用户服务核心实体
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique = true, nullable = false)
private String username;

@Column(unique = true, nullable = false)
private String email;

@Column(nullable = false)
private String password;

@Enumerated(EnumType.STRING)
private UserStatus status;

@Enumerated(EnumType.STRING)
private UserRole role;

@CreationTimestamp
private LocalDateTime createdAt;

@UpdateTimestamp
private LocalDateTime updatedAt;

// 构造函数、getter、setter
}

// 用户状态枚举
public enum UserStatus {
ACTIVE, INACTIVE, SUSPENDED, PENDING_VERIFICATION
}

// 用户角色枚举
public enum UserRole {
ADMIN, USER, OPERATOR, GUEST
}

2.2 用户服务API设计

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
// 用户服务控制器
@RestController
@RequestMapping("/api/users")
@Validated
public class UserController {

private final UserService userService;
private final UserMapper userMapper;

public UserController(UserService userService, UserMapper userMapper) {
this.userService = userService;
this.userMapper = userMapper;
}

// 用户注册
@PostMapping("/register")
public ResponseEntity<UserResponse> register(@Valid @RequestBody UserRegistrationRequest request) {
User user = userService.register(request);
UserResponse response = userMapper.toResponse(user);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

// 用户登录
@PostMapping("/login")
public ResponseEntity<LoginResponse> login(@Valid @RequestBody LoginRequest request) {
LoginResponse response = userService.login(request);
return ResponseEntity.ok(response);
}

// 获取用户信息
@GetMapping("/{id}")
public ResponseEntity<UserResponse> getUser(@PathVariable Long id) {
User user = userService.findById(id);
UserResponse response = userMapper.toResponse(user);
return ResponseEntity.ok(response);
}

// 更新用户信息
@PutMapping("/{id}")
public ResponseEntity<UserResponse> updateUser(
@PathVariable Long id,
@Valid @RequestBody UserUpdateRequest request) {
User user = userService.updateUser(id, request);
UserResponse response = userMapper.toResponse(user);
return ResponseEntity.ok(response);
}

// 删除用户
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}

// 获取用户列表
@GetMapping
public ResponseEntity<Page<UserResponse>> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) String keyword) {
Page<User> users = userService.findUsers(page, size, keyword);
Page<UserResponse> responses = users.map(userMapper::toResponse);
return ResponseEntity.ok(responses);
}

// 用户认证
@PostMapping("/authenticate")
public ResponseEntity<AuthenticationResponse> authenticate(@RequestBody AuthenticationRequest request) {
AuthenticationResponse response = userService.authenticate(request);
return ResponseEntity.ok(response);
}

// 刷新Token
@PostMapping("/refresh-token")
public ResponseEntity<TokenResponse> refreshToken(@RequestBody RefreshTokenRequest request) {
TokenResponse response = userService.refreshToken(request);
return ResponseEntity.ok(response);
}
}

2.3 用户服务业务逻辑

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
// 用户服务实现
@Service
@Transactional
public class UserServiceImpl implements UserService {

private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final JwtTokenProvider jwtTokenProvider;
private final RedisTemplate<String, Object> redisTemplate;
private final EmailService emailService;

public UserServiceImpl(UserRepository userRepository,
PasswordEncoder passwordEncoder,
JwtTokenProvider jwtTokenProvider,
RedisTemplate<String, Object> redisTemplate,
EmailService emailService) {
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
this.jwtTokenProvider = jwtTokenProvider;
this.redisTemplate = redisTemplate;
this.emailService = emailService;
}

@Override
public User register(UserRegistrationRequest request) {
// 检查用户名是否已存在
if (userRepository.existsByUsername(request.getUsername())) {
throw new BusinessException("用户名已存在");
}

// 检查邮箱是否已存在
if (userRepository.existsByEmail(request.getEmail())) {
throw new BusinessException("邮箱已存在");
}

// 创建用户
User user = new User();
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setPassword(passwordEncoder.encode(request.getPassword()));
user.setStatus(UserStatus.PENDING_VERIFICATION);
user.setRole(UserRole.USER);

User savedUser = userRepository.save(user);

// 发送验证邮件
emailService.sendVerificationEmail(savedUser);

return savedUser;
}

@Override
public LoginResponse login(LoginRequest request) {
// 查找用户
User user = userRepository.findByUsername(request.getUsername())
.orElseThrow(() -> new BusinessException("用户名或密码错误"));

// 验证密码
if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
throw new BusinessException("用户名或密码错误");
}

// 检查用户状态
if (user.getStatus() != UserStatus.ACTIVE) {
throw new BusinessException("用户账户未激活或被禁用");
}

// 生成JWT Token
String accessToken = jwtTokenProvider.generateAccessToken(user);
String refreshToken = jwtTokenProvider.generateRefreshToken(user);

// 存储Token到Redis
String tokenKey = "user:token:" + user.getId();
redisTemplate.opsForValue().set(tokenKey, accessToken, Duration.ofHours(24));

// 更新最后登录时间
user.setLastLoginAt(LocalDateTime.now());
userRepository.save(user);

return LoginResponse.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.tokenType("Bearer")
.expiresIn(3600)
.user(UserResponse.builder()
.id(user.getId())
.username(user.getUsername())
.email(user.getEmail())
.role(user.getRole())
.status(user.getStatus())
.build())
.build();
}

@Override
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new BusinessException("用户不存在"));
}

@Override
public User updateUser(Long id, UserUpdateRequest request) {
User user = findById(id);

// 更新用户信息
if (request.getEmail() != null) {
user.setEmail(request.getEmail());
}
if (request.getPassword() != null) {
user.setPassword(passwordEncoder.encode(request.getPassword()));
}

return userRepository.save(user);
}

@Override
public void deleteUser(Long id) {
User user = findById(id);
userRepository.delete(user);

// 清除Redis中的Token
String tokenKey = "user:token:" + id;
redisTemplate.delete(tokenKey);
}

@Override
public Page<User> findUsers(int page, int size, String keyword) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());

if (StringUtils.hasText(keyword)) {
return userRepository.findByUsernameContainingOrEmailContaining(
keyword, keyword, pageable);
}

return userRepository.findAll(pageable);
}

@Override
public AuthenticationResponse authenticate(AuthenticationRequest request) {
String token = request.getToken();

if (!jwtTokenProvider.validateToken(token)) {
throw new BusinessException("无效的Token");
}

String username = jwtTokenProvider.getUsernameFromToken(token);
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new BusinessException("用户不存在"));

return AuthenticationResponse.builder()
.authenticated(true)
.user(UserResponse.builder()
.id(user.getId())
.username(user.getUsername())
.email(user.getEmail())
.role(user.getRole())
.status(user.getStatus())
.build())
.build();
}

@Override
public TokenResponse refreshToken(RefreshTokenRequest request) {
String refreshToken = request.getRefreshToken();

if (!jwtTokenProvider.validateRefreshToken(refreshToken)) {
throw new BusinessException("无效的刷新Token");
}

String username = jwtTokenProvider.getUsernameFromRefreshToken(refreshToken);
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new BusinessException("用户不存在"));

// 生成新的访问Token
String newAccessToken = jwtTokenProvider.generateAccessToken(user);

return TokenResponse.builder()
.accessToken(newAccessToken)
.tokenType("Bearer")
.expiresIn(3600)
.build();
}
}

3. API网关设计与实现

3.1 Spring Cloud Gateway配置

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
// API网关配置
@Configuration
@EnableWebFlux
public class GatewayConfig {

@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
// 用户服务路由
.route("user-service", r -> r.path("/api/users/**")
.filters(f -> f
.addRequestHeader("X-Service", "user-service")
.addResponseHeader("X-Response-Time", LocalDateTime.now().toString())
.circuitBreaker(config -> config
.setName("user-service-cb")
.setFallbackUri("forward:/fallback/user-service")))
.uri("lb://user-service"))

// 设备服务路由
.route("device-service", r -> r.path("/api/devices/**")
.filters(f -> f
.addRequestHeader("X-Service", "device-service")
.circuitBreaker(config -> config
.setName("device-service-cb")
.setFallbackUri("forward:/fallback/device-service")))
.uri("lb://device-service"))

// 订单服务路由
.route("order-service", r -> r.path("/api/orders/**")
.filters(f -> f
.addRequestHeader("X-Service", "order-service")
.circuitBreaker(config -> config
.setName("order-service-cb")
.setFallbackUri("forward:/fallback/order-service")))
.uri("lb://order-service"))

// 接入服务路由
.route("access-service", r -> r.path("/api/access/**")
.filters(f -> f
.addRequestHeader("X-Service", "access-service")
.circuitBreaker(config -> config
.setName("access-service-cb")
.setFallbackUri("forward:/fallback/access-service")))
.uri("lb://access-service"))

.build();
}

@Bean
public GlobalFilter customGlobalFilter() {
return new CustomGlobalFilter();
}

@Bean
public GatewayFilter customGatewayFilter() {
return new CustomGatewayFilter();
}
}

3.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
// 自定义全局过滤器
@Component
@Order(-1)
public class CustomGlobalFilter implements GlobalFilter {

private static final Logger logger = LoggerFactory.getLogger(CustomGlobalFilter.class);

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();

// 记录请求日志
logger.info("Request: {} {}", request.getMethod(), request.getURI());

// 添加请求ID
String requestId = UUID.randomUUID().toString();
ServerHttpRequest mutatedRequest = request.mutate()
.header("X-Request-ID", requestId)
.build();

ServerWebExchange mutatedExchange = exchange.mutate()
.request(mutatedRequest)
.build();

// 记录响应日志
return chain.filter(mutatedExchange)
.doOnSuccess(aVoid -> {
ServerHttpResponse response = mutatedExchange.getResponse();
logger.info("Response: {} {}",
response.getStatusCode(),
requestId);
})
.doOnError(throwable -> {
logger.error("Error processing request: {} - {}",
requestId, throwable.getMessage());
});
}
}

3.3 认证授权过滤器

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
// 认证授权过滤器
@Component
public class AuthenticationFilter implements GlobalFilter {

private final UserServiceClient userServiceClient;
private final RedisTemplate<String, Object> redisTemplate;

public AuthenticationFilter(UserServiceClient userServiceClient,
RedisTemplate<String, Object> redisTemplate) {
this.userServiceClient = userServiceClient;
this.redisTemplate = redisTemplate;
}

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();

// 跳过不需要认证的路径
if (isPublicPath(path)) {
return chain.filter(exchange);
}

// 获取Token
String token = extractToken(request);
if (token == null) {
return unauthorizedResponse(exchange);
}

// 验证Token
return validateToken(token)
.flatMap(user -> {
// 添加用户信息到请求头
ServerHttpRequest mutatedRequest = request.mutate()
.header("X-User-ID", user.getId().toString())
.header("X-User-Role", user.getRole().name())
.build();

ServerWebExchange mutatedExchange = exchange.mutate()
.request(mutatedRequest)
.build();

return chain.filter(mutatedExchange);
})
.onErrorResume(throwable -> unauthorizedResponse(exchange));
}

private boolean isPublicPath(String path) {
List<String> publicPaths = Arrays.asList(
"/api/users/register",
"/api/users/login",
"/api/users/refresh-token",
"/actuator/health"
);

return publicPaths.stream().anyMatch(path::startsWith);
}

private String extractToken(ServerHttpRequest request) {
String authorization = request.getHeaders().getFirst("Authorization");
if (authorization != null && authorization.startsWith("Bearer ")) {
return authorization.substring(7);
}
return null;
}

private Mono<UserResponse> validateToken(String token) {
// 先从Redis缓存中获取
String cacheKey = "token:" + token;
UserResponse cachedUser = (UserResponse) redisTemplate.opsForValue().get(cacheKey);

if (cachedUser != null) {
return Mono.just(cachedUser);
}

// 调用用户服务验证Token
return userServiceClient.authenticate(AuthenticationRequest.builder()
.token(token)
.build())
.map(AuthenticationResponse::getUser)
.doOnNext(user -> {
// 缓存用户信息
redisTemplate.opsForValue().set(cacheKey, user, Duration.ofMinutes(30));
});
}

private Mono<Void> unauthorizedResponse(ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
response.getHeaders().add("Content-Type", "application/json");

String body = "{\"error\":\"Unauthorized\",\"message\":\"Invalid or missing token\"}";
DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());

return response.writeWith(Mono.just(buffer));
}
}

4. 设备服务设计与实现

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
// 设备实体
@Entity
@Table(name = "devices")
public class Device {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique = true, nullable = false)
private String deviceId;

@Column(nullable = false)
private String deviceName;

@Column(nullable = false)
private String deviceType;

@Column(nullable = false)
private String manufacturer;

@Column(nullable = false)
private String model;

@Column(nullable = false)
private String serialNumber;

@Enumerated(EnumType.STRING)
private DeviceStatus status;

@Column(nullable = false)
private Long userId;

@Column
private String location;

@Column
private String description;

@Column
private String firmwareVersion;

@Column
private String hardwareVersion;

@CreationTimestamp
private LocalDateTime createdAt;

@UpdateTimestamp
private LocalDateTime updatedAt;

@Column
private LocalDateTime lastOnlineAt;

// 构造函数、getter、setter
}

// 设备状态枚举
public enum DeviceStatus {
ONLINE, OFFLINE, MAINTENANCE, ERROR, DISABLED
}

// 设备类型枚举
public enum DeviceType {
SENSOR, ACTUATOR, GATEWAY, CAMERA, CONTROLLER
}

4.2 设备服务API设计

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
// 设备服务控制器
@RestController
@RequestMapping("/api/devices")
@Validated
public class DeviceController {

private final DeviceService deviceService;
private final DeviceMapper deviceMapper;

public DeviceController(DeviceService deviceService, DeviceMapper deviceMapper) {
this.deviceService = deviceService;
this.deviceMapper = deviceMapper;
}

// 注册设备
@PostMapping("/register")
public ResponseEntity<DeviceResponse> registerDevice(@Valid @RequestBody DeviceRegistrationRequest request) {
Device device = deviceService.registerDevice(request);
DeviceResponse response = deviceMapper.toResponse(device);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

// 获取设备信息
@GetMapping("/{id}")
public ResponseEntity<DeviceResponse> getDevice(@PathVariable Long id) {
Device device = deviceService.findById(id);
DeviceResponse response = deviceMapper.toResponse(device);
return ResponseEntity.ok(response);
}

// 更新设备信息
@PutMapping("/{id}")
public ResponseEntity<DeviceResponse> updateDevice(
@PathVariable Long id,
@Valid @RequestBody DeviceUpdateRequest request) {
Device device = deviceService.updateDevice(id, request);
DeviceResponse response = deviceMapper.toResponse(device);
return ResponseEntity.ok(response);
}

// 删除设备
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteDevice(@PathVariable Long id) {
deviceService.deleteDevice(id);
return ResponseEntity.noContent().build();
}

// 获取用户设备列表
@GetMapping
public ResponseEntity<Page<DeviceResponse>> getUserDevices(
@RequestParam Long userId,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) DeviceStatus status) {
Page<Device> devices = deviceService.findUserDevices(userId, page, size, status);
Page<DeviceResponse> responses = devices.map(deviceMapper::toResponse);
return ResponseEntity.ok(responses);
}

// 设备上线
@PostMapping("/{id}/online")
public ResponseEntity<DeviceResponse> deviceOnline(@PathVariable Long id) {
Device device = deviceService.deviceOnline(id);
DeviceResponse response = deviceMapper.toResponse(device);
return ResponseEntity.ok(response);
}

// 设备下线
@PostMapping("/{id}/offline")
public ResponseEntity<DeviceResponse> deviceOffline(@PathVariable Long id) {
Device device = deviceService.deviceOffline(id);
DeviceResponse response = deviceMapper.toResponse(device);
return ResponseEntity.ok(response);
}

// 获取设备状态
@GetMapping("/{id}/status")
public ResponseEntity<DeviceStatusResponse> getDeviceStatus(@PathVariable Long id) {
DeviceStatusResponse response = deviceService.getDeviceStatus(id);
return ResponseEntity.ok(response);
}

// 发送设备命令
@PostMapping("/{id}/command")
public ResponseEntity<CommandResponse> sendCommand(
@PathVariable Long id,
@Valid @RequestBody DeviceCommandRequest request) {
CommandResponse response = deviceService.sendCommand(id, request);
return ResponseEntity.ok(response);
}

// 获取设备数据
@GetMapping("/{id}/data")
public ResponseEntity<Page<DeviceDataResponse>> getDeviceData(
@PathVariable Long id,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
Page<DeviceDataResponse> data = deviceService.getDeviceData(id, page, size, startTime, endTime);
return ResponseEntity.ok(data);
}
}

4.3 设备服务业务逻辑

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
// 设备服务实现
@Service
@Transactional
public class DeviceServiceImpl implements DeviceService {

private final DeviceRepository deviceRepository;
private final DeviceDataRepository deviceDataRepository;
private final MqttService mqttService;
private final RedisTemplate<String, Object> redisTemplate;

public DeviceServiceImpl(DeviceRepository deviceRepository,
DeviceDataRepository deviceDataRepository,
MqttService mqttService,
RedisTemplate<String, Object> redisTemplate) {
this.deviceRepository = deviceRepository;
this.deviceDataRepository = deviceDataRepository;
this.mqttService = mqttService;
this.redisTemplate = redisTemplate;
}

@Override
public Device registerDevice(DeviceRegistrationRequest request) {
// 检查设备ID是否已存在
if (deviceRepository.existsByDeviceId(request.getDeviceId())) {
throw new BusinessException("设备ID已存在");
}

// 创建设备
Device device = new Device();
device.setDeviceId(request.getDeviceId());
device.setDeviceName(request.getDeviceName());
device.setDeviceType(request.getDeviceType());
device.setManufacturer(request.getManufacturer());
device.setModel(request.getModel());
device.setSerialNumber(request.getSerialNumber());
device.setStatus(DeviceStatus.OFFLINE);
device.setUserId(request.getUserId());
device.setLocation(request.getLocation());
device.setDescription(request.getDescription());
device.setFirmwareVersion(request.getFirmwareVersion());
device.setHardwareVersion(request.getHardwareVersion());

Device savedDevice = deviceRepository.save(device);

// 缓存设备信息
cacheDeviceInfo(savedDevice);

return savedDevice;
}

@Override
public Device findById(Long id) {
return deviceRepository.findById(id)
.orElseThrow(() -> new BusinessException("设备不存在"));
}

@Override
public Device updateDevice(Long id, DeviceUpdateRequest request) {
Device device = findById(id);

// 更新设备信息
if (request.getDeviceName() != null) {
device.setDeviceName(request.getDeviceName());
}
if (request.getLocation() != null) {
device.setLocation(request.getLocation());
}
if (request.getDescription() != null) {
device.setDescription(request.getDescription());
}

Device savedDevice = deviceRepository.save(device);

// 更新缓存
cacheDeviceInfo(savedDevice);

return savedDevice;
}

@Override
public void deleteDevice(Long id) {
Device device = findById(id);
deviceRepository.delete(device);

// 清除缓存
String cacheKey = "device:" + id;
redisTemplate.delete(cacheKey);
}

@Override
public Page<Device> findUserDevices(Long userId, int page, int size, DeviceStatus status) {
Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());

if (status != null) {
return deviceRepository.findByUserIdAndStatus(userId, status, pageable);
}

return deviceRepository.findByUserId(userId, pageable);
}

@Override
public Device deviceOnline(Long id) {
Device device = findById(id);
device.setStatus(DeviceStatus.ONLINE);
device.setLastOnlineAt(LocalDateTime.now());

Device savedDevice = deviceRepository.save(device);

// 更新缓存
cacheDeviceInfo(savedDevice);

// 发布设备上线事件
publishDeviceEvent(savedDevice, "ONLINE");

return savedDevice;
}

@Override
public Device deviceOffline(Long id) {
Device device = findById(id);
device.setStatus(DeviceStatus.OFFLINE);

Device savedDevice = deviceRepository.save(device);

// 更新缓存
cacheDeviceInfo(savedDevice);

// 发布设备下线事件
publishDeviceEvent(savedDevice, "OFFLINE");

return savedDevice;
}

@Override
public DeviceStatusResponse getDeviceStatus(Long id) {
Device device = findById(id);

// 检查设备是否在线(基于最后在线时间)
boolean isOnline = device.getLastOnlineAt() != null &&
device.getLastOnlineAt().isAfter(LocalDateTime.now().minusMinutes(5));

return DeviceStatusResponse.builder()
.deviceId(device.getId())
.deviceName(device.getDeviceName())
.status(device.getStatus())
.isOnline(isOnline)
.lastOnlineAt(device.getLastOnlineAt())
.build();
}

@Override
public CommandResponse sendCommand(Long id, DeviceCommandRequest request) {
Device device = findById(id);

if (device.getStatus() != DeviceStatus.ONLINE) {
throw new BusinessException("设备离线,无法发送命令");
}

// 构建命令消息
DeviceCommand command = DeviceCommand.builder()
.deviceId(device.getDeviceId())
.commandType(request.getCommandType())
.parameters(request.getParameters())
.timestamp(LocalDateTime.now())
.build();

// 通过MQTT发送命令
String topic = "device/" + device.getDeviceId() + "/command";
mqttService.publish(topic, command);

return CommandResponse.builder()
.commandId(UUID.randomUUID().toString())
.deviceId(device.getDeviceId())
.status("SENT")
.timestamp(LocalDateTime.now())
.build();
}

@Override
public Page<DeviceDataResponse> getDeviceData(Long id, int page, int size,
LocalDateTime startTime, LocalDateTime endTime) {
Device device = findById(id);

Pageable pageable = PageRequest.of(page, size, Sort.by("timestamp").descending());

Page<DeviceData> data;
if (startTime != null && endTime != null) {
data = deviceDataRepository.findByDeviceIdAndTimestampBetween(
device.getDeviceId(), startTime, endTime, pageable);
} else {
data = deviceDataRepository.findByDeviceId(device.getDeviceId(), pageable);
}

return data.map(this::convertToDeviceDataResponse);
}

private void cacheDeviceInfo(Device device) {
String cacheKey = "device:" + device.getId();
redisTemplate.opsForValue().set(cacheKey, device, Duration.ofHours(1));
}

private void publishDeviceEvent(Device device, String eventType) {
DeviceEvent event = DeviceEvent.builder()
.deviceId(device.getId())
.deviceName(device.getDeviceName())
.eventType(eventType)
.timestamp(LocalDateTime.now())
.build();

// 发布到消息队列
// messagePublisher.publish("device.events", event);
}

private DeviceDataResponse convertToDeviceDataResponse(DeviceData data) {
return DeviceDataResponse.builder()
.id(data.getId())
.deviceId(data.getDeviceId())
.dataType(data.getDataType())
.value(data.getValue())
.unit(data.getUnit())
.timestamp(data.getTimestamp())
.build();
}
}

5. 订单服务设计与实现

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
// 订单实体
@Entity
@Table(name = "orders")
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique = true, nullable = false)
private String orderNumber;

@Column(nullable = false)
private Long userId;

@Enumerated(EnumType.STRING)
private OrderStatus status;

@Enumerated(EnumType.STRING)
private OrderType type;

@Column(nullable = false)
private BigDecimal totalAmount;

@Column
private BigDecimal discountAmount;

@Column
private BigDecimal finalAmount;

@Column
private String paymentMethod;

@Column
private String paymentStatus;

@Column
private String shippingAddress;

@Column
private String billingAddress;

@Column
private String notes;

@CreationTimestamp
private LocalDateTime createdAt;

@UpdateTimestamp
private LocalDateTime updatedAt;

@Column
private LocalDateTime paidAt;

@Column
private LocalDateTime shippedAt;

@Column
private LocalDateTime deliveredAt;

@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<OrderItem> items = new ArrayList<>();

// 构造函数、getter、setter
}

// 订单状态枚举
public enum OrderStatus {
PENDING, CONFIRMED, PAID, SHIPPED, DELIVERED, CANCELLED, REFUNDED
}

// 订单类型枚举
public enum OrderType {
ONLINE, OFFLINE, SUBSCRIPTION, BULK
}

// 订单项实体
@Entity
@Table(name = "order_items")
public class OrderItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "order_id")
private Order order;

@Column(nullable = false)
private String productId;

@Column(nullable = false)
private String productName;

@Column(nullable = false)
private Integer quantity;

@Column(nullable = false)
private BigDecimal unitPrice;

@Column(nullable = false)
private BigDecimal totalPrice;

// 构造函数、getter、setter
}

5.2 订单服务API设计

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
// 订单服务控制器
@RestController
@RequestMapping("/api/orders")
@Validated
public class OrderController {

private final OrderService orderService;
private final OrderMapper orderMapper;

public OrderController(OrderService orderService, OrderMapper orderMapper) {
this.orderService = orderService;
this.orderMapper = orderMapper;
}

// 创建订单
@PostMapping
public ResponseEntity<OrderResponse> createOrder(@Valid @RequestBody OrderCreateRequest request) {
Order order = orderService.createOrder(request);
OrderResponse response = orderMapper.toResponse(order);
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}

// 获取订单详情
@GetMapping("/{id}")
public ResponseEntity<OrderResponse> getOrder(@PathVariable Long id) {
Order order = orderService.findById(id);
OrderResponse response = orderMapper.toResponse(order);
return ResponseEntity.ok(response);
}

// 更新订单状态
@PutMapping("/{id}/status")
public ResponseEntity<OrderResponse> updateOrderStatus(
@PathVariable Long id,
@Valid @RequestBody OrderStatusUpdateRequest request) {
Order order = orderService.updateOrderStatus(id, request);
OrderResponse response = orderMapper.toResponse(order);
return ResponseEntity.ok(response);
}

// 取消订单
@PostMapping("/{id}/cancel")
public ResponseEntity<OrderResponse> cancelOrder(@PathVariable Long id) {
Order order = orderService.cancelOrder(id);
OrderResponse response = orderMapper.toResponse(order);
return ResponseEntity.ok(response);
}

// 获取用户订单列表
@GetMapping
public ResponseEntity<Page<OrderResponse>> getUserOrders(
@RequestParam Long userId,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) OrderStatus status) {
Page<Order> orders = orderService.findUserOrders(userId, page, size, status);
Page<OrderResponse> responses = orders.map(orderMapper::toResponse);
return ResponseEntity.ok(responses);
}

// 支付订单
@PostMapping("/{id}/pay")
public ResponseEntity<PaymentResponse> payOrder(
@PathVariable Long id,
@Valid @RequestBody PaymentRequest request) {
PaymentResponse response = orderService.payOrder(id, request);
return ResponseEntity.ok(response);
}

// 发货
@PostMapping("/{id}/ship")
public ResponseEntity<OrderResponse> shipOrder(
@PathVariable Long id,
@Valid @RequestBody ShippingRequest request) {
Order order = orderService.shipOrder(id, request);
OrderResponse response = orderMapper.toResponse(order);
return ResponseEntity.ok(response);
}

// 确认收货
@PostMapping("/{id}/deliver")
public ResponseEntity<OrderResponse> deliverOrder(@PathVariable Long id) {
Order order = orderService.deliverOrder(id);
OrderResponse response = orderMapper.toResponse(order);
return ResponseEntity.ok(response);
}

// 申请退款
@PostMapping("/{id}/refund")
public ResponseEntity<RefundResponse> refundOrder(
@PathVariable Long id,
@Valid @RequestBody RefundRequest request) {
RefundResponse response = orderService.refundOrder(id, request);
return ResponseEntity.ok(response);
}
}

6. 接入服务设计与实现

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
// 接入服务实体
@Entity
@Table(name = "access_logs")
public class AccessLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String requestId;

@Column(nullable = false)
private String clientId;

@Column(nullable = false)
private String userId;

@Column(nullable = false)
private String serviceName;

@Column(nullable = false)
private String endpoint;

@Column(nullable = false)
private String method;

@Column
private String requestBody;

@Column
private String responseBody;

@Column(nullable = false)
private Integer statusCode;

@Column(nullable = false)
private Long responseTime;

@Column
private String userAgent;

@Column
private String clientIp;

@CreationTimestamp
private LocalDateTime createdAt;

// 构造函数、getter、setter
}

// 接入配置实体
@Entity
@Table(name = "access_configs")
public class AccessConfig {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
private String clientId;

@Column(nullable = false)
private String clientSecret;

@Column(nullable = false)
private String clientName;

@Enumerated(EnumType.STRING)
private AccessType accessType;

@Column
private String allowedServices;

@Column
private String allowedEndpoints;

@Column
private Integer rateLimit;

@Column
private Boolean isActive;

@CreationTimestamp
private LocalDateTime createdAt;

@UpdateTimestamp
private LocalDateTime updatedAt;

// 构造函数、getter、setter
}

// 接入类型枚举
public enum AccessType {
WEB, MOBILE, API, THIRD_PARTY
}

6.2 接入服务API设计

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
// 接入服务控制器
@RestController
@RequestMapping("/api/access")
@Validated
public class AccessController {

private final AccessService accessService;
private final AccessLogService accessLogService;

public AccessController(AccessService accessService, AccessLogService accessLogService) {
this.accessService = accessService;
this.accessLogService = accessLogService;
}

// 客户端认证
@PostMapping("/authenticate")
public ResponseEntity<AccessTokenResponse> authenticate(@Valid @RequestBody AccessRequest request) {
AccessTokenResponse response = accessService.authenticate(request);
return ResponseEntity.ok(response);
}

// 刷新访问令牌
@PostMapping("/refresh")
public ResponseEntity<AccessTokenResponse> refreshToken(@Valid @RequestBody RefreshTokenRequest request) {
AccessTokenResponse response = accessService.refreshToken(request);
return ResponseEntity.ok(response);
}

// 验证访问令牌
@PostMapping("/validate")
public ResponseEntity<ValidationResponse> validateToken(@Valid @RequestBody TokenValidationRequest request) {
ValidationResponse response = accessService.validateToken(request);
return ResponseEntity.ok(response);
}

// 获取客户端信息
@GetMapping("/client/{clientId}")
public ResponseEntity<ClientInfoResponse> getClientInfo(@PathVariable String clientId) {
ClientInfoResponse response = accessService.getClientInfo(clientId);
return ResponseEntity.ok(response);
}

// 更新客户端配置
@PutMapping("/client/{clientId}")
public ResponseEntity<ClientInfoResponse> updateClientConfig(
@PathVariable String clientId,
@Valid @RequestBody ClientConfigUpdateRequest request) {
ClientInfoResponse response = accessService.updateClientConfig(clientId, request);
return ResponseEntity.ok(response);
}

// 获取访问日志
@GetMapping("/logs")
public ResponseEntity<Page<AccessLogResponse>> getAccessLogs(
@RequestParam(required = false) String clientId,
@RequestParam(required = false) String userId,
@RequestParam(required = false) String serviceName,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
Page<AccessLogResponse> logs = accessLogService.getAccessLogs(
clientId, userId, serviceName, page, size, startTime, endTime);
return ResponseEntity.ok(logs);
}

// 获取访问统计
@GetMapping("/stats")
public ResponseEntity<AccessStatsResponse> getAccessStats(
@RequestParam(required = false) String clientId,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
@RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
AccessStatsResponse response = accessLogService.getAccessStats(clientId, startDate, endDate);
return ResponseEntity.ok(response);
}

// 撤销访问令牌
@PostMapping("/revoke")
public ResponseEntity<Void> revokeToken(@Valid @RequestBody TokenRevokeRequest request) {
accessService.revokeToken(request);
return ResponseEntity.ok().build();
}
}

6.3 接入服务业务逻辑

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
// 接入服务实现
@Service
@Transactional
public class AccessServiceImpl implements AccessService {

private final AccessConfigRepository accessConfigRepository;
private final RedisTemplate<String, Object> redisTemplate;
private final JwtTokenProvider jwtTokenProvider;

public AccessServiceImpl(AccessConfigRepository accessConfigRepository,
RedisTemplate<String, Object> redisTemplate,
JwtTokenProvider jwtTokenProvider) {
this.accessConfigRepository = accessConfigRepository;
this.redisTemplate = redisTemplate;
this.jwtTokenProvider = jwtTokenProvider;
}

@Override
public AccessTokenResponse authenticate(AccessRequest request) {
// 验证客户端凭据
AccessConfig config = accessConfigRepository.findByClientId(request.getClientId())
.orElseThrow(() -> new BusinessException("无效的客户端ID"));

if (!config.getClientSecret().equals(request.getClientSecret())) {
throw new BusinessException("无效的客户端密钥");
}

if (!config.getIsActive()) {
throw new BusinessException("客户端已被禁用");
}

// 生成访问令牌
String accessToken = generateAccessToken(config);
String refreshToken = generateRefreshToken(config);

// 存储令牌到Redis
String accessTokenKey = "access_token:" + request.getClientId();
String refreshTokenKey = "refresh_token:" + request.getClientId();

redisTemplate.opsForValue().set(accessTokenKey, accessToken, Duration.ofHours(1));
redisTemplate.opsForValue().set(refreshTokenKey, refreshToken, Duration.ofDays(7));

return AccessTokenResponse.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.tokenType("Bearer")
.expiresIn(3600)
.clientId(request.getClientId())
.build();
}

@Override
public AccessTokenResponse refreshToken(RefreshTokenRequest request) {
// 验证刷新令牌
if (!jwtTokenProvider.validateRefreshToken(request.getRefreshToken())) {
throw new BusinessException("无效的刷新令牌");
}

String clientId = jwtTokenProvider.getClientIdFromRefreshToken(request.getRefreshToken());

// 检查刷新令牌是否存在于Redis中
String refreshTokenKey = "refresh_token:" + clientId;
String storedRefreshToken = (String) redisTemplate.opsForValue().get(refreshTokenKey);

if (!request.getRefreshToken().equals(storedRefreshToken)) {
throw new BusinessException("刷新令牌已失效");
}

// 获取客户端配置
AccessConfig config = accessConfigRepository.findByClientId(clientId)
.orElseThrow(() -> new BusinessException("客户端不存在"));

// 生成新的访问令牌
String newAccessToken = generateAccessToken(config);

// 更新Redis中的访问令牌
String accessTokenKey = "access_token:" + clientId;
redisTemplate.opsForValue().set(accessTokenKey, newAccessToken, Duration.ofHours(1));

return AccessTokenResponse.builder()
.accessToken(newAccessToken)
.refreshToken(request.getRefreshToken())
.tokenType("Bearer")
.expiresIn(3600)
.clientId(clientId)
.build();
}

@Override
public ValidationResponse validateToken(TokenValidationRequest request) {
String token = request.getToken();

// 验证令牌格式
if (!jwtTokenProvider.validateToken(token)) {
return ValidationResponse.builder()
.valid(false)
.message("无效的令牌")
.build();
}

// 获取客户端ID
String clientId = jwtTokenProvider.getClientIdFromToken(token);

// 检查令牌是否存在于Redis中
String accessTokenKey = "access_token:" + clientId;
String storedToken = (String) redisTemplate.opsForValue().get(accessTokenKey);

if (!token.equals(storedToken)) {
return ValidationResponse.builder()
.valid(false)
.message("令牌已失效")
.build();
}

// 获取客户端配置
AccessConfig config = accessConfigRepository.findByClientId(clientId)
.orElse(null);

if (config == null || !config.getIsActive()) {
return ValidationResponse.builder()
.valid(false)
.message("客户端不存在或已被禁用")
.build();
}

return ValidationResponse.builder()
.valid(true)
.clientId(clientId)
.clientName(config.getClientName())
.accessType(config.getAccessType())
.allowedServices(config.getAllowedServices())
.allowedEndpoints(config.getAllowedEndpoints())
.build();
}

@Override
public ClientInfoResponse getClientInfo(String clientId) {
AccessConfig config = accessConfigRepository.findByClientId(clientId)
.orElseThrow(() -> new BusinessException("客户端不存在"));

return ClientInfoResponse.builder()
.clientId(config.getClientId())
.clientName(config.getClientName())
.accessType(config.getAccessType())
.allowedServices(config.getAllowedServices())
.allowedEndpoints(config.getAllowedEndpoints())
.rateLimit(config.getRateLimit())
.isActive(config.getIsActive())
.createdAt(config.getCreatedAt())
.updatedAt(config.getUpdatedAt())
.build();
}

@Override
public ClientInfoResponse updateClientConfig(String clientId, ClientConfigUpdateRequest request) {
AccessConfig config = accessConfigRepository.findByClientId(clientId)
.orElseThrow(() -> new BusinessException("客户端不存在"));

// 更新配置
if (request.getAllowedServices() != null) {
config.setAllowedServices(request.getAllowedServices());
}
if (request.getAllowedEndpoints() != null) {
config.setAllowedEndpoints(request.getAllowedEndpoints());
}
if (request.getRateLimit() != null) {
config.setRateLimit(request.getRateLimit());
}
if (request.getIsActive() != null) {
config.setIsActive(request.getIsActive());
}

AccessConfig savedConfig = accessConfigRepository.save(config);

return ClientInfoResponse.builder()
.clientId(savedConfig.getClientId())
.clientName(savedConfig.getClientName())
.accessType(savedConfig.getAccessType())
.allowedServices(savedConfig.getAllowedServices())
.allowedEndpoints(savedConfig.getAllowedEndpoints())
.rateLimit(savedConfig.getRateLimit())
.isActive(savedConfig.getIsActive())
.createdAt(savedConfig.getCreatedAt())
.updatedAt(savedConfig.getUpdatedAt())
.build();
}

@Override
public void revokeToken(TokenRevokeRequest request) {
String clientId = request.getClientId();

// 清除Redis中的令牌
String accessTokenKey = "access_token:" + clientId;
String refreshTokenKey = "refresh_token:" + clientId;

redisTemplate.delete(accessTokenKey);
redisTemplate.delete(refreshTokenKey);
}

private String generateAccessToken(AccessConfig config) {
Map<String, Object> claims = new HashMap<>();
claims.put("clientId", config.getClientId());
claims.put("clientName", config.getClientName());
claims.put("accessType", config.getAccessType().name());
claims.put("type", "access");

return jwtTokenProvider.createToken(claims, config.getClientId(), 3600000); // 1小时
}

private String generateRefreshToken(AccessConfig config) {
Map<String, Object> claims = new HashMap<>();
claims.put("clientId", config.getClientId());
claims.put("type", "refresh");

return jwtTokenProvider.createToken(claims, config.getClientId(), 604800000); // 7天
}
}

7. 服务间通信与集成

7.1 Feign客户端配置

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
// 用户服务客户端
@FeignClient(name = "user-service", fallback = UserServiceClientFallback.class)
public interface UserServiceClient {

@PostMapping("/api/users/authenticate")
AuthenticationResponse authenticate(@RequestBody AuthenticationRequest request);

@GetMapping("/api/users/{id}")
UserResponse getUser(@PathVariable("id") Long id);

@GetMapping("/api/users")
Page<UserResponse> getUsers(@RequestParam int page, @RequestParam int size);
}

// 用户服务降级处理
@Component
public class UserServiceClientFallback implements UserServiceClient {

@Override
public AuthenticationResponse authenticate(AuthenticationRequest request) {
return AuthenticationResponse.builder()
.authenticated(false)
.message("用户服务暂时不可用")
.build();
}

@Override
public UserResponse getUser(Long id) {
return UserResponse.builder()
.id(id)
.username("unknown")
.email("unknown@example.com")
.role(UserRole.GUEST)
.status(UserStatus.INACTIVE)
.build();
}

@Override
public Page<UserResponse> getUsers(int page, int size) {
return Page.empty();
}
}

// 产品服务客户端
@FeignClient(name = "product-service", fallback = ProductServiceClientFallback.class)
public interface ProductServiceClient {

@GetMapping("/api/products/{id}")
ProductResponse getProduct(@PathVariable("id") String id);

@GetMapping("/api/products")
Page<ProductResponse> getProducts(@RequestParam int page, @RequestParam int size);
}

// 支付服务客户端
@FeignClient(name = "payment-service", fallback = PaymentServiceClientFallback.class)
public interface PaymentServiceClient {

@PostMapping("/api/payments/process")
PaymentResponse processPayment(@RequestBody PaymentRequest request);

@PostMapping("/api/payments/refund")
RefundResponse processRefund(@RequestBody RefundRequest request);
}

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
// 消息发布者
@Component
public class MessagePublisher {

private final RabbitTemplate rabbitTemplate;

public MessagePublisher(RabbitTemplate rabbitTemplate) {
this.rabbitTemplate = rabbitTemplate;
}

public void publishOrderEvent(OrderEvent event) {
rabbitTemplate.convertAndSend("order.exchange", "order.created", event);
}

public void publishUserEvent(UserEvent event) {
rabbitTemplate.convertAndSend("user.exchange", "user.registered", event);
}

public void publishDeviceEvent(DeviceEvent event) {
rabbitTemplate.convertAndSend("device.exchange", "device.status.changed", event);
}
}

// 消息监听器
@Component
@RabbitListener(queues = "order.created.queue")
public class OrderEventListener {

private final NotificationService notificationService;

public OrderEventListener(NotificationService notificationService) {
this.notificationService = notificationService;
}

@RabbitHandler
public void handleOrderCreated(OrderEvent event) {
// 处理订单创建事件
notificationService.sendOrderCreatedNotification(event);
}
}

// 事件实体
@Data
@Builder
public class OrderEvent {
private Long orderId;
private String orderNumber;
private Long userId;
private OrderStatus status;
private BigDecimal totalAmount;
private LocalDateTime createdAt;
}

@Data
@Builder
public class UserEvent {
private Long userId;
private String username;
private String email;
private UserStatus status;
private LocalDateTime createdAt;
}

@Data
@Builder
public class DeviceEvent {
private Long deviceId;
private String deviceName;
private DeviceStatus status;
private LocalDateTime timestamp;
}

8. 监控与运维

8.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
// 监控配置
@Configuration
@EnableScheduling
public class MonitoringConfig {

@Bean
public MeterRegistry meterRegistry() {
return new SimpleMeterRegistry();
}

@Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}

@Bean
public CountedAspect countedAspect(MeterRegistry registry) {
return new CountedAspect(registry);
}
}

// 服务健康检查
@Component
public class ServiceHealthIndicator implements HealthIndicator {

private final UserServiceClient userServiceClient;
private final OrderServiceClient orderServiceClient;
private final DeviceServiceClient deviceServiceClient;

public ServiceHealthIndicator(UserServiceClient userServiceClient,
OrderServiceClient orderServiceClient,
DeviceServiceClient deviceServiceClient) {
this.userServiceClient = userServiceClient;
this.orderServiceClient = orderServiceClient;
this.deviceServiceClient = deviceServiceClient;
}

@Override
public Health health() {
Health.Builder builder = new Health.Builder();

// 检查用户服务
try {
userServiceClient.getUsers(0, 1);
builder.withDetail("user-service", "UP");
} catch (Exception e) {
builder.withDetail("user-service", "DOWN");
builder.down();
}

// 检查订单服务
try {
orderServiceClient.getUserOrders(1L, 0, 1, null);
builder.withDetail("order-service", "UP");
} catch (Exception e) {
builder.withDetail("order-service", "DOWN");
builder.down();
}

// 检查设备服务
try {
deviceServiceClient.getUserDevices(1L, 0, 1, null);
builder.withDetail("device-service", "UP");
} catch (Exception e) {
builder.withDetail("device-service", "DOWN");
builder.down();
}

return builder.build();
}
}

8.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
// 链路追踪配置
@Configuration
public class TracingConfig {

@Bean
public Sampler alwaysSampler() {
return Sampler.create(1.0f);
}

@Bean
public Sender sender() {
return OkHttpSender.create("http://zipkin:9411/api/v2/spans");
}

@Bean
public AsyncReporter<Span> spanReporter() {
return AsyncReporter.create(sender());
}

@Bean
public Tracing tracing() {
return Tracing.newBuilder()
.localServiceName("microservices-gateway")
.sampler(alwaysSampler())
.spanReporter(spanReporter())
.build();
}

@Bean
public Tracer tracer() {
return tracing().tracer();
}
}

9. 总结

微服务架构通过将单一应用程序分解为多个小型服务,实现了系统的模块化、可扩展性和可维护性。本文详细介绍的用户服务、API网关、设备服务、订单服务、接入服务等核心微服务,构成了一个完整的微服务生态系统。

9.1 架构优势

  1. 服务独立: 每个服务可以独立开发、部署和扩展
  2. 技术多样性: 不同服务可以使用最适合的技术栈
  3. 故障隔离: 单个服务的故障不会影响整个系统
  4. 团队自治: 不同团队可以独立负责不同的服务
  5. 持续交付: 支持快速迭代和持续部署

9.2 实施要点

  1. 服务拆分: 按照业务领域进行合理的服务拆分
  2. 数据管理: 每个服务拥有自己的数据存储
  3. 服务治理: 实现服务发现、负载均衡、熔断降级
  4. 监控运维: 建立完善的监控和日志系统
  5. 安全管控: 实现服务间认证和授权

9.3 最佳实践

  1. API设计: 遵循RESTful设计原则
  2. 错误处理: 实现统一的错误处理机制
  3. 配置管理: 使用配置中心管理服务配置
  4. 版本控制: 实现API版本管理
  5. 文档管理: 维护完整的API文档

通过本文的学习,您应该已经掌握了微服务架构的核心技术,能够设计和实现完整的微服务系统,为企业的数字化转型提供技术支撑。