package com.ruoyi.phone.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;
|
|
/**
|
* 电话模块开关拦截器。
|
* <p>
|
* <b>作用</b>:当开关关闭({@code sys_config} 中 {@code phone.enabled=false})时,
|
* 命中电话端点的请求会被立即拦下并抛出 {@link ServiceException},
|
* 由 RuoYi 的全局异常处理器返回<b>明确的业务错误提示</b>(而不是 404 或静默返回空数据)。
|
* <p>
|
* 开关值由 {@link PhoneSwitch} 在运行时读取({@code sys_config},10 秒进程内缓存),
|
* 因此改完参数设置<b>不需要重启</b>,最多 10 秒即生效。
|
* <p>
|
* <b>为什么不用 {@code @ConditionalOnProperty} 让 Controller 直接不注册</b>:
|
* <ul>
|
* <li>那样调用方只会拿到 HTTP 404 —— 虽然也是失败,但不是"明确错误",
|
* 电话平台无法区分"模块被关闭"和"地址写错了";</li>
|
* <li>而且 {@code @ConditionalOnProperty} 只在<b>启动时</b>求值一次,
|
* 做不到"改完参数配置就生效",与参数表开关的诉求冲突。</li>
|
* </ul>
|
* <p>
|
* <b>为什么不会影响任务/随访等其它接口</b>:本拦截器只登记在电话模块自己的 8 个精确路径上
|
* (见 {@link PhoneWebConfig}),不会碰到随访/问卷/统计接口。
|
*/
|
@Slf4j
|
@Component
|
public class PhoneAvailabilityInterceptor implements HandlerInterceptor {
|
|
/**
|
* 模块被关闭时返回给调用方的错误提示(电话平台/前端可直接展示)
|
*/
|
public static final String DISABLED_MESSAGE =
|
"电话功能未启用(参数配置 phone.enabled=false),该接口不可用";
|
|
private final PhoneSwitch phoneSwitch;
|
|
public PhoneAvailabilityInterceptor(PhoneSwitch phoneSwitch) {
|
this.phoneSwitch = phoneSwitch;
|
}
|
|
@Override
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
if (!phoneSwitch.isEnabled()) {
|
// request 允许为 null(单元测试直接调 preHandle 时不构造请求对象)
|
String method = request == null ? "-" : request.getMethod();
|
String uri = request == null ? "-" : request.getRequestURI();
|
log.warn("【电话】模块已关闭(参数配置 phone.enabled=false),拒绝访问 {} {}", method, uri);
|
throw new ServiceException(DISABLED_MESSAGE);
|
}
|
return true;
|
}
|
}
|