百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

有了这些开源工具后,明天争取五点下班了!

suiw9 2024-11-17 15:49 45 浏览 0 评论

前言

??一个优秀的开发者,一定是会利用各种工具来提升自己的开发效率。 前段时间,博主在Gitee/Github开源了一个提升开发效率的工具,工具内集成了各种常用工具如csv、excel、ftp、文件系统等等,只需要简单调用API,就可以得到想要的结果,可以极大帮助开发者提升效率,下面来一起看看这款工具如何使用吧。

工具介绍

??报表的导出、导入功能、文件上传、下载等在平常业务中是最常见不过的功能了,许多小伙伴在开发的时候才会去网上找之前别人编写过的案例参考,但是许多博客记载的都是时间比较长远或者不完整的代码,这导致在引入的时候还要处理引入的许多未知问题。

??现在博主开源的“轮子之王”包含了这些常见的功能,源码全开发,每种功能都有相应的例子说明,项目会持续更新迭代,有问题还可以及时给项目提issue,相信比大多数网上的博客代码可靠性更高。

??项目地址如下:

??Gitee:https://gitee.com/it-learning-diary/it-wheels-king

??项目结构如下:

一、excel工具

??该工具实现采用的是开源的easyexcel框架。easyexcel是阿里的开发人员对poi框架进行了优化,解决了poi在大数据量时可能出现OOM异常,并且兼容xls和xlsx两种文件类型的一个开源框架。

??excel工具集成功能如下:

  • excel的导入(可以自定义转换后的excel数据处理的业务逻辑,支持抛出异常、事务回滚、记录解析时的异常数据)
  • 导出(支持固定表头,兼容多sheet页和动态表头,兼容多sheet页)功能。

??excel工具的特点如下:

??使用过easyexcel框架的一些读者知道,每个导入功能都要写一个对应的Listener进行数据转换,在很多时间其实转换的逻辑都是类似的,不同的只不过是转换后数据处理的业务逻辑不一样。

??本开源项目的excel工具则利用Java中的泛型和Java8中的Consumer接口将相同的部分(转换逻辑)抽取出来,不同的部分则单独传入(数据处理的业务逻辑),这样就避免了每个导入都需要创建一个相类似的Listerner,减少了类的创建和提高了开发效率。

??部分源码如下:

 /**
     * 通用导入excel文件方法
     *
     * @param fileStream 导入的文件流
     * @param rowDto 接收excel每行数据的实体
     * @param rowAction 将接收到的实体进行自定义的业务处理逻辑方法
     * @param <T> 实体类型
     */
    public static <T> void importFile(InputStream fileStream, T rowDto, ThrowingConsumer<List<T>> rowAction) {
        // 获取excel通用监听器
        ExcelImportCommonListener<T> commonListener = new ExcelImportCommonListener<>(rowAction);
        // 读取excel文件并导入
        EasyExcel.read(fileStream, rowDto.getClass(), commonListener).sheet().doRead();
    }
    
/**
     * excel文件导出(可以包含多个sheet页),固定表头(通过实体指定属性的方式)
     * @param response
     * @param fileName   导出文件名
     * @param head       导出表头(多个sheet页就是多个集合元素)
     * @param exportData 需要导出数据
     * @param sheetNames sheet页的名称,为空则默认以:sheet + 数字规则命名
     */
    public static <T> void exportFile(String fileName, List<T> head, List<List<T>> exportData, List<String> sheetNames, HttpServletResponse response) {
        if (Objects.isNull(response) || StrUtil.isBlank(fileName) || CollUtil.isEmpty(head)) {
            log.info("ExcelExportUtil exportFile required param can't be empty");
            return;
        }
        ExcelWriter writer = null;
        try {
            response.setContentType(ExportConstant.EXCEL_CONTENT_TYPE);
            response.setCharacterEncoding(ExportConstant.UTF_8);
            response.setHeader(ExportConstant.CONTENT_DISPOSITION, ExportConstant.ATTACHMENT_FILENAME + fileName + ExportConstant.XLSX_SUFFIX);
            // 设置导出的表格样式
            HorizontalCellStyleStrategy horizontalCellStyleStrategy = getExportDefaultStyle();
            writer = EasyExcel.write(response.getOutputStream()).registerWriteHandler(horizontalCellStyleStrategy).build();
            for (int itemIndex = 0; itemIndex < exportData.size(); itemIndex++) {
                // 表头数据
                Object headData = head.get(itemIndex);
                // sheet页的数据
                List<T> list = exportData.get(itemIndex);
                WriteSheet sheet = EasyExcel.writerSheet(itemIndex, CollUtil.isEmpty(sheetNames) ? ExportConstant.SHEET_NAME + itemIndex + 1 : sheetNames.get(itemIndex)).head(headData.getClass()).build();
                writer.write(list, sheet);
            }
        } catch (Exception e) {
            log.error("ExcelExportUtil exportFile in error:{}", e);
        } finally {
            if (null != writer) {
                writer.finish();
            }
        }
    }

