Swagger 2 vs. Swagger 3 Annotation Comparison Table UPDATING 

In the Spring Boot ecosystem, the annotations changed a great deal between Swagger 2.0 (typically using the Springfox dependency) and Swagger 3.0 (typically using the Springdoc-openapi dependency, based on the OpenAPI 3 spec). Below is a complete correspondence table of the common annotations in Swagger 2.0 vs. Swagger 3.0 (OpenAPI 3): 1. Core annotation correspondence table Description Swagger 2.0 annotation (io.swagger.annotations) Swagger 3.0 annotation (io.swagger.v3.oas.annotations) Notes Mark a controller class @Api(tags = "User API") @Tag(name = "User API") 3.0 removed the description attribute; use name uniformly Mark an API method @ApiOperation(value = "Get user") @Operation(summary = "Get user") In 3.0 value became summary Request/entity class @ApiModel(value = "User object") @Schema(description = "User object") 3.0 greatly simplified this; use @Schema uniformly Entity class property @ApiModelProperty(value = "Name") @Schema(description = "Name") As above, merged into @Schema Ignore a property @ApiModelProperty(hidden = true) @Schema(hidden = true) Ignore a whole class/method @ApiIgnore @Hidden For endpoints or parameters you don’t want exposed in docs 2. Request-parameter annotation correspondence table For method parameters (URL path parameters, query parameters, etc.), 3.0 introduced a more structured configuration: ...

2025-09-25 09:06:35 AM · 2 min

SCA 2023.X — Troubleshooting and Fixing the Nacos Bootstrap Config Failure

Issue source: spring-cloud-alibaba#3931 Affected versions: spring-cloud-alibaba 2023.0.1.3+ 1. Problem Description In Spring Cloud Alibaba 2023.X, placing Nacos config (including extension-configs, shared-configs, etc.) in bootstrap.yml / bootstrap.properties causes the config center’s content to fail to load properly, even though the logs show the bootstrap file itself was read. Moving the same config to application.yml makes everything work again. 2. Root Cause flowchart TD A[bootstrap.yml is read] --> B{SCA version check} B -- 2023.0.1.2 and earlier --> C[✅ Nacos config center loads normally] B -- 2023.0.1.3 and later --> D[❌ extension-configs / shared-configs fail] D --> E[Root cause: SCA 2023.0.1.3 changed the config-load priority mechanism] E --> F[Nacos PropertySource registered in the bootstrap phase is overwritten or discarded by later steps] In short: SCA 2023.0.1.3 made a backward-incompatible internal change, causing the Nacos extension config in bootstrap.yml to be “dropped” in the loading chain, while config in application.yml takes the new path and is unaffected. ...

2025-07-24 10:40:26 PM · 3 min

Some Common Nacos Configurations UPDATING 

