25年四年Java牛马真实面试问题汇总系列(1)

面试问题

  1. springboot2.0与3.0在控制层上有什么不同?

    Spring Boot 3.0 基于 Spring Framework 6.0,与 Spring Boot 2.0(基于 Spring Framework 5.0)相比,在控制器层的注解和返回处理上有一些重要变化。以下是主要差异:

    一、核心依赖与版本要求

    1. Java 版本

      • Spring Boot 2.0:最低 Java 8,推荐 Java 11
      • Spring Boot 3.0:强制要求 Java 17+
    2. Jakarta EE 取代 Java EE

      • Spring Boot 3.0 使用 Jakarta EE 9+ 命名空间(如 jakarta.servlet.* 取代 javax.servlet.*

    二、请求参数注解的变化

    1. @RequestBody 与 JSON 处理
    • Spring Boot 2.0:默认使用 Jackson 作为 JSON 处理器
    • Spring Boot 3.0
      • 默认仍使用 Jackson,但增强了对 Jakarta JSON-BJSON-P 的支持
      • 新增 @HttpMessageReader@HttpMessageWriter 注解用于自定义消息转换器
    1. 路径变量与请求参数
    // Spring Boot 2.0
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable("id") Long userId) { ... }
    
    // Spring Boot 3.0:支持隐式路径变量名绑定(参数名与路径变量名一致时)
    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) { ... }
    
    3. 日期时间参数处理
    • Spring Boot 3.0对java.time包的支持更友好,默认格式化改进:

      // Spring Boot 3.0 直接支持 LocalDate/LocalDateTime 自动转换
      @GetMapping("/events")
      public List<Event> getEvents(@RequestParam LocalDate date) { ... }
      

    三、响应处理的变化

    1. @ResponseBody 与 @RestController
    • 无变化:两者在 Spring Boot 3.0 中继续沿用
    1. 响应状态码设置
    // Spring Boot 2.0:使用 ResponseEntity 设置状态码
    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody User user) {
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
    
    // Spring Boot 3.0:支持 @ResponseStatus 直接标注方法
    @PostMapping("/users")
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@RequestBody User user) { ... }
    
    3. 响应式编程(WebFlux)
    • Spring Boot 3.0对响应式编程的支持更完善:

      // 返回 Flux/Mono(Spring Boot 2.0 和 3.0 均支持)
      @GetMapping("/users")
      public Flux<User> getAllUsers() { ... }
      

    四、新增注解与特性

    1. @ParameterObject(实验性)
    • Spring Boot 3.0 支持将多个请求参数绑定到一个对象:

      // 绑定所有请求参数到 UserQuery 对象
      @GetMapping("/users")
      public List<User> searchUsers(@ParameterObject UserQuery query) { ... }
      
    1. @Nullable 参数注解
    • 明确标注参数可为空:

      @GetMapping("/items")
      public List<Item> getItems(@RequestParam(required = false) @Nullable String category) { ... }
      
    1. HTTP 方法改进
    • Spring Boot 3.0支持`@HttpExchange作为通用 HTTP 请求注解:

      // 等效于 @GetMapping
      @HttpExchange(method = HttpMethod.GET, path = "/info")
      public String getInfo() { ... }
      

    五、弃用与移除的特性

    1. @CrossOrigin 部分属性弃用
      • maxAge 属性被弃用,推荐使用 allowedOriginPatterns 替代 origins
    2. JAXB 支持移除
      • Spring Boot 3.0 移除了对 JAXB(Java Architecture for XML Binding)的默认支持

    六、示例对比

    Spring Boot 2.0 控制器示例

    import org.springframework.web.bind.annotation.*;
    import javax.validation.Valid;
    
    @RestController
    @RequestMapping("/api/v1")
    public class UserController {
    
        @GetMapping("/users/{id}")
        public ResponseEntity<User> getUser(@PathVariable("id") Long userId) {
            // ...
        }
    
        @PostMapping("/users")
        @ResponseStatus(HttpStatus.CREATED)
        public User createUser(@Valid @RequestBody User user) {
            // ...
        }
    }
    

    Spring Boot 3.0 控制器示例

    import org.springframework.web.bind.annotation.*;
    import jakarta.validation.Valid;
    
    @RestController
    @RequestMapping("/api/v1")
    public class UserController {
    
        @GetMapping("/users/{id}")
        public User getUser(@PathVariable Long id) {  // 简化路径变量绑定
            // ...
        }
    
        @PostMapping("/users")
        @ResponseStatus(HttpStatus.CREATED)
        public User createUser(@Valid @RequestBody User user) {
            // ...
        }
    
        @GetMapping("/search")
        public List<User> searchUsers(@ParameterObject UserQuery query) {  // 参数对象绑定
            // ...
        }
    }
    

    总结

    Spring Boot 3.0 的控制器层变化主要体现在:

    • Java 17+ 强制要求
    • Jakarta EE 命名空间迁移
    • 参数绑定与响应处理的细节优化
    • 响应式编程支持增强
    • 部分旧特性弃用

    升级时需注意依赖版本、命名空间替换及弃用警告。

  2. Java有哪些导包?

    1. 系统核心包java.lang(自动导入,包含基本类型、字符串、系统类等,如StringSystem )。
    2. 集合相关java.util(集合框架,如ListMapArrayListHashMap等 )。
    3. IO 操作java.io(输入输出,如FileInputStreamOutputStream );java.nio(非阻塞 IO 相关,更高效处理 IO )。
    4. 网络编程java.net(网络相关类,如SocketServerSocketURL )。
    5. 数据库操作java.sql(JDBC 相关,如ConnectionStatementResultSet );javax.sql(扩展 JDBC 功能 )。
    6. 并发编程java.util.concurrent(并发工具类,如ExecutorThreadPoolExecutorConcurrentHashMap )。
    7. GUI 开发(可选场景 )java.awtjavax.swing(图形界面开发相关类 )。
  3. redis场景:用户一天可以重置3次密码

    以用户 ID 为 key,存储用户当天已重置密码的次数,结构如user:reset_pwd_count:{userId} 。每次用户发起重置密码请求时,先通过GET命令获取当前次数,若小于 3 则执行重置逻辑,之后用INCR命令自增次数;若达到 3 次则拒绝操作。同时,利用 Redis 的过期时间(expire) ,每天凌晨或用户当天第一次操作时,设置 key 的过期时间为 1 天(86400 秒 ),确保次数统计按天重置。

  4. 微服务:本地开发环境别人误请求到你的接口怎么处理?

    在微服务本地开发环境中,若其他开发者或服务误请求到你的本地接口(例如因配置错误、服务注册冲突、网关路由错误等),可能导致对方调试混乱(如返回错误数据)或你的本地服务被干扰(如频繁无效请求)。此时需从预防处理两方面解决,确保开发环境稳定。

    一、核心原则:隔离与识别

    误请求的本质是 “环境混淆”—— 请求方本应调用公共环境(如测试环境)或其他开发者的服务,却错误指向了你的本地服务。解决的核心是:

    1. 让你的本地服务易于识别(避免被误认);
    2. 限制非预期请求的影响(避免干扰开发);
    3. 快速定位并告知请求方错误(减少协作成本)。

    二、具体处理方案

    (一)预防:从源头减少误请求
    1. 明确区分本地服务与公共服务的标识

      • 服务名 / 路径添加本地标识

        :在本地服务的名称或接口路径中加入个人标识(如你的名字缩写),例如:

        • 原服务名 user-service → 本地改为 user-service-zhangsan
        • 原接口路径 /user/get → 本地改为 /zhangsan/user/get
          这样请求方若看到含个人标识的路径,可立即意识到请求错误。
      • 响应头添加本地标记:在本地服务的所有响应中加入自定义响应头,例如 X-Local-Developer: zhangsan,请求方通过抓包工具(如 Charles)可快速识别是否调用了本地服务。

    2. 严格隔离服务注册环境

      • 本地服务禁止注册到公共注册中心(如测试环境的 Nacos/Eureka),仅注册到本地或团队专属的开发注册中心(见上一篇回答的 “服务发现方案”)。
      • 若必须临时连接公共注册中心,需在服务元数据中添加明确标记(如 environment: local-zhangsan),并告知团队其他成员此时你的服务在公共注册中心的存在。
    3. 网关 / 代理层限制本地服务暴露范围

      • 若使用团队网关或 Nginx 转发,仅允许指定开发者的 IP 或特定标识的请求访问你的本地接口(如通过请求头 X-Developer-Token 验证),非授权请求直接拦截并返回提示。
    (二)发现:快速识别误请求
    1. 本地日志显式告警
      在本地服务的日志中,对所有请求打印来源信息(如请求方 IP、服务名、请求路径),并对非预期的请求(如来自公共环境的 IP、未携带本地标识的请求)用醒目标识(如 [WARNING] 可能是误请求)标注。例如:

      2023-10-01 15:00:00 [INFO] 收到请求:GET /user/get,来源IP:192.168.1.105(同事A的IP,预期)
      2023-10-01 15:00:05 [WARNING] 收到请求:POST /order/create,来源IP:10.0.0.23(测试环境服务器IP,可能是误请求)
      
    2. 主动监控请求来源

      • 使用工具(如 Spring Boot Actuator 的 /metrics 端点、Prometheus+Grafana)监控请求量和来源 IP,若发现来自陌生 IP 或非协作开发者的高频请求,可能是误请求。
      • 对本地服务设置请求阈值(如每分钟超过 100 次非预期请求),触发告警(如弹窗、终端提示音)。
    (三)处理:减少影响并告知对方
    1. 对误请求返回明确提示
      识别到误请求后,不直接返回业务数据,而是返回友好的错误响应,告知请求方 “请求指向了本地开发服务”,例如:

      {
        "code": 400,
        "message": "当前请求指向开发者【zhangsan】的本地服务(非公共环境),请检查服务地址或网关配置是否正确。如需协作调试,请联系 zhangsan@xxx.com",
        "isLocal": true
      }
      

      这样请求方可快速定位错误原因,无需反复排查自身代码。

    2. 临时拦截高频误请求
      若误请求频繁(如每秒数十次),可能影响你的本地开发(如占用 CPU / 内存),可临时通过以下方式拦截:

      • 在代码中对特定来源 IP(如测试环境服务器 IP)的请求直接返回 503(服务不可用),并记录日志;
      • 通过防火墙或 Nginx 临时屏蔽该 IP 对本地端口的访问(调试时再放开)。
    3. 主动联系请求方确认
      根据请求来源 IP 或服务名定位到请求方(可通过团队 IP 分配表或服务负责人清单查询),主动告知对方:
      “你好,检测到你的服务在调用我本地的【user-service】接口(IP:192.168.1.100:8080),可能是配置错误,建议检查网关路由或服务注册中心地址是否指向了开发环境。”

    (四)长期规范:团队协作约定

    为从根本上减少误请求,建议团队制定以下规范:

    1. 环境隔离制度:明确区分生产、测试、开发环境的注册中心、网关地址,禁止本地服务接入非开发环境。

    2. 服务命名规范:本地服务必须包含开发者标识(如 {服务名}-{姓名缩写}),且接口路径统一前缀(如 /dev/{姓名缩写}/{接口路径})。

    3. 协作流程约定:若需调用他人本地服务,需提前沟通并确认对方服务的地址和状态,避免 “盲调”。

    总结

    处理本地接口的误请求,需结合 “预防(标识隔离)- 发现(日志监控)- 处理(提示拦截)- 规范(团队约定)” 四步,既减少对自身开发的干扰,也降低团队协作的沟通成本。核心是让 “本地服务” 有明确的身份标识,让误请求能被快速识别和纠正。

  5. 微服务:子模块继承了父模块中的依赖,怎么排除父模块中某个依赖的相关包?

    • 在 Maven 中,子模块的pom.xml里,对要排除的依赖使用<exclusions>标签。示例:
    <dependency>
        <groupId>父依赖的groupId</groupId>
        <artifactId>父依赖的artifactId</artifactId>
        <version>父依赖版本</version>
        <exclusions>
            <exclusion>
                <groupId>要排除的包的groupId</groupId>
                <artifactId>要排除的包的artifactId</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
    • Gradle 中,在dependencies块里,通过exclude排除:
    implementation('父依赖的groupId:父依赖的artifactId:父依赖版本') {
        exclude group: '要排除的包的groupId', module: '要排除的包的artifactId'
    }
    
  6. try{}catch{}中,e.print会打印日志吗?

    e.printStackTrace()会打印异常堆栈信息到标准错误输出(一般是控制台),但这不是正规的日志记录方式(不会输出到日志文件、不好做日志级别控制等 )。正规做法是用日志框架(如 Log4j2、SLF4J + Logback ),像logger.error(“异常信息”, e)` ,能按日志配置输出到指定位置、设置不同级别记录。

  7. mysql:假设表中有两个varchar字段,在查询的时候用的是=进行筛选,什么情况会出现索引失效?

    • 字段使用函数或表达式:如WHERE UPPER(column1) = 'VALUE' ,对字段做了函数处理,索引无法利用。
    • 类型隐式转换:若字段是varchar,查询时传数值等其他类型,如WHERE column2 = 123(实际应WHERE column2 = '123' ),触发隐式转换,索引失效。
    • 索引列前缀未命中:若建索引时指定了前缀长度(如INDEX idx(column1(10)) ,只取前 10 个字符建索引 ),查询条件若涉及超过前缀长度的精确匹配,可能失效(需看具体数据分布和查询情况 )。
    • 全表扫描更优时:数据量少或查询条件匹配数据多,MySQL 优化器可能选择不走索引,直接全表扫描。
  8. mysql:一对多、多对多在xml文件中用什么 标签?

    • 一对多(MyBatis 中 ):在映射文件(xml )里,用<collection>标签。比如主表实体对应从表多个实体,在主表 resultMap 中,通过<collection property="从表集合属性名" ofType="从表实体类" column="关联字段"> ,配置关联查询语句(嵌套查询或联合查询 ),建立一对多关系映射。
    • 多对多(MyBatis 中 ):需借助中间表,拆分为两个一对多。先在对应实体的 resultMap 里,用<collection> ,关联中间表与另一张表,实现多对多的映射。或者说,从实际映射操作看,多对多本质通过两个一对多配置,借助中间表关联,核心还是<collection>标签(以及可能配合<association>等,看具体关联方式 ) 。
  9. oss:前端直传,怎么请求后端返回的token相关?

    • 交互流程:前端先调用后端的 “获取 OSS 直传 token” 接口(一般是 HTTP 接口,如 RESTful 接口 ),传必要参数(如用户标识、业务标识等 ,用于后端鉴权和生成对应权限的 token )。后端接收请求后,校验身份(如通过登录态 token ),然后调用 OSS SDK(如阿里云 OSS 的 Java SDK ),生成包含上传权限(如允许上传的 bucket、object 路径、有效期等 )的临时 token(如 OSS 的 STS token ),将 token 信息(包括 accessKeyId、accessKeySecret、securityToken、过期时间等 )封装为 JSON 返回给前端。前端拿到这些 token 信息后,使用 OSS 前端 SDK(如 ali-oss ),配置这些参数,直接与 OSS 服务端交互进行文件上传。
  10. 有哪些加密算法?比如用户登录时,怎么加密解密的?

    1. 加密算法分类及常见算法:
      • 对称加密:加密和解密用相同密钥,如 AES(高级加密标准 ,安全性高,应用广泛 )、DES(数据加密标准,较老旧,安全性不如 AES )。
      • 非对称加密:有公钥和私钥,公钥加密私钥解密,或私钥加密公钥解密,如 RSA(常用于密钥交换、数字签名 )、ECC(椭圆曲线加密,效率高,适合移动等场景 )。
      • 哈希算法(单向,一般用于验证 ):如 MD5(已不太安全,易碰撞 )、SHA - 1(逐渐被弃用 )、SHA - 256(安全,常用作密码哈希 )、BCrypt(专门用于密码存储,自动处理盐值 )。
    2. 用户登录加密场景:
      • 密码存储与验证(注册时 ):一般用哈希算法,如 BCrypt。用户注册时,前端将密码(可简单做 HTTPS 传输加密 )传到后端,后端用 BCrypt 的hash方法,结合随机盐值,生成哈希值存入数据库。登录时,用户输入密码,后端用相同 BCrypt 的verify方法,拿数据库存的哈希值和用户输入密码做校验,匹配则登录成功。
      • 传输过程(可选加密 ):若不用 HTTPS,可在前端用对称加密(如 AES )对密码等敏感信息加密,后端用相同密钥解密;但更推荐直接用 HTTPS(基于 SSL/TLS,结合非对称加密交换密钥、对称加密传输数据 )保障传输安全。
      • token 相关(如 JWT ):生成 JWT 时,可选用 HS256(对称加密 ,用服务端密钥签名 )或 RS256(非对称加密 ,用私钥签名,公钥验签 )等算法,保障 token 传输和验证过程的安全性 。
  11. spring security原理?

    Spring Security 是 Java 领域流行的 Web 应用安全管理框架,核心功能包括认证和授权,其原理如下:

    过滤器机制

    • 入口过滤器:Spring Security 处理请求的入口是DelegatingFilterProxy,它实现了javax.servlet.Filter接口,本身不处理请求,而是将请求交给代理对象FilterChainProxy 。在早期项目中需在web.xml配置,Spring Boot 项目中则以ServletContainerInitializer为基础配置,FilterChainProxy采用延迟加载,首次请求时才初始化并注入到DelegatingFilterProxy
    • 双过滤器链:Web 应用中存在两条过滤器链,一条是基于 Servlet 标准、生命周期由 Web 容器托管的过滤器链;另一条是 Spring Security 框架内部、由 Spring 容器托管的虚拟过滤器链。FilterChainProxy内部维护虚拟过滤器链,遍历其中的过滤器处理 Web 请求,且支持插入或替换过滤器 ,过滤器顺序会影响安全校验结果。

    认证原理

    • 认证方式多样:支持基于表单的认证(用户在登录页面输入用户名和密码,与存储在数据库等位置的信息匹配 )、HTTP 基本认证、基于 Token 的认证(如 JWT )等多种认证方式。
    • 认证流程:以基于表单认证为例,用户提交用户名和密码后,UsernamePasswordAuthenticationFilter过滤器拦截请求,将用户名、密码等参数封装成UsernamePasswordAuthenticationTokenAuthenticationManager作为认证核心接口,其实现类ProviderManager负责验证用户提供的认证信息。验证逻辑中,会调用UserDetailsService接口的loadUserByUsername(String username)方法从存储(如数据库 )中加载用户信息(包括用户名、密码、角色等 ),并通过PasswordEncoder对密码进行校验(常见的如BCryptPasswordEncoder ,采用加盐哈希算法 )。若验证通过,生成包含用户信息和权限的已认证Authentication对象。

    授权原理

    • 授权决策:过滤器链处理请求过程中,将创建的令牌送入最后一个过滤器FilterSecurityInterceptor进行最终授权验证。它依据配置的访问规则(如基于角色或权限 )判断用户是否有权限访问请求的资源。
    • 基于角色授权:角色与用户记录关联,在UserDetails对象中以GrantedAuthority对象形式表示角色信息。在配置中使用.hasRole().hasAnyRole()方法实现,比如.antMatchers("/admin/**").hasRole("ADMIN"),表示只有具有 “ADMIN” 角色的用户才能访问 “/admin/” 路径下的资源 。
    • 基于权限授权:权限比角色粒度更细,同样以GrantedAuthority对象表示,常采用 “权限名:资源名” 格式。配置时使用.hasAuthority().hasAnyAuthority()方法,例如限制对特定资源的读写权限。

    安全上下文

    认证成功后,生成的Authentication对象会存入SecurityContext,默认以ThreadLocal方式保存,使得同一个线程中的不同方法能方便访问当前用户认证信息 。请求处理完成后,SecurityContextPersistenceFilter会将SecurityContextSession绑定(如将SecurityContext存入Session ),下次请求时,若Session中有SecurityContext,会取出放入SecurityContextHolder,避免重复身份认证 。

    其他特性原理

    • CSRF 防护:通过在表单中包含唯一的 CSRF 令牌,提交表单时验证该令牌,防止恶意网站利用用户已登录会话进行非法操作 。
    • 会话管理:能处理会话创建、销毁、超时等情况,例如用户长时间未活动,自动使会话过期并要求重新登录。
  12. 怎么查看当前有哪些Java程序正在执行,注意不是看进程是程序名称?

    Windows 系统

    • 任务管理器:
      • 按下 Ctrl + Shift + Esc 组合键打开任务管理器。
      • 切换到 “详细信息” 选项卡,找到所有 java.exe 进程。
      • 右键点击某个 java.exe 进程,选择 “属性” - “详细信息”,查看命令行参数。比如命令行是 java -jar C:\myproject\myapp.jar ,那正在执行的 Java 程序就是 myapp.jar;若是 java -cp C:\lib\*;C:\classes com.example.MyMainClass , 则正在执行的 Java 程序名称是 com.example.MyMainClass
    • 使用 JDK 自带工具:
      • 打开命令提示符,进入 JDK 安装目录的 bin 文件夹(若已配置环境变量则可直接执行 )。
      • 执行 jps -l 命令,该命令会列出所有正在运行的 Java 虚拟机进程的进程 ID 和主类或 JAR 包的完整路径。比如输出 12345 com.example.demo.DemoApplication ,这里 com.example.demo.DemoApplication 就是正在执行的 Java 程序的主类;若输出 67890 C:\projects\myapp.jar ,则表示正在执行 myapp.jar 程序。

    Linux 系统

    • 使用 jps 命令:
      • 打开终端,直接执行 jps -l 命令(前提是已配置好 JDK 环境变量 )。
      • 它会显示正在运行的 Java 进程的进程 ID 和对应的主类或 JAR 包的完整路径。例如显示 10086 com.example.biz.Startup ,这意味着 com.example.biz.Startup 是正在执行的 Java 程序主类;如果显示 20000 /home/user/apps/myapp.jar , 则正在执行的是 myapp.jar 程序。
    • ps 命令结合 grep:
      • 在终端执行 ps -ef | grep java 命令,会列出所有与 Java 相关的进程信息。
      • 从输出结果中,找到启动 Java 程序的命令行参数。比如输出中包含 java -jar /var/apps/myproject.jar ,那正在执行的 Java 程序就是 myproject.jar;若包含 java -cp /path/to/classes com.company.app.Main , 则正在执行的 Java 程序名称是 com.company.app.Main

    macOS 系统

    • 活动监视器:
      • 打开 “应用程序” - “实用工具” - “活动监视器”。
      • 在 “窗口” 菜单中选择 “CPU” 选项卡,找到所有 java 进程。
      • 选中一个 java 进程,点击 “窗口” - “检查器”,在弹出的窗口中查看 “打开的文件和端口”,从中找到启动 Java 程序的命令行,进而确定程序名称,如 java -jar /Users/user/Documents/app.jar ,则正在执行的 Java 程序是 app.jar
    • 使用 jps 和 ps 命令:
      • 与 Linux 系统类似,通过在终端执行 jps -lps -ef | grep java 命令,根据输出结果中的命令行参数确定正在执行的 Java 程序名称 ,操作方法和 Linux 下一致。
  13. mvn中,packageinstall有什么区别?

    在 Maven 中,packageinstall是两个常用的生命周期阶段,它们的主要区别在于构建产物的处理方式作用范围。以下是详细对比:

    1. package 阶段

    • 作用:将项目源代码编译并打包为最终的分发格式(如 JAR、WAR、ZIP 等)。
    • 输出位置:产物默认放在项目的target目录下(如target/my-project-1.0.0.jar)。
    • 生命周期包含validate → initialize → compile → test → package
    • 适用场景:
      • 本地开发时快速验证打包是否正常。
      • 仅需要在当前项目内部使用构建产物。

    示例命令

    mvn package
    

    2. install 阶段

    • 作用:在package的基础上,将构建产物安装到本地 Maven 仓库(默认位于~/.m2/repository)。
    • 输出位置:
      • 产物保存到本地仓库,路径由项目的groupIdartifactIdversion决定(如~/.m2/repository/com/example/my-project/1.0.0/my-project-1.0.0.jar)。
      • 同时生成 POM 文件和元数据,供其他项目依赖。
    • 生命周期包含validate → initialize → compile → test → package → install
    • 适用场景:
      • 本地多模块项目间的依赖(子模块依赖父模块)。
      • 本地开发的库需要被其他项目引用。

    示例命令

    mvn install
    

    核心区别对比表

    特性packageinstall
    构建产物位置仅在项目的target目录下同时安装到本地 Maven 仓库
    其他项目能否依赖否(仅当前项目可用)是(本地仓库全局可用)
    典型使用时机快速测试打包多模块项目开发或本地库开发
    执行速度较快(不涉及仓库操作)稍慢(需写入仓库)

    延伸:与 deploy 的区别

    • deploy:将构建产物发布到远程 Maven 仓库(如公司内部 Nexus 或 Maven Central),供团队或开源社区共享。需额外配置distributionManagement

    总结

    • 用 package:如果你只是想快速验证项目打包结果。
    • 用 install:如果你需要在本地环境中让其他项目依赖当前项目。
    • 用 deploy:如果你需要将项目发布到远程仓库供多人使用。

面试问题持续更新中。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

章鱼飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值