diff --git a/yami-shop-api/src/main/java/com/yami/shop/api/ApiApplication.java b/yami-shop-api/src/main/java/com/yami/shop/api/ApiApplication.java index 5c5f18b..396ae18 100644 --- a/yami-shop-api/src/main/java/com/yami/shop/api/ApiApplication.java +++ b/yami-shop-api/src/main/java/com/yami/shop/api/ApiApplication.java @@ -8,28 +8,37 @@ * 版权所有,侵权必究! */ +// 声明该类所在的包名,在Java中包用于对类进行组织和分类管理,方便代码的模块化以及避免类名冲突等问题。 package com.yami.shop.api; - +// 引入Spring Boot相关的核心注解,用于标记这是一个Spring Boot应用程序,它会开启Spring Boot的自动配置等一系列功能,简化Spring应用的搭建和部署流程。 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +// 用于以编程方式构建Spring Boot应用程序,特别是在需要对应用的启动配置等进行更多定制化操作时会用到,比如配置应用的启动类、配置文件等信息。 import org.springframework.boot.builder.SpringApplicationBuilder; +// Spring Boot提供的一个用于支持将Spring Boot应用部署为Web应用(例如部署到Servlet容器中)的基础类,通常需要继承它来做相关的适配和初始化工作。 import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +// 用于指定Spring需要扫描的组件所在的基础包路径,Spring会在这些包及其子包下查找带有相关注解(如 @Component、@Service等)的类,并将它们注册为Spring容器中的组件,便于进行依赖注入等操作。 import org.springframework.context.annotation.ComponentScan; /** * @author lgh + * 该类是整个API应用的启动类,负责启动Spring Boot应用,配置相关的组件扫描以及支持将应用部署到Servlet容器等功能。 */ @SpringBootApplication +// 通过 @ComponentScan 注解指定Spring要扫描的基础包路径为 "com.yami.shop",意味着Spring会在这个包及其子包下查找并注册各种Spring组件(如控制器、服务类、数据访问层等)到Spring容器中,以便进行后续的依赖注入和业务逻辑处理。 @ComponentScan(basePackages = {"com.yami.shop"}) -public class ApiApplication extends SpringBootServletInitializer{ +public class ApiApplication extends SpringBootServletInitializer { + // 应用的主入口方法,Java应用程序从这个方法开始执行。当运行这个类的 main 方法时,会启动Spring Boot应用,加载配置、初始化Spring容器并启动相关的Web服务等(如果是Web应用的话)。 public static void main(String[] args) { - SpringApplication.run(ApiApplication.class, args); + // 使用SpringApplication类的静态方法 run 来启动Spring Boot应用,传入当前启动类(ApiApplication.class)以及命令行参数 args,Spring Boot会根据配置自动完成一系列的初始化和启动操作。 + SpringApplication.run(ApiApplication.class, args); } - + + // 重写SpringBootServletInitializer类中的configure方法,用于配置Spring Boot应用在Servlet容器中的启动方式,这里返回一个SpringApplicationBuilder对象,并指定应用的启动类为ApiApplication.class,以便在Servlet容器中正确地启动Spring Boot应用。 @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) { return builder.sources(ApiApplication.class); } -} +} \ No newline at end of file diff --git a/yami-shop-bean/src/main/java/com/yami/shop/bean/SmsInfoContext.java b/yami-shop-bean/src/main/java/com/yami/shop/bean/SmsInfoContext.java index b094616..c66e840 100644 --- a/yami-shop-bean/src/main/java/com/yami/shop/bean/SmsInfoContext.java +++ b/yami-shop-bean/src/main/java/com/yami/shop/bean/SmsInfoContext.java @@ -8,37 +8,68 @@ * 版权所有,侵权必究! */ +// 声明该类所在的包名,表明这个类属于 `com.yami.shop.bean` 包,在Java项目中,包用于对类进行分类组织,方便代码管理和避免类名冲突等情况。 package com.yami.shop.bean; import java.util.ArrayList; import java.util.List; +// 导入 `SmsInfoBo` 类,从类名推测它是与短信信息相关的业务对象(Business Object),这个类应该包含了短信相关的各种属性以及对应的业务逻辑所需要的数据结构,会在本类中用于存储和操作短信相关的信息。 import com.yami.shop.bean.bo.SmsInfoBo; - +// 导入 `hutool` 工具库中用于集合操作的工具类 `CollectionUtil`,它提供了许多便捷的方法来处理集合相关的常见操作,例如判断集合是否为空、对集合进行合并、拆分等操作,在这里主要用于判断短信信息列表是否为空的情况。 import cn.hutool.core.collection.CollectionUtil; /** * @author lanhai + * 这个类 `SmsInfoContext` 的作用是作为短信信息的上下文管理类,它利用 `ThreadLocal` 机制来实现在多线程环境下,每个线程都能独立地管理自己的短信信息集合(以 `SmsInfoBo` 列表形式存储), + * 提供了获取、设置、添加以及清理短信信息的相关方法,方便在不同的业务逻辑中对当前线程的短信信息进行操作,避免了多线程之间短信信息数据的相互干扰。 */ public class SmsInfoContext { - /** The request holder. */ + /** + * The request holder. + * 定义一个静态的 `ThreadLocal` 变量 `smsInfoHolder`,用于在每个线程中存储短信信息列表(类型为 `List`)。 + * `ThreadLocal` 的作用是让每个线程都有自己独立的变量副本,也就是说,不同线程通过这个 `smsInfoHolder` 访问到的短信信息列表是相互独立的,互不影响, + * 这样就可以在多线程的场景下安全地处理各自线程相关的短信业务数据。 + */ private static ThreadLocal> smsInfoHolder = new ThreadLocal>(); - - public static List get(){ + /** + * 获取当前线程中存储的短信信息列表。 + * 首先通过 `smsInfoHolder.get()` 方法尝试获取当前线程对应的短信信息列表,然后使用 `CollectionUtil.isEmpty(list)` 判断获取到的列表是否为空。 + * 如果为空(意味着当前线程还没有设置过短信信息列表或者之前设置的列表被清理了等情况),则返回一个新创建的空的 `ArrayList`,这样调用这个方法的地方可以放心地使用返回的列表进行后续操作,不用担心出现空指针异常等问题。 + * 如果获取到的列表不为空,则直接返回当前线程通过 `smsInfoHolder` 存储的短信信息列表,以便后续对已有的短信信息进行操作,比如遍历、修改等。 + * + * @return 当前线程中存储的短信信息列表,如果当前线程原本没有设置过短信信息列表,则返回一个新的空列表。 + */ + public static List get() { List list = smsInfoHolder.get(); if (CollectionUtil.isEmpty(list)) { return new ArrayList<>(); } return smsInfoHolder.get(); } - - public static void set(List smsInfoBos){ - smsInfoHolder.set(smsInfoBos); + + /** + * 设置当前线程中存储的短信信息列表。 + * 该方法接收一个 `List` 类型的参数 `smsInfoBos`,然后通过 `smsInfoHolder.set(smsInfoBos)` 将这个参数对应的短信信息列表设置到当前线程的 `ThreadLocal` 变量中, + * 这样在当前线程后续的其他代码中通过 `get` 方法获取到的就是新设置的这个短信信息列表了,方便在不同的业务逻辑阶段更新当前线程所使用的短信信息数据。 + * + * @param smsInfoBos 要设置到当前线程的短信信息列表。 + */ + public static void set(List smsInfoBos) { + smsInfoHolder.set(smsInfoBos); } - - public static void put(SmsInfoBo smsInfoBo){ + + /** + * 向当前线程中存储的短信信息列表中添加一条短信信息(`SmsInfoBo` 对象)。 + * 首先通过 `smsInfoHolder.get()` 获取当前线程已有的短信信息列表,接着使用 `CollectionUtil.isEmpty(smsInfoBos)` 判断这个列表是否为空。 + * 如果为空,说明当前线程还没有短信信息列表,那么就创建一个新的空的 `ArrayList` 作为初始的短信信息列表。然后将传入的短信信息对象 `smsInfoBo` 添加到这个列表中, + * 最后再通过 `smsInfoHolder.set(smsInfoBos)` 将更新后的包含了新添加短信信息的列表重新设置回当前线程的 `ThreadLocal` 变量中,确保线程中存储的短信信息列表始终是最新的状态,方便后续继续操作。 + * + * @param smsInfoBo 要添加到当前线程短信信息列表中的短信信息对象。 + */ + public static void put(SmsInfoBo smsInfoBo) { List smsInfoBos = smsInfoHolder.get(); if (CollectionUtil.isEmpty(smsInfoBos)) { smsInfoBos = new ArrayList<>(); @@ -46,9 +77,14 @@ public class SmsInfoContext { smsInfoBos.add(smsInfoBo); smsInfoHolder.set(smsInfoBos); } - + + /** + * 清理当前线程中存储的短信信息列表。 + * 首先通过 `smsInfoHolder.get()` 获取当前线程中存储的短信信息列表,判断其是否不为 `null`,如果不为 `null`,则调用 `smsInfoHolder.remove()` 方法将当前线程对应的短信信息列表从 `ThreadLocal` 变量中移除, + * 这样当前线程后续再通过 `get` 等方法获取短信信息列表时,得到的就是初始的默认状态(比如为空的情况)。这个方法常用于在某个业务逻辑执行完毕后,清理当前线程相关的短信信息数据,防止数据残留导致的内存占用以及可能出现的数据混乱等问题。 + */ public static void clean() { - if (smsInfoHolder.get() != null) { + if (smsInfoHolder.get()!= null) { smsInfoHolder.remove(); } }