Backend Development 23 min read

Spring Boot + MyBatisPlus Project Setup and Implementation Guide

This article provides a comprehensive step‑by‑step guide on selecting technologies, configuring Gradle, integrating Spring Boot 2.1.5 with MyBatisPlus, setting up FastJSON, Hutool, Undertow, and other tools, and includes complete source code for entity, mapper, service, controller, and utility classes to build a clean Java backend application.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Spring Boot + MyBatisPlus Project Setup and Implementation Guide

1. Technology Selection

Parser: FastJSON

Development tools: JDK 1.8, Gradle, IDEA

Framework: SpringBoot 2.1.5.RELEASE

ORM: MyBatisPlus 3.1.2

Database: MySQL 8.0.21

Apache tools: HttpClient, Lang3

Version control: Git

Web server: Undertow

Utility library: Hutool

Lombok, Druid connection pool

2. Brief Description of Spring Boot Evolution

With the rise of dynamic languages (Ruby, Groovy, Scala, Node.js), Java development became cumbersome due to extensive configuration, low efficiency, complex deployment, and difficult third‑party integration. Spring Boot emerged to address these issues by adopting a "convention over configuration" approach, enabling rapid creation of standalone, production‑grade applications with minimal manual setup.

3. Spring Boot Plugins Used

spring-boot-devtools – hot deployment to avoid frequent restarts during development.

spring-boot-starter-aop – provides powerful AOP capabilities for decoupling.

spring-boot-starter-undertow – integrates Undertow as the embedded servlet container.

spring-boot-starter-test – testing utilities.

mybatis-plus-boot-starter – integrates MyBatisPlus.

spring-boot-configuration-processor – assists with configuration metadata.

4. FastJSON

Alibaba's JSON parser. Official documentation: https://github.com/alibaba/fastjson

5. Hutool

Hutool is a Java utility library that simplifies code, reduces boilerplate, and provides a rich set of reusable components.

6. Gradle

Gradle is an open‑source build automation tool based on Apache Ant and Maven concepts, using a Groovy‑based DSL (also Kotlin DSL) to replace XML configuration.

Official site: https://gradle.org/

Install Gradle, configure environment variables, and learn basic usage before proceeding.

7. Project Structure

The project combines Kotlin, SpringBoot, and MyBatisPlus to create a minimal front‑back separation framework. It upgrades a Java‑based SpringBoot + MyBatisPlus 3.x + Gradle stack; source code is available for download.

8. Gradle Configuration

plugins {
    id 'java'
    id 'idea'
}

/**
 * Use Groovy syntax to define version variables
 */
def spring_boot_version = "2.1.5.RELEASE"
def mybatis_plus_version = "3.1.2"
def mysql_version = "8.0.21"
def druid_version = "1.1.23"
def logback_version = "1.2.1"
def fastjson_version = "1.2.73"
def lombok_version = "1.18.12"
def lang_version = "3.4"
def io_version = "2.6"
def guava_version = "18.0"
def hutool_version = "5.3.10"

group = 'com.flong'
version = '0.0.1-SNAPSHOT'

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

repositories {
    // Alibaba Cloud mirror
    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
    mavenLocal()
    mavenCentral()
}

dependencies {
    implementation "org.springframework.boot:spring-boot-starter:${spring_boot_version}"
    // Exclude Tomcat, use Undertow
    compile("org.springframework.boot:spring-boot-starter-web:${spring_boot_version}") { exclude module: "spring-boot-starter-tomcat" }
    compile "org.springframework.boot:spring-boot-starter-undertow:${spring_boot_version}"
    runtime "mysql:mysql-connector-java:5.1.42"
    compile "org.springframework.boot:spring-boot-devtools:${spring_boot_version}"
    compile "org.springframework.boot:spring-boot-configuration-processor:${spring_boot_version}"
    compile "org.springframework.boot:spring-boot-starter-test:${spring_boot_version}"
    compile "com.baomidou:mybatis-plus-extension:${mybatis_plus_version}"
    compile "com.baomidou:mybatis-plus-boot-starter:${mybatis_plus_version}"
    compile "mysql:mysql-connector-java:${mysql_version}"
    compile "com.alibaba:druid:${druid_version}"
    compile "ch.qos.logback:logback-classic:${logback_version}"
    compile "com.alibaba:fastjson:${fastjson_version}"
    annotationProcessor "org.projectlombok:lombok:${lombok_version}"
    compileOnly "org.projectlombok:lombok:${lombok_version}"
    compile "org.apache.commons:commons-lang3:${lang_version}"
    compile "commons-io:commons-io:${io_version}"
    compile "com.google.guava:guava:${guava_version}"
    compile "cn.hutool:hutool-all:${hutool_version}"
}

