Documents a Foreigner Needs to Apply for or Renew a Residence Permit via Marriage Certificate in Zhenjiang, China

Assume the spouse is a foreigner, the wife. The wife’s Registration Form of Temporary Residence (for overseas persons) Obtain it from the local police station. A photocopy of the main page of the wife’s passport (If any) A photocopy of the wife’s previous residence permit inside her passport The husband’s letter of invitation (the immigration administration’s photo studio can provide it) A photocopy of the husband’s household registration booklet (hukou) ...

2026-06-02 11:12:13 AM · 1 min

A Close Look at Common Caching Strategies UPDATING 

The Three Cache Brothers Cache Penetration What it is: a flood of requests querying data that doesn’t exist in the database. The cache has nothing, so it keeps hammering the database. Prevention: Cache null values Even when the database finds nothing, put an empty marker in the cache (with a short TTL, e.g. 2 minutes; only after that TTL expires can the database be queried again) The next time the same id comes in, it’s blocked directly Pros: effectively intercepts large numbers of penetration requests Cons: A malicious attack with many different non-existent keys fills the cache with useless data and wastes memory It delays data consistency; new data has to wait for the cache to expire Bloom filter (recommended) At startup, put all legitimate ids into the Bloom filter If the Bloom filter says no, it really doesn’t exist Pros: No high-memory-usage risk No data-consistency risk Cons: There’s a tiny false-positive rate Insertions and deletions need maintenance; when data updates, the Bloom filter must be updated in sync Rate limiting and validation at the interface layer Intercept at the API gateway or Controller layer Parameter validation, rate limiting, and degradation Mutex-based rebuild A mutex mainly solves cache breakdown (a hot key expiring), but in the cache-empty-object scenario, if there are many concurrent requests for a non-existent key, a lock can be used Each access lets one thread query the DB while the others wait Big companies’ practice ...

2026-05-05 10:46:44 PM · 3 min

The Fundamentals You Need to Build a Chat Room UPDATING 

The TCP Three-Way Handshake Client — Server Purpose of the three-way handshake: the client’s send and receive are both fine, and the server’s send and receive are both fine. First handshake: the client sends SYN (synchronize request) Client: I know nothing, so I’ll send out a SYN message and see if anyone receives it. If no one replies, I send it a few more times (timeout retransmission). At this moment, what the client knows is: I sent it, but I don’t know whether anyone received it ❌ Can I receive messages? Unknown ❌ Does the other side exist? Unknown ❌ Second handshake: the server replies SYN+ACK (synchronize + acknowledge) The server received the client’s SYN. ...

2026-04-03 11:45:26 AM · 17 min

Why the Backend Sometimes Needs to Maintain a Refresh_Tokens Table

The Normal JWT Request Flow sequenceDiagram participant User as User participant Frontend as Frontend (browser/app) participant Auth as Auth server participant Backend as Backend API server Note over User,Backend: 1. Login phase User->>Frontend: enter username/password Frontend->>Auth: POST /login (credentials) Auth->>Auth: verify credentials Auth-->>Frontend: return access_token + refresh_token Frontend->>Frontend: store tokens (memory/localStorage) Frontend-->>User: login successful Note over User,Backend: 2. Normal request phase User->>Frontend: request a protected resource Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: verify access_token signature and expiry Backend-->>Frontend: return the requested resource Frontend-->>User: display data Note over User,Backend: 3. Access token expires User->>Frontend: keep requesting Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token (expired) Backend-->>Frontend: 401 Unauthorized (token expired) Frontend->>Frontend: detects 401, triggers refresh logic Note over Frontend,Auth: 4. Token refresh phase Frontend->>Auth: POST /refreshrefresh_token Auth->>Auth: verify refresh_token Auth-->>Frontend: return a new access_token (optionally a new refresh_token) Frontend->>Frontend: update the stored access_token Frontend->>Backend: retry the original request (new access_token) Backend-->>Frontend: return the requested resource Frontend-->>User: display data Why You Can’t Rely on JWT Alone Once a refresh token is issued and the backend doesn’t store it, it becomes an uncontrollable long-term pass You can’t forcibly log a user out You can’t log out a single device You can’t tell whether a token has been stolen (an attacker who gets the refresh token can keep refreshing the access token forever) You can’t implement session management The Flow After Using a refresh_tokens Table sequenceDiagram participant User as User participant Frontend as Frontend participant Auth as Auth server participant DB as Database (refresh_tokens table) participant Backend as Backend API server Note over User,DB: 1. Login phase (issue token + persist) User->>Frontend: enter username/password Frontend->>Auth: POST /login Auth->>Auth: verify credentials Auth->>DB: generate a unique refresh_token_idINSERT INTO refresh_tokens(user_id, token_hash, expires_at, device_info, ip_address, revoked) DB-->>Auth: insert successful Auth->>Auth: generate access_token + refresh_token(refresh_token contains the id reference) Auth-->>Frontend: return access_token + refresh_token Frontend->>Frontend: store tokens Frontend-->>User: login successful Note over User,Backend: 2. Normal request (same as before) User->>Frontend: request a resource Frontend->>Backend: GET /api/resourceAuthorization: Bearer access_token Backend->>Backend: verify access_token Backend-->>Frontend: return the resource Note over Frontend,DB: 3. Access token expires → refresh Frontend->>Backend: GET /api/resource (access_token expired) Backend-->>Frontend: 401 Unauthorized Frontend->>Auth: POST /refreshrefresh_token Note over Auth,DB: 4. Refresh verification (multi-step checks) Auth->>Auth: parse refresh_token, extract token_id Auth->>DB: SELECT * FROM refresh_tokensWHERE id = token_id DB-->>Auth: return the record Auth->>Auth: verification checklist: Note over Auth: ✅ does token_hash match✅ is it expired (expires_at > now())✅ is it revoked (revoked = false)✅ is the user still valid✅ does device info match (optional) alt all checks pass Auth->>DB: UPDATE refresh_tokensSET last_used_at = now(), last_used_ip = current_ipWHERE id = token_id Auth->>Auth: generate a new access_token(optional: extend refresh_token validity) Auth-->>Frontend: return the new access_token Frontend->>Frontend: update access_token Frontend->>Backend: retry the original request (new token) Backend-->>Frontend: return the resource else checks fail Auth-->>Frontend: 401/403 (refresh failed) Frontend->>Frontend: clear all tokens Frontend->>User: redirect to the login page end Note over User,DB: 5. Explicit logout User->>Frontend: click logout Frontend->>Auth: POST /logoutrefresh_token Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE id = token_id Auth-->>Frontend: logout successful Frontend->>Frontend: clear local tokens Frontend-->>User: logged out Note over User,DB: 6. Security scenario: password change User->>Frontend: change password Frontend->>Auth: POST /change-password Auth->>DB: UPDATE refresh_tokensSET revoked = trueWHERE user_id = current_user_id Note over DB: revoke all of the user's refresh_tokens(force all devices to log in again) Auth-->>Frontend: password change successful Frontend->>Frontend: clear local tokens Frontend-->>User: please log in again

