diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/AsyncConfig.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/AsyncConfig.java
index 02534a18e..f1e71362a 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/AsyncConfig.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/AsyncConfig.java
@@ -3,6 +3,16 @@
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
+/**
+ * 异步任务配置类
+ *
+ *
通过 {@code @EnableAsync} 开启 Spring 对方法级异步调用的支持,
+ * 使发短信、发邮件、推送模板消息等非核心耗时操作可以从主请求线程中剥离、
+ * 在独立线程池中后台执行,避免阻塞小程序接口的响应。
+ *
+ * @author litemall
+ * @since 1.0
+ */
@Configuration
@EnableAsync
public class AsyncConfig {
diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/CorsConfig.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/CorsConfig.java
index 29f01ea25..d785fa22c 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/CorsConfig.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/CorsConfig.java
@@ -6,25 +6,47 @@
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
+/**
+ * 跨域资源共享(CORS)配置类
+ *
+ * 浏览器中的 H5 或管理端与后端接口属于不同源(协议、域名、端口任一不同即跨域),
+ * 浏览器会拦截跨域请求。这里通过注册一个全局 CorsFilter,对 {@code /**} 所有接口
+ * 放行跨域预检与实际请求,使前端能够正常调用后端 API。
+ *
+ * 注意:当前为方便演示,放行源、请求头、请求方法均为 "*",生产环境应收紧为具体域名。
+ *
+ * @author litemall
+ * @since 1.0
+ */
@Configuration
public class CorsConfig {
- // 当前跨域请求最大有效时长。这里默认30天
+ /** 跨域预检请求(OPTIONS)的缓存时长,单位秒;设为 30 天,避免每次请求都发预检 */
private long maxAge = 30 * 24 * 60 * 60;
+ /**
+ * 构造一条 CORS 规则:允许任意来源、任意请求头、任意 HTTP 方法,并携带凭证
+ *
+ * @return 配置好的 CorsConfiguration
+ */
private CorsConfiguration buildConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
- corsConfiguration.addAllowedOrigin("*"); // 1 设置访问源地址
- corsConfiguration.addAllowedHeader("*"); // 2 设置访问源请求头
- corsConfiguration.addAllowedMethod("*"); // 3 设置访问源请求方法
+ corsConfiguration.addAllowedOrigin("*"); // 允许任意访问源(生产环境建议改为具体域名)
+ corsConfiguration.addAllowedHeader("*"); // 允许请求携带任意请求头
+ corsConfiguration.addAllowedMethod("*"); // 允许 GET/POST/PUT/DELETE 等任意方法
corsConfiguration.setMaxAge(maxAge);
- corsConfiguration.setAllowCredentials(true);
+ corsConfiguration.setAllowCredentials(true); // 允许携带 Cookie 等凭证信息
return corsConfiguration;
}
+ /**
+ * 将跨域规则注册到所有接口路径上,交由 Spring 过滤器链处理
+ *
+ * @return 全局跨域过滤器
+ */
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
- source.registerCorsConfiguration("/**", buildConfig()); // 4 对接口配置跨域设置
+ source.registerCorsConfiguration("/**", buildConfig());
return new CorsFilter(source);
}
}
diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/GlobalExceptionHandler.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/GlobalExceptionHandler.java
index a14078ef4..646074eb4 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/GlobalExceptionHandler.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/GlobalExceptionHandler.java
@@ -17,12 +17,26 @@
import javax.validation.ValidationException;
import java.util.Set;
+/**
+ * 全局异常处理器
+ *
+ * 统一拦截 Controller 层抛出的异常,避免异常堆栈直接暴露给前端。
+ * 所有被捕获的异常都会被转换成 {@link ResponseUtil} 约定的统一 JSON 结构
+ * (错误码 + 提示消息),同时打印错误日志便于后端排查。
+ *
+ * 方法命名统一为 badArgument / serious 两类:参数类问题返回“参数错误”,
+ * 其余未预期异常统一返回“系统错误”。
+ *
+ * @author litemall
+ * @since 1.0
+ */
@ControllerAdvice
@Order
public class GlobalExceptionHandler {
private Log logger = LogFactory.getLog(GlobalExceptionHandler.class);
+ /** 非法入参:业务代码主动抛出的 IllegalArgumentException */
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public Object badArgumentHandler(IllegalArgumentException e) {
@@ -30,6 +44,7 @@ public Object badArgumentHandler(IllegalArgumentException e) {
return ResponseUtil.badArgumentValue();
}
+ /** 参数类型不匹配:如预期 Integer 却传入了字符串 */
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
@ResponseBody
public Object badArgumentHandler(MethodArgumentTypeMismatchException e) {
@@ -37,6 +52,7 @@ public Object badArgumentHandler(MethodArgumentTypeMismatchException e) {
return ResponseUtil.badArgumentValue();
}
+ /** 缺少必填的请求参数 */
@ExceptionHandler(MissingServletRequestParameterException.class)
@ResponseBody
public Object badArgumentHandler(MissingServletRequestParameterException e) {
@@ -44,6 +60,7 @@ public Object badArgumentHandler(MissingServletRequestParameterException e) {
return ResponseUtil.badArgumentValue();
}
+ /** 请求体不可读:JSON 格式错误导致无法反序列化 */
@ExceptionHandler(HttpMessageNotReadableException.class)
@ResponseBody
public Object badArgumentHandler(HttpMessageNotReadableException e) {
@@ -51,6 +68,7 @@ public Object badArgumentHandler(HttpMessageNotReadableException e) {
return ResponseUtil.badArgumentValue();
}
+ /** 参数校验异常:提取第一个校验失败字段及其提示信息,返回 402 */
@ExceptionHandler(ValidationException.class)
@ResponseBody
public Object badArgumentHandler(ValidationException e) {
@@ -66,6 +84,7 @@ public Object badArgumentHandler(ValidationException e) {
return ResponseUtil.badArgumentValue();
}
+ /** 兜底处理:所有未被上面匹配的异常,统一按系统错误返回 */
@ExceptionHandler(Exception.class)
@ResponseBody
public Object seriousHandler(Exception e) {
diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/JacksonConfig.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/JacksonConfig.java
index 74000936d..463bacad9 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/JacksonConfig.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/JacksonConfig.java
@@ -20,15 +20,34 @@
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
+/**
+ * Jackson JSON 序列化全局配置
+ *
+ * 统一规定后端返回给前端的 JSON 规则:
+ *
+ * - 时间类型按 “yyyy-MM-dd HH:mm:ss / yyyy-MM-dd / HH:mm:ss” 格式化,不再输出时间戳;
+ * - 值为 null 的字段不输出,减小报文体积;
+ * - 反序列化时忽略前端多传的未知字段,避免直接报错。
+ *
+ *
+ * @author litemall
+ * @since 1.0
+ */
@Configuration
public class JacksonConfig {
+ /**
+ * 自定义 ObjectMapper 构建器,最高优先级覆盖 Spring Boot 默认配置
+ *
+ * @return Jackson2ObjectMapperBuilderCustomizer 定制器
+ */
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public Jackson2ObjectMapperBuilderCustomizer customJackson() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
+ // LocalDateTime / LocalDate / LocalTime 的序列化与反序列化统一格式
builder.serializerByType(LocalDateTime.class,
new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
builder.serializerByType(LocalDate.class,
@@ -41,8 +60,11 @@ public void customize(Jackson2ObjectMapperBuilder builder) {
new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
builder.deserializerByType(LocalTime.class,
new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
+ // null 字段不参与序列化
builder.serializationInclusion(JsonInclude.Include.NON_NULL);
+ // 前端多传未知字段时不报错,提升接口兼容性
builder.failOnUnknownProperties(false);
+ // 关闭把日期写成时间戳数组的默认行为
builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
};
diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/ValidatorConfiguration.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/ValidatorConfiguration.java
index 73cc47431..b80442215 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/ValidatorConfiguration.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/ValidatorConfiguration.java
@@ -8,8 +8,23 @@
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
+/**
+ * 参数校验器配置类
+ *
+ * 配置 JSR-303 参数校验(@Valid / @NotBlank 等)使用 Hibernate Validator 实现,
+ * 并开启 fail_fast:一旦遇到第一个校验失败就立即返回,不必等全部字段校验完,
+ * 便于接口快速给出明确的错误提示。
+ *
+ * @author litemall
+ * @since 1.0
+ */
@Configuration
public class ValidatorConfiguration {
+ /**
+ * 构造并注册全局 Validator
+ *
+ * @return fail-fast 模式的 Validator 实例
+ */
@Bean
public Validator validator() {
ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
@@ -17,7 +32,6 @@ public Validator validator() {
.addProperty("hibernate.validator.fail_fast", "true")
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
-
return validator;
}
}
diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxConfig.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxConfig.java
index c97a92e53..ef79d3dbb 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxConfig.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxConfig.java
@@ -11,11 +11,24 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+/**
+ * 微信小程序与微信支付配置类
+ *
+ * 把 {@link WxProperties}(来自 application.yml 的 litemall.wx.* 配置)装配成
+ * 小程序服务 {@link WxMaService} 和微信支付服务 {@link WxPayService} 两个 bean,
+ * 供登录、解密用户数据、统一下单等业务直接注入使用。
+ *
+ * @author litemall
+ * @since 1.0
+ */
@Configuration
public class WxConfig {
@Autowired
private WxProperties properties;
+ /**
+ * 小程序连接配置:appid、secret、消息校验 token、消息加解密密钥
+ */
@Bean
public WxMaConfig wxMaConfig() {
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
@@ -26,7 +39,7 @@ public WxMaConfig wxMaConfig() {
return config;
}
-
+ /** 小程序服务:封装 code 换 session、获取用户信息等能力 */
@Bean
public WxMaService wxMaService(WxMaConfig maConfig) {
WxMaService service = new WxMaServiceImpl();
@@ -34,6 +47,10 @@ public WxMaService wxMaService(WxMaConfig maConfig) {
return service;
}
+ /**
+ * 微信支付配置:商户号 mchId、商户密钥 mchKey、支付结果通知地址等,
+ * 交易类型固定 JSAPI(小程序内支付),签名方式 MD5
+ */
@Bean
public WxPayConfig wxPayConfig() {
WxPayConfig payConfig = new WxPayConfig();
@@ -47,11 +64,11 @@ public WxPayConfig wxPayConfig() {
return payConfig;
}
-
+ /** 微信支付服务:封装统一下单、查询订单、退款等能力 */
@Bean
public WxPayService wxPayService(WxPayConfig payConfig) {
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
-}
\ No newline at end of file
+}
diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxProperties.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxProperties.java
index a5f3dace5..789635662 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxProperties.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/config/WxProperties.java
@@ -3,24 +3,41 @@
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
+/**
+ * 微信小程序 / 微信支付配置属性
+ *
+ * 将 application.yml 中前缀为 {@code litemall.wx} 的配置项绑定到本类字段,
+ * 供 {@link WxConfig} 装配微信服务时读取。敏感信息(secret、mchKey)应放在配置文件或环境变量中,不要写死在代码里。
+ *
+ * @author litemall
+ * @since 1.0
+ */
@Configuration
@ConfigurationProperties(prefix = "litemall.wx")
public class WxProperties {
+ /** 小程序唯一标识(appid) */
private String appId;
+ /** 小程序 appSecret,用于 code 换 session_key */
private String appSecret;
+ /** 微信支付商户号 mch-id */
private String mchId;
+ /** 微信支付商户密钥 mch-key */
private String mchKey;
+ /** 支付结果异步通知地址 notify-url */
private String notifyUrl;
+ /** 商户证书本地路径 key-path */
private String keyPath;
+ /** 小程序服务器消息校验 token */
private String token;
+ /** 小程序消息加解密 aes-key */
private String aesKey;
public String getToken() {
diff --git a/litemall-core/src/main/java/org/linlinjava/litemall/core/express/ExpressService.java b/litemall-core/src/main/java/org/linlinjava/litemall/core/express/ExpressService.java
index d6438da63..0d15c72de 100644
--- a/litemall-core/src/main/java/org/linlinjava/litemall/core/express/ExpressService.java
+++ b/litemall-core/src/main/java/org/linlinjava/litemall/core/express/ExpressService.java
@@ -15,14 +15,14 @@
import java.util.Map;
/**
- * 物流查询服务
- *
- * 快递鸟即时查询API http://www.kdniao.com/api-track
+ * 封装快递鸟即时查询,为订单详情提供物流轨迹及快递公司名称。
+ *
关闭开关或请求、解析异常时返回 null;非空响应仍须检查 Success,
+ * 不能把返回对象直接当作查询成功。
*/
public class ExpressService {
private final Log logger = LogFactory.getLog(ExpressService.class);
- //请求url
+ // 服务商即时查询入口;enable 为 false 时不会发送请求。
private String ReqURL = "http://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx";
private ExpressProperties properties;
@@ -36,10 +36,9 @@ public void setProperties(ExpressProperties properties) {
}
/**
- * 获取物流供应商名
- *
- * @param vendorCode
- * @return
+ * 将订单中的快递公司编码转换为页面展示名称。
+ * @param vendorCode 与 vendors 配置中 code 对应的公司编码
+ * @return 配置中的公司名称;没有匹配项时返回 null
*/
public String getVendorName(String vendorCode) {
for (Map item : properties.getVendors()) {
@@ -49,16 +48,20 @@ public String getVendorName(String vendorCode) {
return null;
}
+ /**
+ * 提供可选快递公司,供后台发货时选择。
+ * @return 配置中的公司列表,每项包含 code 和 name;返回原列表而非副本
+ */
public List