复制代码

??使用案例如下(在工具中每个项目都有具体的案例,不懂的还可以留言跟博主沟通):

/**
     * 导入用户数据案例
     *
     * @param file
     */
    @Transactional(rollbackFor = Exception.class)
    public void uploadUserListDemoWithExcel(MultipartFile file, String username) throws Exception {
        // 此处先校验导入的文件类型是否为excel
        String type = FileTypeUtil.getType(file.getInputStream());
        if (StrUtil.isBlank(type) || type.contains(ImportConstant.XLS_TYPE) || type.contains(ImportConstant.XLSX_TYPE)) {
            // 返回校验失败信息
            return;
        }
        User user = new User();
        user.setId(100);
        user.setName("外层");
        user.setPassword("外层");
        userService.save(user);
        // 调用统一导入方法
        ExcelImportUtil.importFile(file.getInputStream(), new UserDto(), UserServiceImpl::saveUserList);
    }

 /**
     * 导出案例
     *
     * @param response
     */
    public void exportUserListDemoWithExcel(HttpServletResponse response) {
        // 表头(使用excel中的注解定义,如果表头不固定,请使用ExcelExportUtil.exportWithDynamicData进行导出)
        List<UserExportVo> head = Stream.of(new UserExportVo()).collect(Collectors.toList());
        // 数据(使用两层list为了兼容多个sheet页,如果是不同的sheet页则放在不同的List集合中)
        List<List<UserExportVo>> exportDataList = new ArrayList<>();
        List<UserExportVo> exportItem = new ArrayList<>();
        // 查询数据
        List<User> dbData = userService.list();
        // 将数据转换成导出需要的实际数据格式,此处只是演示
        for (User user : dbData) {
            UserExportVo vo = new UserExportVo();
            BeanUtil.copyProperties(user, vo);
            exportItem.add(vo);
        }
        exportDataList.add(exportItem);
        // sheet页名称-自定义,如果没有则传空
        List<String> sheetNameList = Stream.of("sheet1").collect(Collectors.toList());
        ExcelExportUtil.exportFile("user", head, exportDataList, sheetNameList, response);
    }
复制代码

二、csv工具

??Csv即逗号分隔值,也可以称为字符分隔符,与excel等文件相比,excel文件中会包含许多格式信息,占用的空间会更大,所以Csv在很多大数据场景导出、导入场景是非常常见的。该工具实现采用的是开源的univocity-parsers框架实现。

??之前有一篇专门讲解轮子之王项目为何使用univocity-parsers框架集成csv的详细过程,有兴趣的读者可以点击链接查看:集成csv工具的前因后果

