You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 50用户压测返回其他用户数据、空指针异常如何解决?

问题根因

你遇到的并发串数据、空指针问题核心是Spring Bean作用域使用错误:默认@Component标注的类都是单例(singleton),整个应用运行周期内仅存在一个实例。你将Employee、EmployeePerformance这类承载请求业务数据的POJO声明为单例Bean,还直接在Controller、Service中通过@Autowired注入全局使用,多并发请求时不同线程会同时修改同一个实例的属性,就会出现数据互相覆盖、拿到其他用户信息的情况,甚至属性赋值到一半被其他线程修改就会触发空指针异常。

具体问题点

  • Controller中@Autowired注入的Employee是全局单例,每次请求调用set方法赋值时都会覆盖该实例的原有值,并发场景下多个请求同时赋值,后续逻辑自然会拿到其他用户的参数
  • Service中@Autowired注入的EmployeePerformance是全局单例,且你将请求返回的结果赋值给了类成员变量this.empPerformance,多线程同时调用时会互相覆盖该成员变量的指向,也会导致数据错乱
修改方案
  1. 移除业务数据类的@Component注解,这类纯数据承载的POJO不需要交给Spring管理,每次使用时直接new新实例即可
// 删除Employee、EmployeePerformance类上的@Component注解
public class Employee {
    // 原有属性、get/set方法全部保留
}

public class EmployeePerformance {
    // 原有属性、get/set方法全部保留
}
  1. Controller中不要注入Employee,每次请求直接创建新实例,保证线程隔离
@RequestMapping("/employee")
public class EmployeeController {

    @Autowired
    EmployeeService employeeservice;
    
    // 删除这行注入代码
    // @Autowired
    // Employee employee;
    
    @RequestMapping("/getDetails")
    public void getEmployeeDetails() throws HttpException, IOException, JAXBException {
        // 每次请求新建独立的Employee实例
        Employee employee = new Employee();
        employee.setEmpId("100");
        employee.setEmpName("Nuno");
        employee.setDept("Research");
        employee.setLocation("India");
        
        EmployeePerformance emp = employeeservice.EmployeeDetails(employee);
        System.out.println(emp.toString());
    }
}
  1. Service中删除EmployeePerformance的成员变量声明和注入代码,所有请求相关的变量都放在方法内部定义,避免多线程共享
@Component
public class EmployeeService {

    // 删除这两行成员变量代码
    // @Autowired
    // EmployeePerformance empPerformance;
    
    @Autowired
    private AutowireCapableBeanFactory beanFactory;
    
    public EmployeePerformance EmployeeDetails(Employee emp) throws HttpException, IOException, JAXBException {
        // 直接返回方法调用结果,不需要赋值给类成员变量
        return getDetails(emp);
    }

    private EmployeePerformance getDetails(Employee emp) throws HttpException, IOException, JAXBException {
        String result;
        String url=emp.getEmpName();
        
        HttpClient client = new HttpClient();
        GetMethod method = new GetMethod(url);
        method.addRequestHeader("3454362523", emp.getEmpId());
        
        client.executeMethod(method);
        result = method.getResponseBodyAsString();
        
        JAXBContext jaxbContext = JAXBContext.newInstance(EmployeePerformance.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        
        EmployeePerformance empPerformance = (EmployeePerformance) jaxbUnmarshaller
                .unmarshal(new InputSource(new StringReader(result)));
        
        empPerformance.setProject("Banking");
        empPerformance.setRating("Good");
        
        return empPerformance;
    }
}
  1. 可选优化:如果确实需要将POJO交给Spring管理,给对应类加上@Scope("prototype")注解,设置为原型作用域,每次注入都会创建新的实例;不过对于纯数据类,更推荐直接new,性能更高逻辑也更清晰。

内容的提问来源于stack exchange,提问作者Krishna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 01:18:03