bootstrap config bootstrap.yaml server: port: 10888 tomcat: uri-encoding: UTF-8 spring: profiles: active: dev application: name: archive-service cloud: nacos: config: file-extension: yaml shared-configs: - data-id: shared-spring.yaml refresh: false - data-id: shared-redis.yaml refresh: false - data-id: shared-mybatis.yaml refresh: false - data-id: shared-logs.yaml refresh: false - data-id: shared-feign.yaml refresh: false - data-id: shared-logs.yaml # shared logging config refresh: false # - data-id: shared-feign.yaml # shared feign config # refresh: false lia: jdbc: database: tb_archive bootstrap-dev.yaml spring: cloud: nacos: server-addr: 192.168.2.115:8848 # nacos registry discovery: namespace: f923fb34-cb0a-4c06-8fca-ad61ea61a3f0 group: DEFAULT_GROUP ip: 192.168.2.115 logging: level: asia.liminality: debug nacos config shared-spring.yaml spring: jackson: default-property-inclusion: non_null main: allow-bean-definition-overriding: true mvc: pathmatch: # Fixes the exception: swagger Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException # Because Springfox's path matching is based on AntPathMatcher, while Spring Boot 2.6.X uses PathPatternMatcher matching-strategy: ant_path_matcher shared-redis.yaml spring: redis: host: ${lia.redis.host:192.168.2.115} password: ${lia.redis.password:github} lettuce: pool: max-active: ${lia.redis.pool.max-active:8} max-idle: ${lia.redis.pool.max-idle:8} min-idle: ${lia.redis.pool.min-idle:1} max-wait: ${lia.redis.pool.max-wait:300} shared-mybatis.yaml MySQL spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://${sh.jdbc.host:127.0.0.1}/${sh.jdbc.database}?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false username: ${lia.jdbc.username:root} password: ${lia.jdbc.password:794211} mybatis-plus: configuration: default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler global-config: db-config: logic-delete-field: deletedAt logic-not-delete-value: "null" logic-delete-value: "now()" id-type: assign_id insert-strategy: not_null update-strategy: not_null PostgreSQL spring: datasource: driver-class-name: org.postgresql.Driver url: jdbc:postgresql://${lia.jdbc.host:192.168.2.115}:${lia.jdbc.port:5432}/${lia.jdbc.database}?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai username: ${lia.jdbc.username:postgres} password: ${lia.jdbc.password:github} mybatis-plus: configuration: default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler global-config: db-config: logic-delete-field: deletedAt logic-not-delete-value: "null" logic-delete-value: "now()" id-type: assign_id insert-strategy: ignored update-strategy: ignored select-strategy: not_null shared-logs.yaml logging: pattern: dateformat: HH:mm:ss.SSS console: "%clr(%d{${LOG_DATEFORMAT_PATTERN}}){faint}-[${hostname}][%X{requestId:-sys}] %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n" file: "%d{${LOG_DATEFORMAT_PATTERN}}-[${hostname}][%X{requestId:-sys}]-${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n" file: path: "logs/${spring.application.name}" shared-feign.yaml feign: client: config: default: # the default global config loggerLevel: BASIC # log level; BASIC is the basic request and response info httpclient: enabled: true # enable Feign's HttpClient support max-connections: 200 # max connections max-connections-per-route: 50 # max connections per route sentinel: enabled: true

2025-06-24 07:01:02 PM · 2 min

How to Download Wistia Videos

Automatic tool (unmaintained) Paste the video link you got by right-clicking the Wistia player here: Parse video Manual method Right-click on the playing video Choose “Copy link.” Find the video ID in the link You’ll see something like: wvideo=tra6gsm6rl Here tra6gsm6rl is the video’s ID. If it’s not in the link, you can also: Open the page source (view source) and search for: hashedId=tra6gsm6rl Open the embed page Visit in your browser: ...

2025-05-23 08:26:17 PM · 1 min

A Guide to Suffering Through WeChat Mini Program Development UPDATING 

The auth interaction flow between a WeChat Mini Program and the backend The core flow of WeChat Mini Program login: the mini program gets a temporary credential code → the backend exchanges the code for an openid → the backend issues its own JWT to the mini program. Below is the overall flow diagram. sequenceDiagram participant MP as WeChat Mini Program participant WX as WeChat server participant GW as gateway participant Auth as auth module participant User as user-service participant DB as lia_user database MP->>WX: wx.login() to get code WX-->>MP: returns temporary code MP->>GW: POST /auth/wx-login {code} GW->>Auth: forward the request Auth->>WX: code2session(code) WX-->>Auth: returns openid + session_key Auth->>User: OpenFeign to query/create the user User->>DB: query by openid DB-->>User: user record (or empty) User-->>Auth: return userId Auth->>Auth: generate JWT Auth-->>MP: return token + user info MP->>MP: store into Storage Breaking down the key points 1. The mini program gets the code (frontend) ...

2025-04-23 02:02:30 PM · 2 min

Message Middleware: Interview Questions UPDATING 