??部分源码如下:

 /**
     * 使用实体bean接收csv数据文件并进行数据落盘
     *
     * @param inputStream
     * @param errorList
     * @param rowDtoClass
     * @param rowAction
     * @param <T>
     */
    public static <T> void importCsvWithBean(InputStream inputStream, List<String> errorList, Class rowDtoClass, ThrowingConsumer<List<T>> rowAction) {
        // 定义bean解析者:用于将csv中数据绑定到实体属性中,然后存储带list集合上
        BeanListProcessor<T> rowProcessor = new BeanListProcessor<>(rowDtoClass);
        CsvParserSettings setting = getDefaultSetting(errorList);
        setting.setProcessor(rowProcessor);
        // 创建csv文件解析
        CsvParser csvParser = new CsvParser(setting);
        csvParser.parse(inputStream);
        // 获取数据映射后的集合
        List<T> dataList = rowProcessor.getBeans();
        // 校验必填字段
        for (T row : dataList) {
            // 校验导入字段
            ImportValid.validRequireField(row, errorList);
        }
        // 执行数据持久化
        persistentBeanDataToDb(dataList, rowAction);
    }
    
   /**
     * 导出csv文件(表头和行都以实体的方式)
     *
     * @param response
     * @param head
     * @param rowDataList
     */
    public static <T> void exportCsvWithBean(HttpServletResponse response, String fileName, T head, List<T> rowDataList) {
        CsvWriter writer = null;
        try {
            // 设置响应头格式
            response.setContentType(ExportConstant.EXCEL_CONTENT_TYPE);
            response.setCharacterEncoding(ExportConstant.UTF_8);
            response.setHeader(ExportConstant.CONTENT_DISPOSITION, ExportConstant.ATTACHMENT_FILENAME + fileName + ExportConstant.CSV_SUFFIX);

            // 设置导出格式
            CsvWriterSettings setting = getDefaultWriteSetting();
            // 创见bean处理器,用于处理写入数据
            BeanWriterProcessor<?> beanWriter = new BeanWriterProcessor<>(head.getClass());
            setting.setRowWriterProcessor(beanWriter);

            // 导出数据
            writer = new CsvWriter(response.getOutputStream(), setting);
            writer.processRecords(rowDataList);
            writer.flush();
        } catch (Exception e) {
            log.error("CsvExportUtil exportCsvWithBean in error:{}", e);
        } finally {
            if (Objects.nonNull(writer)) {
                writer.close();
            }
        }
    } 

复制代码

??使用案例如下:

/**
     * 导出案例
     *
     * @param response
     */
    public void exportUserListWithCsv(HttpServletResponse response) {
        List<UserExportCsvVo> exportItem = new ArrayList<>();
        // 查询数据
        List<User> dbData = userService.list();
        // 使用字符串数组方式作为表头导出csv数据
        List<Object> head = Stream.of("id", "name", "password").collect(Collectors.toList());
        List<List<Object>> dataList = new ArrayList<>();
        for (User user : dbData) {
            List<Object> row = new ArrayList<>();
            row.add(user.getId());
            row.add(user.getName());
            row.add(user.getPassword());
            dataList.add(row);
        }
        CsvExportUtil.exportCsvWithString(response, "demo", head, dataList);
    }

 /**
     * 导入用户数据案例(csv模式)
     *
     * @param file
     */
@Transactional(rollbackFor = Exception.class)
    public void uploadUserListWithCsv(MultipartFile file) throws Exception {
        // 此处先校验导入的文件类型是否为csv
        String type = FileTypeUtil.getType(file.getInputStream());
        if (StrUtil.isBlank(type) || type.contains(ImportConstant.CSV_TYPE)) {
            // 返回校验失败信息
            return;
        }
        User user = new User();
        user.setId(100);
        user.setName("外层");
        user.setPassword("外层");
        userService.save(user);
        List<String> errorLogList = new ArrayList<>();
        // 调用统一导入方法
        // 方式一:使用csv数据映射到dto实体的方式进行数据导入
        //CsvImportUtil.importCsvWithBean(file.getInputStream(), errorLogList, UserCsvDto.class, UserServiceImpl::saveUserListWithCsv);

        // 方式二、使用csv数据映射到字符串数组的方式进行数据导入
        CsvImportUtil.importCsvWithString(file.getInputStream(), errorLogList, UserCsvDto.class, UserServiceImpl::saveUserListWithCsvStringArrDemo);

        // 如果存在解析异常,输出解析异常并进行事务回滚
        if (CollUtil.isNotEmpty(errorLogList)) {
            throw new RuntimeException(StrUtil.toString(errorLogList));
        }
    }
复制代码

三、ftp工具

??Ftp文件上传下载相比excel、csv等出现的场景较少,但是,如果你参与的项目是政府或者涉及到第三方旧系统对接的时候,很多时候就需要使用到它。因为很多旧系统或者政府项目使用的技术比较旧或者有制度限制,一般都是以文件的形式与你进行交互,此时ftp工具就很有效了。

??Ftp工具使用的commons-net开源框架进行实现,具体的集成流程之前单独使用一篇文章进行了非常详细的介绍,有需要的读者可以点击后面链接查看:手把手教你搭建ftp服务器,并用程序完成ftp上传下载功能

