package com.ruoyi.satisfaction.config;
import com.ruoyi.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 满意度模块开关拦截器。
*
* 作用:当开关关闭({@code sys_config} 中 {@code satisfaction.enabled=false})时,
* 命中满意度端点的请求会被立即拦下并抛出 {@link ServiceException},
* 由 RuoYi 的全局异常处理器返回明确的业务错误提示(而不是 404 或静默返回空数据)。
*
* 开关值由 {@link SatisfactionSwitch} 在运行时读取({@code sys_config},10 秒进程内缓存),
* 因此改完参数设置不需要重启,最多 10 秒即生效。
*
* 为什么不用 {@code @ConditionalOnProperty} 让 Controller 直接不注册:
*
* - 那样调用方只会拿到 HTTP 404 —— 虽然也是失败,但不是"明确错误",
* 前端/外链无法区分"模块被关闭"和"地址写错了";
* - 而且 {@code @ConditionalOnProperty} 只在启动时求值一次,
* 做不到"改完参数配置就生效",与参数表开关的诉求冲突。
*
*
* 为什么不会影响其它业务与启动:
*
* - 本拦截器只登记在 17 个满意度端点的精确路径上
* (见 {@link SatisfactionWebConfig}),不会碰到随访/问卷/其它接口;
* - 模块关闭时,Controller 与 Service 依旧是普通 Bean(启动不受影响);
* 其它模块通过 {@code SatisfactionFacade} 取数时拿到的是安全空值/全零,
* 只有"专门调满意度端点"的请求才会收到错误。
*
*/
@Slf4j
@Component
public class SatisfactionAvailabilityInterceptor implements HandlerInterceptor {
/**
* 模块被关闭时返回给调用方的错误提示(前端可直接展示)
*/
public static final String DISABLED_MESSAGE =
"满意度功能未启用(参数配置 satisfaction.enabled=false),该接口不可用";
private final SatisfactionSwitch satisfactionSwitch;
public SatisfactionAvailabilityInterceptor(SatisfactionSwitch satisfactionSwitch) {
this.satisfactionSwitch = satisfactionSwitch;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!satisfactionSwitch.isEnabled()) {
// request 允许为 null(单元测试直接调 preHandle 时不构造请求对象)
String method = request == null ? "-" : request.getMethod();
String uri = request == null ? "-" : request.getRequestURI();
log.warn("【满意度】模块已关闭(参数配置 satisfaction.enabled=false),拒绝访问 {} {}", method, uri);
throw new ServiceException(DISABLED_MESSAGE);
}
return true;
}
}