Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Spring Boot Core Concepts and Development Foundations

Tech Aug 21 13
  • Web Development: Spring Web MVC, Spring MVC, Spring WebFlux for building reactive and traditional web applications.
  • Data Access: Spring Data, Spring Data JPA, Spring Data Redis, Spring Data MongoDB streamline interaction with different data stores.
  • Security: Spring Security provides robust authentication and authorization features.
  • Rapid Application Development: Spring Boot simplifies project setup and configuration.
  • Microservices: Spring Cloud offers a collection of tools for building distributed systems.

Understanding the Spring Framework

At its core, Spring is an open-source, lightweight framework created to address the complexity of enterprise Java development. It fundamentally relies on a three-tier architectural approach, often integrating with the Model-View-Controller (MVC) pattern:

  • Presentation Layer (e.g., Spring MVC): Handles client requests and sends back responses. Spring MVC separates application logic into three distinct components:
    • View: Responsible for rendering data to the user and capturing user input.
    • Model: Represents the application's data and business logic, managing data persistence and business rules.
    • Controller: Acts as an intermediary, processing user requests, invoking business logic (model), and selecting the appropriate view.
  • Business Logic Layer (Spring IoC): Manages core application business rules and operations. Spring's Inversion of Control (IoC) container is central here.
    • Inversion of Control (IoC): A design principle where the framework (Spring container) controls the creation and lifecycle management of objects, rather than the objects themselves. Instead of an object actively looking up its dependencies (the "normal" flow), the container "inverts" this control by injecting dependencies into the object.
    • Dependency Injection (DI): A specific implementation of IoC where the dependencies of a component are provided to it by an external entity (the Spring container), rather than the component creating them itself. This makes components more modular and testable.
    • Aspect-Oriented Programming (AOP): A programming paradigm that modularizes cross-cutting concerns (e.g., logging, transaction management, security) by encapsulating them into aspects. This helps in keeping business logic clean and focused.
  • Persistence Layer (e.g., Spring JDBC, ORM frameworks like JPA/Hibernate, MyBatis): Manages data storage and retrieval, persisting application data to databases.

Introducing Spring Boot

Spring Boot is an extension of the Spring Framework that aims to simplify the development of production-ready Spring applications. Its primary philosophy is "Convention Over Configuration" (CoC).

Convention Over Configuration (CoC)

CoC is a paradigm that suggests developers should follow predefined conventions within a framework rather than spending extensive time on explicit configurations. This approach significantly streamlines development, reduces potential configuration errors, and boosts productivity, allowing developers to concentrate on business logic.

In Spring Boot, CoC manifests through:

  • Automatic Configuration: Based on classpath dependencies, Spring Boot automatically configures common functionalities like web servers, database connections, and security. For instance, including spring-boot-starter-web automatically configures an embedded Tomcat server and Spring MVC.
  • Default Project Structure: Spring Boot applications typically have a main class annotated with @SpringBootApplication. Spring Boot scans this class and its sub-packages for components, eliminating the need to explicitly declare every bean.
  • Externalized Configuration: Properties in application.properties or application.yml are automatically loaded and used to customize application behavior.
  • Embedded Servers: Spring Boot includes embedded web servers (Tomcat, Jetty, Undertow), removing the need for separate server deployments.
  • Logging Setup: Default logging systems like Logback are pre-configured, requiring minimal developer intervention for basic logging.

Key Benefits of Spring Boot

  • Simplifies Spring development for rapid project initiation.
  • Offers "opinionated" defaults for faster setup, reducing boilerplate configuration.
  • Integrates embedded servers, simplifying web application deployment.
  • Minimizes XML configuration and code generation requirements.

Creating a Spring Boot Project

Before diving into project creation, it's useful to briefly understand common architectural styles:

  • Monolithic Architecture: All application services are bundled into a single deployment unit (e.g., a WAR file). While simple to develop and deploy initially, it can become challenging to scale and maintain as the application grows.
  • Microservices Architecture: An application is composed of a suite of small, independently deployable services that communicate via lightweight mechanisms (like HTTP/REST or message brokers). This offers better scalability, resilience, and independent development.

Spring Boot is highly suitable for building microservices, but can also be used for monolithic applications.

