diff --git a/pom.xml b/pom.xml index 3adb944..6f236b3 100644 --- a/pom.xml +++ b/pom.xml @@ -66,12 +66,83 @@ spring-boot-starter-actuator + + + + + org.springframework.boot + spring-boot-starter-security + + + io.jsonwebtoken + jjwt-api + 0.12.3 + + + io.jsonwebtoken + jjwt-impl + 0.12.3 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.12.3 + runtime + + + + + cn.dev33 + sa-token-spring-boot3-starter + 1.37.0 + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.apache.commons + commons-pool2 + + + + + org.springframework.boot + spring-boot-starter-cache + + + com.github.ben-manes.caffeine + caffeine + + + + + com.mysql + mysql-connector-j + runtime + + + + + org.postgresql + postgresql + runtime + + org.springframework.boot spring-boot-starter-test test + + org.springframework.security + spring-security-test + test + diff --git a/springboot.log b/springboot.log index a75fc6c..5b93523 100644 --- a/springboot.log +++ b/springboot.log @@ -7,697 +7,113 @@ =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.2.3) -2026-03-07T08:57:24.832Z INFO 1395465 --- [springboot-scaffold] [ main] c.e.s.SpringbootScaffoldApplication : Starting SpringbootScaffoldApplication v1.0.0 using Java 21.0.10 with PID 1395465 (/home/llm/Projects/springboot-scaffold/target/springboot-scaffold-1.0.0.jar started by llm in /home/llm/Projects/springboot-scaffold) -2026-03-07T08:57:24.840Z DEBUG 1395465 --- [springboot-scaffold] [ main] c.e.s.SpringbootScaffoldApplication : Running with Spring Boot v3.2.3, Spring v6.1.4 -2026-03-07T08:57:24.843Z INFO 1395465 --- [springboot-scaffold] [ main] c.e.s.SpringbootScaffoldApplication : No active profile set, falling back to 1 default profile: "default" -2026-03-07T08:57:32.385Z INFO 1395465 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. -2026-03-07T08:57:32.453Z INFO 1395465 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 30 ms. Found 0 JPA repository interfaces. -2026-03-07T08:57:39.150Z INFO 1395465 --- [springboot-scaffold] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8082 (http) -2026-03-07T08:57:39.218Z INFO 1395465 --- [springboot-scaffold] [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] -2026-03-07T08:57:39.222Z INFO 1395465 --- [springboot-scaffold] [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.19] -2026-03-07T08:57:39.853Z INFO 1395465 --- [springboot-scaffold] [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext -2026-03-07T08:57:39.862Z INFO 1395465 --- [springboot-scaffold] [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 14718 ms -2026-03-07T08:57:41.622Z INFO 1395465 --- [springboot-scaffold] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... -2026-03-07T08:57:43.594Z INFO 1395465 --- [springboot-scaffold] [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA -2026-03-07T08:57:43.610Z INFO 1395465 --- [springboot-scaffold] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. -2026-03-07T08:57:43.680Z INFO 1395465 --- [springboot-scaffold] [ main] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:file:~/h2/springboot_scaffold' -2026-03-07T08:57:47.458Z INFO 1395465 --- [springboot-scaffold] [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] -2026-03-07T08:57:47.796Z INFO 1395465 --- [springboot-scaffold] [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 6.4.4.Final -2026-03-07T08:57:48.002Z INFO 1395465 --- [springboot-scaffold] [ main] o.h.c.internal.RegionFactoryInitiator : HHH000026: Second-level cache disabled -2026-03-07T08:57:49.405Z INFO 1395465 --- [springboot-scaffold] [ main] o.s.o.j.p.SpringPersistenceUnitInfo : No LoadTimeWeaver setup: ignoring JPA class transformer -2026-03-07T08:57:56.408Z INFO 1395465 --- [springboot-scaffold] [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) -2026-03-07T08:57:56.727Z INFO 1395465 --- [springboot-scaffold] [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' -Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter. -2026-03-07T08:58:00.775Z WARN 1395465 --- [springboot-scaffold] [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning -2026-03-07T08:58:01.509Z INFO 1395465 --- [springboot-scaffold] [ main] o.s.b.a.w.s.WelcomePageHandlerMapping : Adding welcome page: class path resource [static/index.html] -2026-03-07T08:58:10.592Z INFO 1395465 --- [springboot-scaffold] [ main] o.s.b.a.e.web.EndpointLinksResolver : Exposing 1 endpoint(s) beneath base path '/actuator' -2026-03-07T08:58:11.582Z INFO 1395465 --- [springboot-scaffold] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port 8082 (http) with context path '' -2026-03-07T08:58:11.689Z INFO 1395465 --- [springboot-scaffold] [ main] c.e.s.SpringbootScaffoldApplication : Started SpringbootScaffoldApplication in 49.545 seconds (process running for 52.6) -2026-03-07T08:58:55.808Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' -2026-03-07T08:58:55.810Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' -2026-03-07T08:58:55.824Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 8 ms -2026-03-07T08:58:56.276Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: RootController.index() 参数: [] -2026-03-07T08:58:56.277Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: RootController.index() 耗时: 1ms -2026-03-07T09:04:54.453Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: RootController.index() 参数: [] -2026-03-07T09:04:54.454Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: RootController.index() 耗时: 1ms -2026-03-07T09:04:54.926Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -2026-03-07T09:04:54.927Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:04:54.927Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -2026-03-07T09:04:54.932Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:04:54.936Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -Creating a new SqlSession -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7edf21ef] was not registered for synchronization because synchronization is not active -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e00c432] was not registered for synchronization because synchronization is not active -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40942315] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.0 -JDBC Connection [HikariProxyConnection@1678050146 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -JDBC Connection [HikariProxyConnection@990931398 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -JDBC Connection [HikariProxyConnection@130499610 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Preparing: SELECT COUNT(*) FROM users -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -==> Parameters: -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e00c432] -<== Columns: COUNT(*) -<== Row: 0 -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7edf21ef] -2026-03-07T09:04:55.109Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 183ms -2026-03-07T09:04:55.106Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:04:55.110Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:04:55.110Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 183ms -<== Total: 1 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40942315] -2026-03-07T09:04:55.136Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:04:55.136Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:04:55.136Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 204ms -2026-03-07T09:05:06.090Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7377beec] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@978555190 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -2026-03-07T09:05:06.093Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:05:06.093Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@90950fc] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@428815786 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -2026-03-07T09:05:06.089Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:05:06.094Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@440b2f50] was not registered for synchronization because synchronization is not active -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7377beec] -2026-03-07T09:05:06.096Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 6ms -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@90950fc] -2026-03-07T09:05:06.100Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:05:06.100Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:05:06.100Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 7ms -As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66 -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.5 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@440b2f50] -2026-03-07T09:05:06.117Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:05:06.118Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:05:06.118Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 29ms -2026-03-07T09:05:36.083Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:05:36.083Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@34150731] was not registered for synchronization because synchronization is not active -2026-03-07T09:05:36.084Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50a60d1e] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@770987400 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -JDBC Connection [HikariProxyConnection@1647938239 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@34150731] -2026-03-07T09:05:36.086Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:05:36.082Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50a60d1e] -2026-03-07T09:05:36.087Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 3ms -2026-03-07T09:05:36.087Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@736d353] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.6666666666666666 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@736d353] -2026-03-07T09:05:36.093Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:05:36.093Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:05:36.093Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 11ms -2026-03-07T09:05:36.086Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:05:36.094Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 11ms -2026-03-07T09:06:06.078Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:06:06.078Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -2026-03-07T09:06:06.080Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@43ee2751] was not registered for synchronization because synchronization is not active -2026-03-07T09:06:06.077Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:06:06.081Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40db3c0a] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1204923380 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@43ee2751] -2026-03-07T09:06:06.082Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 2ms -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17dc9322] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@565369255 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17dc9322] -2026-03-07T09:06:06.084Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:06:06.084Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.75 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40db3c0a] -2026-03-07T09:06:06.086Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:06:06.087Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:06:06.087Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 10ms -2026-03-07T09:06:06.084Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 6ms -2026-03-07T09:06:36.080Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17588e60] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1674264023 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17588e60] -2026-03-07T09:06:36.082Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:06:36.085Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4cd52d5e] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1429246749 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4cd52d5e] -2026-03-07T09:06:36.086Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:06:36.077Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:06:36.086Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79bd0b9e] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79bd0b9e] -2026-03-07T09:06:36.085Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 5ms -2026-03-07T09:06:36.087Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:06:36.093Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:06:36.093Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 16ms -2026-03-07T09:06:36.086Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:06:36.095Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 17ms -2026-03-07T09:06:41.293Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:06:41.293Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1a0b0f13] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@462297636 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1a0b0f13] -2026-03-07T09:06:41.296Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2d32d6a] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@25026644 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2d32d6a] -2026-03-07T09:06:41.301Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 5ms -2026-03-07T09:06:41.294Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:06:41.301Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b43759c] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8333333333333334 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b43759c] -2026-03-07T09:06:41.302Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:06:41.302Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:06:41.299Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:06:41.306Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:06:41.306Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 13ms -2026-03-07T09:06:41.309Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 15ms -2026-03-07T09:08:41.365Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:08:41.365Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5f9384ac] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@250235960 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -2026-03-07T09:08:41.369Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:08:41.365Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35e2cef0] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8571428571428571 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35e2cef0] -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5f9384ac] -2026-03-07T09:08:41.371Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 6ms -2026-03-07T09:08:41.369Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2412cfb] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@945724641 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2412cfb] -2026-03-07T09:08:41.371Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:08:41.378Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:08:41.378Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 13ms -2026-03-07T09:08:41.382Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:08:41.383Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:08:41.383Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 14ms -2026-03-07T09:09:11.381Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:09:11.389Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@339b8b85] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@2044663817 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -2026-03-07T09:09:11.385Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:09:11.393Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@e836b18] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.875 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@e836b18] -2026-03-07T09:09:11.378Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@25bb0795] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1706570017 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@339b8b85] -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@25bb0795] -2026-03-07T09:09:11.401Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 23ms -2026-03-07T09:09:11.398Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:09:11.403Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:09:11.404Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 23ms -2026-03-07T09:09:11.407Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:09:11.407Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:09:11.407Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 22ms -2026-03-07T09:09:57.591Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:09:57.591Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@76aff600] was not registered for synchronization because synchronization is not active -2026-03-07T09:09:57.592Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:09:57.592Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62fcd225] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@216920430 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -2026-03-07T09:09:57.593Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b9672e8] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@103531179 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8888888888888888 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@76aff600] -2026-03-07T09:09:57.599Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:09:57.599Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:09:57.599Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 8ms -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62fcd225] -2026-03-07T09:09:57.600Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:09:57.600Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:09:57.600Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 8ms -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b9672e8] -2026-03-07T09:09:57.603Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 10ms -2026-03-07T09:10:15.699Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:10:15.699Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -2026-03-07T09:10:15.700Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ee6ebd7] was not registered for synchronization because synchronization is not active -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6f7c93a3] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.9 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6f7c93a3] -2026-03-07T09:10:15.702Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:10:15.702Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:10:15.702Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 3ms -JDBC Connection [HikariProxyConnection@995189036 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ee6ebd7] -2026-03-07T09:10:15.704Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 4ms -2026-03-07T09:10:15.720Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:10:15.724Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@619fee3f] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1251411904 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@619fee3f] -2026-03-07T09:10:15.734Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:10:15.738Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:10:15.738Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 18ms -2026-03-07T09:10:45.697Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@41732ca4] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1767511888 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@41732ca4] -2026-03-07T09:10:45.698Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 7ms -2026-03-07T09:10:45.694Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:10:45.699Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16edaf1a] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.9090909090909091 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16edaf1a] -2026-03-07T09:10:45.700Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:10:45.700Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:10:45.695Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:10:45.702Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@634584d5] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1658574820 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@634584d5] -2026-03-07T09:10:45.705Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 6ms -2026-03-07T09:10:45.703Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:10:45.709Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:10:45.710Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 15ms -2026-03-07T09:11:15.696Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:11:15.698Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@78a4240e] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@611531950 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -2026-03-07T09:11:15.694Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:11:15.699Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2709c912] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.9166666666666666 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2709c912] -2026-03-07T09:11:15.700Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:11:15.700Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:11:15.700Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 6ms -2026-03-07T09:11:15.700Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4900755b] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@985053914 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4900755b] -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@78a4240e] -2026-03-07T09:11:15.704Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 6ms -2026-03-07T09:11:15.708Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:11:15.708Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:11:15.708Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 12ms -2026-03-07T09:11:20.259Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.list() 参数: [] -2026-03-07T09:11:20.260Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.findAll() -2026-03-07T09:11:20.260Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.e.s.service.impl.UserServiceImpl : 📊 [UserService] 查询所有用户 -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@75988cd9] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8461538461538461 -JDBC Connection [HikariProxyConnection@1859934865 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM users ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@75988cd9] -2026-03-07T09:11:20.265Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.findAll() => ArrayList -2026-03-07T09:11:20.265Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.findAll() -2026-03-07T09:11:20.265Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.list() 耗时: 6ms -2026-03-07T09:13:39.723Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:13:39.723Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66b24c60] was not registered for synchronization because synchronization is not active -2026-03-07T09:13:39.720Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@abcee10] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1337876771 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@abcee10] -2026-03-07T09:13:39.726Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:13:39.726Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@dfe33ca] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@101992541 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8571428571428571 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66b24c60] -2026-03-07T09:13:39.728Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:13:39.728Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:13:39.728Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 6ms -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@dfe33ca] -2026-03-07T09:13:39.728Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:13:39.728Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:13:39.728Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 6ms -2026-03-07T09:13:39.724Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 4ms -2026-03-07T09:13:46.169Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.list() 参数: [] -2026-03-07T09:13:46.169Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.findAll() -2026-03-07T09:13:46.169Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.e.s.service.impl.UserServiceImpl : 📊 [UserService] 查询所有用户 -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5d32c3a4] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8666666666666667 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5d32c3a4] -2026-03-07T09:13:46.171Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.findAll() => ArrayList -2026-03-07T09:13:46.171Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.findAll() -2026-03-07T09:13:46.171Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.list() 耗时: 2ms -2026-03-07T09:13:50.492Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:13:50.506Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:13:50.506Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53c286a4] was not registered for synchronization because synchronization is not active -2026-03-07T09:13:50.510Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@47d7de43] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@927509680 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@47d7de43] -2026-03-07T09:13:50.512Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:13:50.513Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@31bcbe4a] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@201598228 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.875 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@53c286a4] -2026-03-07T09:13:50.517Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:13:50.520Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:13:50.521Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 29ms -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@31bcbe4a] -2026-03-07T09:13:50.524Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 11ms -2026-03-07T09:13:50.517Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:13:50.532Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-8] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 26ms -2026-03-07T09:13:58.593Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b758231] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@2126245868 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b758231] -2026-03-07T09:13:58.595Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:13:58.600Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@31c79940] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8823529411764706 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@31c79940] -2026-03-07T09:13:58.601Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:13:58.601Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:13:58.593Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:13:58.602Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4cf45f69] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1134251079 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -2026-03-07T09:13:58.600Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 7ms -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4cf45f69] -2026-03-07T09:13:58.608Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 13ms -2026-03-07T09:13:58.606Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:13:58.611Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:13:58.611Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 18ms -2026-03-07T09:14:28.582Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:14:28.582Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -2026-03-07T09:14:28.582Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@54ca2e3c] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1838371682 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@54ca2e3c] -2026-03-07T09:14:28.583Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:14:28.584Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3de435fb] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8888888888888888 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3de435fb] -2026-03-07T09:14:28.584Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2770fa1] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@859350386 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2770fa1] -2026-03-07T09:14:28.583Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 1ms -2026-03-07T09:14:28.589Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:14:28.590Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 7ms -2026-03-07T09:14:28.587Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:14:28.591Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:14:28.591Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 9ms -2026-03-07T09:14:58.931Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:14:58.932Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -2026-03-07T09:14:58.936Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:14:58.936Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ff48ae6] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@908619933 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -2026-03-07T09:14:58.938Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3989ee74] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.8947368421052632 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3989ee74] -2026-03-07T09:14:58.940Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:14:58.940Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:14:58.940Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 9ms -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ff48ae6] -2026-03-07T09:14:58.944Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:14:58.944Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:14:58.944Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 8ms -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3fbc7956] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@721325685 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3fbc7956] -2026-03-07T09:14:58.948Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 10ms -2026-03-07T09:15:28.926Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:15:28.926Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5021275e] was not registered for synchronization because synchronization is not active -2026-03-07T09:15:28.928Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:15:28.929Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f87579d] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@469087888 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -2026-03-07T09:15:28.929Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e8dc242] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.9 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5e8dc242] -2026-03-07T09:15:28.930Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:15:28.930Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:15:28.930Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 8ms -JDBC Connection [HikariProxyConnection@1372181421 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5021275e] -2026-03-07T09:15:28.934Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:15:28.934Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:15:28.934Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 8ms -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3f87579d] -2026-03-07T09:15:28.938Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-3] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 9ms -2026-03-07T09:15:58.931Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:15:58.936Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10ce968c] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@1714135762 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -2026-03-07T09:15:58.932Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@42485dce] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@2065854273 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -2026-03-07T09:15:58.934Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:15:58.939Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@447777c4] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.9047619047619048 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@447777c4] -2026-03-07T09:15:58.940Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:15:58.940Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@10ce968c] -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@42485dce] -2026-03-07T09:15:58.944Z INFO 1395465 --- [springboot-scaffold] [io-8082-exec-10] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 10ms -2026-03-07T09:15:58.944Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:15:58.945Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:15:58.944Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 12ms -2026-03-07T09:15:58.947Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-6] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 16ms -2026-03-07T09:16:28.924Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ed3de82] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@349902318 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2ed3de82] -2026-03-07T09:16:28.928Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-4] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 4ms -2026-03-07T09:16:28.926Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:16:28.930Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@89ed8c5] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@736052548 wrapping conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@89ed8c5] -2026-03-07T09:16:28.927Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -2026-03-07T09:16:28.932Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66047844] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.9090909090909091 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@66047844] -2026-03-07T09:16:28.933Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:16:28.933Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:16:28.933Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-2] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 6ms -2026-03-07T09:16:28.931Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:16:28.937Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:16:28.937Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-9] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 11ms -2026-03-07T09:16:58.931Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listOrders() 参数: [] -2026-03-07T09:16:58.931Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: OrderService.findAll() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79f75a00] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@692524477 wrapping conn1: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -2026-03-07T09:16:58.932Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: UserController.count() 参数: [] -==> Preparing: SELECT * FROM orders ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@79f75a00] -2026-03-07T09:16:58.933Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: OrderService.findAll() => ArrayList -2026-03-07T09:16:58.934Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 开始: ProductOrderController.listProducts() 参数: [] -2026-03-07T09:16:58.937Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: OrderService.findAll() -2026-03-07T09:16:58.937Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-1] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listOrders() 耗时: 6ms -Creating a new SqlSession -2026-03-07T09:16:58.938Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔹 [AOP @Before] 即将执行: UserServiceImpl.count() -Creating a new SqlSession -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@140850d4] was not registered for synchronization because synchronization is not active -Cache Hit Ratio [com.example.scaffold.mapper.UserMapper]: 0.9130434782608695 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@140850d4] -2026-03-07T09:16:58.939Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : ✅ [AOP @AfterReturning] 方法返回: UserServiceImpl.count() => Long -2026-03-07T09:16:58.939Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔸 [AOP @After] 执行完成: UserServiceImpl.count() -2026-03-07T09:16:58.939Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-5] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: UserController.count() 耗时: 7ms -SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@75cdad47] was not registered for synchronization because synchronization is not active -JDBC Connection [HikariProxyConnection@411658786 wrapping conn2: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA] will not be managed by Spring -==> Preparing: SELECT * FROM products ORDER BY created_at DESC -==> Parameters: -<== Total: 0 -Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@75cdad47] -2026-03-07T09:16:58.940Z INFO 1395465 --- [springboot-scaffold] [nio-8082-exec-7] c.example.scaffold.aop.LearningAspect : 🔄 [AOP @Around] 完成: ProductOrderController.listProducts() 耗时: 6ms +2026-03-07T09:46:43.594Z INFO 1411782 --- [springboot-scaffold] [ main] c.e.s.SpringbootScaffoldApplication : Starting SpringbootScaffoldApplication v1.0.0 using Java 21.0.10 with PID 1411782 (/home/llm/Projects/springboot-scaffold/target/springboot-scaffold-1.0.0.jar started by llm in /home/llm/Projects/springboot-scaffold) +2026-03-07T09:46:43.612Z DEBUG 1411782 --- [springboot-scaffold] [ main] c.e.s.SpringbootScaffoldApplication : Running with Spring Boot v3.2.3, Spring v6.1.4 +2026-03-07T09:46:43.616Z INFO 1411782 --- [springboot-scaffold] [ main] c.e.s.SpringbootScaffoldApplication : No active profile set, falling back to 1 default profile: "default" +2026-03-07T09:46:51.883Z INFO 1411782 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode +2026-03-07T09:46:51.893Z INFO 1411782 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. +2026-03-07T09:46:51.970Z INFO 1411782 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 44 ms. Found 0 JPA repository interfaces. +2026-03-07T09:46:52.055Z INFO 1411782 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode +2026-03-07T09:46:52.058Z INFO 1411782 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode. +2026-03-07T09:46:52.120Z INFO 1411782 --- [springboot-scaffold] [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 20 ms. Found 0 Redis repository interfaces. +2026-03-07T09:47:00.903Z INFO 1411782 --- [springboot-scaffold] [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port 8082 (http) +2026-03-07T09:47:00.979Z INFO 1411782 --- [springboot-scaffold] [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] +2026-03-07T09:47:00.986Z INFO 1411782 --- [springboot-scaffold] [ main] o.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/10.1.19] +2026-03-07T09:47:01.536Z INFO 1411782 --- [springboot-scaffold] [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext +2026-03-07T09:47:01.543Z INFO 1411782 --- [springboot-scaffold] [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 17641 ms +2026-03-07T09:47:03.138Z INFO 1411782 --- [springboot-scaffold] [ main] c.e.s.config.database.DatabaseConfig : 🚀 使用 H2 内存数据库 +2026-03-07T09:47:03.393Z INFO 1411782 --- [springboot-scaffold] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... +2026-03-07T09:47:05.499Z INFO 1411782 --- [springboot-scaffold] [ main] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection conn0: url=jdbc:h2:file:~/h2/springboot_scaffold user=SA +2026-03-07T09:47:05.513Z INFO 1411782 --- [springboot-scaffold] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. +2026-03-07T09:47:05.595Z INFO 1411782 --- [springboot-scaffold] [ main] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:file:~/h2/springboot_scaffold' +2026-03-07T09:47:06.561Z WARN 1411782 --- [springboot-scaffold] [ main] o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final void org.springframework.web.filter.OncePerRequestFilter.doFilter(jakarta.servlet.ServletRequest,jakarta.servlet.ServletResponse,jakarta.servlet.FilterChain) throws jakarta.servlet.ServletException,java.io.IOException] because it is marked as final, consider using interface-based JDK proxies instead. +2026-03-07T09:47:06.561Z WARN 1411782 --- [springboot-scaffold] [ main] o.s.aop.framework.CglibAopProxy : Unable to proxy interface-implementing method [public final void org.springframework.web.filter.GenericFilterBean.init(jakarta.servlet.FilterConfig) throws jakarta.servlet.ServletException] because it is marked as final, consider using interface-based JDK proxies instead. +2026-03-07T09:47:08.518Z ERROR 1411782 --- [springboot-scaffold] [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Exception starting filter [jwtAuthenticationFilter] + +java.lang.NullPointerException: Cannot invoke "org.apache.commons.logging.Log.isDebugEnabled()" because "this.logger" is null + at org.springframework.web.filter.GenericFilterBean.init(GenericFilterBean.java:239) ~[spring-web-6.1.4.jar!/:6.1.4] + at org.apache.catalina.core.ApplicationFilterConfig.initFilter(ApplicationFilterConfig.java:263) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.ApplicationFilterConfig.(ApplicationFilterConfig.java:102) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.StandardContext.filterStart(StandardContext.java:4287) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4902) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322) ~[tomcat-embed-core-10.1.19.jar!/:na] + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na] + at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-10.1.19.jar!/:na] + at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) ~[na:na] + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:845) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322) ~[tomcat-embed-core-10.1.19.jar!/:na] + at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na] + at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-10.1.19.jar!/:na] + at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:145) ~[na:na] + at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:240) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.StandardService.startInternal(StandardService.java:433) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:921) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.apache.catalina.startup.Tomcat.start(Tomcat.java:437) ~[tomcat-embed-core-10.1.19.jar!/:na] + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:126) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.(TomcatWebServer.java:105) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:499) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:218) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:188) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:618) ~[spring-context-6.1.4.jar!/:6.1.4] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.3.jar!/:3.2.3] + at com.example.scaffold.SpringbootScaffoldApplication.main(SpringbootScaffoldApplication.java:9) ~[!/:1.0.0] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na] + at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[springboot-scaffold-1.0.0.jar:1.0.0] + at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[springboot-scaffold-1.0.0.jar:1.0.0] + at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58) ~[springboot-scaffold-1.0.0.jar:1.0.0] + +2026-03-07T09:47:08.551Z ERROR 1411782 --- [springboot-scaffold] [ main] o.apache.catalina.core.StandardContext : One or more Filters failed to start. Full details will be found in the appropriate container log file +2026-03-07T09:47:08.555Z ERROR 1411782 --- [springboot-scaffold] [ main] o.apache.catalina.core.StandardContext : Context [] startup failed due to previous errors +2026-03-07T09:47:08.698Z INFO 1411782 --- [springboot-scaffold] [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat] +2026-03-07T09:47:08.716Z WARN 1411782 --- [springboot-scaffold] [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server +2026-03-07T09:47:08.720Z INFO 1411782 --- [springboot-scaffold] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... +2026-03-07T09:47:08.971Z INFO 1411782 --- [springboot-scaffold] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed. +2026-03-07T09:47:09.105Z INFO 1411782 --- [springboot-scaffold] [ main] .s.b.a.l.ConditionEvaluationReportLogger : + +Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled. +2026-03-07T09:47:09.207Z ERROR 1411782 --- [springboot-scaffold] [ main] o.s.boot.SpringApplication : Application run failed + +org.springframework.context.ApplicationContextException: Unable to start web server + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:165) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:618) ~[spring-context-6.1.4.jar!/:6.1.4] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:334) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.3.jar!/:3.2.3] + at com.example.scaffold.SpringbootScaffoldApplication.main(SpringbootScaffoldApplication.java:9) ~[!/:1.0.0] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na] + at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:91) ~[springboot-scaffold-1.0.0.jar:1.0.0] + at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:53) ~[springboot-scaffold-1.0.0.jar:1.0.0] + at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:58) ~[springboot-scaffold-1.0.0.jar:1.0.0] +Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:145) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.(TomcatWebServer.java:105) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:499) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:218) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:188) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162) ~[spring-boot-3.2.3.jar!/:3.2.3] + ... 13 common frames omitted +Caused by: java.lang.IllegalStateException: StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[] failed to start + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.rethrowDeferredStartupExceptions(TomcatWebServer.java:207) ~[spring-boot-3.2.3.jar!/:3.2.3] + at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:129) ~[spring-boot-3.2.3.jar!/:3.2.3] + ... 18 common frames omitted + diff --git a/src/main/java/com/example/scaffold/cache/CacheConfig.java b/src/main/java/com/example/scaffold/cache/CacheConfig.java new file mode 100644 index 0000000..9764e6d --- /dev/null +++ b/src/main/java/com/example/scaffold/cache/CacheConfig.java @@ -0,0 +1,100 @@ +package com.example.scaffold.cache; + +import com.github.benmanes.caffeine.cache.Caffeine; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCacheManager; +import org.springframework.cache.interceptor.KeyGenerator; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; + +/** + * 缓存配置 - 支持 Caffeine(本地) 和 Redis(分布式) + * + * 学习要点: + * 1. @EnableCaching - 启用 Spring Cache + * 2. @Cacheable - 缓存方法结果 + * 3. @CacheEvict - 清除缓存 + * 4. @CachePut - 更新缓存 + */ +@Slf4j +@Configuration +@EnableCaching +public class CacheConfig { + + /** + * Caffeine 本地缓存 - 默认 + */ + @Bean + @Primary + @ConditionalOnProperty(name = "cache.type", havingValue = "caffeine", matchIfMissing = true) + public CacheManager caffeineCacheManager() { + log.info("🚀 启用 Caffeine 本地缓存"); + CaffeineCacheManager cacheManager = new CaffeineCacheManager(); + cacheManager.setCaffeine(Caffeine.newBuilder() + // 初始容量 + .initialCapacity(100) + // 最大容量 + .maximumSize(1000) + // 写入后过期时间 + .expireAfterWrite(10, TimeUnit.MINUTES) + // 记录命中率 + .recordStats() + ); + return cacheManager; + } + + /** + * Redis 分布式缓存 + */ + @Bean + @ConditionalOnProperty(name = "cache.type", havingValue = "redis") + public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) { + log.info("🚀 启用 Redis 分布式缓存"); + + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() + // 键序列化 + .serializeKeysWith(RedisSerializationContext.SerializationPair + .fromSerializer(new StringRedisSerializer())) + // 值序列化 + .serializeValuesWith(RedisSerializationContext.SerializationPair + .fromSerializer(new GenericJackson2JsonRedisSerializer())) + // 过期时间 + .entryTtl(Duration.ofMinutes(10)) + // 不缓存 null + .disableCachingNullValues(); + + return RedisCacheManager.builder(connectionFactory) + .cacheDefaults(config) + .transactionAware() + .build(); + } + + /** + * 自定义缓存 Key 生成器 + */ + @Bean + public KeyGenerator customKeyGenerator() { + return (target, method, params) -> { + StringBuilder sb = new StringBuilder(); + sb.append(target.getClass().getSimpleName()).append(":"); + sb.append(method.getName()).append(":"); + for (Object param : params) { + sb.append(param).append("-"); + } + return sb.toString(); + }; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/scaffold/cache/CacheService.java b/src/main/java/com/example/scaffold/cache/CacheService.java new file mode 100644 index 0000000..d276892 --- /dev/null +++ b/src/main/java/com/example/scaffold/cache/CacheService.java @@ -0,0 +1,143 @@ +package com.example.scaffold.cache; + +import com.example.scaffold.entity.User; +import com.example.scaffold.mapper.UserMapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; + +import java.util.concurrent.TimeUnit; + +/** + * 缓存服务 - 演示 Spring Cache 和 Redis 操作 + * + * 学习要点: + * 1. @Cacheable - 方法结果缓存 + * 2. @CachePut - 更新缓存 + * 3. @CacheEvict - 清除缓存 + * 4. RedisTemplate - 直接操作 Redis + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class CacheService { + + private final UserMapper userMapper; + private final StringRedisTemplate redisTemplate; + + /** + * 根据ID查询用户 - 使用缓存 + * + * @Cacheable 注解说明: + * - value: 缓存名称 + * - key: 缓存键(支持 SpEL 表达式) + * - unless: 条件,为 true 时不缓存 + */ + @Cacheable(value = "users", key = "#id", unless = "#result == null") + public User getUserById(Long id) { + log.info("🔍 [Cache] 从数据库查询用户: id={}", id); + return userMapper.findById(id); + } + + /** + * 更新用户 - 更新缓存 + * + * @CachePut 注解说明: + * - 方法一定会执行 + * - 执行后更新缓存 + */ + @CachePut(value = "users", key = "#user.id") + public User updateUser(User user) { + log.info("💾 [Cache] 更新用户并刷新缓存: id={}", user.getId()); + userMapper.update(user); + return user; + } + + /** + * 删除用户 - 清除缓存 + * + * @CacheEvict 注解说明: + * - 清除指定缓存 + * - allEntries = true: 清除所有条目 + * - beforeInvocation = true: 方法执行前清除 + */ + @CacheEvict(value = "users", key = "#id") + public void deleteUser(Long id) { + log.info("🗑️ [Cache] 删除用户并清除缓存: id={}", id); + userMapper.deleteById(id); + } + + /** + * 清除所有用户缓存 + */ + @CacheEvict(value = "users", allEntries = true) + public void clearUserCache() { + log.info("🧹 [Cache] 清除所有用户缓存"); + } + + // ==================== Redis 直接操作 ==================== + + /** + * Redis String 操作 + */ + public void setString(String key, String value, long timeout, TimeUnit unit) { + redisTemplate.opsForValue().set(key, value, timeout, unit); + log.info("📝 [Redis] SET {} = {} (TTL: {} {})", key, value, timeout, unit); + } + + public String getString(String key) { + String value = redisTemplate.opsForValue().get(key); + log.info("📝 [Redis] GET {} = {}", key, value); + return value; + } + + /** + * Redis Hash 操作 + */ + public void setHash(String key, String field, String value) { + redisTemplate.opsForHash().put(key, field, value); + log.info("📝 [Redis] HSET {} {} = {}", key, field, value); + } + + public String getHash(String key, String field) { + Object value = redisTemplate.opsForHash().get(key, field); + log.info("📝 [Redis] HGET {} {} = {}", key, field, value); + return value != null ? value.toString() : null; + } + + /** + * Redis List 操作 + */ + public void pushToList(String key, String value) { + redisTemplate.opsForList().rightPush(key, value); + log.info("📝 [Redis] RPUSH {} {}", key, value); + } + + /** + * Redis Set 操作 + */ + public void addToSet(String key, String value) { + redisTemplate.opsForSet().add(key, value); + log.info("📝 [Redis] SADD {} {}", key, value); + } + + /** + * Redis 分布式锁 + */ + public boolean tryLock(String key, String value, long timeout, TimeUnit unit) { + Boolean success = redisTemplate.opsForValue() + .setIfAbsent(key, value, timeout, unit); + log.info("🔒 [Redis] TRY_LOCK {} = {}", key, success); + return Boolean.TRUE.equals(success); + } + + public void unlock(String key) { + redisTemplate.delete(key); + log.info("🔓 [Redis] UNLOCK {}", key); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/scaffold/learning/AdvancedLearningController.java b/src/main/java/com/example/scaffold/learning/AdvancedLearningController.java new file mode 100644 index 0000000..2516e92 --- /dev/null +++ b/src/main/java/com/example/scaffold/learning/AdvancedLearningController.java @@ -0,0 +1,206 @@ +package com.example.scaffold.learning; + +import com.example.scaffold.cache.CacheService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * 高级功能学习控制器 + * + * 学习内容: + * 1. Redis 数据类型操作 + * 2. 缓存策略 + * 3. 分布式锁 + * 4. 认证方案对比 + */ +@Slf4j +@RestController +@RequestMapping("/api/learning/advanced") +@RequiredArgsConstructor +public class AdvancedLearningController { + + private final StringRedisTemplate redisTemplate; + private final CacheService cacheService; + + @Value("${auth.type:none}") + private String authType; + + @Value("${cache.type:caffeine}") + private String cacheType; + + @Value("${spring.datasource.driver-class-name}") + private String dbDriver; + + /** + * 系统配置概览 + */ + @GetMapping("/config") + public Map getConfig() { + String dbType = dbDriver.contains("h2") ? "H2" : + dbDriver.contains("mysql") ? "MySQL" : + dbDriver.contains("postgresql") ? "PostgreSQL" : "Unknown"; + + return Map.of( + "认证方案", Map.of( + "当前", authType, + "可选", "none | jwt | satoken", + "说明", Map.of( + "none", "无认证,开发测试用", + "jwt", "Spring Security + JWT,标准方案", + "satoken", "Sa-Token,轻量级方案" + ) + ), + "缓存方案", Map.of( + "当前", cacheType, + "可选", "caffeine | redis", + "说明", Map.of( + "caffeine", "本地缓存,单机高性能", + "redis", "分布式缓存,支持集群" + ) + ), + "数据库", Map.of( + "当前", dbType, + "可选", "H2 | MySQL | PostgreSQL", + "驱动", dbDriver + ) + ); + } + + /** + * Redis 数据类型演示 + */ + @GetMapping("/redis/types") + public Map redisTypes() { + return Map.of( + "String", "字符串,最基本的数据类型", + "Hash", "哈希,适合存储对象", + "List", "列表,支持队列/栈操作", + "Set", "集合,去重、交并差运算", + "SortedSet", "有序集合,支持排名", + "Bitmap", "位图,海量布尔值存储", + "HyperLogLog", "基数统计,UV统计", + "Geo", "地理位置,附近的人", + "Stream", "流,消息队列" + ); + } + + /** + * Redis String 操作演示 + */ + @PostMapping("/redis/string") + public Map redisString(@RequestParam String key, + @RequestParam String value, + @RequestParam(defaultValue = "60") long ttl) { + cacheService.setString(key, value, ttl, TimeUnit.SECONDS); + return Map.of( + "操作", "SET", + "key", key, + "value", value, + "ttl", ttl + "秒" + ); + } + + @GetMapping("/redis/string") + public Map getRedisString(@RequestParam String key) { + String value = cacheService.getString(key); + return Map.of( + "操作", "GET", + "key", key, + "value", value, + "存在", value != null + ); + } + + /** + * 缓存穿透/击穿/雪崩解决方案 + */ + @GetMapping("/cache/problems") + public Map cacheProblems() { + return Map.of( + "缓存穿透", Map.of( + "问题", "查询不存在的数据,每次都打到数据库", + "解决", "布隆过滤器 | 缓存空值", + "代码", "@Cacheable(unless=\"#result == null\")" + ), + "缓存击穿", Map.of( + "问题", "热点key过期,大量请求打到数据库", + "解决", "互斥锁 | 逻辑过期", + "代码", "synchronized 或 Redis 分布式锁" + ), + "缓存雪崩", Map.of( + "问题", "大量key同时过期,数据库压力激增", + "解决", "随机过期时间 | 多级缓存", + "代码", "expire + random(60)" + ) + ); + } + + /** + * 分布式锁演示 + */ + @PostMapping("/redis/lock") + public Map distributedLock(@RequestParam String resource, + @RequestParam(defaultValue = "10") long ttl) { + String lockKey = "lock:" + resource; + String lockValue = Thread.currentThread().getName(); + + boolean locked = cacheService.tryLock(lockKey, lockValue, ttl, TimeUnit.SECONDS); + + if (locked) { + try { + // 模拟业务操作 + Thread.sleep(1000); + return Map.of( + "success", true, + "message", "获取锁成功,执行业务操作", + "resource", resource, + "lockKey", lockKey + ); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + return Map.of("success", false, "error", "业务中断"); + } finally { + cacheService.unlock(lockKey); + } + } else { + return Map.of( + "success", false, + "message", "获取锁失败,资源被占用", + "resource", resource + ); + } + } + + /** + * JWT vs Sa-Token 对比 + */ + @GetMapping("/auth/compare") + public Map authCompare() { + return Map.of( + "Spring Security + JWT", Map.of( + "优点", "标准方案、生态完善、社区活跃", + "缺点", "配置复杂、学习曲线陡、代码量大", + "适用", "大型项目、企业级应用", + "复杂度", "⭐⭐⭐⭐⭐" + ), + "Sa-Token", Map.of( + "优点", "轻量级、API简洁、功能丰富、文档友好", + "缺点", "相对较新、生态不如Spring Security", + "适用", "中小型项目、快速开发", + "复杂度", "⭐⭐" + ), + "选择建议", Map.of( + "快速开发", "Sa-Token", + "企业级", "Spring Security", + "学习成本", "Sa-Token 更低", + "扩展性", "Spring Security 更强" + ) + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/scaffold/security/jwt/JwtAuthenticationFilter.java b/src/main/java/com/example/scaffold/security/jwt/JwtAuthenticationFilter.java new file mode 100644 index 0000000..3707436 --- /dev/null +++ b/src/main/java/com/example/scaffold/security/jwt/JwtAuthenticationFilter.java @@ -0,0 +1,97 @@ +package com.example.scaffold.security.jwt; + +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * JWT 认证过滤器 + * + * 学习要点: + * 1. OncePerRequestFilter - 确保每个请求只过滤一次 + * 2. SecurityContextHolder - Spring Security 上下文 + * 3. 认证流程:提取 Token → 验证 → 设置上下文 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private final JwtUtil jwtUtil; + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + try { + // 1. 从请求中提取 JWT Token + String jwt = getJwtFromRequest(request); + + // 2. 验证 Token + if (StringUtils.hasText(jwt) && jwtUtil.validateToken(jwt)) { + // 3. 从 Token 中获取用户信息 + String username = jwtUtil.getUsernameFromToken(jwt); + Long userId = jwtUtil.getUserIdFromToken(jwt); + + // 4. 获取角色(这里简化处理,实际应从数据库或Token中解析) + List authorities = Arrays.asList( + new SimpleGrantedAuthority("ROLE_USER") + ); + + // 5. 创建认证对象 + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken( + new JwtUserDetails(userId, username), + null, + authorities + ); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + + // 6. 设置 Security 上下文 + SecurityContextHolder.getContext().setAuthentication(authentication); + + log.debug("JWT 认证成功: userId={}, username={}", userId, username); + } + } catch (Exception e) { + log.error("JWT 认证失败: {}", e.getMessage()); + SecurityContextHolder.clearContext(); + } + + // 继续过滤器链 + filterChain.doFilter(request, response); + } + + /** + * 从请求头中提取 JWT Token + * + * 支持格式: + * Authorization: Bearer + */ + private String getJwtFromRequest(HttpServletRequest request) { + String bearerToken = request.getHeader("Authorization"); + if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) { + return bearerToken.substring(7); + } + return null; + } + + /** + * JWT 用户信息 + */ + public record JwtUserDetails(Long userId, String username) {} +} \ No newline at end of file diff --git a/src/main/java/com/example/scaffold/security/jwt/JwtSecurityConfig.java b/src/main/java/com/example/scaffold/security/jwt/JwtSecurityConfig.java new file mode 100644 index 0000000..cf7f876 --- /dev/null +++ b/src/main/java/com/example/scaffold/security/jwt/JwtSecurityConfig.java @@ -0,0 +1,103 @@ +package com.example.scaffold.security.jwt; + +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +/** + * JWT Security 配置 + * + * 学习要点: + * 1. @ConditionalOnProperty - 条件化配置 + * 2. SecurityFilterChain - 安全过滤器链 + * 3. 无状态会话(Stateless Session) + */ +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +@ConditionalOnProperty(name = "auth.type", havingValue = "jwt") +public class JwtSecurityConfig { + + private final JwtAuthenticationFilter jwtAuthenticationFilter; + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + // 禁用 CSRF(JWT 不需要) + .csrf(AbstractHttpConfigurer::disable) + + // 配置无状态会话 + .sessionManagement(session -> + session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) + ) + + // 配置请求授权 + .authorizeHttpRequests(auth -> auth + // 公开端点 + .requestMatchers("/", "/index.html", "/ioc.html", "/aop.html", + "/mybatis.html", "/transaction.html", + "/css/**", "/js/**", "/favicon.ico").permitAll() + .requestMatchers("/api/auth/**", "/h2-console/**").permitAll() + .requestMatchers("/api/learning/**").permitAll() + // 其他需要认证 + .anyRequest().authenticated() + ) + + // 添加 JWT 过滤器 + .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) + + // H2 Console 配置 + .headers(headers -> headers.frameOptions(frame -> frame.sameOrigin())); + + return http.build(); + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + /** + * 内存用户(演示用,实际应从数据库加载) + */ + @Bean + public UserDetailsService userDetailsService() { + UserDetails admin = User.builder() + .username("admin") + .password(passwordEncoder().encode("admin123")) + .roles("ADMIN", "USER") + .build(); + + UserDetails user = User.builder() + .username("user") + .password(passwordEncoder().encode("user123")) + .roles("USER") + .build(); + + return new InMemoryUserDetailsManager(admin, user); + } + + @Bean + public AuthenticationManager authenticationManager() { + DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); + provider.setUserDetailsService(userDetailsService()); + provider.setPasswordEncoder(passwordEncoder()); + return new ProviderManager(provider); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/scaffold/security/jwt/JwtUtil.java b/src/main/java/com/example/scaffold/security/jwt/JwtUtil.java new file mode 100644 index 0000000..3d3c841 --- /dev/null +++ b/src/main/java/com/example/scaffold/security/jwt/JwtUtil.java @@ -0,0 +1,140 @@ +package com.example.scaffold.security.jwt; + +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * JWT 工具类 + * + * 学习要点: + * 1. JWT 结构:Header.Payload.Signature + * 2. 签名算法:HS256、HS512 + * 3. Token 过期机制 + * 4. 刷新 Token 策略 + */ +@Slf4j +@Component +public class JwtUtil { + + @Value("${auth.jwt.secret:your-secret-key-here-must-be-at-least-256-bits}") + private String secret; + + @Value("${auth.jwt.expiration:86400000}") + private Long expiration; + + private SecretKey getSigningKey() { + return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)); + } + + /** + * 生成 JWT Token + * + * @param userId 用户ID + * @param username 用户名 + * @param roles 角色列表 + * @return JWT Token + */ + public String generateToken(Long userId, String username, String... roles) { + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + expiration); + + Map claims = new HashMap<>(); + claims.put("userId", userId); + claims.put("username", username); + claims.put("roles", roles); + + return Jwts.builder() + .claims(claims) + .subject(username) + .issuedAt(now) + .expiration(expiryDate) + .signWith(getSigningKey(), Jwts.SIG.HS256) + .compact(); + } + + /** + * 从 Token 中获取用户名 + */ + public String getUsernameFromToken(String token) { + Claims claims = parseToken(token); + return claims != null ? claims.getSubject() : null; + } + + /** + * 从 Token 中获取用户ID + */ + public Long getUserIdFromToken(String token) { + Claims claims = parseToken(token); + return claims != null ? claims.get("userId", Long.class) : null; + } + + /** + * 验证 Token 是否有效 + */ + public boolean validateToken(String token) { + try { + parseToken(token); + return true; + } catch (ExpiredJwtException e) { + log.warn("JWT Token 已过期: {}", e.getMessage()); + } catch (UnsupportedJwtException e) { + log.warn("不支持的 JWT Token: {}", e.getMessage()); + } catch (MalformedJwtException e) { + log.warn("无效的 JWT Token: {}", e.getMessage()); + } catch (SecurityException e) { + log.warn("JWT 签名验证失败: {}", e.getMessage()); + } catch (IllegalArgumentException e) { + log.warn("JWT Token 为空或非法: {}", e.getMessage()); + } + return false; + } + + /** + * 解析 Token + */ + private Claims parseToken(String token) { + return Jwts.parser() + .verifyWith(getSigningKey()) + .build() + .parseSignedClaims(token) + .getPayload(); + } + + /** + * 检查 Token 是否即将过期(用于刷新) + * + * @param token JWT Token + * @param threshold 阈值(毫秒) + * @return 是否即将过期 + */ + public boolean isTokenExpiredSoon(String token, long threshold) { + try { + Claims claims = parseToken(token); + Date expiration = claims.getExpiration(); + return expiration.getTime() - System.currentTimeMillis() < threshold; + } catch (Exception e) { + return true; + } + } + + /** + * 刷新 Token + */ + public String refreshToken(String token) { + Claims claims = parseToken(token); + Long userId = claims.get("userId", Long.class); + String username = claims.getSubject(); + String roles = claims.get("roles", String.class); + + return generateToken(userId, username, roles); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/scaffold/security/satoken/SaTokenConfig.java b/src/main/java/com/example/scaffold/security/satoken/SaTokenConfig.java new file mode 100644 index 0000000..5dd1fdf --- /dev/null +++ b/src/main/java/com/example/scaffold/security/satoken/SaTokenConfig.java @@ -0,0 +1,71 @@ +package com.example.scaffold.security.satoken; + +import cn.dev33.satoken.context.SaHolder; +import cn.dev33.satoken.filter.SaServletFilter; +import cn.dev33.satoken.interceptor.SaInterceptor; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.stp.StpUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * Sa-Token 配置 + * + * 学习要点: + * 1. Sa-Token 相比 Spring Security 更轻量 + * 2. 支持分布式 Session + * 3. 支持登录设备控制 + * 4. 支持权限认证、角色认证 + */ +@Slf4j +@Configuration +@ConditionalOnProperty(name = "auth.type", havingValue = "satoken") +public class SaTokenConfig implements WebMvcConfigurer { + + /** + * 注册 Sa-Token 拦截器 + */ + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new SaInterceptor(handle -> { + // 登录校验 + StpUtil.checkLogin(); + })) + .addPathPatterns("/api/**") + .excludePathPatterns( + "/api/auth/**", + "/api/learning/**", + "/api/users/count" + ); + } + + /** + * Sa-Token 全局过滤器 + */ + @Bean + public SaServletFilter saServletFilter() { + return new SaServletFilter() + // 拦截路径 + .addInclude("/**") + // 排除路径 + .addExclude("/", "/index.html", "/ioc.html", "/aop.html", + "/mybatis.html", "/transaction.html", "/users.html", "/api.html", + "/css/**", "/js/**", "/favicon.ico", + "/h2-console/**") + // 认证函数 + .setAuth(obj -> { + SaRouter.match("/api/**") + .notMatch("/api/auth/**", "/api/learning/**") + .check(r -> StpUtil.checkLogin()); + }) + // 异常处理 + .setError(e -> { + log.error("Sa-Token 认证失败: {}", e.getMessage()); + return "{\"code\": 401, \"message\": \"未登录\"}"; + }); + } +} \ No newline at end of file diff --git a/src/main/resources/static/api.html b/src/main/resources/static/api.html index e38c30c..56f5067 100644 --- a/src/main/resources/static/api.html +++ b/src/main/resources/static/api.html @@ -242,6 +242,22 @@
+ +
+ GET + 反射 - 类信息 +
/api/learning/reflection/class-info
+ +
+
+ +
+ GET + 高级 - 性能统计 +
/api/learning/advanced/performance
+ +
+
diff --git a/target/classes/application-advanced.yml b/target/classes/application-advanced.yml new file mode 100644 index 0000000..7bc88d1 --- /dev/null +++ b/target/classes/application-advanced.yml @@ -0,0 +1,46 @@ +# 高级配置 - 可插拔组件 +spring: + config: + activate: + on-profile: advanced + + # 数据库选择: h2 / mysql / postgresql + datasource: + driver-class-name: ${DB_DRIVER:org.h2.Driver} + url: ${DB_URL:jdbc:h2:file:~/h2/springboot_scaffold} + username: ${DB_USER:sa} + password: ${DB_PASS:} + + # Redis 缓存 + redis: + host: ${REDIS_HOST:localhost} + port: ${REDIS_PORT:6379} + password: ${REDIS_PASS:} + database: ${REDIS_DB:0} + timeout: 3000ms + lettuce: + pool: + max-active: 8 + max-idle: 8 + min-idle: 0 + +# 鉴权方案选择: none / jwt / satoken +auth: + type: ${AUTH_TYPE:jwt} # none | jwt | satoken + jwt: + secret: ${JWT_SECRET:your-secret-key} + expiration: ${JWT_EXPIRATION:86400000} # 24小时 + satoken: + timeout: ${SA_TIMEOUT:86400} # 24小时 + activity-timeout: ${SA_ACTIVITY_TIMEOUT:1800} # 30分钟 + +# 缓存配置 +cache: + type: ${CACHE_TYPE:caffeine} # caffeine | redis + redis: + time-to-live: 600000 # 10分钟 + +# MyBatis 多数据库适配 +mybatis: + configuration: + database-id: ${DB_TYPE:h2} # h2 | mysql | postgresql \ No newline at end of file diff --git a/target/classes/application-learn.yml b/target/classes/application-learn.yml new file mode 100644 index 0000000..4d5be24 --- /dev/null +++ b/target/classes/application-learn.yml @@ -0,0 +1,29 @@ +# Learn profile: keep dependencies and runtime simple for first-round learning +spring: + config: + activate: + on-profile: learn + datasource: + url: jdbc:h2:mem:springboot_scaffold_learn;MODE=MYSQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE + driver-class-name: org.h2.Driver + username: sa + password: + h2: + console: + enabled: true + +app: + profile: learn + enabled-modules: + - ioc + - aop + - mybatis + - transaction + - users + +auth: + type: none + learning-note: "learn 模式默认不开启鉴权,专注 Spring 核心学习" + +cache: + type: caffeine diff --git a/target/classes/application.properties b/target/classes/application.properties index 21224e8..b5f9457 100644 --- a/target/classes/application.properties +++ b/target/classes/application.properties @@ -1,7 +1,10 @@ spring.application.name=springboot-scaffold -server.port=8082 +server.port=8083 +server.forward-headers-strategy=framework -# H2 Database +spring.profiles.active=${APP_PROFILE:learn} + +# H2 Database (default baseline; learn profile overrides to in-memory) spring.h2.console.enabled=true spring.datasource.url=jdbc:h2:file:~/h2/springboot_scaffold spring.datasource.driverClassName=org.h2.Driver diff --git a/target/classes/com/example/scaffold/aop/PerformanceAspect.class b/target/classes/com/example/scaffold/aop/PerformanceAspect.class index ca9396d..2ec8cd0 100644 Binary files a/target/classes/com/example/scaffold/aop/PerformanceAspect.class and b/target/classes/com/example/scaffold/aop/PerformanceAspect.class differ diff --git a/target/classes/com/example/scaffold/cache/CacheConfig.class b/target/classes/com/example/scaffold/cache/CacheConfig.class new file mode 100644 index 0000000..6ef72b1 Binary files /dev/null and b/target/classes/com/example/scaffold/cache/CacheConfig.class differ diff --git a/target/classes/com/example/scaffold/cache/CacheService.class b/target/classes/com/example/scaffold/cache/CacheService.class new file mode 100644 index 0000000..8fb6a18 Binary files /dev/null and b/target/classes/com/example/scaffold/cache/CacheService.class differ diff --git a/target/classes/com/example/scaffold/config/LearningProfileInfo.class b/target/classes/com/example/scaffold/config/LearningProfileInfo.class new file mode 100644 index 0000000..1bf42a7 Binary files /dev/null and b/target/classes/com/example/scaffold/config/LearningProfileInfo.class differ diff --git a/target/classes/com/example/scaffold/config/database/DatabaseConfig.class b/target/classes/com/example/scaffold/config/database/DatabaseConfig.class new file mode 100644 index 0000000..c0caef1 Binary files /dev/null and b/target/classes/com/example/scaffold/config/database/DatabaseConfig.class differ diff --git a/target/classes/com/example/scaffold/controller/AuthController$LoginRequest.class b/target/classes/com/example/scaffold/controller/AuthController$LoginRequest.class new file mode 100644 index 0000000..3733e4c Binary files /dev/null and b/target/classes/com/example/scaffold/controller/AuthController$LoginRequest.class differ diff --git a/target/classes/com/example/scaffold/controller/AuthController.class b/target/classes/com/example/scaffold/controller/AuthController.class new file mode 100644 index 0000000..3b33621 Binary files /dev/null and b/target/classes/com/example/scaffold/controller/AuthController.class differ diff --git a/target/classes/com/example/scaffold/controller/VerificationController.class b/target/classes/com/example/scaffold/controller/VerificationController.class new file mode 100644 index 0000000..34a02ef Binary files /dev/null and b/target/classes/com/example/scaffold/controller/VerificationController.class differ diff --git a/target/classes/com/example/scaffold/learning/AdvancedLearningController.class b/target/classes/com/example/scaffold/learning/AdvancedLearningController.class new file mode 100644 index 0000000..e3c2d1c Binary files /dev/null and b/target/classes/com/example/scaffold/learning/AdvancedLearningController.class differ diff --git a/target/classes/com/example/scaffold/learning/IocLearningController$LearningBean.class b/target/classes/com/example/scaffold/learning/IocLearningController$LearningBean.class index 1939eb5..262d1a7 100644 Binary files a/target/classes/com/example/scaffold/learning/IocLearningController$LearningBean.class and b/target/classes/com/example/scaffold/learning/IocLearningController$LearningBean.class differ diff --git a/target/classes/com/example/scaffold/learning/IocLearningController.class b/target/classes/com/example/scaffold/learning/IocLearningController.class index 862f123..929280e 100644 Binary files a/target/classes/com/example/scaffold/learning/IocLearningController.class and b/target/classes/com/example/scaffold/learning/IocLearningController.class differ diff --git a/target/classes/com/example/scaffold/learning/ReflectionLearningController.class b/target/classes/com/example/scaffold/learning/ReflectionLearningController.class new file mode 100644 index 0000000..9136043 Binary files /dev/null and b/target/classes/com/example/scaffold/learning/ReflectionLearningController.class differ diff --git a/target/classes/com/example/scaffold/learning/lifecycle/IocLifecycleTracker.class b/target/classes/com/example/scaffold/learning/lifecycle/IocLifecycleTracker.class new file mode 100644 index 0000000..f146ba4 Binary files /dev/null and b/target/classes/com/example/scaffold/learning/lifecycle/IocLifecycleTracker.class differ diff --git a/target/classes/com/example/scaffold/learning/lifecycle/LazySingletonLifecycleBean.class b/target/classes/com/example/scaffold/learning/lifecycle/LazySingletonLifecycleBean.class new file mode 100644 index 0000000..8efe6e7 Binary files /dev/null and b/target/classes/com/example/scaffold/learning/lifecycle/LazySingletonLifecycleBean.class differ diff --git a/target/classes/com/example/scaffold/learning/lifecycle/LifecycleDemoBean.class b/target/classes/com/example/scaffold/learning/lifecycle/LifecycleDemoBean.class new file mode 100644 index 0000000..1f4da4c Binary files /dev/null and b/target/classes/com/example/scaffold/learning/lifecycle/LifecycleDemoBean.class differ diff --git a/target/classes/com/example/scaffold/learning/lifecycle/PrototypeLifecycleBean.class b/target/classes/com/example/scaffold/learning/lifecycle/PrototypeLifecycleBean.class new file mode 100644 index 0000000..c0ecb9d Binary files /dev/null and b/target/classes/com/example/scaffold/learning/lifecycle/PrototypeLifecycleBean.class differ diff --git a/target/classes/com/example/scaffold/learning/lifecycle/SingletonLifecycleBean.class b/target/classes/com/example/scaffold/learning/lifecycle/SingletonLifecycleBean.class new file mode 100644 index 0000000..6ea089b Binary files /dev/null and b/target/classes/com/example/scaffold/learning/lifecycle/SingletonLifecycleBean.class differ diff --git a/target/classes/com/example/scaffold/learning/reflection/ReflectionLabTarget.class b/target/classes/com/example/scaffold/learning/reflection/ReflectionLabTarget.class new file mode 100644 index 0000000..991ec11 Binary files /dev/null and b/target/classes/com/example/scaffold/learning/reflection/ReflectionLabTarget.class differ diff --git a/target/classes/com/example/scaffold/security/LearningPermitAllSecurityConfig.class b/target/classes/com/example/scaffold/security/LearningPermitAllSecurityConfig.class new file mode 100644 index 0000000..d4a8609 Binary files /dev/null and b/target/classes/com/example/scaffold/security/LearningPermitAllSecurityConfig.class differ diff --git a/target/classes/com/example/scaffold/security/jwt/JwtAuthenticationFilter$JwtUserDetails.class b/target/classes/com/example/scaffold/security/jwt/JwtAuthenticationFilter$JwtUserDetails.class new file mode 100644 index 0000000..f390c2c Binary files /dev/null and b/target/classes/com/example/scaffold/security/jwt/JwtAuthenticationFilter$JwtUserDetails.class differ diff --git a/target/classes/com/example/scaffold/security/jwt/JwtAuthenticationFilter.class b/target/classes/com/example/scaffold/security/jwt/JwtAuthenticationFilter.class new file mode 100644 index 0000000..d09485b Binary files /dev/null and b/target/classes/com/example/scaffold/security/jwt/JwtAuthenticationFilter.class differ diff --git a/target/classes/com/example/scaffold/security/jwt/JwtSecurityConfig.class b/target/classes/com/example/scaffold/security/jwt/JwtSecurityConfig.class new file mode 100644 index 0000000..eeec28e Binary files /dev/null and b/target/classes/com/example/scaffold/security/jwt/JwtSecurityConfig.class differ diff --git a/target/classes/com/example/scaffold/security/jwt/JwtUtil.class b/target/classes/com/example/scaffold/security/jwt/JwtUtil.class new file mode 100644 index 0000000..44a3ca5 Binary files /dev/null and b/target/classes/com/example/scaffold/security/jwt/JwtUtil.class differ diff --git a/target/classes/com/example/scaffold/security/satoken/SaTokenConfig.class b/target/classes/com/example/scaffold/security/satoken/SaTokenConfig.class new file mode 100644 index 0000000..0219154 Binary files /dev/null and b/target/classes/com/example/scaffold/security/satoken/SaTokenConfig.class differ diff --git a/target/classes/static/advanced.html b/target/classes/static/advanced.html new file mode 100644 index 0000000..a8bdeae --- /dev/null +++ b/target/classes/static/advanced.html @@ -0,0 +1,260 @@ + + + + + + 高级功能学习 - Spring Boot + + + +
+
+

🚀 高级功能学习

+

Redis 缓存 | 分布式锁 | 多数据库 | 认证方案

+
+ + + +
+

🧪 实验任务卡(高级模块)

+ +
    +
  • 目标:比较 learn/advanced profile 下可用能力差异
  • +
  • 步骤1:先查看“系统配置”和“认证方案对比”
  • +
  • 步骤2:执行 Redis SET/GET + 分布式锁接口
  • +
  • 预期:advanced 模式下功能更完整,返回字段更丰富
  • +
  • 常见坑:本机无 Redis 导致接口失败(属于环境问题)
  • +
+
+ +
+

⚙️ 系统配置

+ +
+
+ +
+

🔐 认证方案对比

+ + 进入鉴权实验室 +
+
+ +
+

💾 Redis 数据类型

+
+

String

字符串,最基本类型

+

Hash

哈希,存储对象

+

List

列表,队列/栈

+

Set

集合,去重运算

+

SortedSet

有序集合,排名

+
+ +
+ +
+

🧪 Redis 操作测试

+
+ + + +
+ + +
+
+ +
+

🔒 分布式锁演示

+

模拟多个请求竞争同一资源

+ + +
+
+ +
+

⚠️ 缓存三大问题

+
+

缓存穿透

+

问题:查询不存在的数据,每次都打到数据库

+

解决:布隆过滤器 | 缓存空值

+
+
+

缓存击穿

+

问题:热点key过期,大量请求打到数据库

+

解决:互斥锁 | 逻辑过期

+
+
+

缓存雪崩

+

问题:大量key同时过期,数据库压力激增

+

解决:随机过期时间 | 多级缓存

+
+ +
+
+
+ + + + \ No newline at end of file diff --git a/target/classes/static/api.html b/target/classes/static/api.html index d801914..e38c30c 100644 --- a/target/classes/static/api.html +++ b/target/classes/static/api.html @@ -49,6 +49,8 @@ .tab-content.active { display: block; } .json-input { width: 100%; min-height: 100px; padding: 10px; border: 1px solid #ddd; border-radius: 5px; font-family: monospace; font-size: 0.9em; } + .profile-banner { background:#fff7e6;border-left:4px solid #fa8c16;padding:12px 14px;border-radius:8px;margin-bottom:18px; color:#874d00; } + .tools { margin: 10px 0 16px; } @@ -68,6 +70,12 @@ 🔌 API +
正在读取 profile...
+
+ + 进入修复验证实验室 +
+
👥 用户 API
📦 产品 API
@@ -248,6 +256,27 @@ document.getElementById(tab + 'Tab').classList.add('active'); } + async function loadProfileBanner() { + try { + const res = await fetch('/api/profile'); + const data = await res.json(); + const enabled = (data.enabledModules || []).join(', '); + document.getElementById('profileBanner').textContent = `当前 profile: ${data.profile} | 鉴权模式: ${data.authType || 'none'} | 已启用模块: ${enabled}`; + } catch (e) { + document.getElementById('profileBanner').textContent = '当前 profile 读取失败,请检查 /api/profile'; + } + } + + async function copyCurl() { + const curl = `curl -X GET "${window.location.origin}/api/users"`; + try { + await navigator.clipboard.writeText(curl); + alert('已复制: ' + curl); + } catch (e) { + alert('复制失败,请手动复制: ' + curl); + } + } + async function testApi(method, url, body, resultId) { const resultDiv = document.getElementById(resultId); resultDiv.classList.add('show'); @@ -275,6 +304,8 @@ resultDiv.innerHTML = `Error\n\n${e.message}`; } } + + loadProfileBanner(); \ No newline at end of file diff --git a/target/classes/static/auth-lab.html b/target/classes/static/auth-lab.html new file mode 100644 index 0000000..8b3ca21 --- /dev/null +++ b/target/classes/static/auth-lab.html @@ -0,0 +1,142 @@ + + + + + + 鉴权实验室 - Spring Boot + + + +
+
+

🔐 Spring 鉴权实验室

+

登录 → 取 Token → 访问受保护接口 → 对比 learn/advanced 模式

+
+ + + +
+ 实验任务卡 +
    +
  • 步骤1:点击“读取当前模式”,确认现在是 learn / advanced
  • +
  • 步骤2:用 admin/admin123 登录,拿到 token
  • +
  • 步骤3:带上 token 调用当前实验接口,观察是否放行或返回 503/401
  • +
  • 步骤4:切换 auth.type 后对比 none/jwt/satoken 行为差异
  • +
+
+ +
+

当前模式

+
+ +
+
点击按钮读取...
+
+ +
+

登录拿 Token

+
+ + + +
+
演示账号:admin/admin123 或 user/user123
+
点击登录后显示响应...
+
+ +
+

接口访问实验

+
+ + +
+
当前页面会优先从 localStorage 读取 token 并自动加到 Authorization 头里。learn 模式下接口通常直接放行;advanced+jwt 下更适合观察真实鉴权链路。
+
点击按钮后显示接口结果...
+
+
+ + + diff --git a/target/classes/static/index.html b/target/classes/static/index.html index d137181..8b915a8 100644 --- a/target/classes/static/index.html +++ b/target/classes/static/index.html @@ -41,6 +41,9 @@ .status-item { background: white; padding: 20px 30px; border-radius: 10px; text-align: center; } .status-item .value { font-size: 2em; font-weight: bold; color: #667eea; } .status-item .label { color: #666; margin-top: 5px; } + .lab { background:#fff7e6; border:1px solid #ffe58f; border-radius:10px; padding:16px; margin-bottom:20px; } + .lab h4 { margin-bottom:8px; color:#ad6800; } + .lab ul { margin-left:18px; color:#444; line-height:1.7; } footer { text-align: center; padding: 30px; color: #666; margin-top: 40px; } @@ -69,6 +72,22 @@
-
订单数量
+
+
-
+
当前 Profile
+
+ + +
+

🧪 实验任务卡(事务模块)

+

鉴权学习建议:learn=none(先学核心),advanced=jwt/satoken(再学安全链路)

+
    +
  • 目标:理解事务回滚与 REQUIRES_NEW 差异
  • +
  • 步骤1:到 transaction.html 创建普通订单(rollback=false)
  • +
  • 步骤2:再创建模拟失败订单(rollback=true)
  • +
  • 预期:主事务回滚,但独立事务可保留日志/部分数据(取决于实现)
  • +
  • 观察点:查看控制台事务日志(TransactionInterceptor TRACE)
  • +
@@ -142,6 +165,55 @@ 开始学习 → +
+

🚀 高级功能

+

Redis 缓存、分布式锁、多数据库、认证方案对比,从小白到高手的进阶之路。

+
    +
  • Redis 数据类型操作
  • +
  • 缓存穿透/击穿/雪崩
  • +
  • 分布式锁实现
  • +
  • JWT vs Sa-Token
  • +
  • 多数据库切换
  • +
+ 进阶学习 → +
+ +
+

🪞 反射实验室

+

动态查看类结构、通过构造器创建对象、修改私有字段、调用私有方法,理解 Spring 等框架底层为什么依赖反射。

+
    +
  • 类/字段/方法元信息
  • +
  • 反射构造对象
  • +
  • 私有字段修改
  • +
  • 公开/私有/静态方法调用
  • +
+ 开始实验 → +
+ +
+

🔐 鉴权实验室

+

一步步体验登录、带 Token 请求、鉴权放行/拦截,对比 learn / advanced 模式差异。

+
    +
  • 登录拿 Token
  • +
  • 自动携带 Authorization
  • +
  • 当前模式读取
  • +
  • 交互式错误观察
  • +
+ 开始实验 → +
+ +
+

🩺 修复验证实验室

+

自己点检查,不靠口头确认。直接验证 profile、H2、用户服务、MyBatis 和鉴权模式。

+
    +
  • 一键总览检查
  • +
  • 数据库链路验证
  • +
  • 用户服务验证
  • +
  • MyBatis 查询验证
  • +
+ 开始验证 → +
+

🔌 API 测试面板

在线测试所有 API 接口,查看请求响应,理解 RESTful API 工作原理。

@@ -172,7 +244,7 @@
-

🍃 Spring Boot 学习脚手架 | H2 控制台 (JDBC: jdbc:h2:file:~/h2/springboot_scaffold, 用户: sa)

+

🍃 Spring Boot 学习脚手架 | H2 控制台 (learn 模式 JDBC: jdbc:h2:mem:springboot_scaffold_learn, 用户: sa)

@@ -180,17 +252,19 @@ // 加载状态数据 async function loadStatus() { try { - const [beans, users, products, orders] = await Promise.all([ + const [beans, users, products, orders, profile] = await Promise.all([ fetch('/api/learning/ioc/beans').then(r => r.json()), fetch('/api/users/count').then(r => r.json()), fetch('/api/products').then(r => r.json()), - fetch('/api/orders').then(r => r.json()) + fetch('/api/orders').then(r => r.json()), + fetch('/api/profile').then(r => r.json()) ]); document.getElementById('beanCount').textContent = beans.total || '-'; document.getElementById('userCount').textContent = users.count || 0; document.getElementById('productCount').textContent = products.length || 0; document.getElementById('orderCount').textContent = orders.length || 0; + document.getElementById('activeProfile').textContent = profile.profile || '-'; } catch (e) { console.error('加载状态失败:', e); } diff --git a/target/classes/static/ioc.html b/target/classes/static/ioc.html index 473f3f1..8dc0fe4 100644 --- a/target/classes/static/ioc.html +++ b/target/classes/static/ioc.html @@ -3,173 +3,200 @@ - IoC 容器学习 - Spring Boot + IoC 生命周期可视化实验室 - Spring Boot
-

📦 IoC 容器学习

-

控制反转 (Inversion of Control) 与依赖注入 (Dependency Injection)

+

📦 IoC 生命周期可视化实验室

+

把“类加载”“Bean 创建”“单例/多例/懒加载”拆开看,自己动手触发、自己观察结果。

- + - -
-

📚 核心概念

-
-

什么是 IoC?

-

控制反转 (Inversion of Control):将对象的创建和管理交给 Spring 容器,而不是由开发者手动创建。

-

依赖注入 (Dependency Injection):IoC 的一种实现方式,通过构造器、Setter 或字段将依赖注入到对象中。

+ +
+ 🧪 实验任务卡 +
    +
  • 先点“加载总览”,搞清楚 JVM 类加载 和 Spring Bean 生命周期不是一回事
  • +
  • 再点“比较三种作用域”,对比 singleton / prototype / lazy singleton 的实例 ID 和 hashCode
  • +
  • 然后分别连续点击“获取单例 / 获取多例 / 获取懒加载单例”,观察时间线变化
  • +
  • 最后重置时间线,再重新做一遍,看看第一次触发和第二次触发的区别
  • +
+
+ +
+
+

📚 核心概念总览

+ +
点击按钮查看“类加载 vs Bean 生命周期”...
-
-

为什么用 IoC?

-
    -
  • 解耦:对象之间不直接依赖,通过接口交互
  • -
  • 可测试:方便使用 Mock 对象进行单元测试
  • -
  • 可维护:集中管理对象生命周期
  • -
  • AOP 支持:便于实现切面编程
  • -
+ +
+

🆚 作用域对比实验

+ + +
观察重点:singleton 两次获取是否同一实例?prototype 为什么每次都变?lazy singleton 第一次获取前是否就已经创建?
+
- + +
+

🎯 单点触发实验

+ + + +
点击上面的按钮,观察实例 ID / hashCode / 访问次数如何变化...
+
+ +
+
+

🕰️ 生命周期时间线

+ +
时间线加载中...
+
+ +
+

📊 Bean 作用域解释

+ + + + + +
作用域创建时机实例特点
singleton通常容器启动时全局一个实例,反复获取同一个对象
prototype每次 getBean 时每次都是新实例,不进单例池
lazy singleton第一次真正使用时启动不创建,首次获取才创建,之后复用
+
+

记住这句话

+

类加载 ≠ Bean 创建;Bean 创建 ≠ 每次请求都 new。

+
+
+
+

🔍 查看所有 Bean

-

Spring 容器中管理的所有 Bean 对象

- -
-

📊 Bean 作用域

- - - - - - -
作用域说明使用场景
singleton默认,整个应用只有一个实例无状态的服务、配置类
prototype每次请求都创建新实例有状态的对象
request每个 HTTP 请求一个实例Web 应用
session每个 HTTP 会话一个实例用户会话数据
- -
-
- -
-

⚡ 性能统计

-

实时监控方法执行时间和调用次数

- - -
-
- -
-

💉 依赖注入方式对比

- - - - - -
方式优点缺点推荐度
构造器注入明确依赖、不可变、易测试参数多时代码长⭐⭐⭐⭐⭐
Setter 注入可选依赖、灵活可能为 null⭐⭐⭐
字段注入代码简洁隐藏依赖、难测试
-
- + - \ No newline at end of file + diff --git a/target/classes/static/reflection.html b/target/classes/static/reflection.html new file mode 100644 index 0000000..d6ee7a5 --- /dev/null +++ b/target/classes/static/reflection.html @@ -0,0 +1,119 @@ + + + + + + 反射可视化实验室 - Spring Boot + + + +
+
+

🪞 反射可视化实验室

+

不只说“反射很重要”,而是让你自己查看类信息、动态构造对象、读写字段、调用私有方法。

+
+ + + +
+ 实验任务卡 +
    +
  • 先看类信息,理解反射能拿到哪些元数据
  • +
  • 再用构造器动态创建对象,观察实例内容
  • +
  • 再读写私有字段,理解为什么框架可以“跳过表面上的访问限制”
  • +
  • 最后调用私有方法和静态方法,感受反射为什么是框架底层利器
  • +
+
+ +
+
+

概念总览

+ +
+
+
+

类元信息

+ +
+
+
+ +
+
+

动态构造对象

+ + + +
+
+
+

私有字段读写

+ + +
+
+
+ +
+
+

方法调用实验

+ + +
+
+
+

框架为什么依赖反射

+ +
+
+
+
+ + + diff --git a/target/classes/static/verify-lab.html b/target/classes/static/verify-lab.html new file mode 100644 index 0000000..ea9466d --- /dev/null +++ b/target/classes/static/verify-lab.html @@ -0,0 +1,120 @@ + + + + + + 修复验证实验室 - Spring Boot + + + +
+
+

🩺 修复验证实验室

+

不是“我说修好了”,而是你自己点检查,看到哪里坏、为什么坏、修没修好。

+
+ + + +
+ 参与式验证任务卡 +
    +
  • 先点“一键跑总览”,确认当前 profile / auth / datasource 状态
  • +
  • 再分别点数据库、用户服务、MyBatis 产品查询,感受“哪个环节坏了就在哪一步暴露”
  • +
  • 最后打开 H2 Console,验证修复后跳转是不是仍保持 https
  • +
  • 如果某一步失败,不要只看失败,要看返回里的 hint —— 那是排查方向
  • +
+
+ +
+ + +
点击按钮开始验证...
+
+ +
+
+

数据库链路

+ +
验证 DataSource / JDBC / H2 是否可用。
+
+
+ +
+

用户服务链路

+ +
验证 JPA / Service / 用户数据查询是否正常。
+
+
+ +
+

MyBatis 链路

+ +
验证 MyBatis Mapper / SQL / 数据库查询是否正常。
+
+
+ +
+

鉴权模式

+ +
对照当前 profile,理解 why learn=none / advanced=jwt。
+
+
+
+
+ + + diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index feed0ef..ed7ec4c 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -1,26 +1,47 @@ com/example/scaffold/dto/OrderCreateRequest.class com/example/scaffold/learning/MyBatisLearningController.class +com/example/scaffold/learning/reflection/ReflectionLabTarget.class +com/example/scaffold/config/database/DatabaseConfig.class +com/example/scaffold/SpringbootScaffoldApplication.class +com/example/scaffold/learning/lifecycle/IocLifecycleTracker.class +com/example/scaffold/controller/AuthController.class +com/example/scaffold/security/LearningPermitAllSecurityConfig.class +com/example/scaffold/learning/IocLearningController.class +com/example/scaffold/learning/lifecycle/PrototypeLifecycleBean.class +com/example/scaffold/learning/lifecycle/LifecycleDemoBean.class +com/example/scaffold/controller/VerificationController.class +com/example/scaffold/dto/ProductCreateRequest.class +com/example/scaffold/learning/lifecycle/SingletonLifecycleBean.class +com/example/scaffold/learning/IocLearningController$LearningBean.class +com/example/scaffold/controller/RootController.class +com/example/scaffold/learning/AopLearningController.class +com/example/scaffold/security/jwt/JwtUtil.class +com/example/scaffold/cache/CacheConfig.class +com/example/scaffold/config/LearningProfileInfo.class com/example/scaffold/controller/HelloController.class com/example/scaffold/service/UserService.class -com/example/scaffold/SpringbootScaffoldApplication.class com/example/scaffold/service/impl/UserServiceImpl.class com/example/scaffold/controller/UserController.class -com/example/scaffold/learning/IocLearningController.class +com/example/scaffold/learning/ReflectionLearningController.class +com/example/scaffold/security/jwt/JwtSecurityConfig.class com/example/scaffold/aop/LearningAspect.class com/example/scaffold/service/impl/OrderService.class com/example/scaffold/controller/ProductOrderController.class com/example/scaffold/mapper/ProductMapper.class +com/example/scaffold/security/jwt/JwtAuthenticationFilter$JwtUserDetails.class +com/example/scaffold/cache/CacheService.class com/example/scaffold/mapper/OrderMapper.class +com/example/scaffold/security/jwt/JwtAuthenticationFilter.class com/example/scaffold/aop/PerformanceAspect.class com/example/scaffold/entity/User.class com/example/scaffold/dto/UserCreateRequest.class -com/example/scaffold/dto/ProductCreateRequest.class +com/example/scaffold/learning/lifecycle/LazySingletonLifecycleBean.class +com/example/scaffold/learning/AdvancedLearningController.class +com/example/scaffold/security/satoken/SaTokenConfig.class com/example/scaffold/entity/Order.class com/example/scaffold/mapper/UserMapper.class com/example/scaffold/learning/TransactionLearningController.class -com/example/scaffold/learning/IocLearningController$LearningBean.class -com/example/scaffold/controller/RootController.class -com/example/scaffold/learning/AopLearningController.class com/example/scaffold/aop/PerformanceAspect$MethodStats.class com/example/scaffold/config/AppConfig.class +com/example/scaffold/controller/AuthController$LoginRequest.class com/example/scaffold/entity/Product.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index 9a56105..0a71d32 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -1,24 +1,43 @@ -/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/mapper/ProductMapper.java -/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/controller/UserController.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/AopLearningController.java -/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/entity/Product.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/entity/Order.java -/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/mapper/UserMapper.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/dto/ProductCreateRequest.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/security/jwt/JwtAuthenticationFilter.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/security/jwt/JwtUtil.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/cache/CacheConfig.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/lifecycle/SingletonLifecycleBean.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/controller/HelloController.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/service/impl/UserServiceImpl.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/dto/OrderCreateRequest.java -/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/TransactionLearningController.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/security/satoken/SaTokenConfig.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/aop/PerformanceAspect.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/ReflectionLearningController.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/entity/User.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/IocLearningController.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/controller/ProductOrderController.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/mapper/OrderMapper.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/config/AppConfig.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/lifecycle/LifecycleDemoBean.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/security/LearningPermitAllSecurityConfig.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/controller/RootController.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/service/UserService.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/cache/CacheService.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/config/database/DatabaseConfig.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/SpringbootScaffoldApplication.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/controller/VerificationController.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/dto/UserCreateRequest.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/mapper/ProductMapper.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/config/LearningProfileInfo.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/controller/UserController.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/entity/Product.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/AdvancedLearningController.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/mapper/UserMapper.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/lifecycle/IocLifecycleTracker.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/reflection/ReflectionLabTarget.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/TransactionLearningController.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/lifecycle/PrototypeLifecycleBean.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/lifecycle/LazySingletonLifecycleBean.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/controller/AuthController.java +/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/security/jwt/JwtSecurityConfig.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/learning/MyBatisLearningController.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/service/impl/OrderService.java -/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/SpringbootScaffoldApplication.java -/home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/dto/UserCreateRequest.java /home/llm/Projects/springboot-scaffold/src/main/java/com/example/scaffold/aop/LearningAspect.java diff --git a/target/springboot-scaffold-1.0.0.jar b/target/springboot-scaffold-1.0.0.jar index c919ac4..e7e6024 100644 Binary files a/target/springboot-scaffold-1.0.0.jar and b/target/springboot-scaffold-1.0.0.jar differ diff --git a/target/springboot-scaffold-1.0.0.jar.original b/target/springboot-scaffold-1.0.0.jar.original index aeaf95b..261048c 100644 Binary files a/target/springboot-scaffold-1.0.0.jar.original and b/target/springboot-scaffold-1.0.0.jar.original differ