tasks.withType(JavaCompile) { options.encoding = "UTF-8" }
[compileJava, javadoc, compileTestJava]*.options*.encoding = "UTF-8"

9. Database SQL Script

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
  `user_id` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT '用户Id主键,IdWork生成',
  `user_name` varchar(255) DEFAULT '' COMMENT '用户名',
  `pass_word` varchar(255) DEFAULT '' COMMENT '密码',
  `del_flag` int(2) unsigned NOT NULL DEFAULT '0' COMMENT '是否删除,0-不删除,1-删除',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`user_id`) USING BTREE,
  UNIQUE KEY `id` (`id`) USING BTREE
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

10. SpringBoot + MyBatisPlus Pagination Configuration

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {
    /** Pagination plugin */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

11. Condition Wrapper Builder

package com.flong.springboot.core.util;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.flong.springboot.core.vo.Condition;
import java.lang.reflect.Field;
import java.util.List;
import com.flong.springboot.core.enums.JoinType;
import com.flong.springboot.core.exception.BaseException;

/** Convert condition list to QueryWrapper */
public class BuildConditionWrapper {
    public static
QueryWrapper
build(List
conditions, Class
clazz) {
        QueryWrapper wrapper = Wrappers.query();
        if (conditions == null || conditions.size() == 0) { return wrapper; }
        try {
            for (int i = 0; i < conditions.size(); i++) {
                Condition condition = conditions.get(i);
                if (condition.getFieldName() == null) { throw new BaseException("Missing fieldName!"); }
                String columnName = getColumnName(condition.getFieldName(), clazz);
                if (condition == null || condition.getOperation() == null) { throw new BaseException("Operation cannot be null!"); }
                switch (condition.getOperation()) {
                    case EQ: wrapper.eq(columnName, condition.getValue()); break;
                    case GT: wrapper.gt(columnName, condition.getValue()); break;
                    case LT: wrapper.lt(columnName, condition.getValue()); break;
                    case NEQ: wrapper.ne(columnName, condition.getValue()); break;
                    case GTANDEQ: wrapper.ge(columnName, condition.getValue()); break;
                    case LTANDEQ: wrapper.le(columnName, condition.getValue()); break;
                    case LIKE: wrapper.like(columnName, condition.getValue()); break;
                    case ISNULL: wrapper.isNull(columnName); break;
                    case IN: wrapper.inSql(columnName, condition.getValue()); break;
                    default: break;
                }
                if (condition.getJoinType() == JoinType.OR && i < conditions.size() - 1) { wrapper.or(); }
            }
            return wrapper;
        } catch (Exception e) { throw new BaseException("Invalid query condition"); }
    }

    public static
QueryWrapper
buildWarpper(List
conditions) {
        QueryWrapper wrapper = Wrappers.query();
        if (conditions == null || conditions.size() == 0) { return wrapper; }
        try {
            for (int i = 0; i < conditions.size(); i++) {
                Condition condition = conditions.get(i);
                if (condition.getFieldName() == null) { throw new BaseException("Missing fieldName!"); }
                String columnName = condition.getFieldName();
                if (condition == null || condition.getOperation() == null) { throw new BaseException("Operation cannot be null!"); }
                switch (condition.getOperation()) {
                    case EQ: wrapper.eq(columnName, condition.getValue()); break;
                    case GT: wrapper.gt(columnName, condition.getValue()); break;
                    case LT: wrapper.lt(columnName, condition.getValue()); break;
                    case NEQ: wrapper.ne(columnName, condition.getValue()); break;
                    case GTANDEQ: wrapper.ge(columnName, condition.getValue()); break;
                    case LTANDEQ: wrapper.le(columnName, condition.getValue()); break;
                    case LIKE: wrapper.like(columnName, condition.getValue()); break;
                    case IN: wrapper.inSql(columnName, condition.getValue()); break;
                    default: break;
                }
                if (condition.getJoinType() == JoinType.OR && i < conditions.size() - 1) { wrapper.or(); }
            }
            return wrapper;
        } catch (Exception e) { throw new BaseException("Invalid query condition"); }
    }

    public static String getColumnName(String fieldName, Class clazz) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            TableField tableFieldAnno = field.getAnnotation(TableField.class);
            String columnName = "";
            if (tableFieldAnno != null && StrUtil.isNotBlank(tableFieldAnno.value())) {
                columnName = tableFieldAnno.value();
            } else {
                columnName = NamingStrategyUtils.camelToUnderline(field.getName());
            }
            return columnName;
        } catch (NoSuchFieldException e) {
            throw new BaseException("Invalid query condition");
        }
    }
}