Project Generation

The most common way to create a Spring Boot project is through the Spring Initializr, a web-based tool. Integrated Development Environments (IDEs) like IntelliJ IDEA often embed this functionality directly.

When creating a project, you'll select build tools (Maven/Gradle), language (Java/Kotlin/Groovy), Spring Boot version, and various "starter" dependencies. For Java versions, modern Spring Boot releases primarily support JDK 17 and JDK 21. If using older JDKs (e.g., JDK 8), you might need to adjust the Spring Initializr service URL in your IDE (e.g., to a mirror that supports older Spring Boot versions compatible with JDK 8).

Project Structure and Core Components

  • @SpringBootApplication: This annotation on the main application class marks it as the entry point for a Spring Boot application. It's a meta-annotation that combines @SpringBootConfiguration, @EnableAutoConfiguration, and @ComponentScan.
  • Starter Dependencies: Spring Boot dependencies typically follow the naming convention spring-boot-starter-* (e.g., spring-boot-starter-web). These starters bundle common dependencies needed for specific functionalities, simplifying dependency management.
  • Packaging: Spring Boot applications can be packaged as executable JAR files, which include the embedded server and all dependencies.

Configuration with application.properties and application.yml

Spring Boot uses global configuration files, primarily application.properties (key-value pairs) or application.yml (YAML format).

Common Configuration Examples

To change the default web server port or customize the startup banner:

# --- application.properties ---
server.port=8081
# To use a custom banner, create a 'banner.txt' file in src/main/resources
# and place ASCII art content generated from sites like https://www.bootschool.net/ascii-art/search

# --- application.yml ---
server:
  port: 8081
# To use a custom banner, create a 'banner.txt' file in src/main/resources
# and place ASCII art content generated from sites like https://www.bootschool.net/ascii-art/search

YAML Specifics

YAML offers a more structured and readable way to represent hierarchical data compared to properties files. Its strictly sensitive to indentation.

# Example of nested configuration in YAML
app:
  user:
    display-name: "Jane Doe"
    contact-email: "jane.doe@example.com"
  preferences:
    theme-mode: "dark"
    enable-notifications: true

# Example of a list in YAML
favorite-fruits:
  - Apple
  - Banana
  - Cherry

# Inline list syntax
holiday-destinations: [Paris, Tokyo, Rome]

You can inject these configuration values into Java objects using @ConfigurationProperties or into individual fields using @Value.

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "app.user")
public class UserProfileSettings {
    private String displayName;
    private String contactEmail;

    // Getters and Setters
    public String getDisplayName() { return displayName; }
    public void setDisplayName(String displayName) { this.displayName = displayName; }
    public String getContactEmail() { return contactEmail; }
    public void setContactEmail(String contactEmail) { this.contactEmail = contactEmail; }
}

// In another component
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
public class ApplicationPreferencesService {
    @Value("${app.preferences.theme-mode}")
    private String currentThemeMode;

    public void logApplicationTheme() {
        System.out.println("Application theme is set to: " + currentThemeMode);
    }
}

To load properties from a custom file (not application.properties/application.yml), use @PropertySource:

import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Value;

@Component
@PropertySource("classpath:custom-app.properties")
public class CustomConfigurationLoader {
    @Value("${service.api.key}")
    private String serviceApiKey;

    public String getServiceApiKey() {
        return serviceApiKey;
    }
}

Understanding Spring Boot Auto-Configuration

