Workbook workbook = WorkbookFactory.create(file.getInputStream());造成资源泄露怎么解决
时间: 2024-12-12 22:27:56 浏览: 12
当你通过`WorkbookFactory.create()`方法创建`Workbook`对象并依赖于文件输入流(如`file.getInputStream()`),如果处理不当,可能会导致输入流未关闭,进而引发资源泄露。为了避免这种情况,你可以按照以下步骤来管理资源:
1. 使用try-with-resources语句:这是一种自动管理文件流的Java特性,当代码块结束时,会自动关闭流,例如:
```java
try (InputStream inputStream = file.getInputStream();
Workbook workbook = WorkbookFactory.create(inputStream)) {
// 使用workbook...
} catch (IOException e) {
// 错误处理
}
```
2. 显式关闭:如果没有使用try-with-resources,记得在完成操作后手动关闭流:
```java
InputStream inputStream = file.getInputStream();
Workbook workbook = WorkbookFactory.create(inputStream);
// ...其他操作...
try {
inputStream.close(); // 关闭输入流
} finally {
workbook.close(); // 关闭workbook
}
```
确保无论哪种方式,都在合适的位置释放了资源,以防止内存泄漏。
相关问题
@RequestMapping(value = "/excel", method = RequestMethod.POST) @ResponseBody public String uploadExcel(@RequestParam("file") MultipartFile file, Model model) { try { List<People> employees = new ArrayList<>(); InputStream inputStream = file.getInputStream(); Workbook workbook = WorkbookFactory.create(inputStream); Sheet sheet = workbook.getSheetAt(0); for (int i = 1; i <= sheet.getLastRowNum(); i++) { Row row = sheet.getRow(i); if (row != null) { String name = row.getCell(0).getStringCellValue(); int age = (int) row.getCell(1).getNumericCellValue(); String sex = row.getCell(2).getStringCellValue(); People employee; int bed = (int) row.getCell(3).getNumericCellValue(); String str=Integer.toString(bed); int room_id =(int) row.getCell(4).getNumericCellValue(); if(sex.equals("女")) { employee = new People(name, age, "1", str,room_id); }else { employee = new People(name, age, "0", str,room_id); } employees.add(employee); } } model.addAttribute("employees", employees); for (People employee : employees) { peopleService.PeopleAdd1(employee); } return "result"; } catch (IOException | EncryptedDocumentException e) { e.printStackTrace(); } return "error";
这是一个使用Spring MVC框架进行Excel文件上传的Java代码。通过@RequestMapping注解指定请求路径和请求方法,@RequestParam注解获取上传的文件,@ResponseBody注解表示返回的是字符串类型的数据。在方法中,首先获取上传的Excel文件,然后通过WorkbookFactory类创建Workbook对象,获取Sheet对象,遍历Sheet中每一行数据,获取单元格数据并将其放入People对象中,最后将People对象添加到List集合中。最后,将List集合中的所有People对象添加到数据库中,并返回"result"字符串。如果发生异常,则返回"error"字符串。
帮我用springboot写一个项目,需求是:1.用户点击按钮上传excel文件,2.把excel文件存到数据库,3.把excel其中的一些数据进行修改和删除,4.excel文件支持多行表头,5.最后输出修改后的excel文件,给我看看各代码的结构还有详细代码
好的,我可以帮你实现这个需求。首先我们需要创建一个Spring Boot项目,可以使用Spring Initializr快速创建一个基础项目。
项目结构:
```
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── demo
│ │ │ ├── controller
│ │ │ │ └── ExcelController.java
│ │ │ ├── model
│ │ │ │ └── ExcelData.java
│ │ │ ├── repository
│ │ │ │ └── ExcelDataRepository.java
│ │ │ ├── service
│ │ │ │ ├── ExcelDataService.java
│ │ │ │ └── ExcelDataServiceImpl.java
│ │ │ └── utils
│ │ │ ├── ExcelUtils.java
│ │ │ ├── FileStorageException.java
│ │ │ └── FileStorageProperties.java
│ │ ├── resources
│ │ │ ├── static
│ │ │ │ └── index.html
│ │ │ ├── templates
│ │ │ └── application.properties
│ │ └── resources
│ └── test
│ └── java
│ └── com
│ └── example
│ └── demo
│ └── DemoApplicationTests.java
└── pom.xml
```
接下来我们先来看一下代码实现:
1. ExcelController.java
该类为控制器类,主要用于接收前端的请求并返回相应的结果。
```java
@RestController
public class ExcelController {
@Autowired
private ExcelDataService excelDataService;
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
try {
excelDataService.store(file);
return ResponseEntity.status(HttpStatus.OK).body("File uploaded successfully!");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("Fail to upload file!");
}
}
@GetMapping("/download")
public ResponseEntity<Resource> downloadFile() {
String filename = "output.xlsx";
Resource resource = excelDataService.loadFileAsResource(filename);
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
@PostMapping("/modify")
public ResponseEntity<String> modifyData(@RequestBody List<ExcelData> dataList) {
try {
excelDataService.modifyData(dataList);
return ResponseEntity.status(HttpStatus.OK).body("Data modified successfully!");
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body("Fail to modify data!");
}
}
}
```
2. ExcelDataService.java / ExcelDataServiceImpl.java
该类为服务类,主要用于处理上传/下载/修改文件的相关操作。
```java
public interface ExcelDataService {
void store(MultipartFile file);
Resource loadFileAsResource(String filename);
void modifyData(List<ExcelData> dataList);
}
@Service
public class ExcelDataServiceImpl implements ExcelDataService {
private final Path fileStorageLocation;
private final ExcelDataRepository excelDataRepository;
@Autowired
public ExcelDataServiceImpl(FileStorageProperties fileStorageProperties, ExcelDataRepository excelDataRepository) {
this.fileStorageLocation = Paths.get(fileStorageProperties.getUploadDir())
.toAbsolutePath().normalize();
this.excelDataRepository = excelDataRepository;
try {
Files.createDirectories(this.fileStorageLocation);
} catch (Exception ex) {
throw new FileStorageException("Could not create the directory where the uploaded files will be stored.", ex);
}
}
@Override
public void store(MultipartFile file) {
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
try {
if (fileName.contains("..")) {
throw new FileStorageException("Filename contains invalid path sequence " + fileName);
}
Path targetLocation = this.fileStorageLocation.resolve(fileName);
Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
List<ExcelData> dataList = ExcelUtils.readExcel(targetLocation.toFile());
excelDataRepository.saveAll(dataList);
} catch (IOException ex) {
throw new FileStorageException("Could not store file " + fileName + ". Please try again!", ex);
}
}
@Override
public Resource loadFileAsResource(String filename) {
try {
Path filePath = this.fileStorageLocation.resolve(filename).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists()) {
return resource;
} else {
throw new FileStorageException("File not found " + filename);
}
} catch (MalformedURLException ex) {
throw new FileStorageException("File not found " + filename, ex);
}
}
@Override
public void modifyData(List<ExcelData> dataList) {
for (ExcelData data : dataList) {
Optional<ExcelData> existingData = excelDataRepository.findById(data.getId());
if (existingData.isPresent()) {
ExcelData newData = existingData.get();
newData.setName(data.getName());
newData.setAge(data.getAge());
excelDataRepository.save(newData);
}
}
Path targetLocation = this.fileStorageLocation.resolve("output.xlsx");
ExcelUtils.writeExcel(targetLocation.toFile(), excelDataRepository.findAll());
}
}
```
3. ExcelData.java
该类为数据模型类,对应数据库中的一张表。
```java
@Entity
@Table(name = "excel_data")
public class ExcelData {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Integer age;
// getter and setter methods
}
```
4. ExcelDataRepository.java
该类为数据仓库类,用于操作数据库中的数据。
```java
@Repository
public interface ExcelDataRepository extends JpaRepository<ExcelData, Long> {
}
```
5. ExcelUtils.java
该类为工具类,主要用于读写Excel文件。
```java
public class ExcelUtils {
public static List<ExcelData> readExcel(File file) {
List<ExcelData> dataList = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(file)) {
Workbook workbook = WorkbookFactory.create(fis);
Sheet sheet = workbook.getSheetAt(0);
Iterator<Row> iterator = sheet.iterator();
boolean hasHeader = true;
String[] headers = null;
while (iterator.hasNext()) {
Row currentRow = iterator.next();
if (hasHeader) {
headers = readHeaders(currentRow);
hasHeader = false;
} else {
ExcelData data = new ExcelData();
for (int i = 0; i < headers.length; i++) {
String header = headers[i];
Cell cell = currentRow.getCell(i);
if (cell != null) {
switch (header) {
case "Name":
data.setName(cell.getStringCellValue());
break;
case "Age":
data.setAge((int) cell.getNumericCellValue());
break;
}
}
}
if (data.getName() != null && data.getAge() != null) {
dataList.add(data);
}
}
}
} catch (IOException | InvalidFormatException e) {
e.printStackTrace();
}
return dataList;
}
private static String[] readHeaders(Row row) {
List<String> headers = new ArrayList<>();
Iterator<Cell> cellIterator = row.iterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
headers.add(cell.getStringCellValue());
}
return headers.toArray(new String[0]);
}
public static void writeExcel(File file, List<ExcelData> dataList) {
try (FileOutputStream fos = new FileOutputStream(file)) {
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet();
int rowIndex = 0;
Row headerRow = sheet.createRow(rowIndex++);
headerRow.createCell(0).setCellValue("Name");
headerRow.createCell(1).setCellValue("Age");
for (ExcelData data : dataList) {
Row row = sheet.createRow(rowIndex++);
row.createCell(0).setCellValue(data.getName());
row.createCell(1).setCellValue(data.getAge());
}
workbook.write(fos);
} catch (IOException e) {
e.printStackTrace();
}
}
}
```
6. FileStorageException.java / FileStorageProperties.java
该类为异常类和配置类,用于处理文件上传下载时的异常和配置文件上传下载的路径。
```java
public class FileStorageException extends RuntimeException {
public FileStorageException(String message) {
super(message);
}
public FileStorageException(String message, Throwable cause) {
super(message, cause);
}
}
@Configuration
@ConfigurationProperties(prefix = "file")
public class FileStorageProperties {
private String uploadDir;
public String getUploadDir() {
return uploadDir;
}
public void setUploadDir(String uploadDir) {
this.uploadDir = uploadDir;
}
}
```
最后,我们需要在application.properties文件中添加以下配置:
```
file.upload-dir=/path/to/uploaded/files
```
这个路径指的是上传的文件存储的路径,可以根据实际情况进行修改。
好了,以上就是实现这个需求的全部代码。需要注意的是,这里只提供了一个基础的实现,实际应用中可能还需要对文件进行校验、处理异常等操作。
阅读全文