??部分源码如下:

/**
     * 上传
     *
     * @return
     */
    public boolean upload(FtpUploadParam param) {
        boolean flag = false;
        FTPClient ftpClient = new FTPClient();
        //1 测试连接
        if (connect(ftpClient, param.getHostname(), param.getPort(), param.getUsername(), param.getPassword())) {
            try {
                //2 检查工作目录是否存在,不存在则创建
                if (!ftpClient.changeWorkingDirectory(param.getWorkingPath())) {
                    ftpClient.makeDirectory(param.getWorkingPath());
                }
                // 将文件编码成Ftp服务器支持的编码类型(FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码。)
                String fileName = new String(param.getSaveName().getBytes(ftpClientCharset), ftpServerCharset);
                // 3 上传文件
                if (ftpClient.storeFile(fileName, param.getInputStream())) {
                    flag = true;
                } else {
                    log.warn("FtpUtils uploadFile unsuccessfully!!");
                }
            } catch (IOException e) {
                log.error("FtpUtils upload in error:{}", e);
            } finally {
                disconnect(ftpClient);
            }
        }
        return flag;
    }
/**
     * @description: 下载ftp文件
     * @param:
     * @param: param
     * @param: downloadFileName
     * @return:
     * @date: 2022/7/14 10:56
     */
    public boolean download(FtpDownloadParam param, String downloadFileName) {
        FTPClient ftpClient = new FTPClient();
        FileOutputStream out = null;
        boolean downloadResult = false;
        //1 测试连接
        if (connect(ftpClient, param.getHostname(), param.getPort(), param.getUsername(), param.getPassword())) {
            try {
                String localPath = param.getDownloadPath() + param.getFileName();
                out = new FileOutputStream(new File(localPath));
                //2 检查工作目录是否存在,不存在返回
                // if (!ftpClient.changeWorkingDirectory(param.getWorkingPath())) {
                //    return false;
                // }
                /*
                 * 打开FTP服务器的PASS模式(不记得FTP协议支持的模式请翻到文章第一阶段)
                 * 这个方法的意思就是每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据. 因为ftp
                 * server可能每次开启不同的端口来传输数据,但是在linux上,由于安全限制,可能某些端口没有开启,可能出现出现阻塞
                 */
                ftpClient.enterLocalPassiveMode();
                // 设置文件的传输方式-二进制
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
                // 将文件编码成Ftp服务器支持的编码类型(FTP协议里面,规定文件名编码为iso-8859-1,所以目录名或文件名需要转码。)
                // 缺少编码转换会导致:从FTP服务器下载下来的文件是破损的,无法被打开
                downloadResult = ftpClient.retrieveFile(new String(downloadFileName
                        .getBytes(ftpClientCharset), ftpServerCharset), out);
                out.flush();
            } catch (IOException e) {
                log.error("FtpUtils upload in error:{}", e);
                return false;
            } finally {
                try {
                    if (Objects.nonNull(out)) {
                        out.close();
                    }
                } catch (Exception e) {
                    log.error("FtpUtils upload in error:{}", e);
                }
                disconnect(ftpClient);
            }
        }
        return downloadResult;
    }
复制代码

??具体使用案例如下:

@PostMapping("/ftp/upload")
    public void upload() {
        try {
            FtpUploadParam param = new FtpUploadParam();
            param.setHostname(ftpConfig.getServerHostname());
            param.setPort(ftpConfig.getServerPort());
            param.setUsername(ftpConfig.getServerUsername());
            param.setPassword(ftpConfig.getServerPassword());
            param.setWorkingPath(ftpConfig.getServerWorkingPath());
            param.setSaveName("xxx.mp3");
            InputStream in = new FileInputStream(new File("D:/uploadfile/like.mp3"));
            param.setInputStream(in);
            ftpUtils.upload(param);
        } catch (Exception e) {
            log.error("TestFtpServerController upload 错误:{}", e);
        }
    }

    @PostMapping("/ftp/download")
    public void download() {
        try {
            FtpDownloadParam param = new FtpDownloadParam();
            param.setHostname(ftpConfig.getServerHostname());
            param.setPort(ftpConfig.getServerPort());
            param.setUsername(ftpConfig.getServerUsername());
            param.setPassword(ftpConfig.getServerPassword());
            param.setWorkingPath(ftpConfig.getServerWorkingPath());
            param.setDownloadPath("D:/downloadFile/");
            param.setFileName("xxx.mp3");
            ftpUtils.download(param, "xxxx.mp3");
        } catch (Exception e) {
            log.error("TestFtpServerController download 错误:{}", e);
        }

    }

