404 Not Found

404 Not Found


nginx

Your First Spring Boot Application

A single @SpringBootApplication annotation is all it takes to launch the entire application—the magic of Spring Boot lies in the ingenious combination of three annotations.

1. What You'll Learn


2. A True Story About a New Project

(1) Pain Point: It takes half a day to set up a project

Alice recalled her experience using traditional Spring MVC when she first started out: creating a project required configuring web.xml, applicationContext.xml, and spring-mvc.xml, as well as installing Tomcat and configuring the JNDI data source. Just getting the project up and running took half a day, not to mention debugging startup order and bean loading issues.

(2) The Spring Boot Solution

Spring Boot requires just one annotation and one main method:

JAVA
@SpringBootApplication
public class OrderFlowApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderFlowApplication.class, args);
    }
}

(3) Revenue

Alice used Spring Boot to create the OrderFlow project. It took her just 5 minutes to go from scratch to her first API response—no XML required, no external container needed, and the startup logs were clear and easy to read.


3. Breaking Down the @SpringBootApplication Annotation

(1) A combination of three annotations

@SpringBootApplication is a composite annotation equivalent to using the following three annotations simultaneously:

100%
graph TB
    A["@SpringBootApplication"] --> B["@SpringBootConfiguration"]
    A --> C["@EnableAutoConfiguration"]
    A --> D["@ComponentScan"]
    B --> B1["Marks class as<br/>Configuration bean source"]
    C --> C1["Triggers auto-configuration<br/>based on classpath"]
    D --> D1["Scans components<br/>in same package tree"]
Annotation Function Equivalent Traditional Notation
@SpringBootConfiguration Mark the current class as a configuration class @Configuration
@EnableAutoConfiguration Enable Auto-Configuration @EnableAutoConfiguration
@ComponentScan Component Scan <context:component-scan>

(2) @ComponentScan scanning rules

@ComponentScan By default, the scan covers the package containing the main launch class and all its subpackages.

TEXT
com.orderflow ← The package containing the main launch class
├── OrderFlowApplication.java           ← @SpringBootApplication
├── controller/ ← Scanned by @ComponentScan
│   └── OrderController.java
├── service/ ← Scanned by @ComponentScan
│   └── OrderService.java
└── repository/ ← Scanned by @ComponentScan
    └── OrderRepository.java
com.other ← ⚠️ Not included in the scan!
🔥 Common Mistake: If you place the Controller in a package that is either one level above or at the same level as the package containing the main launch class, Spring Boot will not scan for it, resulting in a 404 error.


4. SpringApplication.run() Startup Process

(1) Startup Sequence

The execution process of SpringApplication.run() is a carefully designed pipeline:

100%
sequenceDiagram
    participant Main as main()
    participant SA as SpringApplication
    participant Ctx as ApplicationContext
    participant Bean as Beans

    Main->>SA: new SpringApplication()
    SA->>SA: infer Primary Sources
    SA->>SA: check Web Application Type
    SA->>SA: load Initializers & Listeners
    Main->>SA: run(args)
    SA->>SA: create Bootstrap Context
    SA->>SA: prepare Environment
    SA->>SA: print Banner
    SA->>Ctx: create ApplicationContext
    SA->>Ctx: prepare Context (register sources)
    SA->>Ctx: refresh Context
    Ctx->>Bean: instantiate Beans
    Ctx->>Bean: auto-configure
    SA->>SA: call Runners
    SA->>Main: return ApplicationContext

(2) Determining the Web Application Type

Spring Boot Automatically Detects Application Type:

Condition Type Container Used
classpath contains spring-webmvc SERVLET Tomcat / Jetty / Undertow
classpath contains spring-webflux but not spring-webmvc REACTIVE Netty
None NONE No embedded containers

(1) ▶ Example: Customizing SpringApplication Startup

JAVA
@SpringBootApplication
public class OrderFlowApplication {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(OrderFlowApplication.class);
        app.setBannerMode(Banner.Mode.CONSOLE);
        app.setWebApplicationType(WebApplicationType.SERVLET);
        app.run(args);
    }
}

Output:

TEXT
// Execution Successful

5. Configuration File Format

(1) Properties vs. YAML

Spring Boot supports two configuration file formats that are functionally equivalent but differ in syntax.

(1) ▶ Example: How to write application.properties

PROPERTIES
server.port=8080
spring.application.name=orderflow-service
spring.datasource.url=jdbc:mysql://localhost:3306/orderflow
spring.datasource.username=root
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=update

Output:

TEXT
// Execution Successful

(2) ▶ Example: How to write application.yml

YAML
server:
  port: 8080

spring:
  application:
    name: orderflow-service
  datasource:
    url: jdbc:mysql://localhost:3306/orderflow
    username: root
    password: secret
  jpa:
    hibernate:
      ddl-auto: update

Output:

TEXT
The configuration has taken effect.
Dimension Properties YAML
Hierarchical Structure Separated by . Indentation Indicates Hierarchy
Readability Simple key-value pairs, flat Clear hierarchy, suitable for nesting
List Support list[0]=a - a More Intuitive
Repeated prefix Must be repeated Shared prefix at the same level
Parsing Performance Faster Slightly slower (requires parsing hierarchy)
Priority Same Same (properties take precedence when both exist)
⚠️ Note: YAML files are very sensitive to indentation; you must use spaces, not tabs, and indentation must be consistent within the same level.

(2) Quick Reference for Common Configuration Options

Configuration Option Default Value Description
server.port 8080 Application Listening Port
spring.application.name App Name
server.servlet.context-path / Contextual path
spring.main.banner-mode console Banner Display Mode
spring.jpa.show-sql false Print SQL
logging.level.root INFO Global Log Level

6. Customizing the Banner and Startup Logs

(1) Custom Banner

Place a custom banner in src/main/resources/banner.txt so that it automatically displays when Spring Boot starts.

(1) ▶ Example: OrderFlow Custom Banner

TEXT
  ____              _         ____  __
 / ___| _ __   __ _| |_ ___  / ___||  |  ___  _ __
| |    | '_ \ / _` | __/ _ \ \___ \|  |/ _ \| '_ \
| |___ | | | | (_| | ||  __/  ___) |  | (_) | | | |
 \____||_| |_|\__,_|\__\___| |____/|_|\___/|_| |_|

:: OrderFlow Service ::  v${application.version:1.0.0}
:: Spring Boot ${spring-boot.version} ::

Output:

TEXT
Execution Successful

(2) Interpreting the Startup Log

TEXT
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_  __ _   \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` |  \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  / / / /
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.2.5)

2024-01-15 10:00:01.123  INFO 12345 --- [main] c.o.OrderFlowApplication : Starting OrderFlowApplication
2024-01-15 10:00:03.456  INFO 12345 --- [main] o.s.b.w.e.t.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-01-15 10:00:04.789  INFO 12345 --- [main] o.s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories
2024-01-15 10:00:06.012  INFO 12345 --- [main] c.o.OrderFlowApplication : Started in 5.123 seconds
Log Keywords Meaning
Starting OrderFlowApplication App launching
Tomcat initialized with port Starting Embedded Tomcat
Bootstrapping Spring Data JPA Automatically Configure the JPA Repository
Started in X seconds Startup complete, took

7. Run Your First "Hello OrderFlow" Interface

(1) ▶ Example: Hello OrderFlow Controller

JAVA
package com.orderflow.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;

@RestController
public class HelloController {

    @GetMapping("/api/hello")
    public Map<String, String> hello() {
        return Map.of(
            "message", "Hello, OrderFlow!",
            "timestamp", java.time.Instant.now().toString()
        );
    }
}

Output:

TEXT
HTTP 200 OK
Content-Type: application/json

{"status":"success","data":{}}
💻 Output:

TEXT
$ curl http://localhost:8080/api/hello
{"message":"Hello, OrderFlow!","timestamp":"2024-01-15T10:00:00Z"}

(2) ▶ Example: Using @Value for configuration injection

JAVA
@RestController
public class HelloController {

    @Value("${spring.application.name}")
    private String appName;

    @GetMapping("/api/info")
    public Map<String, String> info() {
        return Map.of(
            "application", appName,
            "javaVersion", System.getProperty("java.version")
        );
    }
}

Output:

TEXT
// Execution Successful

8. Comprehensive Example: Complete OrderFlow Startup Configuration

JAVA
// src/main/java/com/orderflow/OrderFlowApplication.java
package com.orderflow;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OrderFlowApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderFlowApplication.class, args);
    }
}

// src/main/java/com/orderflow/controller/OrderFlowController.java
package com.orderflow.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.util.Map;

@RestController
public class OrderFlowController {

    @Value("${spring.application.name:orderflow}")
    private String appName;

    @GetMapping("/api/health")
    public Map<String, Object> health() {
        return Map.of(
            "status", "UP",
            "application", appName,
            "timestamp", Instant.now()
        );
    }
}
YAML
# src/main/resources/application.yml
server:
  port: 8080

spring:
  application:
    name: orderflow-service
💻 Output:

TEXT
$ curl http://localhost:8080/api/health
{"status":"UP","application":"orderflow-service","timestamp":"2024-01-15T10:00:00Z"}

❓ FAQ

Q Can @SpringBootApplication be applied to any class?
A Technically, yes, but it is strongly recommended to place it in the root package. This is because @ComponentScan scans the package containing the main class and its subpackages by default; placing it in the wrong location may prevent other beans from being discovered.
Q Can properties and YAML coexist?
A Yes, but in the case of duplicate properties, the properties definition takes precedence. It is recommended to use only one to avoid confusion. We recommend YAML, as it offers a clearer hierarchy.
Q How do I disable the banner?
A Set spring.main.banner-mode=off in the configuration file, or app.setBannerMode(Banner.Mode.OFF) in the code.
Q What should I do if I get the "Port 8080 already in use" error when starting the app?
A Modify server.port=8081, or locate and terminate the process using the port: lsof -i :8080 (Linux/Mac) or netstat -ano | findstr 8080 (Windows).
Q What causes slow startup?
A Common causes: 1) The classpath is too large, making the scan time-consuming; 2) Hibernate ddl-auto=validate causes slow connections to remote databases; 3) Unnecessary auto-configurations have not been excluded. Use --debug mode to view details.
Q How do I specify the main entry class?
A Configure it using the <mainClass> in the Maven plugin; run the class containing the main method directly in the IDE; the Spring Boot Maven Plugin will automatically detect it during packaging.

📖 Summary


📝 Exercises

  1. Basic Exercise (Difficulty: ⭐): Create a Spring Boot project, customize banner.txt, change the service port to 9090, and after starting the project, verify that the /api/hello endpoint is accessible.

  2. Advanced Exercise (Difficulty ⭐⭐): Replace SpringApplicationBuilder with SpringApplication.run(), disable the banner, set the log level to DEBUG, and customize a /api/app-info endpoint to return the application name and Java version.

  3. Challenge (Difficulty: ⭐⭐⭐): Implement StartupListener and ApplicationListener<ApplicationStartedEvent>, record the application startup time, and print it to the log. Reflect on the design intent behind Spring Boot's event mechanism.

Web-Tutorial.com

Web-Tutorial Tech Team

A team of developers maintaining programming tutorials. Each tutorial is written and reviewed by developers with expertise in that field. We work to keep our content accurate and reliable — if you spot an issue, please let us know.

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