2026-03-02 08:07:07 PM · 3 min

SCA / Spring Cloud / Spring Boot Version Compatibility Table

Data source: Spring Cloud Alibaba official Wiki After Spring Boot 3.3.4 Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version 2025.1.0.0 2025.1.0 4.0.0 Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version 2025.0.0.0 2025.0.0 3.5.0 Component version relationships The component versions each Spring Cloud Alibaba release is compatible with are shown below: Spring Cloud Alibaba Version Sentinel Version Nacos Version RocketMQ Version SchedulerX Version Seata Version 2025.1.0.0 1.8.9 3.1.1 5.3.1 1.13.3 2.5.0 2025.0.0.0 1.8.9 3.0.3 5.3.1 1.13.1 2.5.0 Importing the dependencies <dependencyManagement> <dependencies> <!-- Unified Spring Boot version management --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.5.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Official Spring Cloud version management --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2025.0.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- Unified Spring Cloud Alibaba (Alibaba ecosystem) version --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2025.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> Spring Boot 3.3.4 and earlier 📌 New versions (Calendar Versioning, recommended) Spring Cloud Alibaba Spring Cloud Spring Boot 2023.0.3.2 2023.0.3 3.3.4 2023.0.3.0 2023.0.3 3.3.4 2023.0.1.0 2023.0.1 3.2.4 2023.0.0.0-RC1 2023.0.0 3.2.0 2022.0.0.0 2022.0.0 3.0.2 2022.0.0.0-RC2 2022.0.0-RC2 3.0.2 2022.0.0.0-RC1 2022.0.0-RC1 3.0.0 2021.0.6.2 2021.0.9 2.7.18 2021.0.6.0 2021.0.9 2.7.18 2021.0.5.0 2021.0.5 2.6.13 2021.0.4.0 2021.0.4 2.6.11 2021.0.1.0 2021.0.1 2.6.3 2021.1 2020.0.1 2.4.2 📌 Old versions (RELEASE naming) Spring Cloud Alibaba Spring Cloud Spring Boot 2.2.10.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.9.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.8.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.7.RELEASE Hoxton.SR12 2.3.12.RELEASE 2.2.6.RELEASE Hoxton.SR9 2.3.2.RELEASE 2.2.1.RELEASE Hoxton.SR3 2.2.5.RELEASE 2.2.0.RELEASE Hoxton.RELEASE 2.2.X.RELEASE 2.1.4.RELEASE Greenwich.SR6 2.1.13.RELEASE 2.1.2.RELEASE Greenwich 2.1.X.RELEASE 2.0.4.RELEASE ⛔ Finchley 2.0.X.RELEASE 1.5.1.RELEASE ⛔ Edgware 1.5.X.RELEASE ⛔ means maintenance has stopped ...

2026-02-28 10:39:46 AM · 2 min

Microservice Auth System: Architecture Walkthrough and Interview Prep UPDATING 