复制代码

四、分布式文件系统工具

??非结构化数据通常是使用文件的方式进行存储,这时候不可避免地要使用到文件系统进行管理。 分布式文件系统工具使用了第三方开源框架seaweedfs进行搭建,可以实现程序上传,删除、下载、查询,并有文件分布式存储,避免单点故障,节约成本等特点。

??前面也专门通过一篇文章讲解了:为何要使用seaweedfs框架搭建分布式文件系统的,感兴趣的读者可以通过下方链接进行查看:Gitee图床崩溃后,我使用Seaweedfs搭建了文件系统并封装成轮子开源

??部分源码如下:

/**
     * @description: 上传单个文件到文件服务器
     * @param: file
     * @return: 文件的fid + 文件的请全访问地址
     * @author: it
     */
    public String uploadFile(MultipartFile file) throws Exception {
        FileSource fileSource = getFileSource();
        FileTemplate fileTemplate = new FileTemplate(fileSource.getConnection());
        // 上传文件
        FileHandleStatus handleStatus = fileTemplate.saveFileByStream(file.getOriginalFilename(), file.getInputStream(), contentType);
        // 获取上传文件的访问地址
        String fileUrl = fileTemplate.getFileUrl(handleStatus.getFileId());
        // 关闭当前连接
        fileSource.shutdown();
        return handleStatus.getFileId() + StrUtil.DASHED + fileUrl;
    }
/**
     * @description: 根据文件下载文件
     * @param: fid
     * @param: response
     * @param: fileName
     * @author: it
     */
    public void downloadFileByFid(HttpServletResponse response, HttpServletRequest request, String fid, String fileName) throws Exception {
        FileSource fileSource = getFileSource();
        FileTemplate fileTemplate = new FileTemplate(fileSource.getConnection());
        StreamResponse fileStream = fileTemplate.getFileStream(fid);
        // 设置响应头
        response.setContentType(CommonConstant.CONTENT_TYPE);
        response.setCharacterEncoding(CommonConstant.UTF_8);
        String encodeFileName = buildingFileNameAdapterBrowser(request, fileName);
        response.setHeader(CommonConstant.CONTENT_DISPOSITION, CommonConstant.ATTACHMENT_FILENAME + encodeFileName);
        // 读取并写入到响应输出
        InputStream inputStream = fileStream.getInputStream();
        byte[] fileByte = new byte[inputStream.available()];
        inputStream.read(fileByte);
        response.getOutputStream().write(fileByte);
        response.getOutputStream().flush();
        fileSource.shutdown();
    }
复制代码

??具体使用案例如下:

/**
     * @description: 上传文件
     * @param:
     * @param: file
     * @return:
     * @author: it
     * @date: 2022/7/14 17:01
     */
    @ResponseBody
    @RequestMapping("upload")
    public void uploadFile(MultipartFile file) {
        try {
            String fileUrl = seaweedFsUtil.uploadFile(file);
            System.out.println(fileUrl);
        } catch (Exception e) {
            log.error("TestSeaweedFsController uploadFile in error:{}", e);
        }
    }

    /**
     * @description: 下载文件
     * @param:
     * @param: fileId
     * @return:
     * @author: it
     * @date: 2022/7/14 17:01
     */
    @RequestMapping("download")
    public void downloadFile(HttpServletResponse response, HttpServletRequest request, String fileId, String fileName) {
        try {
            seaweedFsUtil.downloadFileByFid(response, request, fileId, fileName);
        } catch (Exception e) {
            log.error("TestSeaweedFsController downloadFile in error:{}", e);
        }
    }
复制代码

对 Java 程序员有用的开源库

下面是收集的一些有用的第三方库,Java 开发人员可以在他们的应用程序中使用它们来完成很多有用的任务。为了使用这些库,Java 开发人员应该熟悉这一点,这就是本文的重点。如果您有一个想法,那么您可以研究该库并使用它。

