跪拜 Guibai
← All articles
Frontend · Backend · Fullstack

Tracing a Product Detail API Call Through Every Layer of a Spring Boot App

By swipe ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Most backend tutorials teach concepts in isolation; this walkthrough connects them into a single traceable chain. A developer who can follow a request from filter to JSON response can debug production issues across any layer without guessing.

Summary

A public product detail endpoint in a fullstack e-commerce project is dissected layer by layer, from the HTTP entry point through security whitelisting, Redis cache-aside logic, MyBatis-Plus database queries, and category table assembly into a response DTO. The walkthrough covers five cache states—HIT, MISS, NULL_HIT, DEGRADED, and BYPASS—and shows how each one dictates whether the request returns from memory, falls back to MySQL, or throws a business exception. Null value caching with a short TTL prevents repeated database hits for stable 404s, while Redis failures trigger degradation instead of hard errors.

The backend enforces visibility rules that the frontend never sees: anonymous users can only access products with an ON_SALE status, and a disabled category makes an otherwise valid product return a 404. A GlobalExceptionHandler catches business exceptions and wraps them into a unified JSON envelope containing a stable error code and a traceId, giving frontend developers a consistent contract to code against. The traceId, generated or propagated by a filter at the very start of the request, ties every log line from cache lookup to database query back to a single identifier.

A troubleshooting checklist and a set of curl-and-Redis verification steps turn the theory into a repeatable debugging workflow. The chapter closes by contrasting the detail endpoint's simple Redis key with the list endpoint's deliberate lack of caching, showing that not every read deserves a cache.

Takeaways
An endpoint is a chain of Filter, Security, Controller, Facade, cache, database, exception handler, and serializer, not just a Controller method.
Public endpoints still pass through Spring Security; the whitelist `/api/products/**` is what permits anonymous access.
Anonymous access does not mean all data is visible; the backend forces `status_code = ON_SALE` in the database query.
Redis is a performance layer, not the source of truth; MISS, DEGRADED, and BYPASS all fall back to MySQL.
NULL_HIT is a short-TTL marker that turns a stable 404 into a fast business exception without hitting the database again.
The response DTO assembles fields from both the product and category tables; the frontend never receives raw database entities.
Business exceptions carry an ApiCode and HTTP status; GlobalExceptionHandler converts them into a unified JSON error envelope.
A traceId generated at the filter level appears in both response headers and the JSON body, linking frontend errors to backend logs.
Troubleshooting follows a fixed order: check the URL and permissions, then the business code, then Redis, then MySQL conditions, then DTO assembly.
Not every read endpoint needs caching; the product list endpoint deliberately skips Redis because its query parameters make key design complex.
Conclusions

Teaching backend development by tracing a single request end-to-end mirrors how senior engineers actually onboard onto a new codebase—they follow the data, not the class hierarchy.

The distinction between security rules (who can call an endpoint) and business visibility rules (what data the endpoint returns) is a recurring source of bugs that this walkthrough makes explicit.

Null value caching is an underappreciated pattern: it prevents cache penetration attacks on non-existent IDs while keeping the cache layer's abstraction clean.

Returning a DTO instead of a database entity is not just an architectural nicety; it prevents frontend code from coupling to table schemas that change independently.

The traceId pattern, trivial to implement with a single filter, solves the perennial problem of correlating a user's vague bug report with a specific backend request.

Concepts & terms
Cache Aside
An application-level caching strategy where the application first checks the cache; on a miss, it loads data from the database, writes it to the cache, and returns it. The cache is never the source of truth.
Null Value Caching
Storing a special marker in the cache for keys known to not exist, with a short TTL, to prevent repeated database queries for the same missing resource (cache penetration).
DTO (Data Transfer Object)
An object that carries data between processes, shaped specifically for a client's needs rather than mirroring a database table. It can combine fields from multiple entities and hide internal columns.
Cache Degradation
When a cache like Redis is unavailable, the system falls back to querying the primary database directly instead of failing the request, trading performance for availability.
TraceId
A unique identifier generated or propagated at the edge of a system and passed through every service and log line, allowing a single request to be traced across distributed components.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