【面试宝典】线上问题逆向分析1

问题一:前后端联动互相干扰(字段覆盖)

问题根因:数据所有权边界模糊,缺乏数据防护机制。

角色 具体改进措施
后端 1. 数据分层防御 : - 创建ContractSaveRequestDTO,仅包含前端可修改字段 - 自动管理字段(id、createTime、creator等)坚决不放入DTO - 使用@JsonIgnore防止敏感字段意外序列化到前端 2. 字段权限控制 : - Service层显式设置后端管理字段:entity.setCreateTime(now()) - 使用Bean Validation验证入参字段范围 3. 接口文档化:Swagger明确标注每个字段的读写权限
前端 1. 数据提交规范 : - 提交前使用lodash.omit过滤只读字段 - 创建专门的submitData对象,不与页面显示数据混用 2. 请求拦截器 :全局axios拦截器中添加字段过滤逻辑 3. 代码审查清单:将"不提交只读字段"加入团队Code Review清单
QA 1. 契约测试 : - 使用Pact验证接口字段权限定义 - 自动化检查后端不会返回敏感字段 2. 安全专项测试 : - 使用Burp Suite尝试修改只读字段,验证后端防护 - 设计"字段覆盖"专项测试用例 3. 自动化回归:将字段权限检查加入API自动化测试

技术实现示例

javascript 复制代码
// 前端 - 数据清洗
const submitData = {
  ...formData,
  // 显式排除后端管理字段
  id: undefined,
  createTime: undefined, 
  creator: undefined
}

// 后端 - 清晰的DTO设计
public class ContractSaveRequest {
    @NotBlank
    private String title;       // 前端可修改
    
    @NotBlank  
    private String content;     // 前端可修改
    
    // 不包含createTime、creator等后端字段
}

public class ContractService {
    public Contract saveContract(ContractSaveRequest request) {
        Contract entity = convertToEntity(request);
        // 后端确保设置管理字段
        entity.setCreateTime(LocalDateTime.now());
        entity.setCreator(getCurrentUser());
        return repository.save(entity);
    }
}

问题二:Word转PDF失败(特殊格式兼容性)

问题根因:对复杂格式文档兼容性不足,缺乏渐进式降级方案。

角色 具体改进措施
后端 1. 多引擎降级策略 : - 策略模式:Aspose → iText → LibreOffice 依次尝试 - 基于历史成功率智能选择最优引擎 2. 文档预处理 : - 检测文档复杂度,复杂文档直接使用最强引擎 - 移除异常格式、标准化字体 3. 异步化处理 : - 提交转换任务到RabbitMQ异步处理 - 提供任务状态查询接口 /api/tasks/{taskId}/status
前端 1. 用户体验优化 : - 上传时检测文件大小和类型,过大文件提前警告 - 转换中显示进度条和预计等待时间 2. 降级体验 : - 转换失败时提供"下载原Word文件"备选方案 - 复杂文档提示"转换时间较长,请耐心等待" 3. 状态轮询:定时查询转换状态,成功自动刷新
QA 1. 兼容性测试矩阵 : - 构建复杂格式测试库(表格、图表、公式、特殊字体) - 定期运行全引擎兼容性测试套件 2. 混沌工程测试 : - 模拟各转换引擎宕机、超时、内存溢出 - 验证降级策略和系统韧性 3. 性能基准测试:建立各引擎的性能基准,监控性能衰减

技术实现示例

java 复制代码
// 后端 - 多引擎降级策略
@Service
@Slf4j
public class DocumentConverter {
    private final List<ConverterStrategy> strategies;
    
    public ConversionResult convertToPdf(File wordFile) {
        // 预处理:检测文档复杂度
        DocumentComplexity complexity = analyzeComplexity(wordFile);
        
        for (ConverterStrategy strategy : getStrategyOrder(complexity)) {
            try {
                log.info("Trying converter: {}", strategy.getName());
                ConversionResult result = strategy.convert(wordFile);
                metrics.recordSuccess(strategy.getName());
                return result;
            } catch (UnsupportedFormatException e) {
                log.warn("{} unsupported format, trying next", strategy.getName());
                continue; // 格式不支持,继续尝试
            } catch (ConversionException e) {
                log.warn("{} conversion failed, trying next", strategy.getName());
                metrics.recordFailure(strategy.getName());
                // 其他异常,继续尝试
            }
        }
        // 全部失败时的业务降级
        return ConversionResult.fallback("转换失败,请下载Word原文件");
    }
}

问题三:接口幂等导致合同重复创建

问题根因:幂等性保障机制不完整,第三方调用链断裂。

