sendMessageWithAttachments(String to, String subject, String text) {
- // 附件路径 禁止前端传递 有任意读取系统文件风险
- String[] paths = new String[]{"/xxx/xxx", "/xxx/xxx"};
- File[] array = Arrays.stream(paths).map(File::new).toArray(File[]::new);
- MailUtils.sendText(to, subject, text, array);
- return R.ok();
- }
-
-}
diff --git a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisCacheController.java b/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisCacheController.java
deleted file mode 100644
index 2335da4..0000000
--- a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisCacheController.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package org.dromara.demo.controller;
-
-import cn.hutool.core.thread.ThreadUtil;
-import org.dromara.common.core.constant.CacheNames;
-import org.dromara.common.core.domain.R;
-import org.dromara.common.redis.utils.RedisUtils;
-import lombok.RequiredArgsConstructor;
-import org.springframework.cache.annotation.CacheEvict;
-import org.springframework.cache.annotation.CachePut;
-import org.springframework.cache.annotation.Cacheable;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.time.Duration;
-
-/**
- * spring-cache 演示案例
- *
- * @author Lion Li
- */
-// 类级别 缓存统一配置
-//@CacheConfig(cacheNames = CacheNames.DEMO_CACHE)
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/cache")
-public class RedisCacheController {
-
- /**
- * 测试 @Cacheable
- *
- * 表示这个方法有了缓存的功能,方法的返回值会被缓存下来
- * 下一次调用该方法前,会去检查是否缓存中已经有值
- * 如果有就直接返回,不调用方法
- * 如果没有,就调用方法,然后把结果缓存起来
- * 这个注解「一般用在查询方法上」
- *
- * 重点说明: 缓存注解严谨与其他筛选数据功能一起使用
- * 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题
- *
- * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
- */
- @Cacheable(cacheNames = "demo:cache#60s#10m#20#1", key = "#key", condition = "#key != null")
- @GetMapping("/test1")
- public R test1(String key, String value) {
- return R.ok("操作成功", value);
- }
-
- /**
- * 测试 @CachePut
- *
- * 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用
- * 它「通常用在新增或者实时更新方法上」
- *
- * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
- */
- @CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
- @GetMapping("/test2")
- public R test2(String key, String value) {
- return R.ok("操作成功", value);
- }
-
- /**
- * 测试 @CacheEvict
- *
- * 使用了CacheEvict注解的方法,会清空指定缓存
- * 「一般用在删除的方法上」
- *
- * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数
- */
- @CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null")
- @GetMapping("/test3")
- public R test3(String key, String value) {
- return R.ok("操作成功", value);
- }
-
- /**
- * 测试设置过期时间
- * 手动设置过期时间10秒
- * 11秒后获取 判断是否相等
- */
- @GetMapping("/test6")
- public R test6(String key, String value) {
- RedisUtils.setCacheObject(key, value);
- boolean flag = RedisUtils.expire(key, Duration.ofSeconds(10));
- System.out.println("***********" + flag);
- ThreadUtil.sleep(11 * 1000);
- Object obj = RedisUtils.getCacheObject(key);
- return R.ok(value.equals(obj));
- }
-
-}
diff --git a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisLockController.java b/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisLockController.java
deleted file mode 100644
index 237b6ee..0000000
--- a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisLockController.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.dromara.demo.controller;
-
-import cn.hutool.core.thread.ThreadUtil;
-import com.baomidou.lock.LockInfo;
-import com.baomidou.lock.LockTemplate;
-import com.baomidou.lock.annotation.Lock4j;
-import com.baomidou.lock.executor.RedissonLockExecutor;
-import org.dromara.common.core.domain.R;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.time.LocalTime;
-
-
-/**
- * 测试分布式锁的样例
- *
- * @author shenxinquan
- */
-@Slf4j
-@RestController
-@RequestMapping("/demo/redisLock")
-public class RedisLockController {
-
- @Autowired
- private LockTemplate lockTemplate;
-
- /**
- * 测试lock4j 注解
- */
- @Lock4j(keys = {"#key"})
- @GetMapping("/testLock4j")
- public R testLock4j(String key, String value) {
- System.out.println("start:" + key + ",time:" + LocalTime.now());
- ThreadUtil.sleep(10000);
- System.out.println("end :" + key + ",time:" + LocalTime.now());
- return R.ok("操作成功", value);
- }
-
- /**
- * 测试lock4j 工具
- */
- @GetMapping("/testLock4jLockTemplate")
- public R testLock4jLockTemplate(String key, String value) {
- final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);
- if (null == lockInfo) {
- throw new RuntimeException("业务处理中,请稍后再试");
- }
- // 获取锁成功,处理业务
- try {
- ThreadUtil.sleep(8000);
- System.out.println("执行简单方法1 , 当前线程:" + Thread.currentThread().getName());
- } finally {
- //释放锁
- lockTemplate.releaseLock(lockInfo);
- }
- //结束
- return R.ok("操作成功", value);
- }
-
-}
diff --git a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisPubSubController.java b/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisPubSubController.java
deleted file mode 100644
index bdbf033..0000000
--- a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisPubSubController.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package org.dromara.demo.controller;
-
-import org.dromara.common.core.domain.R;
-import org.dromara.common.redis.utils.RedisUtils;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * Redis 发布订阅 演示案例
- *
- * @author Lion Li
- */
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/redis/pubsub")
-public class RedisPubSubController {
-
- /**
- * 发布消息
- *
- * @param key 通道Key
- * @param value 发送内容
- */
- @GetMapping("/pub")
- public R pub(String key, String value) {
- RedisUtils.publish(key, value, consumer -> {
- System.out.println("发布通道 => " + key + ", 发送值 => " + value);
- });
- return R.ok("操作成功");
- }
-
- /**
- * 订阅消息
- *
- * @param key 通道Key
- */
- @GetMapping("/sub")
- public R sub(String key) {
- RedisUtils.subscribe(key, String.class, msg -> {
- System.out.println("订阅通道 => " + key + ", 接收值 => " + msg);
- });
- return R.ok("操作成功");
- }
-
-}
diff --git a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisRateLimiterController.java b/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisRateLimiterController.java
deleted file mode 100644
index f8adf7d..0000000
--- a/water-modules/water-app/src/main/java/org/dromara/demo/controller/RedisRateLimiterController.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.dromara.demo.controller;
-
-import org.dromara.common.core.domain.R;
-import org.dromara.common.ratelimiter.annotation.RateLimiter;
-import org.dromara.common.ratelimiter.enums.LimitType;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-
-/**
- * 测试分布式限流样例
- *
- * @author Lion Li
- */
-@Slf4j
-@RestController
-@RequestMapping("/demo/rateLimiter")
-public class RedisRateLimiterController {
-
- /**
- * 测试全局限流
- * 全局影响
- */
- @RateLimiter(count = 2, time = 10)
- @GetMapping("/test")
- public R test(String value) {
- return R.ok("操作成功", value);
- }
-
- /**
- * 测试请求IP限流
- * 同一IP请求受影响
- */
- @RateLimiter(count = 2, time = 10, limitType = LimitType.IP)
- @GetMapping("/testip")
- public R testip(String value) {
- return R.ok("操作成功", value);
- }
-
- /**
- * 测试集群实例限流
- * 启动两个后端服务互不影响
- */
- @RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER)
- @GetMapping("/testcluster")
- public R testcluster(String value) {
- return R.ok("操作成功", value);
- }
-
- /**
- * 测试请求IP限流(key基于参数获取)
- * 同一IP请求受影响
- *
- * 简单变量获取 #变量 复杂表达式 #{#变量 != 1 ? 1 : 0}
- */
- @RateLimiter(count = 2, time = 10, limitType = LimitType.IP, key = "#value")
- @GetMapping("/testObj")
- public R testObj(String value) {
- return R.ok("操作成功", value);
- }
-
-}
diff --git a/water-modules/water-app/src/main/java/org/dromara/demo/controller/SaTokenTestController.java b/water-modules/water-app/src/main/java/org/dromara/demo/controller/SaTokenTestController.java
deleted file mode 100644
index 66fd3cd..0000000
--- a/water-modules/water-app/src/main/java/org/dromara/demo/controller/SaTokenTestController.java
+++ /dev/null
@@ -1,198 +0,0 @@
-package org.dromara.demo.controller;
-
-import cn.dev33.satoken.annotation.*;
-import lombok.extern.slf4j.Slf4j;
-import org.dromara.common.core.domain.R;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * SaToken 权限测试 接口文档输出测试
- *
- * @author AprilWind
- */
-@Slf4j
-@RestController
-@RequestMapping("/demo/saTokenDoc")
-public class SaTokenTestController {
-
- // ====================== 基础场景:单一校验规则 ======================
-
- /**
- * 场景1:仅登录校验(无角色/权限限制,只需登录态)
- */
- @SaCheckLogin
- @GetMapping("/basic/loginOnly")
- public R loginOnly() {
- log.info("【场景1】仅登录校验通过");
- return R.ok("仅登录校验通过,无需角色/权限");
- }
-
- /**
- * 场景2:单一角色校验(AND模式,默认)
- */
- @SaCheckRole("admin")
- @GetMapping("/basic/singleRole")
- public R singleRole() {
- log.info("【场景2】单一角色(admin)校验通过");
- return R.ok("拥有admin角色,校验通过");
- }
-
- /**
- * 场景3:单一权限校验(AND模式,默认)
- */
- @SaCheckPermission("system:user:view")
- @GetMapping("/basic/singlePermission")
- public R singlePermission() {
- log.info("【场景3】单一权限(system:user:view)校验通过");
- return R.ok("拥有system:user:view权限,校验通过");
- }
-
- /**
- * 场景4:忽略所有权限校验(SaIgnore优先级最高)
- */
- @SaIgnore
- @SaCheckRole("none_exist") // 该注解会被忽略
- @GetMapping("/basic/ignoreAll")
- public R ignoreAll() {
- log.info("【场景4】SaIgnore忽略所有权限校验");
- return R.ok("SaIgnore生效,所有权限校验被忽略");
- }
-
- // ====================== 进阶场景:多条件组合(AND/OR) ======================
-
- /**
- * 场景5:多角色AND模式(必须同时拥有所有角色)
- */
- @SaCheckRole(value = {"admin", "operator"}, mode = SaMode.AND)
- @GetMapping("/advance/multiRoleAnd")
- public R multiRoleAnd() {
- log.info("【场景5】多角色AND模式(admin+operator)校验通过");
- return R.ok("同时拥有admin和operator角色,校验通过");
- }
-
- /**
- * 场景6:多角色OR模式(拥有任一角色即可)
- */
- @SaCheckRole(value = {"admin", "test"}, mode = SaMode.OR)
- @GetMapping("/advance/multiRoleOr")
- public R multiRoleOr() {
- log.info("【场景6】多角色OR模式(admin|test)校验通过");
- return R.ok("拥有admin或test角色,校验通过");
- }
-
- /**
- * 场景7:多权限AND模式(必须同时拥有所有权限)
- */
- @SaCheckPermission(value = {"system:user:edit", "system:log:view"}, mode = SaMode.AND)
- @GetMapping("/advance/multiPermAnd")
- public R multiPermAnd() {
- log.info("【场景7】多权限AND模式(system:user:edit+system:log:view)校验通过");
- return R.ok("同时拥有system:user:edit和system:log:view权限,校验通过");
- }
-
- /**
- * 场景8:多权限OR模式(拥有任一权限即可)
- */
- @SaCheckPermission(value = {"system:user:add", "system:user:delete"}, mode = SaMode.OR)
- @GetMapping("/advance/multiPermOr")
- public R multiPermOr() {
- log.info("【场景8】多权限OR模式(system:user:add|system:user:delete)校验通过");
- return R.ok("拥有system:user:add或system:user:delete权限,校验通过");
- }
-
- // ====================== 高级场景:通配符/混合组合 ======================
-
- /**
- * 场景9:权限通配符匹配(前缀匹配)
- * 拥有system:user:* 即可匹配所有用户模块权限
- */
- @SaCheckPermission("system:user:*")
- @GetMapping("/advanced/permWildcardPrefix")
- public R permWildcardPrefix() {
- log.info("【场景9】权限通配符(system:user:*)校验通过");
- return R.ok("拥有system:user:*前缀权限,校验通过");
- }
-
- /**
- * 场景10:角色通配符匹配(前缀匹配)
- * 拥有admin_* 即可匹配所有admin开头的角色
- */
- @SaCheckRole("admin_*")
- @GetMapping("/advanced/roleWildcardPrefix")
- public R roleWildcardPrefix() {
- log.info("【场景10】角色通配符(admin_*)校验通过");
- return R.ok("拥有admin_*前缀角色,校验通过");
- }
-
- /**
- * 场景11:权限+角色混合AND模式(所有条件必须满足)
- * 需同时满足:拥有admin角色 + 拥有system:user:all权限
- */
- @SaCheckRole("admin")
- @SaCheckPermission("system:user:all")
- @GetMapping("/advanced/mixRolePermAnd")
- public R mixRolePermAnd() {
- log.info("【场景11】角色+权限混合AND(admin+system:user:all)校验通过");
- return R.ok("拥有admin角色且拥有system:user:all权限,校验通过");
- }
-
- /**
- * 场景12:权限+角色混合OR模式(任一条件满足即可)
- * 满足任一:拥有super_admin角色 | 拥有system:manage权限
- */
- @SaCheckRole(value = {"super_admin"}, mode = SaMode.OR)
- @SaCheckPermission(value = {"system:manage"}, mode = SaMode.OR)
- @GetMapping("/advanced/mixRolePermOr")
- public R mixRolePermOr() {
- log.info("【场景12】角色+权限混合OR(super_admin|system:manage)校验通过");
- return R.ok("拥有super_admin角色或system:manage权限,校验通过");
- }
-
- /**
- * 场景13:orRole参数(权限校验失败时,兜底角色校验)
- * 核心逻辑:无system:user:export权限时,检查是否有admin/operator角色
- */
- @SaCheckPermission(value = "system:user:export", orRole = {"admin", "operator"})
- @GetMapping("/advanced/permWithOrRole")
- public R permWithOrRole() {
- log.info("【场景13】权限+orRole兜底校验通过");
- return R.ok("拥有system:user:export权限,或拥有admin/operator角色,校验通过");
- }
-
- // ====================== 特殊场景:临时权限/注解覆盖 ======================
-
- /**
- * 场景14:SaIgnore局部覆盖(方法注解覆盖类注解,若有)
- * 假设类上有@SaCheckLogin,方法上@SaIgnore会覆盖
- */
- @SaIgnore
- @GetMapping("/special/ignoreOverride")
- public R ignoreOverride() {
- log.info("【场景14】SaIgnore覆盖类级别权限注解");
- return R.ok("方法级SaIgnore覆盖类级别权限校验");
- }
-
- /**
- * 场景15:临时权限校验(SaCheckPermission逻辑:临时权限>永久权限)
- * 注:临时权限需通过SaToken API手动设置,如 SaHolder.getStpLogic().setTempPermission("system:temp:test")
- */
- @SaCheckPermission("system:temp:test")
- @GetMapping("/special/tempPermission")
- public R tempPermission() {
- log.info("【场景15】临时权限(system:temp:test)校验通过");
- return R.ok("临时权限校验通过(需先通过API设置临时权限)");
- }
-
- /**
- * 场景16:登录类型指定(多端登录场景,如PC/APP/小程序)
- * 注:需配合SaToken多账号体系配置
- */
- @SaCheckLogin(type = "PC") // 仅校验PC端的登录态
- @GetMapping("/special/loginTypeSpecify")
- public R loginTypeSpecify() {
- log.info("【场景16】指定登录类型(PC)校验通过");
- return R.ok("仅PC端登录态校验通过");
- }
-}
diff --git a/water-modules/water-app/src/main/java/org/dromara/demo/controller/SmsController.java b/water-modules/water-app/src/main/java/org/dromara/demo/controller/SmsController.java
deleted file mode 100644
index b993f60..0000000
--- a/water-modules/water-app/src/main/java/org/dromara/demo/controller/SmsController.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package org.dromara.demo.controller;
-
-import lombok.RequiredArgsConstructor;
-import org.dromara.common.core.domain.R;
-import org.dromara.sms4j.api.SmsBlend;
-import org.dromara.sms4j.api.entity.SmsResponse;
-import org.dromara.sms4j.core.factory.SmsFactory;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-import java.util.LinkedHashMap;
-
-/**
- * 短信演示案例
- * 请先阅读文档 否则无法使用
- *
- * @author Lion Li
- * @version 4.2.0
- */
-@Validated
-@RequiredArgsConstructor
-@RestController
-@RequestMapping("/demo/sms")
-public class SmsController {
- /**
- * 发送短信Aliyun
- *
- * @param phones 电话号
- * @param templateId 模板ID
- */
- @GetMapping("/sendAliyun")
- public R