BFF+CoreService架构下DTO和VO的含义和使用方式

📅 2026/7/8 2:25:19
BFF+CoreService架构下DTO和VO的含义和使用方式
1BFFCoreService的含义BFF:BackEnd For FrontEnd这是一个springboot服务但是不同之处在于它是专门服务于前端的意思是处理前端请求然后调用CoreService的方法完成业务逻辑。他更侧重于处理前端请求更加具体的业务逻辑是CoreService在做。以下是BFF的service层可以看出确实是在转发请求到CoreService服务//这是service层 Service public class AuthServiceImpl implements AuthService { Resource //引入的是User模块暴露的UserFeign类 private UserFeign userFeign; Override public UserBaseLoginVO login(UserLoginRequestVO userLoginRequestVO) { //处理VO为DTO方便后续服务的调用 UserLoginDTO userDTO BeanUtil.copyProperties(userLoginRequestVO, UserLoginDTO.class); //调用User模块的login方法 UserLoginResponseDTO userLoginResponseDTO userFeign.login(userDTO); //处理后return UserBaseLoginVO userLoginVO new UserBaseLoginVO(); userLoginVO.setToken(userLoginResponseDTO.getToken()); userLoginVO.setInfoVO(BeanUtil.copyProperties(userLoginResponseDTO.getInfoVO(), UserBaseInfoVO.class)); return userLoginVO; } }2CoreService核心业务服务掌管了Entity机密的服务。侧重于具体的业务实现而不是Http协议。返回值也不是RT了而是更加具体的对象以下是一个服务的示例这个服务用于实现登录业务里面是具体的数据库表操作和逻辑处理。Service public class UserServiceImpl extends ServiceImplUserMapper, UserEntity implements UserFeign { Resource private JwtUtil jwtUtil; Override public UserLoginResponseDTO login(UserLoginDTO userLoginDTO) { LoginExceptionEnum accountPasswordError LoginExceptionEnum.ACCOUNT_PASSWORD_ERROR; //1,获取账号密码 String account userLoginDTO.getAccount(); ​ //1.5如果账密不正确那就返回错误 if((account.contains( )||userLoginDTO.getPassword().contains( )) ||(account.length()20||account.length()5)){ throw new MyWebException(accountPasswordError); } //2,查找账号如果不存在直接返回错误值 UserEntity userEntity lambdaQuery().eq(UserEntity::getAccount, account).one(); if(ObjectUtil.isEmpty(userEntity)){ throw new MyWebException(accountPasswordError); ​ } //3,查到到用密码加盐 加密 String salt userEntity.getSalt(); String md5 DigestUtil.md5Hex(userLoginDTO.getPassword() salt); ; //4,和数据库的密码比对 String password userEntity.getPassword(); //5,比对失败返回密码错误 if(!StrUtil.equals(md5,password)){ throw new MyWebException(accountPasswordError); } //6,成功生成token封装实体类一并返回 UserInfoDTO userInfoVO new UserInfoDTO(); userInfoVO.setUserName(userEntity.getUserName()); userInfoVO.setAccount(userEntity.getAccount()); userInfoVO.setPhoneNumber(userEntity.getPhoneNumber()); userInfoVO.setId(userEntity.getId()); String tokennull; try { UserInfoDTO userInfoDTO BeanUtil.copyProperties(userEntity, UserInfoDTO.class); token jwtUtil.generateToken(userInfoDTO); } catch (Exception e) { //7,token生成如果失败直接抛异常全局异常处理器处理后返回给前端。 throw new RuntimeException(e); } //8封装最后的login vo返回 UserLoginResponseDTO userLoginResponseDTO new UserLoginResponseDTO(); userLoginResponseDTO.setInfoVO(userInfoVO); userLoginResponseDTO.setToken(token); ​ return userLoginResponseDTO; } }3dto、vo的含义和使用方式dto叫做数据传输对象主要有两个作用一个是限制前端的输入让输入框死于dto限制的字段如CourierLoginDTO另一个是充当安全的数据传输对象​ NotBlank(message 账号不能为空) Size(min 3,max20,message 账号长度错误!) /** * 账号 */ private String account; NotBlank(message 密码不能为空) /** * 密码 */ private String password;这是一个快递员dto类限制登录字段只能是账密不能输入其他如balance字段和role字段不然如果处理不当用户可以随意修改余额(balance)和角色(role)字段但是在BFFCoreService下由于BFF服务侧重于处理前端服务且为了防止BFF服务的请求DTO和CoreService的DTO数据传输对象混淆所以把DTO改为了更加适合前段的VO。如下是BFF的controller层... public class AuthController { ... ​ PostMapping(/login) //注意这里的请求参数变成了VO而不是dto public ResponseEntityUserBaseLoginVO login(RequestBody Valid UserLoginRequestVO userLoginRequestVO){ UserBaseLoginVO userBaseLoginVO authService.login(userLoginRequestVO); return ResponseEntity.success(userBaseLoginVO); } ​ }因此dto的作用少了一个不能限制前端那就只能充当数据传输对象用于屏蔽敏感字段如密码和盐值。因此在CoreService服务中基本上都是DTO的身影了如下图是快递员CoreService的后端Feign具体不用看主要看请求参数和方法返回值public interface CourierFeign { //这边都是DTO作为数据的传输对象了 CourierLoginResponseDTO login (CourierLoginRequestDTO courierLoginRequestDTO); ​ BasePageDTOCourierDTO getCourierList(BasePageRequestDTO basePageRequestDTO); ​ void create(CourierCreateDTO courierCreateDTO); ​ void updateCourier(CourierUpdateDTO courierUpdateDTO); ​ CourierDTO getById(Long courierId); ​ void deleteCourier(Long id); }这样的架构下VO和DTO大幅度分离前端处理服务和核心业务界限清晰。