RabbitMQ How does RabbitMQ guarantee messages are not lost? Where can loss happen publisher -> exchange Producer confirmation mechanism ack publish-confirm nack publish-confirm ack publish-return How to handle a failed message Callback method Log it Save to the database and resend on a schedule exchange -> queue Message persistence Exchange persistence Queue persistence Message persistence queue queue -> consumer Consumer acknowledgment mechanism How is the duplicate-consumption problem in RabbitMQ solved? Causes of duplicate consumption ...

2025-03-23 01:21:54 PM · 1 min

Spring Cloud: Interview Questions UPDATING 

The OpenFeign service-call process flowchart TD A["Business code callsuserClient.getById(1L)"] --> B["JDK dynamic proxy Proxy.invoke"] B --> C["Feign InvocationHandlerMethodHandler"] C --> D["Contract parses annotations@GetMapping / @PathVariable"] D --> E["RequestTemplate builds the HTTP request"] E --> F["Parameter bindingPath / Query / Body / Header"] F --> G["Service name resolution: user-service"] G --> H["Service discovery: Nacos / Eureka"] H --> I["LoadBalancer load balancing"] I --> J["Select instance IP:PORT"] J --> K["HTTP Client executorOkHttp / Apache / JDK"] K --> L["Send HTTP request GET /user/1"] L --> M["Remote service: user-service"] M --> N["Controller handles the request"] N --> O["Return JSON"] O --> P["Feign Decoder deserializes"] P --> Q["JSON → UserDTO"] Q --> R["Return to business code"]

2025-02-23 01:20:18 PM · 1 min

Why Did China Big Tech Companies Pull All Their Public Docker Mirror Sources?

Over 2024 and 2025, the public Docker mirror sites run by Alibaba Cloud, Tencent Cloud, NetEase, iFlytek, and various universities were shut down or throttled in wave after wave. By 2026, “pulling an image feels like surviving a tribulation” is no longer a joke. Many people’s first reaction is to curse the big companies for being stingy. But honestly, it’s not that simple. The mountain of compliance can’t be gone around Docker Hub is a globally open community — anyone can push an image to it, and no one does content review at the entrance. That means it contains everything: images with vulnerabilities, images carrying malware, even content that crosses domestic regulatory red lines, all mixed in. ...

2024-12-23 08:16:01 AM · 3 min

Learning the Cloudflare Business UPDATING 

2024-11-23 12:37:30 AM · 0 min

Spring: Interview Questions UPDATING 