1. 日志库

日志库非常常见,因为您在每个项目中都需要它们。它们对于服务器端应用程序来说是最重要的,因为日志只放置在您可以看到应用程序正在发生什么的地方。尽管 JDK 附带了自己的日志库,但仍有更好的替代方案可用,例如 Log4j、SLF4j 和 LogBack。

Java 开发人员应该熟悉日志库的优缺点,并知道为什么使用 SLF4j 比普通的 Log4j 更好。

2. JSON解析库

在当今的 Web 服务和物联网世界中,JSON 已成为将信息从客户端传输到服务器的首选协议。它们已取代 XML,成为以独立于平台的方式传输信息的首选方式。

不幸的是,JDK 没有JSON 库。但是,有许多优秀的第三方库可以让您解析和创建 JSON 消息,例如 Jackson 和 Gson。

Java Web 开发人员应该至少熟悉这些库中的一个。

3. 单元测试库

单元测试是将普通开发人员与优秀开发人员区分开来的最重要的事情。程序员经常得到不编写单元测试的借口,但避免单元测试的最常见借口是缺乏流行单元测试库的经验和知识,包括 JUnit、Mockito 和 PowerMock。

4. 通用库

Java 开发人员可以使用一些优秀的通用第三方库,例如 Apache Commons 和 Google Guava。我总是在我的项目中包含这些库,因为它们简化了很多任务。

重新发明轮子是没有意义的。我们应该更喜欢使用久经考验的库,而不是时不时地编写我们自己的例程。

Java 开发人员最好熟悉 Google Guava 和 Apache Commons 库。

5. HTTP 库

我不喜欢 JDK 的一件事是它们缺乏对 HTTP 的支持。虽然您可以使用包中的类建立 HTTP 连接 java.net,但使用开源第三方库(如 Apache HttpClient 和 HttpCore)并不容易或无缝。

尽管 JDK 9 带来了对 HTTP 2.0 的支持以及对 HTTP 的更好支持,但我强烈建议所有 Java 开发人员熟悉流行的 HTTP 客户端库,包括 HttpClient 和 HttpCore。

6. XML 解析库

有许多 XML 解析库,包括 Xerces、JAXB、JAXP、Dom4j 和 Xstream。Xerces2 是 Apache Xerces 系列中的下一代高性能、完全兼容的 XML 解析器。这个新版本的 Xerces 引入了 Xerces Native Interface (XNI),这是一个用于构建解析器组件和配置的完整框架,它非常模块化且易于编程。

Apache Xerces2 解析器是 XNI 的参考实现,但其他解析器组件、配置和解析器可以使用 Xerces Native Interface 编写。Dom4j 是另一个用于 Java 应用程序的灵活 XML 框架。

7. Excel 阅读库

信不信由你——所有现实世界的应用程序都必须以某种形式与 Microsoft Office 交互。许多应用程序需要提供在 Excel 中导出数据的功能,如果您必须从 Java 应用程序中执行相同操作,则需要 Apache POI API。

这是一个非常丰富的库,允许您 从 Java 程序读取和写入 XLS 文件。您可以查看该链接以获取在核心 Java 应用程序中读取 Excel 文件的工作示例。

8. 字节码库

如果您正在编写生成代码或与字节码交互的框架或库,那么您需要一个字节码库。

它们允许您读取和修改应用程序生成的字节码。Java 世界中一些流行的字节码库是 javassist 和 Cglib Nodep。

Javassist(JAVA 编程助手)使 Java 字节码操作变得非常简单。它是一个用于在 Java 中编辑字节码的类库。ASM 是另一个有用的字节码编辑库。

9. 数据库连接池库

如果您从 Java 应用程序与数据库进行交互,但不使用数据库连接池库,那么,您会丢失一些东西。

由于在运行时创建数据库连接需要时间并且使请求处理速度变慢,因此始终建议使用数据库连接库。一些流行的是 Commons Pool 和 DBCP。

在 Web 应用程序中,它的 Web 服务器通常提供这些功能,但在核心 Java 应用程序中,您需要将这些连接池库包含到您的类路径中才能使用数据库连接池。

10. 消息库