Tech stack: Spring Boot 3 · Spring Cloud Alibaba · OpenFeign · JWT · Gateway · Nacos How to use this document When you talk about a project in an interview, the worst thing you can do is start from code details. The right order is: First explain what problem it solves → then the overall architecture → then walk through it by request flow → finally handle the deep-dive questions. ...

2026-01-26 06:05:16 PM · 10 min

On What a Hassle Login Is UPDATING 

Everyone who has written a backend, sooner or later, has to fight a hard battle with “login.” It looks like a small feature — a username, a password, a button — but anyone who has actually built it knows this is the part of the whole system with the deepest pits, the most painful changes, and the most fatal failures. It’s a hassle not because the technology is hard, but because it sits right at the intersection of three parties’ interests: users want convenience, product wants growth, and security wants an airtight defense. These three are naturally at odds. Every inch you move toward one, the other two start crying out. ...

2025-12-26 03:56:40 PM · 13 min

Handy Spring Boot Code Snippets UPDATING 

General Dependency management Pinning all three versions in the parent pom.xml Version reference <dependencyManagement> <dependencies> <!-- 1. Spring Boot base version --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>3.5.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 2. Spring Cloud cloud-native base --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2025.0.0</version> <type>pom</type> <scope>import</scope> </dependency> <!-- 3. Spring Cloud Alibaba full dependency core (key!) --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2025.0.0.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> Main class @MapperScan("asia.liminality.user.mapper") @SpringBootApplication @Slf4j public class UserApplication { public static void main(String[] args) throws UnknownHostException { ConfigurableApplicationContext app = SpringApplication.run(UserApplication.class, args); Environment env = app.getEnvironment(); String protocol = "http"; if (env.getProperty("server.ssl.key-store") != null) { protocol = "https"; } log.info("--/\n---------------------------------------------------------------------------------------\n\t" + "Application '{}' is running! Access URLs:\n\t" + "Local: \t\t{}://localhost:{}\n\t" + "External: \t{}://{}:{}\n\t" + "Profile(s): \t{}" + "\n---------------------------------------------------------------------------------------", env.getProperty("spring.application.name"), protocol, env.getProperty("server.port"), protocol, InetAddress.getLocalHost().getHostAddress(), env.getProperty("server.port"), env.getActiveProfiles()); } } domain DTO Result import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class Result<T> { private int code; private String message; private T data; public static <T> Result<T> success(T data) { return new Result<>(200, "success", data); } public static <T> Result<T> success() { return new Result<>(200, "success", null); } public static <T> Result<T> failure(String message) { return new Result<>(500, message, null); } public static <T> Result<T> failure(int code, String message) { return new Result<>(code, message, null); } public static <T> Result<T> failure(String message, T data) { return new Result<>(500, message, data); } } Spring Cloud Gateway AuthGlobalFilter @Slf4j @RequiredArgsConstructor @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { private final JwtUtil jwtUtil; private static final List<String> WHITE_LIST = List.of( "/auth/user/login", "/auth/user/register" ); // Check whether it's in the whitelist private boolean isWhiteList(String path){ return WHITE_LIST.stream().anyMatch(path::startsWith); } private Mono<Void> reject(ServerWebExchange exchange){ exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String path = request.getPath().toString(); if (isWhiteList(path)) { return chain.filter(exchange); } String token = request.getHeaders().getFirst("Authorization"); // Token is empty, deny access if( token == null || token.isEmpty() ){ return reject( exchange ); } // Verify the token try { Integer userId = jwtUtil.parseToken(token); // TODO put userId into the request header log.info("🚪 inject into request header"); } catch (Exception e) { return reject(exchange); } return chain.filter( exchange ); } // Filter priority; the smaller, the earlier @Override public int getOrder() { return -1; } }

2025-11-26 09:51:37 AM · 2 min

Sudden Sensorineural Hearing Loss Treatment Process

September 22, Monday — Day 1: Sudden onset Woke up in the morning with a blocked feeling in the right ear; the left ear was normal. I assumed it was just ear congestion or possibly otitis media, something that would resolve on its own, so I didn’t pay much attention. September 23, Tuesday — Day 2 In addition to the blocked sensation, I noticed an echo when hearing external speech. I started to feel something was wrong, but I still didn’t think it was serious and prioritized work. ...

2025-11-12 12:24:27 PM · 4 min

The Incompatibility Between PostgreSQL and Java's LocalDateTime UPDATING 

Java’s LocalDateTime and PostgreSQL’s time types “aren’t talking about the same kind of time.” First, get clear on PostgreSQL’s two time types TIMESTAMP → without time zone, just a bare time "2026-06-25 10:00:00" TIMESTAMPTZ → with time zone, stored internally as UTC, converted to the session time zone on query On the Java side LocalDateTime → no concept of a time zone, just a bare time ZonedDateTime → with time zone OffsetDateTime → with an offset (e.g. +08:00) Instant → a UTC timestamp Why the error happens The PostgreSQL JDBC driver (especially newer versions 42.x+) is very strict about type matching: ...

2025-10-25 12:55:49 PM · 2 min