Spring Boot's auto-configuration is a cornerstone feature that significantly reduces the manual setup required. Here's a breakdown:

  1. **Dependency Management (spring-boot-starter-parent and spring-boot-dependencies):**The spring-boot-starter-parent in your pom.xml inherits from spring-boot-dependencies. This parent POM acts as a Bill of Materials (BOM), managing versions for a vast array of common libraries and Spring modules. This ensures compatible dependency versions across your project.

  2. **Starter Dependencies:**A "starter" is a set of convenient dependency descriptors that you can include in your application. For example, spring-boot-starter-web includes everything needed for a web application, including an embedded web server, Spring MVC, and other related dependencies. They abstract away the need to manually add and manage transitive dependencies.

  3. @SpringBootApplication: The OrchestratorThe main class of a Spring Boot application is annotated with @SpringBootApplication. This meta-annotation internally comprises:

    • @SpringBootConfiguration: A specialized form of @Configuration, indicating that the class provides Spring Bean definitions.
    • @EnableAutoConfiguration: This is the magic behind auto-configuration. It triggers the auto-configuration process, which attempts to configure Spring beans based on the classpath, other beans, and property settings.
      • Internally, @EnableAutoConfiguration uses @AutoConfigurationPackage (which itself uses an @Import to register the package of the annotated class as a base for component scanning) and more importantly, @Import(AutoConfigurationImportSelector.class).
      • AutoConfigurationImportSelector reads a list of potential auto-configuration classes from META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (or historically META-INF/spring.factories in older versions) within Spring Boot's libraries.
    • @ComponentScan: Enables component scanning within the current package and its sub-packages, automatically detecting and registering components (like @Controller, @Service, @Repository, @Component).

Conclusion: Spring Boot's auto-configuration mechanism scans for relevant auto-configuration classes during application startup (from AutoConfiguration.imports files). Each auto-configuration class typically has @ConditionalOn... annotations. These conditions determine whether a particular auto-configuration should be applied based on the presence of classes, beans, or property values. If the conditions are met (e.g., a specific starter dependency is on the classpath), the corresponding configurations are activated.

Managing Multiple Configuration Profiles

Spring profiles allow you to define environment-specific configurations (e.g., development, test, production) and activate them as needed. This helps manage different settings for databases, logging, and external services without modifying code.

Defining Profile-Specific Files

You can create configuration files named application-{profile-name}.yml or application-{profile-name}.properties in your src/main/resources directory:

  • application.yml (or application.properties): Base configuration, or defines the active profile.
  • application-dev.yml: Configuration specific to the "dev" profile.
  • application-prod.yml: Configuration specific to the "prod" profile.

To activate a profile, you can set the spring.profiles.active property in application.yml:

# application.yml
spring:
  profiles:
    active: dev # Activates the 'dev' profile

Alternatively, profiles can be activated via JVM arguments (-Dspring.profiles.active=prod) or environment variables.

Maven Profile Management for Build-Time Activation

For more complex scenarios, especially when dealing with different resource directories for each profile or packaging, Maven profiles can be used. This allows you to select which profile's resources are included during the build process.