与日志记录和数据库连接类似,消息传递也是许多实际 Java 应用程序的共同特征。

Java 提供 JMS 或 Java 消息传递服务,它不是 JDK 的一部分。对于此组件,您需要包含一个单独的 jms.jar

同样,如果您使用第三方消息传递协议,例如 Tibco RV,那么您需要 tibrv.jar 在应用程序类路径中使用第三方 JAR 。

11. PDF 库

与 Microsoft Excel 类似,PDF 库是另一种普遍存在的格式。如果您需要在应用程序中支持 PDF 功能,例如 在 PDF 文件中导出数据,您可以使用 iText 和 Apache FOP 库。


两者都提供有用的 PDF 相关功能,但 iText 更丰富更好。

12. 日期和时间库

在 Java 8 之前,JDK 的数据和时间库有很多缺陷,因为它们不是线程安全的、不可变的和容易出错的。许多 Java 开发人员依靠 JodaTime 来实现他们的日期和时间要求。

从 JDK 8 开始,没有理由使用 Joda,因为您可以在 JDK 8 的新日期和时间 API中获得所有这些功能,但是如果您使用的是较旧的 Java 版本,那么 JodaTime 是一个值得学习的库。

13. 集合库

尽管 JDK 拥有丰富的集合库,但也有一些第三方库提供了更多选项,例如 Apache Commons 集合、Goldman Sachs 集合、Google 集合和 Trove。

Trove 库特别有用,因为它为 Java 提供了高速的常规和原始集合。

FastUtil 是另一个类似的 API。它通过提供特定类型的映射、集合、列表和优先级队列来扩展 Java 集合框架,这些映射、集合、列表和优先级队列具有较小的内存占用、快速访问和插入;它还提供大(64 位)数组、集合和列表,以及用于二进制和文本文件的快速、实用的 I/O 类。

14. 电子邮件 API

javax.mail 和 Apache Commons Email 都提供了用于从 Java 发送电子邮件的 API 。它建立在 JavaMail API 之上,旨在简化它。

15. HTML 解析库

与JSON和XML类似,HMTL 是我们许多人必须处理的另一种常见格式。值得庆幸的是,我们有 JSoup,它极大地简化了在 Java 应用程序中使用 HTML。

您可以使用JSoup不仅解析 HTML,还可以创建 HTML 文档

它提供了一个非常方便的 API 用于提取和操作数据,使用最好的DOM、CSS 和类似 jquery 的方法。JSoup 实现了 WHATWG HTML5 规范并将HTML解析为与现代浏览器相同的 DOM。

16.密码库

Apache Commons Codec 包包含各种格式的简单编码器和解码器,例如Base64和 Hexadecimal。

除了这些广泛使用的编码器和解码器之外,编解码器包还维护了一组语音编码实用程序。

17. 嵌入式 SQL 数据库库

我真的很喜欢像 H2 这样的内存数据库,你可以将它嵌入到你的 Java 应用程序中。它们非常适合测试您的 SQL 脚本和运行需要数据库的单元测试。但是,H2 不是唯一的 DB,您还可以选择 Apache Derby 和 HSQL。

18. JDBC 故障排除库

有一些很好的 JDBC 扩展库可以让调试更容易,比如 P6spy。

这是一个库,可以无缝拦截和记录数据库数据,而无需更改应用程序的代码。您可以使用它们来记录 SQL 查询及其时间。

例如,如果您在代码中使用PreparedStatment和CallableStatement,这些库可以记录带有参数的准确调用以及执行所需的时间。

19. 序列化库

Google 协议缓冲区是一种以高效且可扩展的格式对结构化数据进行编码的方法。它是Java 序列化的更丰富和更好的替代方案。我强烈建议有经验的 Java 开发人员学习 Google Protobuf。

20. 网络库

一些有用的网络库是 Netty 和 Apache MINA。如果您正在编写需要执行低级网络任务的应用程序,请考虑使用这些库。

以上就是今天小编分享给大家的一些工作中常用的库,了解并熟练的运用他们,不仅可以大大提高你的开发效率,也可以学习优秀代码的设计,提高自己的编码能力。

PS:防止找不到本篇文章,可以收藏点赞,方便翻阅查找哦

下面给大家介绍一下下一段时间项目的一些工作(如果读者有想要集成的轮子,欢迎提issue或者这文章下面留言):

