feat: L2契约对齐-添加validation注解和全局异常处理 [AC-MCA-08][AC-MCA-12]
This commit is contained in:
parent
f09f22f447
commit
0786e6a040
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.wecom.robot.config;
|
||||||
|
|
||||||
|
import com.wecom.robot.dto.ApiResponse;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.validation.FieldError;
|
||||||
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.ConstraintViolationException;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
public ApiResponse<Void> handleValidationException(MethodArgumentNotValidException ex) {
|
||||||
|
String message = ex.getBindingResult().getFieldErrors().stream()
|
||||||
|
.map(FieldError::getDefaultMessage)
|
||||||
|
.collect(Collectors.joining("; "));
|
||||||
|
log.warn("参数校验失败: {}", message);
|
||||||
|
return ApiResponse.error(400, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ConstraintViolationException.class)
|
||||||
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
|
public ApiResponse<Void> handleConstraintViolationException(ConstraintViolationException ex) {
|
||||||
|
String message = ex.getConstraintViolations().stream()
|
||||||
|
.map(ConstraintViolation::getMessage)
|
||||||
|
.collect(Collectors.joining("; "));
|
||||||
|
log.warn("约束校验失败: {}", message);
|
||||||
|
return ApiResponse.error(400, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
public ApiResponse<Void> handleException(Exception ex) {
|
||||||
|
log.error("服务器内部错误", ex);
|
||||||
|
return ApiResponse.error(500, "服务器内部错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
|
@ -31,7 +32,8 @@ public class SessionController {
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public ApiResponse<List<SessionInfo>> getSessions(
|
public ApiResponse<List<SessionInfo>> getSessions(
|
||||||
@RequestParam(required = false) String status,
|
@RequestParam(required = false) String status,
|
||||||
@RequestParam(required = false) String csId) {
|
@RequestParam(required = false) String csId,
|
||||||
|
@RequestParam(required = false) String channelType) {
|
||||||
LambdaQueryWrapper<Session> query = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<Session> query = new LambdaQueryWrapper<>();
|
||||||
|
|
||||||
if (status != null) {
|
if (status != null) {
|
||||||
|
|
@ -42,6 +44,10 @@ public class SessionController {
|
||||||
query.eq(Session::getManualCsId, csId);
|
query.eq(Session::getManualCsId, csId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channelType != null) {
|
||||||
|
query.eq(Session::getChannelType, channelType);
|
||||||
|
}
|
||||||
|
|
||||||
query.orderByDesc(Session::getUpdatedAt);
|
query.orderByDesc(Session::getUpdatedAt);
|
||||||
|
|
||||||
List<Session> sessions = sessionMapper.selectList(query);
|
List<Session> sessions = sessionMapper.selectList(query);
|
||||||
|
|
@ -51,6 +57,7 @@ public class SessionController {
|
||||||
info.setSessionId(session.getSessionId());
|
info.setSessionId(session.getSessionId());
|
||||||
info.setCustomerId(session.getCustomerId());
|
info.setCustomerId(session.getCustomerId());
|
||||||
info.setKfId(session.getKfId());
|
info.setKfId(session.getKfId());
|
||||||
|
info.setChannelType(session.getChannelType());
|
||||||
info.setStatus(session.getStatus());
|
info.setStatus(session.getStatus());
|
||||||
info.setManualCsId(session.getManualCsId());
|
info.setManualCsId(session.getManualCsId());
|
||||||
info.setCreatedAt(session.getCreatedAt());
|
info.setCreatedAt(session.getCreatedAt());
|
||||||
|
|
@ -87,6 +94,7 @@ public class SessionController {
|
||||||
info.setSessionId(session.getSessionId());
|
info.setSessionId(session.getSessionId());
|
||||||
info.setCustomerId(session.getCustomerId());
|
info.setCustomerId(session.getCustomerId());
|
||||||
info.setKfId(session.getKfId());
|
info.setKfId(session.getKfId());
|
||||||
|
info.setChannelType(session.getChannelType());
|
||||||
info.setStatus(session.getStatus());
|
info.setStatus(session.getStatus());
|
||||||
info.setManualCsId(session.getManualCsId());
|
info.setManualCsId(session.getManualCsId());
|
||||||
info.setCreatedAt(session.getCreatedAt());
|
info.setCreatedAt(session.getCreatedAt());
|
||||||
|
|
@ -120,12 +128,9 @@ public class SessionController {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/{sessionId}/accept")
|
@PostMapping("/{sessionId}/accept")
|
||||||
public ApiResponse<Void> acceptSession(@PathVariable String sessionId, @RequestBody AcceptSessionRequest request) {
|
public ApiResponse<Void> acceptSession(
|
||||||
String csId = request.getCsId();
|
@PathVariable String sessionId,
|
||||||
if (csId == null || csId.isEmpty()) {
|
@Valid @RequestBody AcceptSessionRequest request) {
|
||||||
return ApiResponse.error(400, "客服ID不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
Session session = sessionMapper.selectById(sessionId);
|
Session session = sessionMapper.selectById(sessionId);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
return ApiResponse.error(404, "会话不存在");
|
return ApiResponse.error(404, "会话不存在");
|
||||||
|
|
@ -135,14 +140,16 @@ public class SessionController {
|
||||||
return ApiResponse.error(400, "会话状态不正确");
|
return ApiResponse.error(400, "会话状态不正确");
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionManagerService.acceptTransfer(sessionId, csId);
|
sessionManagerService.acceptTransfer(sessionId, request.getCsId());
|
||||||
webSocketService.notifySessionAccepted(sessionId, csId);
|
webSocketService.notifySessionAccepted(sessionId, request.getCsId());
|
||||||
|
|
||||||
return ApiResponse.success(null);
|
return ApiResponse.success(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/{sessionId}/message")
|
@PostMapping("/{sessionId}/message")
|
||||||
public ApiResponse<Void> sendMessage(@PathVariable String sessionId, @RequestBody SendMessageRequest request) {
|
public ApiResponse<Void> sendMessage(
|
||||||
|
@PathVariable String sessionId,
|
||||||
|
@Valid @RequestBody SendMessageRequest request) {
|
||||||
Session session = sessionMapper.selectById(sessionId);
|
Session session = sessionMapper.selectById(sessionId);
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
return ApiResponse.error(404, "会话不存在");
|
return ApiResponse.error(404, "会话不存在");
|
||||||
|
|
@ -159,7 +166,7 @@ public class SessionController {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return ApiResponse.error("消息发送失败");
|
return ApiResponse.error(500, "消息发送失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionManagerService.saveMessage(
|
sessionManagerService.saveMessage(
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,13 @@ package com.wecom.robot.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class AcceptSessionRequest {
|
public class AcceptSessionRequest {
|
||||||
|
|
||||||
|
@NotBlank(message = "客服ID不能为空")
|
||||||
|
@Size(min = 1, max = 64, message = "客服ID长度必须在1-64之间")
|
||||||
private String csId;
|
private String csId;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ public class ApiResponse<T> {
|
||||||
|
|
||||||
public static <T> ApiResponse<T> success(T data) {
|
public static <T> ApiResponse<T> success(T data) {
|
||||||
ApiResponse<T> response = new ApiResponse<>();
|
ApiResponse<T> response = new ApiResponse<>();
|
||||||
response.setCode(200);
|
response.setCode(0);
|
||||||
response.setMessage("success");
|
response.setMessage("success");
|
||||||
response.setData(data);
|
response.setData(data);
|
||||||
return response;
|
return response;
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,31 @@ package com.wecom.robot.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class MessageInfo {
|
public class MessageInfo {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(min = 1, max = 128)
|
||||||
private String msgId;
|
private String msgId;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(min = 1, max = 64)
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
private String senderType;
|
private String senderType;
|
||||||
|
|
||||||
|
@Size(max = 64)
|
||||||
private String senderId;
|
private String senderId;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(min = 1, max = 4096)
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
private String msgType;
|
private String msgType;
|
||||||
private LocalDateTime createdAt;
|
|
||||||
|
private java.time.LocalDateTime createdAt;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,15 @@ package com.wecom.robot.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SendMessageRequest {
|
public class SendMessageRequest {
|
||||||
|
|
||||||
|
@NotBlank(message = "消息内容不能为空")
|
||||||
|
@Size(min = 1, max = 4096, message = "消息内容长度必须在1-4096之间")
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
private String msgType;
|
private String msgType;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,43 @@ package com.wecom.robot.dto;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class SessionInfo {
|
public class SessionInfo {
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(min = 1, max = 64)
|
||||||
private String sessionId;
|
private String sessionId;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
@Size(min = 1, max = 64)
|
||||||
private String customerId;
|
private String customerId;
|
||||||
|
|
||||||
|
@Size(max = 64)
|
||||||
private String kfId;
|
private String kfId;
|
||||||
|
|
||||||
|
@Size(max = 64)
|
||||||
|
private String channelType;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
private String status;
|
private String status;
|
||||||
|
|
||||||
|
@Size(max = 64)
|
||||||
private String manualCsId;
|
private String manualCsId;
|
||||||
private LocalDateTime createdAt;
|
|
||||||
private LocalDateTime updatedAt;
|
@Size(max = 4096)
|
||||||
private String metadata;
|
|
||||||
private int messageCount;
|
|
||||||
private String lastMessage;
|
private String lastMessage;
|
||||||
|
|
||||||
private LocalDateTime lastMessageTime;
|
private LocalDateTime lastMessageTime;
|
||||||
|
|
||||||
|
private int messageCount;
|
||||||
|
|
||||||
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
|
private String metadata;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue