【问题标题】:Springboot component state is kept when making new request.. Concurrency issue?发出新请求时保持Springboot组件状态..并发问题?
【发布时间】:2021-03-28 16:32:07
【问题描述】:

我有一个 SpringBoot 应用程序,它通过 @RestController 公开一个简单的 REST-api。它需要文件上传,并尝试从上传的 excel 文件中读取值。

问题是某些组件的“状态”似乎没有在新请求上重置,就像它是某种并发问题一样。我似乎无法弄清楚。就像我在第一个请求之后发出新的后续请求时,前一个请求的值仍然挂在 ImportProcessor 和后续对象中,它没有被重置,我不知道为什么..

应用程序的服务层@Autowires 一个“ImportProcessor”组件,它有很多通过它的方法修改的字段。示例:

@Component
@NoArgsConstructor
@Slf4j
public class ImportProcessor {

    public static STATE processState = STATE.READY;
    
    @Autowired
    RegulativImporter regulativImporter;

    @Autowired
    DatabaseImporter databaseImporter;

    Sheet strekning;
    Sheet strekning_periode;

    HashMap<Long, TakstkategoriEntity> successfulTakstkategori;
    HashMap<Long, RegulativEntity> successfulRegulativ;
    HashMap<Long, TakstEntity> successfulTakst;

        public ImportJobInfo handleStartProcessingRequest(Workbook workbook) throws FailedToStartProcessingException {
        if (processState == STATE.READY) {
            setProcessState(STATE.IMPORTING);
            ImportJobInfo importJobInfo = startProcessing(workbook);
            cleanUpState();
            return importJobInfo;
        } else {
            throw new FailedToStartProcessingException("Failed to start processing because of insufficient state:",
                processState);
        }
    }

   // Methods that modify and set these objects.. Changes state based on action, initialize hashMaps..
   // Method that inserts part of the Hashmaps to a database using DatabaseImporter
}

这里是调用服务:

@Service
@Slf4j
public class FergeregisterImportServiceImpl implements FergeregisterImportService {

    @Autowired
    ImportProcessor importProcessor;

    @Override
    public ImportJobInfo startImportJob(MultipartFile file) throws FailedToStartProcessingException {
        
        InputStream excelInputStream;
        Workbook workbook;
        ImportJobInfo importJobInfo = null;

        try {
            excelInputStream = file.getInputStream();
            workbook = new XSSFWorkbook(excelInputStream);
            log.info("Successfully converted Excel inputstream to Apache-POI workbook.");
        } catch (IOException e) {
            log.error(e.getMessage() + " | cause: " + e.getCause());
            throw new FailedToStartProcessingException("Failed to convert Excel inputstream to Apache-POI workbook.",
                STATE.FAILED);
        }

        try {
            importJobInfo = importProcessor.handleStartProcessingRequest(workbook);
        } catch (FailedToStartProcessingException e) {
            log.error(e.getMessage(), importProcessor.getProcessState());
            throw e;
        }

        return importJobInfo;
    }
   // Some other methods..
}

如果我不@Autowire ImportProcessor,它可以正常工作并且我没有并发问题。但是,ImportService 似乎绝对不可能调用 CrudRepository 接口的@Autowired DatabaseImporter

如果我能确保 ImportProcessor 对每个新请求都有新的开始,那么一切都会按预期工作。我真的希望我能在这里得到一些提示。谢谢!

【问题讨论】:

    标签: spring-boot concurrency components state autowired


    【解决方案1】:

    如果你没有指定 bean 范围,Spring Boot 是基于 Singleton 模型的,这意味着当你 @Autowired 时指定为 bean 的每个组件(@Component、@Service 或其他),无论在任何地方,它将始终是同一个实例,这就是您的状态不会重置的原因。

    希望这有助于回答您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-23
      • 1970-01-01
      • 2014-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多