<!-- Example pom.xml snippet for Maven profiles -->
<project>
    <groupId>com.example</groupId>
    <artifactId>my-application</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <profiles>
        <profile>
            <id>dev-env</id>
            <properties>
                <activeResourceProfile>dev</activeResourceProfile>
            </properties>
        </profile>
        <profile>
            <id>prod-env</id>
            <properties>
                <activeResourceProfile>prod</activeResourceProfile>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
    </profiles>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <excludes>
                    <!-- Exclude all profile-specific config subfolders to prevent conflicts -->
                    <exclude>config/dev/**</exclude>
                    <exclude>config/prod/**</exclude>
                </excludes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources/config/${activeResourceProfile}</directory>
                <!-- Include only the resources for the currently active Maven profile -->
            </resource>
        </resources>
    </build>
</project>

In this example, the activeResourceProfile property determines which subdirectory within src/main/resources/config/ is included during the build. You would then run Maven with mvn clean package -P dev-env or mvn clean package -P prod-env.

Spring Beans

In Spring, a "Bean" refers to an object that is instantiated, assembled, and managed by the Spring IoC container. These are the fundamental building blocks of any Spring application. Beans are typically defined by configuration metadata (either XML or annotations) and are then wired together to form the application.

REST APIs and RESTful Principles

Representational State Transfer (REST) is an architectural style for distributed hypermedia systems. It emphasizes that a web service should expose resources, and operations on those resources should be performed using standard HTTP methods. The "state" of a resource is "transferred" between client and server, typically via a representation like JSON or XML.

An API adhering to REST principles is called a RESTful API. Key characteristics include:

  • Stateless: Each request from a client to a server must contain all the information needed to understand the request. The server should not store any client context between requests.
  • Client-Server: Clear separation of concerns between the client and the server.
  • Uniform Interface: A standardized way of interacting with resources, primarily through HTTP methods (GET, POST, PUT, DELETE) and self-descriptive messages.
  • Resource-Oriented: Data and functionality are exposed as resources, identified by unique URIs (e.g., /products, /users/123).

In Spring Boot, you build RESTful APIs using @RestController, which is a convenience annotation that combines @Controller and @ResponseBody (meaning the return value of methods should be bound directly to the web response body).

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/api/catalog/items")
public class ItemCatalogController {

    private final List<String> catalogItems = new ArrayList<>();

    public ItemCatalogController() {
        catalogItems.add("Gadget-X");
        catalogItems.add("Widget-Y");
        catalogItems.add("Doodad-Z");
    }

    @GetMapping
    public List<String> getAllItems() {
        return catalogItems;
    }

    @GetMapping("/{index}")
    public ResponseEntity<String> getItemByIndex(@PathVariable int index) {
        if (index >= 0 && index < catalogItems.size()) {
            return new ResponseEntity<>(catalogItems.get(index), HttpStatus.OK);
        }
        return new ResponseEntity<>("Item not found", HttpStatus.NOT_FOUND);
    }

    @PostMapping
    public ResponseEntity<String> addNewItem(@RequestBody String newItemName) {
        catalogItems.add(newItemName);
        return new ResponseEntity<>("Item added: " + newItemName, HttpStatus.CREATED);
    }

    @PutMapping("/{index}")
    public ResponseEntity<String> updateItem(@PathVariable int index, @RequestBody String updatedItemName) {
        if (index >= 0 && index < catalogItems.size()) {
            String oldItemName = catalogItems.set(index, updatedItemName);
            return new ResponseEntity<>("Item '" + oldItemName + "' updated to '" + updatedItemName + "'", HttpStatus.OK);
        }
        return new ResponseEntity<>("Item not found for update", HttpStatus.NOT_FOUND);
    }

    @DeleteMapping("/{index}")
    public ResponseEntity<String> removeItem(@PathVariable int index) {
        if (index >= 0 && index < catalogItems.size()) {
            String removedItemName = catalogItems.remove(index);
            return new ResponseEntity<>("Item '" + removedItemName + "' deleted", HttpStatus.NO_CONTENT);
        }
        return new ResponseEntity<>("Item not found for deletion", HttpStatus.NOT_FOUND);
    }
}

Data Mapping Interfaces

When interacting with databases, mapping query results to Java objects is a common task:

  • **Spring's RowMapper Interface:**In Spring's JDBC template, the RowMapper interface is used to map each row of a java.sql.ResultSet to an object. It provides a flexible way to convert raw database query results into application-specific Java objects, abstracting away the boilerplate code of manually iterating through a ResultSet.

    import org.springframework.jdbc.core.RowMapper;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    
    public class SampleDataMapper implements RowMapper<SampleRecord> {
       @Override
       public SampleRecord mapRow(ResultSet rs, int rowNum) throws SQLException {
           SampleRecord record = new SampleRecord();
           record.setRecordId(rs.getLong("record_id"));
           record.setDataField(rs.getString("data_field"));
           record.setNumericValue(rs.getInt("numeric_val"));
           return record;
       }
    }
    
    
  • **MyBatis-Plus BaseMapper Interface:**MyBatis-Plus is an enhanced version of MyBatis, providing powerful features to simplify development. Its BaseMapper<T> interface offers a set of common CRUD (Create, Read, Update, Delete) operations out-of-the-box for a given entity type T. By simply extending BaseMapper, developers get access to numerous methods without writing any SQL queries for basic operations, leveraging MyBatis's interface programming model.

    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import org.apache.ibatis.annotations.Mapper; // Or no @Mapper if using @MapperScan
    
    // Assuming 'MyDomainEntity' is your entity class representing a database table
    @Mapper // Indicates this is a MyBatis mapper interface
    public interface MyDomainEntityMapper extends BaseMapper<MyDomainEntity> {
       // Basic CRUD operations are inherited from BaseMapper.
       // Custom SQL methods specific to MyDomainEntity can be added here if needed.
    }
    
    
Tags: SpringBoot

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.