写在最后

??开源之路不容易,开源之心不忘记!如果博主开源的项目对您有所帮助,请给项目star,给博主更多动力,如果阅读文章给您有所帮助,请给博主点赞、关注。

相关推荐

俄罗斯的 HTTPS 也要被废了?(俄罗斯网站关闭)

发布该推文的ScottHelme是一名黑客,SecurityHeaders和ReportUri的创始人、Pluralsight作者、BBC常驻黑客。他表示,CAs现在似乎正在停止为俄罗斯域名颁发...

如何强制所有流量使用 HTTPS一网上用户

如何强制所有流量使用HTTPS一网上用户使用.htaccess强制流量到https的最常见方法可能是使用.htaccess重定向请求。.htaccess是一个简单的文本文件,简称为“.h...

https和http的区别(https和http有何区别)

“HTTPS和HTTP都是数据传输的应用层协议,区别在于HTTPS比HTTP安全”。区别在哪里,我们接着往下看:...

快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别

什么是协议?网络协议是计算机之间为了实现网络通信从而达成的一种“约定”或“规则”,正是因为这个“规则”的存在,不同厂商的生产设备、及不同操作系统组成的计算机之间,才可以实现通信。简单来说,计算机与网络...

简述HTTPS工作原理(简述https原理,以及与http的区别)

https是在http协议的基础上加了一层SSL(由网景公司开发),加密由ssl实现,它的目的是为用户提供对网站服务器的身份认证(需要CA),以至于保护交换数据的隐私和完整性,原理如图示。1、客户端发...

21、HTTPS 有几次握手和挥手?HTTPS 的原理什么是(高薪 常问)

HTTPS是3次握手和4次挥手,和HTTP是一样的。HTTPS的原理...

一次安全可靠的通信——HTTPS原理

为什么HTTPS协议就比HTTP安全呢?一次安全可靠的通信应该包含什么东西呢,这篇文章我会尝试讲清楚这些细节。Alice与Bob的通信...

为什么有的网站没有使用https(为什么有的网站点不开)

有的网站没有使用HTTPS的原因可能涉及多个方面,以下是.com、.top域名的一些见解:服务器性能限制:HTTPS使用公钥加密和私钥解密技术,这要求服务器具备足够的计算能力来处理加解密操作。如果服务...

HTTPS是什么?加密原理和证书。SSL/TLS握手过程

秘钥的产生过程非对称加密...

图解HTTPS「转」(图解http 完整版 彩色版 pdf)

我们都知道HTTPS能够加密信息,以免敏感信息被第三方获取。所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议。...

HTTP 和 HTTPS 有何不同?一文带你全面了解

随着互联网时代的高速发展,Web服务器和客户端之间的安全通信需求也越来越高。HTTP和HTTPS是两种广泛使用的Web通信协议。本文将介绍HTTP和HTTPS的区别,并探讨为什么HTTPS已成为We...

HTTP与HTTPS的区别,详细介绍(http与https有什么区别)

HTTP与HTTPS介绍超文本传输协议HTTP协议被用于在Web浏览器和网站服务器之间传递信息,HTTP协议以明文方式发送内容,不提供任何方式的数据加密,如果攻击者截取了Web浏览器和网站服务器之间的...

一文让你轻松掌握 HTTPS(https详解)

一文让你轻松掌握HTTPS原文作者:UC国际研发泽原写在最前:欢迎你来到“UC国际技术”公众号,我们将为大家提供与客户端、服务端、算法、测试、数据、前端等相关的高质量技术文章,不限于原创与翻译。...

如何在Spring Boot应用程序上启用HTTPS?

HTTPS是HTTP的安全版本,旨在提供传输层安全性(TLS)[安全套接字层(SSL)的后继产品],这是地址栏中的挂锁图标,用于在Web服务器和浏览器之间建立加密连接。HTTPS加密每个数据包以安全方...

一文彻底搞明白Http以及Https(http0)

早期以信息发布为主的Web1.0时代,HTTP已可以满足绝大部分需要。证书费用、服务器的计算资源都比较昂贵,作为HTTP安全扩展的HTTPS,通常只应用在登录、交易等少数环境中。但随着越来越多的重要...

取消回复欢迎 发表评论: