Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

SpringBoot Fundamentals and Integration Guide

Tech May 18 6

Learning SpringBoot

Objectives:

  1. Understand the pros and cons of Spring
  2. Understand the features of SpringBoot
  3. Understand the core functionality of SpringBoot
  4. Set up the SpringBoot environment
  5. Configure application.properties
  6. Configure application.yml
  7. Integrate MyBatis with SpringBoot
  8. Integrate JUnit with SpringBoot

Section 1: Introduction to SpringBoot

1. Spring Pros and Cons Analysis

  • Advantages

    • Spring is a lightweight replacement for Java Enterprise Edition (JEE, formerly J2EE). It provides a relatively simple approach to enterprise Java development by using dependency injection and aspect-oriented programming, enabling POJOs to implement EJB functionality.
  • Disadvantages

    • Although Spring's component code is lightweight, its configuration is heavyweight. Initially, Spring used XML configuration, often extensive. Spring 2.5 introduced annotation-based component scanning, reducing explicit XML configuration. Spring 3.0 introduced Java-based configuration, a type-safe, refactorable alternative to XML. All this configuration incurs development overhead, as switching between configuring Spring features and solving business problems wastes time. Like all frameworks, Spring is useful but demands significant effort.
    • Additionally, dependency management is time-consuming. During environment setup, you need to determine which library coordinates to import and their transitive dependencies. Selecting the wrong version can cause incompatibility issues, hindering development progress.

2. SpringBoot Overview

2.1 Design Philosophy

SpringBoot improves upon Spring's disadvantages with a convention over configuration approach, allowing developers to focus on writing business logic without switching between configuration and code, greatly improving efficiency and shortening project timelines.

2.2 Features
  • Quicck start for Spring-based development
  • Out-of-the-box: no code generation or XML configuration required, with defaults adjustable to specific needs
  • Provides common non-functional features for large projects: embedded server, security, metrics, health checks, external configuration, etc.
  • SpringBoot does not enhance Spring's functionality but provides a fast way to use Spring.
2.3 Four Pillars
  • Starter Dependencies: Essentially a Maven POM that defines transitive dependencies for a given feature. Simplifies dependency management.
  • AutoConfiguration: Runtime (application startup) process that determines which Spring configuraton to use based on various factors.
  • CLI: Command-line tool for quickly developing with Spring using Groovy scripts.
  • Actuator: Provides monitoring capabilities (status, beans, environment variables, logs, threads, etc.)

Section 2: SpringBoot Quick Start

1. Code Implementation

1.1 Create Maven Project

Use IntelliJ IDEA to create a simple Maven project (plain Java project).

1.2 Add Starter Dependency

SpringBoot requires inheriting the spring-boot-starter-parent.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
</parent>

To develop Controllers with SpringMVC, import the web starter.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>
1.3 Create SpringBoot Bootstrap Class
@SpringBootApplication
public class PropertyApplication {
    public static void main(String[] args) {
        SpringApplication.run(PropertyApplication.class);
    }
}
1.4 Create Controller

Create UserController in the same or sub-package of the bootstrap class.

@RestController
public class UserController {
    @GetMapping("/welcome")
    public String welcome() {
        return "welcome to springboot";
    }
}
1.5 Test

Run the main method of the bootstrap class. Once the server starts, access http://localhost:8080/welcome in a browser.

2. Quick Start Analysis

2.1 Code Explanation
  • @SpringBootApplication: Marks the startup class with multiple functions (detailed later).
  • SpringApplication.run(PropertyApplication.class): Runs the startup class, parameter is the bytecode object of the bootstrap class.
2.2 Hot Deployment

To avoid restarting after modifying code, add the following dependency.

<!-- Hot deployment -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
</dependency>

Note: If hot deployment fails in IntelliJ IDEA, enable automatic compilation: Shift+Ctrl+Alt+/ then select Registry.

2.3 Quick Project Creation

Demonstrate creating a SpringBoot project quickly in IDEA.

Section 3: SpringBoot Configuration Files

1. Configuration File Types

SpringBoot supports three types:

  • application.properties
  • application.yml
  • application.yaml

SpringBoot loads application.properties or application.yml (or .yaml) from the resources directory by default.

2. YML Configuration

2.1 Introduction

YML (YAML Ain't Markup Language) is a human-readable data serialization format, more concise than XML. Files use .yml or .yaml extension.

2.2 Syntax
  • Simple data:
key: value  # note: space after colon

Example:

port: 9000
  • Object/Map data:
key:
  property1: value1
  property2: value2

Example:

server:
  port: 9000

Note: Same indentation level indicates same hierarchy.

  • Array/List/Set data:
key:
  - value1
  - value2

# Inline format:
key: [value1, value2]

Example:

ages:
  - 20
  - 22
  - 24

ages: [20, 22, 24]

Note: Space after the dash.

3. Configuration Properties Reference

To find available configuration keys, refer to the official documentation: Common Application Properties

Common examples:

# Server port
server.port=8080
# Context path
server.servlet.context-path=/property

YAML equivalent:

server:
  port: 9000
  servlet:
    context-path: /property

4. Mapping Configuration to Java Beans

4.1 Using @Value
person:
  name: zhangsan
  age: 18
@RestController
public class UserController {
    @Value("${person.name}")
    private String name;
    @Value("${person.age}")
    private Integer age;

    @RequestMapping("/welcome")
    public String welcome() {
        return "welcome to springboot, name=" + name + ", age=" + age;
    }
}
4.2 Using @ConfigurationProperties
person:
  name: zhangsan
  age: 18
@RestController
@ConfigurationProperties(prefix = "person")
public class UserController {
    private String name;
    private Integer age;

    @GetMapping("/welcome")
    public String welcome() {
        return "welcome to springboot, name=" + name + ", age=" + age;
    }

    public void setName(String name) { this.name = name; }
    public void setAge(Integer age) { this.age = age; }
}

Note: @ConfigurationProperties requires setter methods; @Value does not.

Section 4: SpringBoot Principle Analysis

1. Starter Dependency Principle

1.1 Analyzing spring-boot-starter-parent

Click on spring-boot-starter-parent in pom.xml. It inherits from spring-boot-dependencies which defines version locks and dependency management.

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-dependencies</artifactId>
  <version>2.0.1.RELEASE</version>
</parent>

In spring-boot-dependencies, common library versions, dependency management, and plugin management are predefined.

1.2 Analyzing spring-boot-starter-web

Clicking on spring-boot-starter-web reveals it bundles dependencies like spring-web, spring-webmvc, tomcat, etc.

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-json</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
  </dependency>
  <dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
  </dependency>
</dependencies>

Thus, starter dependencies simplify dependency management via transitive dependencies.

2. AutoConfiguration Principle

Analyzing the @SpringBootApplication annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
    @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication { ... }

@SpringBootConfiguration is equivalent to @Configuration. @EnableAutoConfiguration enables auto-configuration.

@EnableAutoConfiguration imports AutoConfigurationImportSelector which loads class names from META-INF/spring.factories. These class names are auto-configuration classes (e.g., ServletWebServerFactoryAutoConfiguration).

@Configuration
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
public class ServletWebServerFactoryAutoConfiguration { ... }

@EnableConfigurationProperties(ServerProperties.class) alllows binding properties with prefix server to the fields of ServerProperties:

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
    private Integer port;
    private InetAddress address;
    // ...
}

Section 5: SpringBoot Integration with Other Technologies

1. Integrating MyBatis

1.1 Add Dependencies
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
1.2 Database Configuration
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/property?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
1.3 Create User Table
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) DEFAULT NULL,
  `password` varchar(50) DEFAULT NULL,
  `name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES ('1', 'zhangsan', '123', '张三');
INSERT INTO `user` VALUES ('2', 'lisi', '123', '李四');
1.4 Create Entity
public class User {
    private Long id;
    private String username;
    private String password;
    private String name;
    // getters and setters omitted
}
1.5 Create Mapper Interface
@Mapper
public interface UserMapper {
    List<User> queryUserList();
}
1.6 Mapper XML

Create src/main/resources/mapper/UserMapper.xml:

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.qf.spring.boot.mapper.UserMapper">
    <select id="queryUserList" resultType="user">
        select * from user
    </select>
</mapper>
1.7 Configure MyBatis
mybatis.type-aliases-package=com.qf.spring.boot.model
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
1.8 Controller
@RestController
public class UserController {
    @Autowired
    private UserMapper userMapper;

    @GetMapping("/queryUser")
    public List<User> queryUser() {
        return userMapper.queryUserList();
    }
}

2. Integrating JUnit

2.1 Add Dependency
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
2.2 Test Class
@RunWith(SpringRunner.class)
@SpringBootTest(classes = PropertyApplication.class)
public class MapperTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void test() {
        List<User> users = userMapper.queryUserList();
        System.out.println(users);
    }
}

SpringRunner extends SpringJUnit4ClassRunner. @SpringBootTest specifies the bootstrap class.

3. Integrating JPA

3.1 Add Dependencies
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
3.2 Configure JPA
# DB Configuration (same as above)
# JPA Configuration:
spring.jpa.database=MySQL
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
3.3 Entity
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String name;
    // getters and setters omitted
}
3.4 Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findAll();
}
3.5 Test
@RunWith(SpringRunner.class)
@SpringBootTest(classes = PropertyApplication.class)
public class JpaTest {
    @Autowired
    private UserRepository userRepository;

    @Test
    public void test() {
        List<User> users = userRepository.findAll();
        System.out.println(users);
    }
}
3.6 JDK 9 Issue

If using JDK 9, add:

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>

Section 6: Creating a Custom Starter (rsa-starter)

1. Create Maven Project

(Image: new maven project)

2. Add Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
        <version>2.5.6</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>2.5.6</version>
    </dependency>
</dependencies>

3. Configuration Properties Class

package com.qf.rsa.spring.boot.config;

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

@ConfigurationProperties(prefix = "rsa")
public class RsaProperties {
    private String secret;

    public String getSecret() { return secret; }
    public void setSecret(String secret) { this.secret = secret; }
}

4. Auto-Configuration Class

package com.qf.rsa.spring.boot.config;

import com.qf.rsa.spring.boot.RsaUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.security.NoSuchAlgorithmException;

@Configuration
@ConditionalOnClass(RsaUtil.class)
@EnableConfigurationProperties(RsaProperties.class)
public class RsaAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public RsaUtil rsaUtil(RsaProperties rsaProperties) throws NoSuchAlgorithmException {
        RsaUtil rsaUtil = new RsaUtil();
        rsaUtil.setRsaProperties(rsaProperties);
        rsaUtil.init();
        return rsaUtil;
    }
}

5. Create spring.factories

Create META-INF/spring.factories in resources:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ncom.qf.rsa.spring.boot.config.RsaAutoConfiguration

6. Build & Package

Use mvn install.

7. Test in Another Project

Add the starter as a dependency.

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.