2.4 构建模块化应用
第4章:构建模块化应用
模块化应用是 JDK 9 的核心特性之一,通过模块化系统(Project Jigsaw)实现代码的强封装和显式依赖管理。本章详细讲解如何从零构建一个模块化应用,包括模块定义、编译、打包、运行及调试。
4.1 模块化应用开发流程
- 定义模块:编写
module-info.java声明模块元数据。 - 组织代码:按模块化结构组织源代码。
- 编译模块:使用
javac编译模块。 - 打包模块:将模块打包为模块化 JAR。
- 运行模块:使用
java命令运行模块化应用。 - 调试与优化:使用工具(如
jdeps)分析依赖关系。
4.2 模块化应用实战
场景:构建一个简单的模块化应用,包含以下模块:
com.utils:工具模块,提供字符串处理工具。com.user:用户模块,依赖com.utils,导出用户模型。
4.3 步骤详解
步骤1:定义模块
-
com.utils模块- 模块描述符:
// com.utils/module-info.java module com.utils {exports com.utils; // 导出工具包 } - 工具类:
// com.utils/com/utils/StringUtil.java package com.utils;public class StringUtil {public static String capitalize(String s) {return s.substring(0, 1).toUpperCase() + s.substring(1);} }
- 模块描述符:
-
com.user模块- 模块描述符:
// com.user/module-info.java module com.user {requires com.utils; // 依赖工具模块exports com.user.model; // 导出用户模型包 } - 用户类:
// com.user/com/user/model/User.java package com.user.model;import com.utils.StringUtil;public class User {private String name;public User(String name) {this.name = StringUtil.capitalize(name);}public String getName() { return name; } }
- 模块描述符:
步骤2:组织代码结构
src/
├── com.utils/
│ ├── module-info.java
│ └── com/utils/
│ └── StringUtil.java
└── com.user/├── module-info.java└── com/user/└── model/└── User.java
步骤3:编译模块
使用 javac 编译模块,指定模块源路径和输出目录:
javac -d out --module-source-path src --module com.utils,com.user
编译后的目录结构:
out/
├── com.utils/
│ ├── module-info.class
│ └── com/utils/
│ └── StringUtil.class
└── com.user/├── module-info.class└── com/user/└── model/└── User.class
步骤4:打包模块
将模块打包为模块化 JAR:
# 打包 com.utils 模块
jar --create --file mods/com.utils.jar -C out/com.utils .# 打包 com.user 模块
jar --create --file mods/com.user.jar -C out/com.user .
打包后的目录结构:
mods/
├── com.utils.jar
└── com.user.jar
步骤5:运行模块化应用
使用 java 命令运行模块化应用,指定模块路径和主模块:
java --module-path mods -m com.user/com.user.model.User
步骤6:调试与优化
-
使用
jdeps分析依赖:jdeps --module-path mods -s mods/com.user.jar # 输出示例: com.user -> com.utils com.user -> java.base -
生成模块图:
jdeps --module-path mods --dot-output dots mods/com.user.jar- 生成
dots/com.user.dot文件,可用 Graphviz 工具生成依赖图。
- 生成
4.4 模块化应用最佳实践
1. 最小化模块导出
- 仅导出必要的包,隐藏实现细节。
- 示例:
module com.myapp {exports com.myapp.api; // 仅导出API包 }
2. 使用传递依赖
- 通过
requires transitive声明传递依赖,避免重复依赖。 - 示例:
module com.myapp {requires transitive com.utils; // 传递依赖 }
3. 适配反射框架
- 使用
opens开放反射访问权限,支持 Spring/Hibernate 等框架。 - 示例:
module com.myapp {opens com.myapp.internal to spring.core; // 允许Spring反射访问 }
4. 生成定制化 JRE
- 使用
jlink生成仅包含所需模块的最小化 JRE。 - 示例:
jlink --module-path $JAVA_HOME/jmods:mods \--add-modules com.user,java.base \--output myapp-runtime
4.5 常见问题与解决
| 问题 | 解决方案 |
|---|---|
| 模块未找到(Module not found) | 检查模块路径(--module-path)是否包含依赖模块,确认 requires 声明正确。 |
| 无法访问非导出包 | 使用 exports 导出包或 opens 开放反射访问权限。 |
| 生成的 JRE 缺少必要模块 | 检查 jlink 的 --add-modules 参数是否包含所有依赖模块。 |
4.6 总结
构建模块化应用是 JDK 9 的核心能力,通过模块化系统实现强封装和显式依赖管理,显著提升了代码的安全性和可维护性。开发者应掌握模块定义、编译、打包及运行的全流程,并结合工具链(如 jdeps、jlink)优化应用性能与兼容性。
相关文章:
2.4 构建模块化应用
第4章:构建模块化应用 模块化应用是 JDK 9 的核心特性之一,通过模块化系统(Project Jigsaw)实现代码的强封装和显式依赖管理。本章详细讲解如何从零构建一个模块化应用,包括模块定义、编译、打包、运行及调试。 4.1 模…...
DeepSeek:从入门到精通
在人工智能飞速发展的今天,DeepSeek作为一款备受瞩目的AI工具,正以其强大的功能和开源理念改变着我们的生活和工作方式。本文将带你深入了解DeepSeek,从基础入门到进阶应用,助你快速掌握这一前沿工具。 文末有详细资料可下载 文末…...
JAVA学习第二天
ArryList的构造方法和添加方法 01。构造方法的<>里面可以放数据类型 02. add()可以直接在后面加入数据,也可以指定下标的插入元素。 ArrayList的常用方法 ArrayList存储对象 在Java中,System.out.println()可以打印基本数据…...
DevOps工具链概述
1. DevOps工具链概述 1.1 DevOps工具链的定义 DevOps工具链是支持DevOps实践的一系列工具的集合,这些工具覆盖了软件开发的整个生命周期,包括需求管理、开发、测试、部署和运维等各个环节。它旨在通过工具的集成和自动化,打破开发与运维之间…...
windows系统远程桌面连接ubuntu18.04
记录一下自己在配置过程中遇到的问题,记录遇到的两大坑: windows系统通过xrdp远程桌面连接ubuntu18.04的蓝屏问题。参考以下第一章解决。 同一局域网内网段不同的连接问题。参考以下第三章解决,前提是SSH可连。 1. 在ubuntu上安装xrdp 参考&…...
kafka动态监听主题
简单版本 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.kafka.core.ConsumerFactory; import org.springframework.kafka.listener.ConcurrentMessageListenerContainer; import org.springframework.kafka.listener.Containe…...
Python虚拟环境管理工具 pyenv
情景 我现在在部署一个python 项目,需要用到Python 3.10。但是我本地已经有了一个3.12解释器,有没有一种方法,可以管理python 环境,还可以随意切换。怎么做? window 安装pyenv-win 使用 PowerShell(以管…...
网络安全产品架构图 网络安全相关产品
一、信息安全产品分类 背景 美国将网络和信息安全产品分了9类:鉴别、访问控制、入侵检测、防火墙、公钥基础设施、恶意程序代码防护、漏洞扫描、取证、介质清理或擦除。中国公安部将网络和信息安全产品分了7类:操作系统安全、数据库安全、网络安全、病毒…...
C++ 实践扩展(Qt Creator 联动 Visual Studio 2022)
这里我们将在 VS 上实现 QT 编程,实现如下: 一、Vs 2022 配置(若已安装,可直接跳过) 点击链接:Visual Studio 2022 我们先去 Vs 官网下载,如下: 等待程序安装完成之…...
如何实现Deepseek的本地部署并集成本地知识库?
1、下载并配置Deepseek环境 https://blog.csdn.net/kxg6666/article/details/145593346?spm1001.2014.3001.5501 2、安装AnythingLLM AnythingLLM | The all-in-one AI application for everyone 如官网下载较慢,本文最后提供夸克离线下载链接。下载后默认安装…...
vue学习笔记8
Pinia基础使用 - 计数器案例 定义Store(state action) 组件使用Store getters实现 Pinia中的 getters 直接使用 computed函数 进行模拟, 组件中需要使用需要把 getters return出去 action异步实现 编写方式:异步action函数的写法和组件…...
【自学笔记】Vue基础知识点总览-持续更新
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Vue重点知识点总览一、Vue基础1. Vue简介2. MVVM设计思想3. 响应式数据绑定4. 组件化开发 二、Vue核心特性1. 虚拟DOM2. 模板语法3. 计算属性与监听属性 三、Vue高级…...
ETL的使用(sqoop):数据导入,导出
ETL ETL: 是数据抽取(Extract)、数据转换(Transform)和数据加载(Load)的整个过程 常用的ETL工具 sqoop 1.Apache Sqoop 是 Apache 软件基金会旗下的一个开源项目,旨在帮助用户高效地在 Hado…...
【核心特性】从鸭子类型到Go的io.Writer设计哲学
在编程语言的设计中,鸭子类型和接口设计是两种非常重要的理念。它们都强调了对象的行为和能力,而非其具体的类型或继承关系。Go 语言的io.Writer 接口是这种设计理念的典型代表,它通过简洁的接口定义,实现了强大的功能和灵活性。 …...
多模态模型详解
多模态模型是什么 多模态模型是一种能够处理和理解多种数据类型(如文本、图像、音频、视频等)的机器学习模型,通过融合不同模态的信息来提升任务的性能。其核心在于利用不同模态之间的互补性,增强模型的鲁棒性和准确性。 如何融合…...
Go 语言里中的堆与栈
在 Go 语言里,堆和栈是内存管理的两个重要概念,它们在多个方面存在明显差异: 1. 内存分配与回收方式 栈 分配:Go 语言中,栈内存主要用于存储函数的局部变量和调用信息。当一个函数被调用时,Go 会自动为其…...
八、OSG学习笔记-
前一章节: 七、OSG学习笔记-碰撞检测-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145558132?spm1001.2014.3001.5501 一、了解OSG图元加载显示流程 本章节代码: OsgStudy/wids CuiQingCheng/OsgStudy - 码云 - 开源中国https:…...
本地部署【LLM-deepseek】大模型 ollama+deepseek/conda(python)+openwebui/docker+openwebui
通过ollama本地部署deepseek 总共两步 1.模型部署 2.[web页面] 参考官网 ollama:模型部署 https://ollama.com/ open-webui:web页面 https://github.com/open-webui/open-webui 设备参考 Mac M 芯片 windows未知 蒸馏模型版本:deepseek-r1:14b 运行情况macminim2 24256 本地…...
网络分析工具—WireShark的安装及使用
Wireshark 是一个广泛使用的网络协议分析工具,常被网络管理员、开发人员和安全专家用来捕获和分析网络数据包。它支持多种网络协议,能够帮助用户深入理解网络流量、诊断网络问题以及进行安全分析。 Wireshark 的主要功能 数据包捕获与分析: …...
MobaXterm的图形化界面支持:原理与分辨率问题解决
1. 概述 MobaXterm 是一款功能强大的远程访问工具,支持SSH、RDP、X11、VNC等多种协议,并内置了强大的图形界面支持,让用户能够在远程操作Linux/Unix系统时,享受到类似本地桌面的流畅体验。 与传统的SSH客户端不同,Mo…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