These interview questions were collected from every corner of the internet Talk about the underlying implementation of Spring IOC Reflection The value of the factory Design patterns A few key methods createBeanFactory getBean doGetBean createBean doCreateBean createBeanInstance(getDeclaredConstructor, newInstance) populateBean flowchart TD A[Start] --> B["createBeanFactory()create DefaultListableBeanFactory"] B --> C[Load BeanDefinitionsparse XML/annotations] C --> D["getBean(beanName)external call entry"] D --> E["doGetBean(beanName)"] E --> F{Get singleton from cache?} F -->|Yes| G[Return the cached Bean] F -->|No| H["createBean(beanName, mbd)"] H --> I["doCreateBean(beanName, mbd)"] I --> J["createBeanInstance()getDeclaredConstructor + newInstance"] J --> K["populateBean()property filling / dependency injection"] K --> L["initializeBean()initialization callbacks"] L --> M[Register destroy methods] M --> N[Return the complete Bean instance] Talk about your understanding of Spring IOC — its principle and implementation The IOC idea DI as the means of implementation What is a container, what is a Bean BeanDefinition Where it’s read from XML Annotations Where it’s stored All BeanDefinitions are stored in a Map inside DefaultListableBeanFactory The container lifecycle flowchart TD START([🚀 Program starts]) --> REFRESH["AbstractApplicationContext.refresh()"] REFRESH --> PHASE1 subgraph PHASE1["🔵 Phase 1: Preparation"] direction TB A1["prepareRefresh()\nrecord start time\nset container state to 'active'\ninitialize environment variables"] --> A2 A2["obtainFreshBeanFactory()\ncreate DefaultListableBeanFactory\nthe container's core repository"] --> A3 A3["prepareBeanFactory()\nregister basic BeanPostProcessors\nregister Aware-related processors\nregister the default environment Bean"] end PHASE1 --> PHASE2 subgraph PHASE2["🟢 Phase 2: Load BeanDefinitions (read the blueprints)"] direction TB B1["scan the packages specified by @ComponentScan\nor read the XML config file"] --> B2 B2["parse annotations / XML\nrecognize @Component @Service\n@Repository @Controller @Bean"] --> B3 B3["generate a BeanDefinition for each Bean\nrecord: class name, scope, lazy or not\ninit method, destroy method, dependencies"] --> B4 B4[("store into beanDefinitionMap\nkey = beanName\nvalue = BeanDefinition")] end PHASE2 --> PHASE3 subgraph PHASE3["🟡 Phase 3: Modify BeanDefinitions (edit the blueprints)"] direction TB C1["invokeBeanFactoryPostProcessors()\nrun all BeanFactoryPostProcessors"] --> C2 C2["ConfigurationClassPostProcessor\nhandle @Configuration @Import\n@PropertySource @ComponentScan\n👉 Spring Boot auto-configuration triggers here"] --> C3 C3["PropertySourcesPlaceholderConfigurer\nreplace all ${xxx} placeholders in\nBeanDefinitions with real values"] --> C4 C4[/"all BeanDefinitions finalized\nthe blueprints no longer change"/] end PHASE3 --> PHASE4 subgraph PHASE4["🌸 Phase 4: Register BeanPostProcessors (workers take their posts)"] direction TB D1["registerBeanPostProcessors()\nregister by priority\nPriorityOrdered → Ordered → ordinary"] --> D2 D2["AutowiredAnnotationBeanPostProcessor\nhandles @Autowired @Value"] --> D3 D3["CommonAnnotationBeanPostProcessor\nhandles @PostConstruct @PreDestroy @Resource"] --> D4 D4["AnnotationAwareAspectJAutoProxyCreator\ndetects aspects, generates AOP proxies"] --> D5 D5[/"all workers in place\nwaiting to intervene during Bean creation\nnot working yet"/] end PHASE4 --> PHASE5 subgraph PHASE5["🟣 Phase 5: Initialize container infrastructure"] direction TB E1["initMessageSource()\ninitialize i18n resources"] --> E2 E2["initApplicationEventMulticaster()\ninitialize the event multicaster"] --> E3 E3["onRefresh()\n⭐ Spring Boot starts here\nTomcat / Jetty / Undertow\nthe web container begins listening on a port"] --> E4 E4["registerListeners()\nregister all ApplicationListeners\nlisten for container events"] end PHASE5 --> PHASE6 subgraph PHASE6["🟠 Phase 6: Instantiate all singleton Beans"] direction TB F1["finishBeanFactoryInitialization()\npreInstantiateSingletons()\niterate all non-lazy singleton BeanDefinitions"] --> F2 F2["execute getBean() one by one\ntrigger each Bean's lifecycle\ninstantiate → fill properties → Aware callbacks\n→ pre-processing → init method → post-processing"] --> F3 F3[("all singleton Beans stored in\nthe singletonObjects level-1 cache\n✅ all ready")] end PHASE6 --> PHASE7 subgraph PHASE7["✅ Phase 7: Container ready"] direction TB G1["finishRefresh()\nclean up resources used at startup\ninitialize the lifecycle processor"] --> G2 G2["publish ContextRefreshedEvent\nnotify all listeners: container startup complete"] --> G3 G3[/"container enters running state\ncan handle business requests"/] end G3 --> RUNNING([🎉 Container running normally]) RUNNING -.->|"receive shutdown signal\nCtrl+C / kill / close()"| PHASE8 subgraph PHASE8["🔴 Phase 8: Container destruction"] direction TB H1["publish ContextClosedEvent\nnotify all listeners: container about to close"] --> H2 H2["stop the web container\nTomcat stops accepting new requests"] --> H3 H3["run all Beans' destroy logic\n@PreDestroy → destroy() → destroy-method\ndestroy in reverse registration order"] --> H4 H4["clear all caches\nsingletonObjects cleared\nbeanDefinitionMap cleared"] --> H5 H5["set container state to 'closed'\nactive = false / closed = true"] end H5 --> END([💀 Container destruction complete]) style START fill:#43A047,color:#fff style RUNNING fill:#43A047,color:#fff style END fill:#e53935,color:#fff style REFRESH fill:#1E88E5,color:#fff The Bean lifecycle flowchart TD START([🌱 Start creating the Bean]) --> A A["① Instantiation\nInstantiation\nreflectively call the constructor\nnew an empty shell object\nall fields are null at this point"] --> B B["② Put into the level-3 cache\nsingletonFactories\nexpose the half-built object early\nto prepare for circular dependencies"] --> C C["③ Property filling\npopulateBean()\nhandle @Autowired @Value\ninject the dependent Beans"] --> D subgraph AWARE["④ Aware callbacks"] direction TB D["BeanNameAware\ntell the Bean its own name"] --> E E["BeanFactoryAware\npass the BeanFactory to the Bean"] --> F F["ApplicationContextAware\npass the ApplicationContext to the Bean"] end subgraph INIT["⑤ Initialization initializeBean()"] direction TB G["pre-processing\npostProcessBeforeInitialization()\nall BeanPostProcessors run one by one\n📌 @PostConstruct is called here"] --> INITMETHOD subgraph INITMETHOD["init methods (executed in order)"] direction TB H1["1st: @PostConstruct\n(already run in pre-processing)"] --> H2 H2["2nd: afterPropertiesSet()\nimplement the InitializingBean interface"] --> H3 H3["3rd: init-method\n@Bean(initMethod='xxx') or XML config"] end INITMETHOD --> I I["post-processing\npostProcessAfterInitialization()\nall BeanPostProcessors run one by one\n⭐ AOP proxies are generated here"] end AWARE --> INIT I --> J subgraph CACHE["⑥ Store into the cache"] direction TB J["remove from the level-3 cache singletonFactories\nremove from the level-2 cache earlySingletonObjects"] --> K K["store into the level-1 cache singletonObjects\n✅ complete Bean ready"] end K --> READY([🎉 Bean is now usable]) READY -.->|"container closes"| DESTROY subgraph DESTROY["⑦ Destruction phase (on container close)"] direction TB D1["1st: @PreDestroy\nmethod is called"] --> D2 D2["2nd: destroy()\nimplement the DisposableBean interface"] --> D3 D3["3rd: destroy-method\n@Bean(destroyMethod='xxx') or XML config"] end D3 --> END([💀 Bean destruction complete]) Spring’s three-level cache dependency flow sequenceDiagram participant Spring as Spring container participant L3 as Level-3 cachesingletonFactories participant L2 as Level-2 cacheearlySingletonObjects participant L1 as Level-1 cachesingletonObjects Note over Spring: Start creating A Spring->>Spring: ① new A empty-shell object Spring->>L3: ② store A's ObjectFactory lambda Note over Spring: Injecting properties into A, discovers it needs B Spring->>Spring: ③ new B empty-shell object Spring->>L3: ④ store B's ObjectFactory lambda Note over Spring: Injecting properties into B, discovers it needs A Spring->>L1: ⑤ getBean(A), check level-1 cache L1-->>Spring: ❌ not there Spring->>L2: check level-2 cache L2-->>Spring: ❌ not there Spring->>L3: check level-3 cache L3-->>Spring: ✅ found A's lambda! Spring->>Spring: ⑥ execute the lambda(generate proxy A if a proxy is needed) Spring->>L2: ⑦ put the early reference into the level-2 cache Spring->>L3: remove A from the level-3 cache Note over Spring: B gets A's early reference, B finishes initialization Spring->>L1: ⑧ put B into the level-1 cache ✅ Spring->>L3: remove B from the level-3 cache Note over Spring: Back in A's flow, B is ready, A finishes initialization Spring->>L1: ⑨ put A into the level-1 cache ✅ Spring->>L2: remove A from the level-2 cache Note over L1: Finally: the level-1 cache holds complete A and B ✅ Case Level-3 cache lambda executed Level-2 cache No circular dep, no AOP stored the lambda ❌ not executed not used No circular dep, with AOP stored the lambda ❌ not executed not used Circular dep, no AOP stored the lambda ✅ executed stores the raw object Circular dep, with AOP stored the lambda ✅ executed stores the proxy object When Spring Bean caches are placed and removed When Spring Bean’s three-level caches are placed and removed Cache What it stores When placed When removed Level-3 singletonFactories The Bean’s factory lambda Right after instantiation When the factory is called (promoted to level-2) or when the Bean completes Level-2 earlySingletonObjects The early-exposed half-built Bean The moment the level-3 factory is called When the Bean is fully initialized and placed in level-1 Level-1 singletonObjects The complete, usable Bean After initialization fully completes When the container closes and destroys The difference between BeanFactory and FactoryBean What is a FactoryBean public interface FactoryBean<T> { // Return the Bean instance (can involve complex creation logic) T getObject() throws Exception; // Return the Bean's type Class<?> getObjectType(); // Whether it's a singleton default boolean isSingleton() { return true; } } Similarities Both are used to create Bean objects Differences Creating an object with BeanFactory must follow the strict lifecycle process, which is too complex. If you want to simply customize the creation of some object while still handing it to Spring to manage, you must implement the FactoryBean interface isSingleton — whether it’s a singleton getObjectType — get the returned object’s type getObject — customize the object-creation process Dimension BeanFactory FactoryBean Role Container/factory interface A special Bean Function Manages the lifecycle of all Beans Customizes the creation of a specific Bean Positioning Infrastructure (the IOC container) Business extension (creating complex objects) How it’s used Implemented and used by the Spring framework Implemented by the developer, registered into the container Common implementations DefaultListableBeanFactory SqlSessionFactoryBean, ProxyFactoryBean Who creates whom BeanFactory creates and manages FactoryBean FactoryBean creates business objects flowchart LR subgraph BeanFactory[BeanFactory - IOC container] direction LR Bean1[ordinary Bean] Bean2[ordinary Bean] FB[FactoryBeanspecial Bean] end FB -->|call getObject| Result[business object] User[developer] -->|getBean| BF[BeanFactory] BF -->|return| Bean1 BF -->|return| Bean2 BF -->|return getObject result| Result BF -->|add & prefix| FB Design patterns used in Spring Singleton Prototype (scope set to prototype) Factory BeanFactory Template Method JdbcTemplate TransactionTemplate RestTemplate RedisTemplate Strategy XmlBeanDefinitionReader PropertiesBeanDefinitionReader Observer listener event multicast Adapter HandlerAdapter Decorator BeanWrapper Chain of Responsibility When using AOP, an interceptor chain is generated first The filter chain of Spring MVC Proxy Dynamic proxy Delegate delegate The underlying implementation principle of Spring AOP 🥇 Level 1: characterize it in one sentence (opening) “The underlying essence of Spring AOP is dynamic proxy. When the container initializes a Bean, Spring intercepts via the BeanPostProcessor mechanism, decides whether the Bean needs enhancement, and if so, uses a dynamic proxy to generate a proxy object that replaces the original Bean when registered into the container. All subsequent calls to this Bean actually go through the proxy object.” ...

2024-10-19 11:19:24 PM · 16 min