12. Entity Definition

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.*;
import java.io.Serializable;
import java.util.Date;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@TableName("t_user")
public class User extends Model
implements Serializable {
    @TableId(type = IdType.ID_WORKER)
    private Long userId;
    private String userName;
    private String passWord;
    @TableLogic
    private String delFlag;
    private Date createTime;
}

13. Mapper Interface

BaseMapper extends MyBatisPlus core mapper.

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.flong.springboot.modules.entity.User;

public interface UserMapper extends BaseMapper
{}

14. Service Implementation

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.flong.springboot.modules.entity.User;
import com.flong.springboot.modules.mapper.UserMapper;
import org.springframework.stereotype.Service;

@Service
public class UserService extends ServiceImpl
{}

15. Controller (CRUD & Pagination)

package com.flong.springboot.modules.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.flong.springboot.modules.entity.User;
import com.flong.springboot.modules.mapper.UserMapper;
import com.flong.springboot.modules.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.flong.springboot.core.vo.Conditions;
import com.flong.springboot.core.util.BuildConditionWrapper;
import java.util.List;

/**
 * @Author: liangjl
 * @Date: 2020-08-16
 * @Description: User controller
 */
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserService userService;

    @RequestMapping("/add")
    public void add() {
        userMapper.insert(User.builder().userName("周伯通").passWord("123456").build());
    }

    @PutMapping("/updateById")
    public void updateById(@RequestBody User user) {
        userMapper.updateById(user);
    }

    @DeleteMapping("/deleteByIds")
    public void deleteByIds(@RequestBody List
ids) {
        userMapper.deleteBatchIds(ids);
    }

    @GetMapping("/getOne/{userId}")
    public void getOne(@PathVariable("userId") Long userId) {
        User user = userMapper.selectById(userId);
        System.out.println(JSON.toJSON(user));
    }

    @GetMapping("/page")
    public IPage
page(Page page, Conditions conditions) {
        QueryWrapper
build = BuildConditionWrapper.build(conditions.getConditionList(), User.class);
        // Order by createTime descending via lambda reflection
        build.lambda().orderByDesc(User::getCreateTime);
        return userService.page(page, build);
    }
}

16. WebConfig – Global Configuration

@Configuration
@ConditionalOnClass(WebMvcConfigurer.class)
@Order(Ordered.HIGHEST_PRECEDENCE)
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public HttpMessageConverters customConverters() {
        FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
            SerializerFeature.PrettyFormat,
            SerializerFeature.DisableCircularReferenceDetect,
            SerializerFeature.WriteMapNullValue,
            SerializerFeature.WriteNullStringAsEmpty,
            SerializerFeature.WriteNullListAsEmpty
        );
        fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");
        SerializeConfig serializeConfig = SerializeConfig.globalInstance;
        serializeConfig.put(BigInteger.class, ToStringSerializer.instance);
        serializeConfig.put(Long.class, ToStringSerializer.instance);
        serializeConfig.put(Long.TYPE, ToStringSerializer.instance);
        fastJsonConfig.setSerializeConfig(serializeConfig);
        List
fastMediaTypes = new ArrayList<>();
        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
        fastJsonConverter.setSupportedMediaTypes(fastMediaTypes);
        fastJsonConverter.setFastJsonConfig(fastJsonConfig);
        return new HttpMessageConverters(fastJsonConverter);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // registry.addInterceptor(logInterceptor).addPathPatterns("/**");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .allowCredentials(Boolean.TRUE);
    }
}

17. Running Results

Add user: http://localhost:7011/user/add

Paginated query: http://localhost:7011/user/page?conditionList[0].fieldName=userName&conditionList[0].operation=LIKE&conditionList[0].value=%E5%91%A8

Default page = 1, size = 10; can be customized via current and size parameters.

18. Conclusion & Further Notes

The article summarizes the author's learning experience, invites readers to provide feedback, and encourages joining the Java architecture community for further discussion.

JavaBackend DevelopmentGradleSpring BootREST APIMyBatisPlus
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.