Fat Jar运行提示找不到主类org.example.Main的问题求助
Fat Jar运行提示找不到主类org.example.Main的问题求助
我用IntelliJ打包了一个Fat Jar,但运行的时候总是提示找不到主类,报错信息如下:
HappyBirthdayWisher\build\libs>java -jar HappyBirthdayWisher-1.0-SNAPSHOT.jar Error: Could not find or load main class org.example.Main Caused by: java.lang.ClassNotFoundException: org.example.Main HappyBirthdayWisher\build\libs>java -cp HappyBirthdayWisher-1.0-SNAPSHOT.jar org.example.Main Error: Could not find or load main class org.example.Main Caused by: java.lang.ClassNotFoundException: org.example.Main
我特意检查了Jar包内部的文件结构,org.example.Main对应的Main.class文件确实存在于正确的包路径下。
我的Manifest文件内容如下:
Manifest-Version: 1.0 Main-Class: org.example.Main
真的搞不懂哪里出问题了,希望大家能帮我排查一下!
编辑补充:
- 我整理了Jar包的完整文件列表(内容较多)。
- 以下是我的原始Main类代码:
package org.example; import io.github.cdimascio.dotenv.Dotenv; import org.apache.poi.ss.usermodel.*; import org.example.email.EmailSender; import org.example.entity.Employee; import org.example.mappings.TemplateMappings; import org.example.thymeleaf.ThymeleafTemplateEngine; import org.example.utils.AzureBlobUtils; import org.thymeleaf.TemplateEngine; import org.thymeleaf.context.Context; import javax.mail.MessagingException; import java.io.*; import java.time.*; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class Main { public static void main(String[] args) throws MessagingException { Dotenv dotenv = Dotenv.load(); String employeeInfoFileName = "birthdayWisherFiles/Employee Sample Data.xlsx"; String imageOrderFileName = "birthdayWisherFiles/logicFiles/birthday_image_order.txt"; String emailSentLogFileName = "birthdayWisherFiles/logicFiles/email_sent_log.txt"; String imageCounterFileName = "birthdayWisherFiles/logicFiles/image_counter.txt"; String birthDateColumn = "Birth Date"; String fullNameColumn = "Full Name"; String emailColumn = "Email"; // Azure Blob Storage SAS Token URL String azureBlobUrl = dotenv.get("AZURE_BLOB_URL"); // Get today's month and day MonthDay todayMonthDay = MonthDay.now(); Month currentMonth = todayMonthDay.getMonth(); try { // Get the birthday havers of the day List<Employee> employees = getTodaysBirthdayHavers(azureBlobUrl,employeeInfoFileName, birthDateColumn, fullNameColumn, emailColumn, todayMonthDay); // Fetch and save image order if needed List<String> imageFileNames = getOrUpdateImageOrder(imageOrderFileName, azureBlobUrl, currentMonth); System.out.println("Employees with birthdays today: " + employees); if (employees.isEmpty()) { System.out.println("No birthdays today."); return; } if (imageFileNames.isEmpty()) { System.out.println("No images found in Azure Blob Storage."); return; } // Initialize Thymeleaf template engine TemplateEngine templateEngine = ThymeleafTemplateEngine.initializeTemplateEngine(); // Load or initialize the image counter int[] imageCounter = loadImageCounter(azureBlobUrl,imageCounterFileName); // Save into the list to later log it to a file List<String> emailsSent = new ArrayList<>(); // Send email to each employee for (Employee employee : employees) { // Get image for employee according to the current image order String selectedImage = getImageForEmail(imageFileNames, imageCounter); //increment the counter after getting the image incrementImageCounter(imageCounter,imageFileNames); String fileNameWithoutExtension = selectedImage.substring(selectedImage.lastIndexOf("/") + 1, selectedImage.lastIndexOf(".")); String templateName = determineTemplate(fileNameWithoutExtension); // Create the Thymeleaf context and render the appropriate template assert azureBlobUrl != null; String selectedImageURl = AzureBlobUtils.getAzureBlobImageUrl(azureBlobUrl,selectedImage); Context context = ThymeleafTemplateEngine.createContext(selectedImageURl,employee.getFullName()); String htmlContent = ThymeleafTemplateEngine.renderTemplate(templateEngine, templateName, context); String recipient = employee.getEmail(); String subject = "Happy Birthday, " + employee.getFullName() + "!"; // Send the email EmailSender.sendEmail(recipient, subject, htmlContent); // add to the list the emails with a timestamp saveEmailSentToList(employee.getFullName(),recipient,selectedImage, emailsSent); } // Append the list to file appendEmailSentListToFile(azureBlobUrl,emailSentLogFileName, emailsSent); // Save the updated image counter saveImageCounterToFile(azureBlobUrl,imageCounterFileName, imageCounter[0]); } catch (IOException e) { e.printStackTrace(); } } //Excel stuffs private static List<Employee> getTodaysBirthdayHavers(String blobURL, String filePath, String birthDateColumn, String fullNameColumn, String emailColumn, MonthDay todayMonthDay) throws IOException { try (InputStream inputStream = AzureBlobUtils.getFileInputStream(blobURL, filePath); Workbook workbook = WorkbookFactory.create(inputStream)) { Sheet sheet = workbook.getSheetAt(0); // Get the first sheet if (sheet == null) { System.out.println("No sheets found in the workbook."); return new ArrayList<>(); } int birthDateColumnIndex = findColumnIndex(sheet, birthDateColumn); int fullNameColumnIndex = findColumnIndex(sheet, fullNameColumn); int emailColumnIndex = findColumnIndex(sheet, emailColumn); if (birthDateColumnIndex == -1 || fullNameColumnIndex == -1 || emailColumnIndex == -1) { System.out.println("One or more required columns not found."); return new ArrayList<>(); } return getMatchingEmployees(sheet, birthDateColumnIndex, fullNameColumnIndex, emailColumnIndex, todayMonthDay); } } private static int findColumnIndex(Sheet sheet, String targetColumn) { Row headerRow = sheet.getRow(0); if (headerRow == null) { return -1; } for (Cell cell : headerRow) { if (cell.getCellType() == CellType.STRING && targetColumn.equals(cell.getStringCellValue())) { return cell.getColumnIndex(); } } return -1; } private static List<Employee> getMatchingEmployees(Sheet sheet, int birthDateColumnIndex, int fullNameColumnIndex, int emailColumnIndex, MonthDay todayMonthDay) { List<Employee> employees = new ArrayList<>(); for (int rowIndex = 1; rowIndex <= sheet.getLastRowNum(); rowIndex++) { Row row = sheet.getRow(rowIndex); if (row != null) { Cell birthDateCell = row.getCell(birthDateColumnIndex); Cell fullNameCell = row.getCell(fullNameColumnIndex); Cell emailCell = row.getCell(emailColumnIndex); if (birthDateCell != null && isDateCell(birthDateCell)) { LocalDate birthDate = convertToLocalDate(birthDateCell.getDateCellValue()); MonthDay birthMonthDay = MonthDay.from(birthDate); if (birthMonthDay.equals(todayMonthDay)) { String fullName = fullNameCell != null ? fullNameCell.getStringCellValue() : "Unknown"; String email = emailCell != null ? emailCell.getStringCellValue() : "Unknown"; employees.add(new Employee(fullName, email, birthDate)); } } } } return employees; } private static boolean isDateCell(Cell cell) { return cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell); } private static LocalDate convertToLocalDate(java.util.Date date) { return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); } private static List<String> getOrUpdateImageOrder(String imageOrderFileName, String azureBlobUrl, Month currentMonth) throws IOException { String fileContent = AzureBlobUtils.readTextFileFromBlob(azureBlobUrl, imageOrderFileName); List<String> fileNames; if (fileContent != null && !fileContent.isEmpty()) { // Split the string into lines List<String> lines = new ArrayList<>(List.of(fileContent.split("\\R"))); // "\\R" matches line breaks if (!lines.isEmpty() && Month.valueOf(lines.get(0).toUpperCase()).equals(currentMonth)) { fileNames = lines.subList(1, lines.size()); } else { // 重新获取并生成图片顺序 fileNames = AzureBlobUtils.listBlobFiles(azureBlobUrl, "birthdayImages/" + currentMonth.name().toLowerCase()); Collections.shuffle(fileNames); // 写入文件 StringBuilder sb = new StringBuilder(); sb.append(currentMonth.name()).append("\n"); for (String fileName : fileNames) { sb.append(fileName).append("\n"); } AzureBlobUtils.writeTextFileToBlob(azureBlobUrl, imageOrderFileName, sb.toString()); } } else { // 文件为空或不存在,重新获取并生成图片顺序 fileNames = AzureBlobUtils.listBlobFiles(azureBlobUrl, "birthdayImages/" + currentMonth.name().toLowerCase()); Collections.shuffle(fileNames); // 写入文件 StringBuilder sb = new StringBuilder(); sb.append(currentMonth.name()).append("\n"); for (String fileName : fileNames) { sb.append(fileName).append("\n"); } AzureBlobUtils.writeTextFileToBlob(azureBlobUrl, imageOrderFileName, sb.toString()); } return fileNames; } // 以下为未完整展示的方法占位(原代码截断) private static int[] loadImageCounter(String azureBlobUrl, String imageCounterFileName) throws IOException { // 业务逻辑实现 return new int[]{0}; } private static String getImageForEmail(List<String> imageFileNames, int[] imageCounter) { // 业务逻辑实现 return imageFileNames.get(imageCounter[0] % imageFileNames.size()); } private static void incrementImageCounter(int[] imageCounter, List<String> imageFileNames) { imageCounter[0] = (imageCounter[0] + 1) % imageFileNames.size(); } private static String determineTemplate(String fileNameWithoutExtension) { // 业务逻辑实现 return TemplateMappings.getTemplateName(fileNameWithoutExtension); } private static void saveEmailSentToList(String fullName, String recipient, String selectedImage, List<String> emailsSent) { // 业务逻辑实现 emailsSent.add(LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + " - " + fullName + " <" + recipient + "> - 使用图片:" + selectedImage); } private static void appendEmailSentListToFile(String azureBlobUrl, String emailSentLogFileName, List<String> emailsSent) throws IOException { // 业务逻辑实现 StringBuilder sb = new StringBuilder(); for (String entry : emailsSent) { sb.append(entry).append("\n"); } AzureBlobUtils.appendTextToBlob(azureBlobUrl, emailSentLogFileName, sb.toString()); } private static void saveImageCounterToFile(String azureBlobUrl, String imageCounterFileName, int counter) throws IOException { // 业务逻辑实现 AzureBlobUtils.writeTextFileToBlob(azureBlobUrl, imageCounterFileName, String.valueOf(counter)); } }
备注:内容来源于stack exchange,提问作者Nguyễn Nam Vinh
相关产品推荐
相关产品推荐