角色 具体改进措施
后端 1. 统一幂等框架 : - 开发@Idempotent注解+AOP切面 - Redis原子操作(SETNX)实现防重校验 2. 第三方调用规范 : - 主动生成幂等键idempotentKey = "contract_"+bizId+"_"+MD5(参数) - 调用第三方时强制校验幂等键传递 3. 多级防重:数据库唯一索引 + Redis防重 + 业务逻辑校验
前端 1. 生成幂等键 : - 每次提交生成唯一Idempotency-Key(UUIDv4) - 放在HTTP Header中:Idempotency-Key: <uuid> 2. 交互防重 : - 提交后立即禁用按钮 + Loading状态 - 路由跳转时清理本地幂等键 3. 错误处理:接收到幂等错误时提示"请求已提交,请勿重复操作"
QA 1. 并发专项测试 : - JMeter模拟相同请求并发提交(相同幂等键) - 验证是否只成功一次且结果一致 2. 幂等键有效性测试 : - 测试页面刷新、浏览器回退等场景的幂等性 - 验证幂等键生成规则的全局唯一性 3. 第三方集成测试 : - Mock第三方服务验证幂等键传递正确性 - 测试第三方超时、重试场景下的系统行为

技术实现示例

java 复制代码
// 后端 - 幂等框架
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
    String key() default "";     // 幂等键表达式
    long expireTime() default 10 * 60; // 过期时间(秒)
}

@Aspect
@Component
@Slf4j
public class IdempotentAspect {
    
    @Around("@annotation(idempotent)")
    public Object checkIdempotent(ProceedingJoinPoint joinPoint, 
                                  Idempotent idempotent) throws Throwable {
        String key = generateKey(joinPoint, idempotent);
        
        // Redis原子操作防重
        Boolean firstRequest = redisTemplate.opsForValue()
            .setIfAbsent(key, "PROCESSING", idempotent.expireTime(), TimeUnit.SECONDS);
            
        if (Boolean.FALSE.equals(firstRequest)) {
            // 重复请求,返回缓存结果
            Object cachedResult = redisTemplate.opsForValue().get(key + "_RESULT");
            if (cachedResult != null) {
                log.info("Return cached result for idempotent key: {}", key);
                return cachedResult;
            }
            throw new IdempotentException("请求正在处理中,请勿重复提交");
        }
        
        try {
            Object result = joinPoint.proceed();
            // 缓存成功结果
            redisTemplate.opsForValue()
                .set(key + "_RESULT", result, idempotent.expireTime(), TimeUnit.SECONDS);
            return result;
        } catch (Exception e) {
            // 业务失败,删除幂等键允许重试
            redisTemplate.delete(key);
            throw e;
        }
    }
}

// 第三方调用 - 主动传递幂等键
@Service
public class ThirdPartyService {
    public void callExternalService(Contract contract) {
        // 主动生成并传递幂等键
        String idempotentKey = "contract_" + contract.getId() + "_" + 
                              DigestUtils.md5DigestAsHex(contract.toString().getBytes());
        
        ThirdPartyRequest request = ThirdPartyRequest.builder()
            .idempotentKey(idempotentKey)  // 关键:主动传递
            .data(contract.getData())
            .build();
            
        thirdPartyClient.invoke(request);
    }
}
相关推荐
洛卡卡了9 小时前
我们在用 AI 写代码时,为什么建议要好好维护 AGENTS.md 呢?
面试·agent·claude
PBitW9 小时前
GPT训练我的第三天,明白了应该咋说满分回答!😕😕😕
前端·javascript·面试
自由路飞16 小时前
RAG 混合检索深挖:BM25 和向量分数为什么不能直接相加?
面试
未秃头的程序猿16 小时前
告别"if-else地狱"!Java 21模式匹配,代码优雅了10倍
java·后端·面试
阳光是sunny1 天前
Vue 项目怎么做用户行为全链路监控?轻量插件方案详解
前端·面试·架构
蝎子莱莱爱打怪1 天前
DSpark 讲透:DeepSeek 不换模型,硬把 V4 提速 85%,是怎么做到的?
人工智能·面试·程序员
程序员七平2 天前
面试官:你说你Vibe Coding手拿把掐,那 Claude Code 用户级、项目级、本地级配置怎么隔离?
面试
葫芦和十三2 天前
图解 MongoDB 17|大集合与工作集:数据超过内存怎么办
后端·mongodb·面试
葫芦和十三2 天前
图解 MongoDB 18|复制集拓扑:Primary、Secondary 和 Arbiter 的分工
后端·mongodb·面试
葫芦和十三2 天前
图解 MongoDB 15|journal 与持久化:写入怎么不丢,崩溃怎么恢复
后端·mongodb·面试