- Spring Boot 3.2.5
- JDK 21
Key Changes and Migration Steps
1. Namespace Shift: javax to jakarta
Spring Boot 3 and Spring Framework 6 mandate a migration from the javax.* namespace to the jakarta.* namespace for specifications like Servlet and JPA. This change is a consequence of the Java EE platform's evolution under the Eclipse Foundation, now branded as Jakarta EE.
Action Required:
- Update Imports: Globally replace
import javax.*statements with their correspondingimport jakarta.*equivalents. For example, changeimport javax.servlet.*toimport jakarta.servlet.*. - Add Jakarta Annotations Dependency: Ensure you have the
jakarta.annotation-apidependency.
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.0</version>
</dependency>
2. Spring Framework Specifics
@PathVariable Parameter Names:
In Spring Boot 3, the @PathVariable annotation requires explicit specification of the parameter name. The framework no longer infers it automatically, especially when parameter names are not preserved during compilation.
Action Required: Ensure all @PathVariable annotations include the value attribute.
// Incorrect:
@GetMapping("/projects/{projectCode}")
public ResponseEntity<?> getProject(@PathVariable Long projectCode) { ... }
// Correct:
@GetMapping("/projects/{projectCode}")
public ResponseEntity<?> getProject(@PathVariable(value = "projectCode") Long projectCode) { ... }
3. Mybatis-Plus Dependency Update
Mybatis-Plus requires a version update, and its starter dependency artifact ID has changed.
Action Required:
- Update to Mybatis-Plus version 3.5.5 or later.
- Change the Maven dependency coordinate from
mybatis-plus-boot-startertomybatis-plus-spring-boot3-starter.
<!-- Mybatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.5.5</version>
</dependency>
4. Hibernate Validator Compatibility
Upgrading to Spring Boot 3 may lead to issues with older versions of Hibernate Validator, manifesting as errors like java: 无法访问javax.validation.ConstraintValidator.
Action Required: Update the Hibernate Validator dependency to a compatible version, such as 8.0.1.Final.
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>8.0.1.Final</version>
</dependency>
5. Lombok Compatibility
Incompatibility issues with Lombok can arise, potentially causing errors like java: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCImport does not have member field ‘com.sun.tools.javac.tree.JCTree qualid’.
Action Required: Ensure you are using Lombok version 1.18.30 or later.
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
6. Logging Configuration (Logback)
Version conflicts or misconfigurations with Logback can lead to errors like java.lang.AbstractMethodError: Receiver class org.springframework.boot.logging.logback.RootLogLevelConfigurator does not define or inherit an implementation of the resolved method ‘abstract void configure(ch.qos.logback.classic.LoggerContext)’ of interface ch.qos.logback.classic.spi.Configurator. or SLF4J warnings about missing providers.
Action Required: Align your SLF4J and Logback dependencies to compatible versions. Using the versions specified in the pom.xml example below is recommended.
<!-- SLF4J -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.13</version> <!-- Or a later compatible version -->
</dependency>
<!-- Use a binding that matches your logging framework, e.g., logback-classic -->
<!-- If using logback, slf4j-log4j12 is usually not needed -->
<!-- Logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.6</version> <!-- Or a later compatible version -->
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.5.6</version> <!-- Or a later compatible version -->
</dependency>
Ensure that only one SLF4J binding is present and compatible with your chosen logging framework (e.g., Logback).
7. Handling Unresolved Parameters in Exception Handlers
An error like java.lang.IllegalStateException: Could not resolve parameter [1]... No suitable resolver in exception handlers often occurs when method parameter names are not available at runtime. This is exacerbated by compile-time settings that strip parameter names.
Action Required:
- Ensure your Java compiler is configured to retain parameter names (e.g., using the
-parametersflag during compilation). - For methods that require parameter resolution, explicitly use annotations like
@RequestParamor@RequestBodyto define the parameter's binding.
Recommended Project Structure (Dependancy Management)
To streamline version management and ensure consistency across dependencies, consider using a dedicated module (e.g., a Bill of Materials - BOM) to manage external dependency versions.
Example pom.xml Snippet for Dependency Management
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>3.2.5</spring-boot.version>
<mysql-connector.version>8.0.33</mysql-connector.version>
<mybatis-plus.version>3.5.5</mybatis-plus.version>
<slf4j.version>2.0.13</slf4j.version>
<logback.version>1.5.6</logback.version>
<jackson.version>2.16.1</jackson.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-collections4.version>4.4</commons-collections4.version>
<guava.version>33.0.0-jre</guava.version>
<hibernate-validator.version>8.0.1.Final</hibernate-validator.version>
<commons-io.version>2.11.0</commons-io.version>
<jakarta.annotation.version>2.1.0</jakarta.annotation.version>
</properties>
<!-- Dependency Management Section -->
<dependencyManagement>
<dependencies>
<!-- Spring Boot Parent POM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<!-- Google Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- MySQL Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql-connector.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Mybatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- SLF4J API -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<!-- Apache Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- Jakarta Annotations -->
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>${jakarta.annotation.version}</version>
</dependency>
</dependencies>
</dependencyManagement>