Backend Development 7 min read

Building Reactive CRUD APIs with Spring WebFlux and MongoDB

This guide introduces MongoDB fundamentals and demonstrates how to integrate it with Spring WebFlux to create a fully reactive CRUD service, covering dependencies, configuration, entity definitions, repository interfaces, service logic, and controller endpoints.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Building Reactive CRUD APIs with Spring WebFlux and MongoDB

Environment: Spring Boot 2.5.8

MongoDB Introduction

MongoDB is an open‑source, distributed document database written in C++. It stores data as JSON‑like documents, allowing flexible schemas, automatic sharding for high‑load scalability, and rich query capabilities.

Key Features:

Document‑oriented storage with simple operations.

Index any field to accelerate sorting and queries.

Supports replication and sharding for horizontal scaling.

Rich JSON‑based query language for nested objects and arrays.

Update commands can replace whole documents or modify specific fields.

Map/Reduce for batch processing and aggregation, written in JavaScript.

GridFS for storing large files.

Server‑side JavaScript execution for custom functions.

WebFlux Introduction

Spring WebFlux is a fully non‑blocking, reactive web framework added in Spring 5.0. It runs on Netty, Undertow, or Servlet 3.1+ containers and supports back‑pressure via Reactive Streams, coexisting with Spring MVC.

Dependencies and Configuration

<code>&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-data-mongodb-reactive&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-webflux&lt;/artifactId&gt;
&lt;/dependency&gt;</code>

Configuration (application.yml):

<code>spring:
  data:
    mongodb:
      uri: mongodb://localhost:27017/demo
---
logging:
  level:
    '[org.springframework.data.mongodb.core]': debug</code>

Entity & Repository

<code>@Document(collection = "c_users")
public class Users {
    // Primary key maps to MongoDB _id
    @Id
    private Long id;
    private String username;
    private String password;
    private Integer age;
    private String email;
}

public interface UsersRepository extends ReactiveSortingRepository&lt;Users, Long&gt; {
}
</code>

Service Class

<code>@Service
public class UsersService {
    @Resource
    private ReactiveMongoTemplate template;
    @Resource
    private UsersRepository ur;

    // Save a user
    public Mono&lt;Users&gt; save(Users user) {
        return ur.save(user);
    }

    // Update user information
    public Mono&lt;UpdateResult&gt; updateInfo(Users user) {
        return template.updateFirst(
            query(where("id").is(user.getId())),
            update("email", user.getEmail()).set("username", user.getUsername()),
            Users.class);
    }

    // Delete a user by id
    public Mono&lt;Void&gt; remove(Long id) {
        return ur.deleteAll(ur.findById(id));
    }

    // Fuzzy search by username
    public Flux&lt;Users&gt; queryUsersLike(String keyword) {
        Pattern pattern = Pattern.compile("^.*" + keyword + ".*$");
        return template.find(query(where("username").regex(pattern)), Users.class);
    }

    // Retrieve all users
    public Flux&lt;Users&gt; queryUsers() {
        return ur.findAll();
    }

    // Paginated query
    public Flux&lt;Users&gt; queryPager(Integer page, Integer size) {
        Pageable pageable = PageRequest.of(page, size);
        Query query = new Query();
        return template.find(query.with(pageable), Users.class);
    }
}
</code>

Controller Interface

<code>@Resource
private UsersService us;

@PostMapping("save")
public Mono&lt;Users&gt; save(@RequestBody Users users) {
    return us.save(users);
}

@PostMapping("update")
public Mono&lt;UpdateResult&gt; update(@RequestBody Users user) {
    return us.updateInfo(user);
}

@GetMapping("/remove/{id}")
public Mono&lt;Void&gt; remove(@PathVariable("id") Long id) {
    return us.remove(id);
}

@GetMapping("query")
public Flux&lt;Users&gt; query() {
    return us.queryUsers();
}

@GetMapping("/queryLike")
public Flux&lt;Users&gt; queryLike(String keyword) {
    return us.queryUsersLike(keyword);
}

@GetMapping("/queryPager")
public Flux&lt;Users&gt; queryPager(Integer page, Integer size) {
    return us.queryPager(page, size);
}
</code>

Repository Supported Query Syntax

Javareactive programmingSpring BootCRUDMongoDBSpring WebFlux
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

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.