init
This commit is contained in:
		| @ -0,0 +1,70 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaIgnore; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.mail.utils.MailUtils; | ||||
| 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.io.File; | ||||
| import java.util.Arrays; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 邮件发送案例 | ||||
|  * | ||||
|  * @author Michelle.Chung | ||||
|  */ | ||||
| @SaIgnore | ||||
| @Validated | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/mail") | ||||
| public class MailController { | ||||
|  | ||||
|     /** | ||||
|      * 发送邮件 | ||||
|      * | ||||
|      * @param to      接收人 | ||||
|      * @param subject 标题 | ||||
|      * @param text    内容 | ||||
|      */ | ||||
|     @GetMapping("/sendSimpleMessage") | ||||
|     public R<Void> sendSimpleMessage(String to, String subject, String text) { | ||||
|         MailUtils.sendText(to, subject, text); | ||||
|         return R.ok(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 发送邮件(带附件) | ||||
|      * | ||||
|      * @param to       接收人 | ||||
|      * @param subject  标题 | ||||
|      * @param text     内容 | ||||
|      * @param filePath 附件路径 | ||||
|      */ | ||||
|     @GetMapping("/sendMessageWithAttachment") | ||||
|     public R<Void> sendMessageWithAttachment(String to, String subject, String text, String filePath) { | ||||
|         MailUtils.sendText(to, subject, text, new File(filePath)); | ||||
|         return R.ok(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 发送邮件(多附件) | ||||
|      * | ||||
|      * @param to       接收人 | ||||
|      * @param subject  标题 | ||||
|      * @param text     内容 | ||||
|      * @param paths    附件路径 | ||||
|      */ | ||||
|     @GetMapping("/sendMessageWithAttachments") | ||||
|     public R<Void> sendMessageWithAttachments(String to, String subject, String text, String[] paths) { | ||||
|         File[] array = Arrays.stream(paths).map(File::new).toArray(File[]::new); | ||||
|         MailUtils.sendText(to, subject, text, array); | ||||
|         return R.ok(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,92 @@ | ||||
| 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 | ||||
|      * <p> | ||||
|      * 表示这个方法有了缓存的功能,方法的返回值会被缓存下来 | ||||
|      * 下一次调用该方法前,会去检查是否缓存中已经有值 | ||||
|      * 如果有就直接返回,不调用方法 | ||||
|      * 如果没有,就调用方法,然后把结果缓存起来 | ||||
|      * 这个注解「一般用在查询方法上」 | ||||
|      * <p> | ||||
|      * 重点说明: 缓存注解严谨与其他筛选数据功能一起使用 | ||||
|      * 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题 | ||||
|      * <p> | ||||
|      * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数 | ||||
|      */ | ||||
|     @Cacheable(cacheNames = "demo:cache#60s#10m#20", key = "#key", condition = "#key != null") | ||||
|     @GetMapping("/test1") | ||||
|     public R<String> test1(String key, String value) { | ||||
|         return R.ok("操作成功", value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 测试 @CachePut | ||||
|      * <p> | ||||
|      * 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用 | ||||
|      * 它「通常用在新增或者实时更新方法上」 | ||||
|      * <p> | ||||
|      * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数 | ||||
|      */ | ||||
|     @CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null") | ||||
|     @GetMapping("/test2") | ||||
|     public R<String> test2(String key, String value) { | ||||
|         return R.ok("操作成功", value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 测试 @CacheEvict | ||||
|      * <p> | ||||
|      * 使用了CacheEvict注解的方法,会清空指定缓存 | ||||
|      * 「一般用在删除的方法上」 | ||||
|      * <p> | ||||
|      * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数 | ||||
|      */ | ||||
|     @CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null") | ||||
|     @GetMapping("/test3") | ||||
|     public R<String> test3(String key, String value) { | ||||
|         return R.ok("操作成功", value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 测试设置过期时间 | ||||
|      * 手动设置过期时间10秒 | ||||
|      * 11秒后获取 判断是否相等 | ||||
|      */ | ||||
|     @GetMapping("/test6") | ||||
|     public R<Boolean> 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)); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| 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<String> 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<String> 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); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,47 @@ | ||||
| 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<Void> 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<Void> sub(String key) { | ||||
|         RedisUtils.subscribe(key, String.class, msg -> { | ||||
|             System.out.println("订阅通道 => " + key + ", 接收值 => " + msg); | ||||
|         }); | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| 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<String> test(String value) { | ||||
|         return R.ok("操作成功", value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 测试请求IP限流 | ||||
|      * 同一IP请求受影响 | ||||
|      */ | ||||
|     @RateLimiter(count = 2, time = 10, limitType = LimitType.IP) | ||||
|     @GetMapping("/testip") | ||||
|     public R<String> testip(String value) { | ||||
|         return R.ok("操作成功", value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 测试集群实例限流 | ||||
|      * 启动两个后端服务互不影响 | ||||
|      */ | ||||
|     @RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER) | ||||
|     @GetMapping("/testcluster") | ||||
|     public R<String> 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<String> testObj(String value) { | ||||
|         return R.ok("操作成功", value); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,82 @@ | ||||
| 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<Object> sendAliyun(String phones, String templateId) { | ||||
|         LinkedHashMap<String, String> map = new LinkedHashMap<>(1); | ||||
|         map.put("code", "1234"); | ||||
|         SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); | ||||
|         SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map); | ||||
|         return R.ok(smsResponse); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 发送短信Tencent | ||||
|      * | ||||
|      * @param phones     电话号 | ||||
|      * @param templateId 模板ID | ||||
|      */ | ||||
|     @GetMapping("/sendTencent") | ||||
|     public R<Object> sendTencent(String phones, String templateId) { | ||||
|         LinkedHashMap<String, String> map = new LinkedHashMap<>(1); | ||||
| //        map.put("2", "测试测试"); | ||||
|         map.put("1", "1234"); | ||||
|         SmsBlend smsBlend = SmsFactory.getSmsBlend("config2"); | ||||
|         SmsResponse smsResponse = smsBlend.sendMessage(phones, templateId, map); | ||||
|         return R.ok(smsResponse); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 添加黑名单 | ||||
|      * | ||||
|      * @param phone 手机号 | ||||
|      */ | ||||
|     @GetMapping("/addBlacklist") | ||||
|     public R<Object> addBlacklist(String phone){ | ||||
|         SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); | ||||
|         smsBlend.joinInBlacklist(phone); | ||||
|         return R.ok(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 移除黑名单 | ||||
|      * | ||||
|      * @param phone 手机号 | ||||
|      */ | ||||
|     @GetMapping("/removeBlacklist") | ||||
|     public R<Object> removeBlacklist(String phone){ | ||||
|         SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); | ||||
|         smsBlend.removeFromBlacklist(phone); | ||||
|         return R.ok(); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,31 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RequestPart; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
|  | ||||
| /** | ||||
|  * swagger3 用法示例 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  */ | ||||
| @RestController | ||||
| @RequestMapping("/swagger/demo") | ||||
| public class Swagger3DemoController { | ||||
|  | ||||
|     /** | ||||
|      * 上传请求 | ||||
|      * 必须使用 @RequestPart 注解标注为文件 | ||||
|      * | ||||
|      * @param file 文件 | ||||
|      */ | ||||
|     @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||||
|     public R<String> upload(@RequestPart("file") MultipartFile file) { | ||||
|         return R.ok("操作成功", file.getOriginalFilename()); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,90 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.web.core.BaseController; | ||||
| import org.dromara.demo.domain.TestDemo; | ||||
| import org.dromara.demo.mapper.TestDemoMapper; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.web.bind.annotation.DeleteMapping; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 测试批量方法 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-05-30 | ||||
|  */ | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/batch") | ||||
| public class TestBatchController extends BaseController { | ||||
|  | ||||
|     /** | ||||
|      * 为了便于测试 直接引入mapper | ||||
|      */ | ||||
|     private final TestDemoMapper testDemoMapper; | ||||
|  | ||||
|     /** | ||||
|      * 新增批量方法 可完美替代 saveBatch 秒级插入上万数据 (对mysql负荷较大) | ||||
|      * <p> | ||||
|      * 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度 | ||||
|      */ | ||||
|     @PostMapping("/add") | ||||
| //    @DS("slave") | ||||
|     public R<Void> add() { | ||||
|         List<TestDemo> list = new ArrayList<>(); | ||||
|         for (int i = 0; i < 1000; i++) { | ||||
|             TestDemo testDemo = new TestDemo(); | ||||
|             testDemo.setOrderNum(-1); | ||||
|             testDemo.setTestKey("批量新增"); | ||||
|             testDemo.setValue("测试新增"); | ||||
|             list.add(testDemo); | ||||
|         } | ||||
|         return toAjax(testDemoMapper.insertBatch(list)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 新增或更新 可完美替代 saveOrUpdateBatch 高性能 | ||||
|      * <p> | ||||
|      * 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度 | ||||
|      */ | ||||
|     @PostMapping("/addOrUpdate") | ||||
| //    @DS("slave") | ||||
|     public R<Void> addOrUpdate() { | ||||
|         List<TestDemo> list = new ArrayList<>(); | ||||
|         for (int i = 0; i < 1000; i++) { | ||||
|             TestDemo testDemo = new TestDemo(); | ||||
|             testDemo.setOrderNum(-1); | ||||
|             testDemo.setTestKey("批量新增"); | ||||
|             testDemo.setValue("测试新增"); | ||||
|             list.add(testDemo); | ||||
|         } | ||||
|         testDemoMapper.insertBatch(list); | ||||
|         for (int i = 0; i < list.size(); i++) { | ||||
|             TestDemo testDemo = list.get(i); | ||||
|             testDemo.setTestKey("批量新增或修改"); | ||||
|             testDemo.setValue("批量新增或修改"); | ||||
|             if (i % 2 == 0) { | ||||
|                 testDemo.setId(null); | ||||
|             } | ||||
|         } | ||||
|         return toAjax(testDemoMapper.insertOrUpdateBatch(list)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除批量方法 | ||||
|      */ | ||||
|     @DeleteMapping() | ||||
| //    @DS("slave") | ||||
|     public R<Void> remove() { | ||||
|         return toAjax(testDemoMapper.delete(new LambdaQueryWrapper<TestDemo>() | ||||
|             .eq(TestDemo::getOrderNum, -1L))); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,147 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.core.utils.MapstructUtils; | ||||
| import org.dromara.common.core.utils.ValidatorUtils; | ||||
| import org.dromara.common.core.validate.AddGroup; | ||||
| import org.dromara.common.core.validate.EditGroup; | ||||
| import org.dromara.common.core.validate.QueryGroup; | ||||
| import org.dromara.common.web.core.BaseController; | ||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||
| import org.dromara.common.mybatis.core.page.PageQuery; | ||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||
| import org.dromara.common.excel.core.ExcelResult; | ||||
| import org.dromara.common.excel.utils.ExcelUtil; | ||||
| import org.dromara.common.log.annotation.Log; | ||||
| import org.dromara.common.log.enums.BusinessType; | ||||
| import org.dromara.demo.domain.TestDemo; | ||||
| import org.dromara.demo.domain.bo.TestDemoBo; | ||||
| import org.dromara.demo.domain.bo.TestDemoImportVo; | ||||
| import org.dromara.demo.domain.vo.TestDemoVo; | ||||
| import org.dromara.demo.service.ITestDemoService; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
|  | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import jakarta.validation.constraints.NotEmpty; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
|  | ||||
| import java.util.*; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| /** | ||||
|  * 测试单表Controller | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @Validated | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/demo") | ||||
| public class TestDemoController extends BaseController { | ||||
|  | ||||
|     private final ITestDemoService testDemoService; | ||||
|  | ||||
|     /** | ||||
|      * 查询测试单表列表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:demo:list") | ||||
|     @GetMapping("/list") | ||||
|     public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) { | ||||
|         return testDemoService.queryPageList(bo, pageQuery); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 自定义分页查询 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:demo:list") | ||||
|     @GetMapping("/page") | ||||
|     public TableDataInfo<TestDemoVo> page(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) { | ||||
|         return testDemoService.customPageList(bo, pageQuery); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 导入数据 | ||||
|      * | ||||
|      * @param file 导入文件 | ||||
|      */ | ||||
|     @Log(title = "测试单表", businessType = BusinessType.IMPORT) | ||||
|     @SaCheckPermission("demo:demo:import") | ||||
|     @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||||
|     public R<Void> importData(@RequestPart("file") MultipartFile file) throws Exception { | ||||
|         ExcelResult<TestDemoImportVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), TestDemoImportVo.class, true); | ||||
|         List<TestDemo> list = MapstructUtils.convert(excelResult.getList(), TestDemo.class); | ||||
|         testDemoService.saveBatch(list); | ||||
|         return R.ok(excelResult.getAnalysis()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 导出测试单表列表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:demo:export") | ||||
|     @Log(title = "测试单表", businessType = BusinessType.EXPORT) | ||||
|     @PostMapping("/export") | ||||
|     public void export(@Validated TestDemoBo bo, HttpServletResponse response) { | ||||
|         List<TestDemoVo> list = testDemoService.queryList(bo); | ||||
|         // 测试雪花id导出 | ||||
| //        for (TestDemoVo vo : list) { | ||||
| //            vo.setId(1234567891234567893L); | ||||
| //        } | ||||
|         ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取测试单表详细信息 | ||||
|      * | ||||
|      * @param id 测试ID | ||||
|      */ | ||||
|     @SaCheckPermission("demo:demo:query") | ||||
|     @GetMapping("/{id}") | ||||
|     public R<TestDemoVo> getInfo(@NotNull(message = "主键不能为空") | ||||
|                                  @PathVariable("id") Long id) { | ||||
|         return R.ok(testDemoService.queryById(id)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 新增测试单表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:demo:add") | ||||
|     @Log(title = "测试单表", businessType = BusinessType.INSERT) | ||||
|     @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "{repeat.submit.message}") | ||||
|     @PostMapping() | ||||
|     public R<Void> add(@RequestBody TestDemoBo bo) { | ||||
|         // 使用校验工具对标 @Validated(AddGroup.class) 注解 | ||||
|         // 用于在非 Controller 的地方校验对象 | ||||
|         ValidatorUtils.validate(bo, AddGroup.class); | ||||
|         return toAjax(testDemoService.insertByBo(bo)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 修改测试单表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:demo:edit") | ||||
|     @Log(title = "测试单表", businessType = BusinessType.UPDATE) | ||||
|     @RepeatSubmit | ||||
|     @PutMapping() | ||||
|     public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) { | ||||
|         return toAjax(testDemoService.updateByBo(bo)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除测试单表 | ||||
|      * | ||||
|      * @param ids 测试ID串 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:demo:remove") | ||||
|     @Log(title = "测试单表", businessType = BusinessType.DELETE) | ||||
|     @DeleteMapping("/{ids}") | ||||
|     public R<Void> remove(@NotEmpty(message = "主键不能为空") | ||||
|                           @PathVariable Long[] ids) { | ||||
|         return toAjax(testDemoService.deleteWithValidByIds(Arrays.asList(ids), true)); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,55 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.demo.domain.TestDemoEncrypt; | ||||
| import org.dromara.demo.mapper.TestDemoEncryptMapper; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| 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.HashMap; | ||||
| import java.util.Map; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 测试数据库加解密功能 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  */ | ||||
| @Validated | ||||
| @RestController | ||||
| @RequestMapping("/demo/encrypt") | ||||
| public class TestEncryptController { | ||||
|  | ||||
|     @Autowired | ||||
|     private TestDemoEncryptMapper mapper; | ||||
|     @Value("${mybatis-encryptor.enable}") | ||||
|     private Boolean encryptEnable; | ||||
|  | ||||
|     /** | ||||
|      * 测试数据库加解密 | ||||
|      * | ||||
|      * @param key   测试key | ||||
|      * @param value 测试value | ||||
|      */ | ||||
|     @GetMapping() | ||||
|     public R<Map<String, TestDemoEncrypt>> test(String key, String value) { | ||||
|         if (!encryptEnable) { | ||||
|             throw new RuntimeException("加密功能未开启!"); | ||||
|         } | ||||
|         Map<String, TestDemoEncrypt> map = new HashMap<>(2); | ||||
|         TestDemoEncrypt demo = new TestDemoEncrypt(); | ||||
|         demo.setTestKey(key); | ||||
|         demo.setValue(value); | ||||
|         mapper.insert(demo); | ||||
|         map.put("加密", demo); | ||||
|         TestDemoEncrypt testDemo = mapper.selectById(demo.getId()); | ||||
|         map.put("解密", testDemo); | ||||
|         return R.ok(map); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,160 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import cn.hutool.core.collection.CollUtil; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Data; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.dromara.common.excel.core.ExcelResult; | ||||
| import org.dromara.common.excel.utils.ExcelUtil; | ||||
| import org.dromara.demo.domain.vo.ExportDemoVo; | ||||
| import org.dromara.demo.listener.ExportDemoListener; | ||||
| import org.dromara.demo.service.IExportExcelService; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.HashMap; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * 测试Excel功能 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  */ | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/excel") | ||||
| public class TestExcelController { | ||||
|  | ||||
|     private final IExportExcelService exportExcelService; | ||||
|  | ||||
|     /** | ||||
|      * 单列表多数据 | ||||
|      */ | ||||
|     @GetMapping("/exportTemplateOne") | ||||
|     public void exportTemplateOne(HttpServletResponse response) { | ||||
|         Map<String, String> map = new HashMap<>(); | ||||
|         map.put("title", "单列表多数据"); | ||||
|         map.put("test1", "数据测试1"); | ||||
|         map.put("test2", "数据测试2"); | ||||
|         map.put("test3", "数据测试3"); | ||||
|         map.put("test4", "数据测试4"); | ||||
|         map.put("testTest", "666"); | ||||
|         List<TestObj> list = new ArrayList<>(); | ||||
|         list.add(new TestObj("单列表测试1", "列表测试1", "列表测试2", "列表测试3", "列表测试4")); | ||||
|         list.add(new TestObj("单列表测试2", "列表测试5", "列表测试6", "列表测试7", "列表测试8")); | ||||
|         list.add(new TestObj("单列表测试3", "列表测试9", "列表测试10", "列表测试11", "列表测试12")); | ||||
|         ExcelUtil.exportTemplate(CollUtil.newArrayList(map, list), "单列表.xlsx", "excel/单列表.xlsx", response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 多列表多数据 | ||||
|      */ | ||||
|     @GetMapping("/exportTemplateMuliti") | ||||
|     public void exportTemplateMuliti(HttpServletResponse response) { | ||||
|         Map<String, String> map = new HashMap<>(); | ||||
|         map.put("title1", "标题1"); | ||||
|         map.put("title2", "标题2"); | ||||
|         map.put("title3", "标题3"); | ||||
|         map.put("title4", "标题4"); | ||||
|         map.put("author", "Lion Li"); | ||||
|         List<TestObj1> list1 = new ArrayList<>(); | ||||
|         list1.add(new TestObj1("list1测试1", "list1测试2", "list1测试3")); | ||||
|         list1.add(new TestObj1("list1测试4", "list1测试5", "list1测试6")); | ||||
|         list1.add(new TestObj1("list1测试7", "list1测试8", "list1测试9")); | ||||
|         List<TestObj1> list2 = new ArrayList<>(); | ||||
|         list2.add(new TestObj1("list2测试1", "list2测试2", "list2测试3")); | ||||
|         list2.add(new TestObj1("list2测试4", "list2测试5", "list2测试6")); | ||||
|         List<TestObj1> list3 = new ArrayList<>(); | ||||
|         list3.add(new TestObj1("list3测试1", "list3测试2", "list3测试3")); | ||||
|         List<TestObj1> list4 = new ArrayList<>(); | ||||
|         list4.add(new TestObj1("list4测试1", "list4测试2", "list4测试3")); | ||||
|         list4.add(new TestObj1("list4测试4", "list4测试5", "list4测试6")); | ||||
|         list4.add(new TestObj1("list4测试7", "list4测试8", "list4测试9")); | ||||
|         list4.add(new TestObj1("list4测试10", "list4测试11", "list4测试12")); | ||||
|         Map<String, Object> multiListMap = new HashMap<>(); | ||||
|         multiListMap.put("map", map); | ||||
|         multiListMap.put("data1", list1); | ||||
|         multiListMap.put("data2", list2); | ||||
|         multiListMap.put("data3", list3); | ||||
|         multiListMap.put("data4", list4); | ||||
|         ExcelUtil.exportTemplateMultiList(multiListMap, "多列表.xlsx", "excel/多列表.xlsx", response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 导出下拉框 | ||||
|      * | ||||
|      * @param response / | ||||
|      */ | ||||
|     @GetMapping("/exportWithOptions") | ||||
|     public void exportWithOptions(HttpServletResponse response) { | ||||
|         exportExcelService.exportWithOptions(response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 多个sheet导出 | ||||
|      */ | ||||
|     @GetMapping("/exportTemplateMultiSheet") | ||||
|     public void exportTemplateMultiSheet(HttpServletResponse response) { | ||||
|         List<TestObj1> list1 = new ArrayList<>(); | ||||
|         list1.add(new TestObj1("list1测试1", "list1测试2", "list1测试3")); | ||||
|         list1.add(new TestObj1("list1测试4", "list1测试5", "list1测试6")); | ||||
|         List<TestObj1> list2 = new ArrayList<>(); | ||||
|         list2.add(new TestObj1("list2测试1", "list2测试2", "list2测试3")); | ||||
|         list2.add(new TestObj1("list2测试4", "list2测试5", "list2测试6")); | ||||
|         List<TestObj1> list3 = new ArrayList<>(); | ||||
|         list3.add(new TestObj1("list3测试1", "list3测试2", "list3测试3")); | ||||
|         list3.add(new TestObj1("list3测试4", "list3测试5", "list3测试6")); | ||||
|         List<TestObj1> list4 = new ArrayList<>(); | ||||
|         list4.add(new TestObj1("list4测试1", "list4测试2", "list4测试3")); | ||||
|         list4.add(new TestObj1("list4测试4", "list4测试5", "list4测试6")); | ||||
|  | ||||
|         List<Map<String, Object>> list = new ArrayList<>(); | ||||
|         Map<String, Object> sheetMap1 = new HashMap<>(); | ||||
|         sheetMap1.put("data1", list1); | ||||
|         Map<String, Object> sheetMap2 = new HashMap<>(); | ||||
|         sheetMap2.put("data2", list2); | ||||
|         Map<String, Object> sheetMap3 = new HashMap<>(); | ||||
|         sheetMap3.put("data3", list3); | ||||
|         Map<String, Object> sheetMap4 = new HashMap<>(); | ||||
|         sheetMap4.put("data4", list4); | ||||
|  | ||||
|         list.add(sheetMap1); | ||||
|         list.add(sheetMap2); | ||||
|         list.add(sheetMap3); | ||||
|         list.add(sheetMap4); | ||||
|         ExcelUtil.exportTemplateMultiSheet(list, "多sheet列表", "excel/多sheet列表.xlsx", response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 导入表格 | ||||
|      */ | ||||
|     @PostMapping(value = "/importWithOptions", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) | ||||
|     public List<ExportDemoVo> importWithOptions(@RequestPart("file") MultipartFile file) throws Exception { | ||||
|         // 处理解析结果 | ||||
|         ExcelResult<ExportDemoVo> excelResult = ExcelUtil.importExcel(file.getInputStream(), ExportDemoVo.class, new ExportDemoListener()); | ||||
|         return excelResult.getList(); | ||||
|     } | ||||
|  | ||||
|     @Data | ||||
|     @AllArgsConstructor | ||||
|     static class TestObj1 { | ||||
|         private String test1; | ||||
|         private String test2; | ||||
|         private String test3; | ||||
|     } | ||||
|  | ||||
|     @Data | ||||
|     @AllArgsConstructor | ||||
|     static class TestObj { | ||||
|         private String name; | ||||
|         private String list1; | ||||
|         private String list2; | ||||
|         private String list3; | ||||
|         private String list4; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,71 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.core.utils.MessageUtils; | ||||
| import lombok.Data; | ||||
| import org.hibernate.validator.constraints.Range; | ||||
| 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 jakarta.validation.constraints.NotBlank; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 测试国际化 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  */ | ||||
| @Validated | ||||
| @RestController | ||||
| @RequestMapping("/demo/i18n") | ||||
| public class TestI18nController { | ||||
|  | ||||
|     /** | ||||
|      * 通过code获取国际化内容 | ||||
|      * code为 messages.properties 中的 key | ||||
|      * <p> | ||||
|      * 测试使用 user.register.success | ||||
|      * | ||||
|      * @param code 国际化code | ||||
|      */ | ||||
|     @GetMapping() | ||||
|     public R<Void> get(String code) { | ||||
|         return R.ok(MessageUtils.message(code)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Validator 校验国际化 | ||||
|      * 不传值 分别查看异常返回 | ||||
|      * <p> | ||||
|      * 测试使用 not.null | ||||
|      */ | ||||
|     @GetMapping("/test1") | ||||
|     public R<Void> test1(@NotBlank(message = "{not.null}") String str) { | ||||
|         return R.ok(str); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Bean 校验国际化 | ||||
|      * 不传值 分别查看异常返回 | ||||
|      * <p> | ||||
|      * 测试使用 not.null | ||||
|      */ | ||||
|     @GetMapping("/test2") | ||||
|     public R<TestI18nBo> test2(@Validated TestI18nBo bo) { | ||||
|         return R.ok(bo); | ||||
|     } | ||||
|  | ||||
|     @Data | ||||
|     public static class TestI18nBo { | ||||
|  | ||||
|         @NotBlank(message = "{not.null}") | ||||
|         private String name; | ||||
|  | ||||
|         @NotNull(message = "{not.null}") | ||||
|         @Range(min = 0, max = 100, message = "{length.not.valid}") | ||||
|         private Integer age; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,76 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.web.core.BaseController; | ||||
| import org.dromara.common.sensitive.annotation.Sensitive; | ||||
| import org.dromara.common.sensitive.core.SensitiveStrategy; | ||||
| import lombok.Data; | ||||
| import org.dromara.common.sensitive.core.SensitiveService; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
|  | ||||
| /** | ||||
|  * 测试数据脱敏控制器 | ||||
|  * <p> | ||||
|  * 默认管理员不过滤 | ||||
|  * 需自行根据业务重写实现 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @version 3.6.0 | ||||
|  * @see SensitiveService | ||||
|  */ | ||||
| @RestController | ||||
| @RequestMapping("/demo/sensitive") | ||||
| public class TestSensitiveController extends BaseController { | ||||
|  | ||||
|     /** | ||||
|      * 测试数据脱敏 | ||||
|      */ | ||||
|     @GetMapping("/test") | ||||
|     public R<TestSensitive> test() { | ||||
|         TestSensitive testSensitive = new TestSensitive(); | ||||
|         testSensitive.setIdCard("210397198608215431"); | ||||
|         testSensitive.setPhone("17640125371"); | ||||
|         testSensitive.setAddress("北京市朝阳区某某四合院1203室"); | ||||
|         testSensitive.setEmail("17640125371@163.com"); | ||||
|         testSensitive.setBankCard("6226456952351452853"); | ||||
|         return R.ok(testSensitive); | ||||
|     } | ||||
|  | ||||
|     @Data | ||||
|     static class TestSensitive { | ||||
|  | ||||
|         /** | ||||
|          * 身份证 | ||||
|          */ | ||||
|         @Sensitive(strategy = SensitiveStrategy.ID_CARD) | ||||
|         private String idCard; | ||||
|  | ||||
|         /** | ||||
|          * 电话 | ||||
|          */ | ||||
|         @Sensitive(strategy = SensitiveStrategy.PHONE, roleKey = "common") | ||||
|         private String phone; | ||||
|  | ||||
|         /** | ||||
|          * 地址 | ||||
|          */ | ||||
|         @Sensitive(strategy = SensitiveStrategy.ADDRESS, perms = "system:user:query") | ||||
|         private String address; | ||||
|  | ||||
|         /** | ||||
|          * 邮箱 | ||||
|          */ | ||||
|         @Sensitive(strategy = SensitiveStrategy.EMAIL, roleKey = "common", perms = "system:user:query1") | ||||
|         private String email; | ||||
|  | ||||
|         /** | ||||
|          * 银行卡 | ||||
|          */ | ||||
|         @Sensitive(strategy = SensitiveStrategy.BANK_CARD, roleKey = "common1", perms = "system:user:query") | ||||
|         private String bankCard; | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,107 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaCheckPermission; | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.core.validate.AddGroup; | ||||
| import org.dromara.common.core.validate.EditGroup; | ||||
| import org.dromara.common.core.validate.QueryGroup; | ||||
| import org.dromara.common.web.core.BaseController; | ||||
| import org.dromara.common.excel.utils.ExcelUtil; | ||||
| import org.dromara.common.idempotent.annotation.RepeatSubmit; | ||||
| import org.dromara.common.log.annotation.Log; | ||||
| import org.dromara.common.log.enums.BusinessType; | ||||
| import org.dromara.demo.domain.bo.TestTreeBo; | ||||
| import org.dromara.demo.domain.vo.TestTreeVo; | ||||
| import org.dromara.demo.service.ITestTreeService; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
|  | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import jakarta.validation.constraints.NotEmpty; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import java.util.Arrays; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 测试树表Controller | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @Validated | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/tree") | ||||
| public class TestTreeController extends BaseController { | ||||
|  | ||||
|     private final ITestTreeService testTreeService; | ||||
|  | ||||
|     /** | ||||
|      * 查询测试树表列表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:tree:list") | ||||
|     @GetMapping("/list") | ||||
|     public R<List<TestTreeVo>> list(@Validated(QueryGroup.class) TestTreeBo bo) { | ||||
|         List<TestTreeVo> list = testTreeService.queryList(bo); | ||||
|         return R.ok(list); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 导出测试树表列表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:tree:export") | ||||
|     @Log(title = "测试树表", businessType = BusinessType.EXPORT) | ||||
|     @GetMapping("/export") | ||||
|     public void export(@Validated TestTreeBo bo, HttpServletResponse response) { | ||||
|         List<TestTreeVo> list = testTreeService.queryList(bo); | ||||
|         ExcelUtil.exportExcel(list, "测试树表", TestTreeVo.class, response); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取测试树表详细信息 | ||||
|      * | ||||
|      * @param id 测试树ID | ||||
|      */ | ||||
|     @SaCheckPermission("demo:tree:query") | ||||
|     @GetMapping("/{id}") | ||||
|     public R<TestTreeVo> getInfo(@NotNull(message = "主键不能为空") | ||||
|                                  @PathVariable("id") Long id) { | ||||
|         return R.ok(testTreeService.queryById(id)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 新增测试树表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:tree:add") | ||||
|     @Log(title = "测试树表", businessType = BusinessType.INSERT) | ||||
|     @RepeatSubmit | ||||
|     @PostMapping() | ||||
|     public R<Void> add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) { | ||||
|         return toAjax(testTreeService.insertByBo(bo)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 修改测试树表 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:tree:edit") | ||||
|     @Log(title = "测试树表", businessType = BusinessType.UPDATE) | ||||
|     @RepeatSubmit | ||||
|     @PutMapping() | ||||
|     public R<Void> edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) { | ||||
|         return toAjax(testTreeService.updateByBo(bo)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除测试树表 | ||||
|      * | ||||
|      * @param ids 测试树ID串 | ||||
|      */ | ||||
|     @SaCheckPermission("demo:tree:remove") | ||||
|     @Log(title = "测试树表", businessType = BusinessType.DELETE) | ||||
|     @DeleteMapping("/{ids}") | ||||
|     public R<Void> remove(@NotEmpty(message = "主键不能为空") | ||||
|                           @PathVariable Long[] ids) { | ||||
|         return toAjax(testTreeService.deleteWithValidByIds(Arrays.asList(ids), true)); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,33 @@ | ||||
| package org.dromara.demo.controller; | ||||
|  | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.websocket.dto.WebSocketMessageDto; | ||||
| import org.dromara.common.websocket.utils.WebSocketUtils; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| 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; | ||||
|  | ||||
| /** | ||||
|  * WebSocket 演示案例 | ||||
|  * | ||||
|  * @author zendwang | ||||
|  */ | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/websocket") | ||||
| @Slf4j | ||||
| public class WeSocketController { | ||||
|  | ||||
|     /** | ||||
|      * 发布消息 | ||||
|      * | ||||
|      * @param dto 发送内容 | ||||
|      */ | ||||
|     @GetMapping("/send") | ||||
|     public R<Void> send(WebSocketMessageDto dto) throws InterruptedException { | ||||
|         WebSocketUtils.publishMessage(dto); | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| package org.dromara.demo.controller; | ||||
| @ -0,0 +1,92 @@ | ||||
| package org.dromara.demo.controller.queue; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaIgnore; | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.redis.utils.QueueUtils; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.redisson.api.RBoundedBlockingQueue; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
|  | ||||
| /** | ||||
|  * 有界队列 演示案例 | ||||
|  * <p> | ||||
|  * 轻量级队列 重量级数据量 请使用 MQ | ||||
|  * <p> | ||||
|  * 集群测试通过 同一个数据只会被消费一次 做好事务补偿 | ||||
|  * 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @version 3.6.0 | ||||
|  */ | ||||
| @Slf4j | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/queue/bounded") | ||||
| public class BoundedQueueController { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 添加队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      * @param capacity  容量 | ||||
|      */ | ||||
|     @GetMapping("/add") | ||||
|     public R<Void> add(String queueName, int capacity) { | ||||
|         // 用完了一定要销毁 否则会一直存在 | ||||
|         boolean b = QueueUtils.destroyBoundedQueue(queueName); | ||||
|         log.info("通道: {} , 删除: {}", queueName, b); | ||||
|         // 初始化设置一次即可 | ||||
|         if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) { | ||||
|             log.info("通道: {} , 设置容量: {}", queueName, capacity); | ||||
|         } else { | ||||
|             log.info("通道: {} , 设置容量失败", queueName); | ||||
|             return R.fail("操作失败"); | ||||
|         } | ||||
|         for (int i = 0; i < 11; i++) { | ||||
|             String data = "data-" + i; | ||||
|             boolean flag = QueueUtils.addBoundedQueueObject(queueName, data); | ||||
|             if (flag == false) { | ||||
|                 log.info("通道: {} , 发送数据: {} 失败, 通道已满", queueName, data); | ||||
|             } else { | ||||
|                 log.info("通道: {} , 发送数据: {}", queueName, data); | ||||
|             } | ||||
|         } | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      */ | ||||
|     @GetMapping("/remove") | ||||
|     public R<Void> remove(String queueName) { | ||||
|         String data = "data-" + 5; | ||||
|         if (QueueUtils.removeBoundedQueueObject(queueName, data)) { | ||||
|             log.info("通道: {} , 删除数据: {}", queueName, data); | ||||
|         } else { | ||||
|             return R.fail("操作失败"); | ||||
|         } | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      */ | ||||
|     @GetMapping("/get") | ||||
|     public R<Void> get(String queueName) { | ||||
|         String data; | ||||
|         do { | ||||
|             data = QueueUtils.getBoundedQueueObject(queueName); | ||||
|             log.info("通道: {} , 获取数据: {}", queueName, data); | ||||
|         } while (data != null); | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,97 @@ | ||||
| package org.dromara.demo.controller.queue; | ||||
|  | ||||
| import cn.dev33.satoken.annotation.SaIgnore; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.redis.utils.QueueUtils; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
|  | ||||
| import java.util.concurrent.CompletableFuture; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| /** | ||||
|  * 延迟队列 演示案例 | ||||
|  * <p> | ||||
|  * 轻量级队列 重量级数据量 请使用 MQ | ||||
|  * 例如: 创建订单30分钟后过期处理 | ||||
|  * <p> | ||||
|  * 集群测试通过 同一个数据只会被消费一次 做好事务补偿 | ||||
|  * 集群测试流程 两台集群分别开启订阅 在其中一台发送数据 观察接收消息的规律 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @version 3.6.0 | ||||
|  */ | ||||
| @SaIgnore | ||||
| @Slf4j | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/queue/delayed") | ||||
| public class DelayedQueueController { | ||||
|  | ||||
|     /** | ||||
|      * 订阅队列 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      */ | ||||
|     @GetMapping("/subscribe") | ||||
|     public R<Void> subscribe(String queueName) { | ||||
|         log.info("通道: {} 监听中......", queueName); | ||||
|         // 项目初始化设置一次即可 | ||||
|         QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> { | ||||
|             // 观察接收时间 | ||||
|             log.info("通道: {}, 收到数据: {}", queueName, orderNum); | ||||
|             return CompletableFuture.runAsync(() -> { | ||||
|                 // 异步处理数据逻辑 不要在上方处理业务逻辑 | ||||
|                 log.info("数据处理: {}", orderNum); | ||||
|             }); | ||||
|         }, true); | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 添加队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      * @param orderNum  订单号 | ||||
|      * @param time      延迟时间(秒) | ||||
|      */ | ||||
|     @GetMapping("/add") | ||||
|     public R<Void> add(String queueName, String orderNum, Long time) { | ||||
|         QueueUtils.addDelayedQueueObject(queueName, orderNum, time, TimeUnit.SECONDS); | ||||
|         // 观察发送时间 | ||||
|         log.info("通道: {} , 发送数据: {}", queueName, orderNum); | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      * @param orderNum  订单号 | ||||
|      */ | ||||
|     @GetMapping("/remove") | ||||
|     public R<Void> remove(String queueName, String orderNum) { | ||||
|         if (QueueUtils.removeDelayedQueueObject(queueName, orderNum)) { | ||||
|             log.info("通道: {} , 删除数据: {}", queueName, orderNum); | ||||
|         } else { | ||||
|             return R.fail("操作失败"); | ||||
|         } | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 销毁队列 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      */ | ||||
|     @GetMapping("/destroy") | ||||
|     public R<Void> destroy(String queueName) { | ||||
|         // 用完了一定要销毁 否则会一直存在 | ||||
|         QueueUtils.destroyDelayedQueue(queueName); | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,22 @@ | ||||
| package org.dromara.demo.controller.queue; | ||||
|  | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
|  | ||||
| /** | ||||
|  * 实体类 注意不允许使用内部类 否则会找不到类 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @version 3.6.0 | ||||
|  */ | ||||
| @Data | ||||
| @NoArgsConstructor | ||||
| public class PriorityDemo implements Comparable<PriorityDemo> { | ||||
|     private String name; | ||||
|     private Integer orderNum; | ||||
|  | ||||
|     @Override | ||||
|     public int compareTo(PriorityDemo other) { | ||||
|         return Integer.compare(getOrderNum(), other.getOrderNum()); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,89 @@ | ||||
| package org.dromara.demo.controller.queue; | ||||
|  | ||||
| import cn.hutool.core.util.RandomUtil; | ||||
| import org.dromara.common.core.domain.R; | ||||
| import org.dromara.common.redis.utils.QueueUtils; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| 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; | ||||
|  | ||||
| /** | ||||
|  * 优先队列 演示案例 | ||||
|  * <p> | ||||
|  * 轻量级队列 重量级数据量 请使用 MQ | ||||
|  * <p> | ||||
|  * 集群测试通过 同一个消息只会被消费一次 做好事务补偿 | ||||
|  * 集群测试流程 在其中一台发送数据 两端分别调用获取接口 一次获取一条 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @version 3.6.0 | ||||
|  */ | ||||
| @Slf4j | ||||
| @RequiredArgsConstructor | ||||
| @RestController | ||||
| @RequestMapping("/demo/queue/priority") | ||||
| public class PriorityQueueController { | ||||
|  | ||||
|     /** | ||||
|      * 添加队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      */ | ||||
|     @GetMapping("/add") | ||||
|     public R<Void> add(String queueName) { | ||||
|         // 用完了一定要销毁 否则会一直存在 | ||||
|         boolean b = QueueUtils.destroyPriorityQueue(queueName); | ||||
|         log.info("通道: {} , 删除: {}", queueName, b); | ||||
|  | ||||
|         for (int i = 0; i < 10; i++) { | ||||
|             int randomNum = RandomUtil.randomInt(10); | ||||
|             PriorityDemo data = new PriorityDemo(); | ||||
|             data.setName("data-" + i); | ||||
|             data.setOrderNum(randomNum); | ||||
|             if (QueueUtils.addPriorityQueueObject(queueName, data)) { | ||||
|                 log.info("通道: {} , 发送数据: {}", queueName, data); | ||||
|             } else { | ||||
|                 log.info("通道: {} , 发送数据: {}, 发送失败", queueName, data); | ||||
|             } | ||||
|         } | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 删除队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      * @param name      对象名 | ||||
|      * @param orderNum  排序号 | ||||
|      */ | ||||
|     @GetMapping("/remove") | ||||
|     public R<Void> remove(String queueName, String name, Integer orderNum) { | ||||
|         PriorityDemo data = new PriorityDemo(); | ||||
|         data.setName(name); | ||||
|         data.setOrderNum(orderNum); | ||||
|         if (QueueUtils.removePriorityQueueObject(queueName, data)) { | ||||
|             log.info("通道: {} , 删除数据: {}", queueName, data); | ||||
|         } else { | ||||
|             return R.fail("操作失败"); | ||||
|         } | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 获取队列数据 | ||||
|      * | ||||
|      * @param queueName 队列名 | ||||
|      */ | ||||
|     @GetMapping("/get") | ||||
|     public R<Void> get(String queueName) { | ||||
|         PriorityDemo data; | ||||
|         do { | ||||
|             data = QueueUtils.getPriorityQueueObject(queueName); | ||||
|             log.info("通道: {} , 获取数据: {}", queueName, data); | ||||
|         } while (data != null); | ||||
|         return R.ok("操作成功"); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,68 @@ | ||||
| package org.dromara.demo.domain; | ||||
|  | ||||
| import com.baomidou.mybatisplus.annotation.*; | ||||
| import org.dromara.common.tenant.core.TenantEntity; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
|  | ||||
| import java.io.Serial; | ||||
|  | ||||
| /** | ||||
|  * 测试单表对象 test_demo | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @TableName("test_demo") | ||||
| public class TestDemo extends TenantEntity { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 主键 | ||||
|      */ | ||||
|     @TableId(value = "id") | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 部门id | ||||
|      */ | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户id | ||||
|      */ | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 排序号 | ||||
|      */ | ||||
|     @OrderBy(asc = false, sort = 1) | ||||
|     private Integer orderNum; | ||||
|  | ||||
|     /** | ||||
|      * key键 | ||||
|      */ | ||||
|     private String testKey; | ||||
|  | ||||
|     /** | ||||
|      * 值 | ||||
|      */ | ||||
|     private String value; | ||||
|  | ||||
|     /** | ||||
|      * 版本 | ||||
|      */ | ||||
|     @Version | ||||
|     private Long version; | ||||
|  | ||||
|     /** | ||||
|      * 删除标志 | ||||
|      */ | ||||
|     @TableLogic | ||||
|     private Long delFlag; | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,29 @@ | ||||
| package org.dromara.demo.domain; | ||||
|  | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import org.dromara.common.encrypt.annotation.EncryptField; | ||||
| import org.dromara.common.encrypt.enumd.AlgorithmType; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
|  | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @TableName("test_demo") | ||||
| public class TestDemoEncrypt extends TestDemo { | ||||
|  | ||||
|     /** | ||||
|      * key键 | ||||
|      */ | ||||
|     // @EncryptField(algorithm=AlgorithmType.SM2, privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgZSlOvw8FBiH+aFJWLYZP/VRjg9wjfRarTkGBZd/T3N+gCgYIKoEcz1UBgi2hRANCAAR5DGuQwJqkxnbCsP+iPSDoHWIF4RwcR5EsSvT8QPxO1wRkR2IhCkzvRb32x2CUgJFdvoqVqfApFDPZzShqzBwX", publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEeQxrkMCapMZ2wrD/oj0g6B1iBeEcHEeRLEr0/ED8TtcEZEdiIQpM70W99sdglICRXb6KlanwKRQz2c0oaswcFw==") | ||||
|     @EncryptField(algorithm = AlgorithmType.RSA, privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANBBEeueWlXlkkj2+WY5l+IWe42d8b5K28g+G/CFKC/yYAEHtqGlCsBOrb+YBkG9mPzmuYA/n9k0NFIc8E8yY5vZQaroyFBrTTWEzG9RY2f7Y3svVyybs6jpXSUs4xff8abo7wL1Y/wUaeatTViamxYnyTvdTmLm3d+JjRij68rxAgMBAAECgYAB0TnhXraSopwIVRfmboea1b0upl+BUdTJcmci412UjrKr5aE695ZLPkXbFXijVu7HJlyyv94NVUdaMACV7Ku/S2RuNB70M7YJm8rAjHFC3/i2ZeIM60h1Ziy4QKv0XM3pRATlDCDNhC1WUrtQCQSgU8kcp6eUUppruOqDzcY04QJBAPm9+sBP9CwDRgy3e5+V8aZtJkwDstb0lVVV/KY890cydVxiCwvX3fqVnxKMlb+x0YtH0sb9v+71xvK2lGobaRECQQDVePU6r/cCEfpc+nkWF6osAH1f8Mux3rYv2DoBGvaPzV2BGfsLed4neRfCwWNCKvGPCdW+L0xMJg8+RwaoBUPhAkAT5kViqXxFPYWJYd1h2+rDXhMdH3ZSlm6HvDBDdrwlWinr0Iwcx3iSjPV93uHXwm118aUj4fg3LDJMCKxOwBxhAkByrQXfvwOMYygBprRBf/j0plazoWFrbd6lGR0f1uI5IfNnFRPdeFw1DEINZ2Hw+6zEUF44SqRMC+4IYJNc02dBAkBCgy7RvfyV/A7N6kKXxTHauY0v6XwSSvpeKtRJkbIcRWOdIYvaHO9L7cklj3vIEdwjSUp9K4VTBYYlmAz1xh03", publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQQRHrnlpV5ZJI9vlmOZfiFnuNnfG+StvIPhvwhSgv8mABB7ahpQrATq2/mAZBvZj85rmAP5/ZNDRSHPBPMmOb2UGq6MhQa001hMxvUWNn+2N7L1csm7Oo6V0lLOMX3/Gm6O8C9WP8FGnmrU1YmpsWJ8k73U5i5t3fiY0Yo+vK8QIDAQAB") | ||||
|     private String testKey; | ||||
|  | ||||
|     /** | ||||
|      * 值 | ||||
|      */ | ||||
|     // @EncryptField // 什么也不写走默认yml配置 | ||||
|     // @EncryptField(algorithm = AlgorithmType.SM4, password = "10rfylhtccpuyke5") | ||||
|     @EncryptField(algorithm = AlgorithmType.AES, password = "10rfylhtccpuyke5") | ||||
|     private String value; | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,65 @@ | ||||
| package org.dromara.demo.domain; | ||||
|  | ||||
| import com.baomidou.mybatisplus.annotation.TableId; | ||||
| import com.baomidou.mybatisplus.annotation.TableLogic; | ||||
| import com.baomidou.mybatisplus.annotation.TableName; | ||||
| import com.baomidou.mybatisplus.annotation.Version; | ||||
| import org.dromara.common.tenant.core.TenantEntity; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
|  | ||||
| import java.io.Serial; | ||||
|  | ||||
| /** | ||||
|  * 测试树表对象 test_tree | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @TableName("test_tree") | ||||
| public class TestTree extends TenantEntity { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 主键 | ||||
|      */ | ||||
|     @TableId(value = "id") | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 父ID | ||||
|      */ | ||||
|     private Long parentId; | ||||
|  | ||||
|     /** | ||||
|      * 部门id | ||||
|      */ | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户id | ||||
|      */ | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 树节点名 | ||||
|      */ | ||||
|     private String treeName; | ||||
|  | ||||
|     /** | ||||
|      * 版本 | ||||
|      */ | ||||
|     @Version | ||||
|     private Long version; | ||||
|  | ||||
|     /** | ||||
|      * 删除标志 | ||||
|      */ | ||||
|     @TableLogic | ||||
|     private Long delFlag; | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,62 @@ | ||||
| package org.dromara.demo.domain.bo; | ||||
|  | ||||
| import org.dromara.common.core.validate.AddGroup; | ||||
| import org.dromara.common.core.validate.EditGroup; | ||||
| import org.dromara.common.mybatis.core.domain.BaseEntity; | ||||
| import org.dromara.demo.domain.TestDemo; | ||||
| import io.github.linpeilie.annotations.AutoMapper; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
|  | ||||
| import jakarta.validation.constraints.NotBlank; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
|  | ||||
| /** | ||||
|  * 测试单表业务对象 test_demo | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
|  | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @AutoMapper(target = TestDemo.class, reverseConvertGenerate = false) | ||||
| public class TestDemoBo extends BaseEntity { | ||||
|  | ||||
|     /** | ||||
|      * 主键 | ||||
|      */ | ||||
|     @NotNull(message = "主键不能为空", groups = {EditGroup.class}) | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 部门id | ||||
|      */ | ||||
|     @NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户id | ||||
|      */ | ||||
|     @NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 排序号 | ||||
|      */ | ||||
|     @NotNull(message = "排序号不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private Integer orderNum; | ||||
|  | ||||
|     /** | ||||
|      * key键 | ||||
|      */ | ||||
|     @NotBlank(message = "key键不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private String testKey; | ||||
|  | ||||
|     /** | ||||
|      * 值 | ||||
|      */ | ||||
|     @NotBlank(message = "值不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private String value; | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,53 @@ | ||||
| package org.dromara.demo.domain.bo; | ||||
|  | ||||
| import com.alibaba.excel.annotation.ExcelProperty; | ||||
| import lombok.Data; | ||||
|  | ||||
| import jakarta.validation.constraints.NotBlank; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
|  | ||||
| /** | ||||
|  * 测试单表业务对象 test_demo | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @Data | ||||
| public class TestDemoImportVo { | ||||
|  | ||||
|     /** | ||||
|      * 部门id | ||||
|      */ | ||||
|     @NotNull(message = "部门id不能为空") | ||||
|     @ExcelProperty(value = "部门id") | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户id | ||||
|      */ | ||||
|     @NotNull(message = "用户id不能为空") | ||||
|     @ExcelProperty(value = "用户id") | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 排序号 | ||||
|      */ | ||||
|     @NotNull(message = "排序号不能为空") | ||||
|     @ExcelProperty(value = "排序号") | ||||
|     private Long orderNum; | ||||
|  | ||||
|     /** | ||||
|      * key键 | ||||
|      */ | ||||
|     @NotBlank(message = "key键不能为空") | ||||
|     @ExcelProperty(value = "key键") | ||||
|     private String testKey; | ||||
|  | ||||
|     /** | ||||
|      * 值 | ||||
|      */ | ||||
|     @NotBlank(message = "值不能为空") | ||||
|     @ExcelProperty(value = "值") | ||||
|     private String value; | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,54 @@ | ||||
| package org.dromara.demo.domain.bo; | ||||
|  | ||||
| import org.dromara.common.core.validate.AddGroup; | ||||
| import org.dromara.common.core.validate.EditGroup; | ||||
| import org.dromara.common.mybatis.core.domain.BaseEntity; | ||||
| import org.dromara.demo.domain.TestTree; | ||||
| import io.github.linpeilie.annotations.AutoMapper; | ||||
| import jakarta.validation.constraints.NotBlank; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
|  | ||||
| /** | ||||
|  * 测试树表业务对象 test_tree | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
|  | ||||
| @Data | ||||
| @EqualsAndHashCode(callSuper = true) | ||||
| @AutoMapper(target = TestTree.class, reverseConvertGenerate = false) | ||||
| public class TestTreeBo extends BaseEntity { | ||||
|  | ||||
|     /** | ||||
|      * 主键 | ||||
|      */ | ||||
|     @NotNull(message = "主键不能为空", groups = {EditGroup.class}) | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 父ID | ||||
|      */ | ||||
|     private Long parentId; | ||||
|  | ||||
|     /** | ||||
|      * 部门id | ||||
|      */ | ||||
|     @NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户id | ||||
|      */ | ||||
|     @NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 树节点名 | ||||
|      */ | ||||
|     @NotBlank(message = "树节点名不能为空", groups = {AddGroup.class, EditGroup.class}) | ||||
|     private String treeName; | ||||
|  | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| package org.dromara.demo.domain; | ||||
| @ -0,0 +1,122 @@ | ||||
| package org.dromara.demo.domain.vo; | ||||
|  | ||||
| import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | ||||
| import com.alibaba.excel.annotation.ExcelProperty; | ||||
| import jakarta.validation.constraints.NotEmpty; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import lombok.AllArgsConstructor; | ||||
| import lombok.Data; | ||||
| import lombok.NoArgsConstructor; | ||||
| import org.dromara.common.core.enums.UserStatus; | ||||
| import org.dromara.common.core.validate.AddGroup; | ||||
| import org.dromara.common.core.validate.EditGroup; | ||||
| import org.dromara.common.excel.annotation.ExcelDictFormat; | ||||
| import org.dromara.common.excel.annotation.ExcelEnumFormat; | ||||
| import org.dromara.common.excel.convert.ExcelDictConvert; | ||||
| import org.dromara.common.excel.convert.ExcelEnumConvert; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.io.Serializable; | ||||
|  | ||||
| /** | ||||
|  * 带有下拉选的Excel导出 | ||||
|  * | ||||
|  * @author Emil.Zhang | ||||
|  */ | ||||
| @Data | ||||
| @ExcelIgnoreUnannotated | ||||
| @AllArgsConstructor | ||||
| @NoArgsConstructor | ||||
| public class ExportDemoVo implements Serializable { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 用户昵称 | ||||
|      */ | ||||
|     @ExcelProperty(value = "用户名", index = 0) | ||||
|     @NotEmpty(message = "用户名不能为空", groups = AddGroup.class) | ||||
|     private String nickName; | ||||
|  | ||||
|     /** | ||||
|      * 用户类型 | ||||
|      * </p> | ||||
|      * 使用ExcelEnumFormat注解需要进行下拉选的部分 | ||||
|      */ | ||||
|     @ExcelProperty(value = "用户类型", index = 1, converter = ExcelEnumConvert.class) | ||||
|     @ExcelEnumFormat(enumClass = UserStatus.class, textField = "info") | ||||
|     @NotEmpty(message = "用户类型不能为空", groups = AddGroup.class) | ||||
|     private String userStatus; | ||||
|  | ||||
|     /** | ||||
|      * 性别 | ||||
|      * <p> | ||||
|      * 使用ExcelDictFormat注解需要进行下拉选的部分 | ||||
|      */ | ||||
|     @ExcelProperty(value = "性别", index = 2, converter = ExcelDictConvert.class) | ||||
|     @ExcelDictFormat(dictType = "sys_user_sex") | ||||
|     @NotEmpty(message = "性别不能为空", groups = AddGroup.class) | ||||
|     private String gender; | ||||
|  | ||||
|     /** | ||||
|      * 手机号 | ||||
|      */ | ||||
|     @ExcelProperty(value = "手机号", index = 3) | ||||
|     @NotEmpty(message = "手机号不能为空", groups = AddGroup.class) | ||||
|     private String phoneNumber; | ||||
|  | ||||
|     /** | ||||
|      * Email | ||||
|      */ | ||||
|     @ExcelProperty(value = "Email", index = 4) | ||||
|     @NotEmpty(message = "Email不能为空", groups = AddGroup.class) | ||||
|     private String email; | ||||
|  | ||||
|     /** | ||||
|      * 省 | ||||
|      * <p> | ||||
|      * 级联下拉,仅判断是否选了 | ||||
|      */ | ||||
|     @ExcelProperty(value = "省", index = 5) | ||||
|     @NotNull(message = "省不能为空", groups = AddGroup.class) | ||||
|     private String province; | ||||
|  | ||||
|     /** | ||||
|      * 数据库中的省ID | ||||
|      * </p> | ||||
|      * 处理完毕后再判断是否市正确的值 | ||||
|      */ | ||||
|     @NotNull(message = "请勿手动输入", groups = EditGroup.class) | ||||
|     private Integer provinceId; | ||||
|  | ||||
|     /** | ||||
|      * 市 | ||||
|      * <p> | ||||
|      * 级联下拉 | ||||
|      */ | ||||
|     @ExcelProperty(value = "市", index = 6) | ||||
|     @NotNull(message = "市不能为空", groups = AddGroup.class) | ||||
|     private String city; | ||||
|  | ||||
|     /** | ||||
|      * 数据库中的市ID | ||||
|      */ | ||||
|     @NotNull(message = "请勿手动输入", groups = EditGroup.class) | ||||
|     private Integer cityId; | ||||
|  | ||||
|     /** | ||||
|      * 县 | ||||
|      * <p> | ||||
|      * 级联下拉 | ||||
|      */ | ||||
|     @ExcelProperty(value = "县", index = 7) | ||||
|     @NotNull(message = "县不能为空", groups = AddGroup.class) | ||||
|     private String area; | ||||
|  | ||||
|     /** | ||||
|      * 数据库中的县ID | ||||
|      */ | ||||
|     @NotNull(message = "请勿手动输入", groups = EditGroup.class) | ||||
|     private Integer areaId; | ||||
| } | ||||
| @ -0,0 +1,111 @@ | ||||
| package org.dromara.demo.domain.vo; | ||||
|  | ||||
| import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | ||||
| import com.alibaba.excel.annotation.ExcelProperty; | ||||
| import org.dromara.common.excel.annotation.ExcelNotation; | ||||
| import org.dromara.common.excel.annotation.ExcelRequired; | ||||
| import org.dromara.common.translation.annotation.Translation; | ||||
| import org.dromara.common.translation.constant.TransConstant; | ||||
| import org.dromara.demo.domain.TestDemo; | ||||
| import io.github.linpeilie.annotations.AutoMapper; | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.io.Serializable; | ||||
| import java.util.Date; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 测试单表视图对象 test_demo | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @Data | ||||
| @ExcelIgnoreUnannotated | ||||
| @AutoMapper(target = TestDemo.class) | ||||
| public class TestDemoVo implements Serializable { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 主键 | ||||
|      */ | ||||
|     @ExcelProperty(value = "主键") | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 部门id | ||||
|      */ | ||||
|     @ExcelRequired | ||||
|     @ExcelProperty(value = "部门id") | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户id | ||||
|      */ | ||||
|     @ExcelRequired | ||||
|     @ExcelProperty(value = "用户id") | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 排序号 | ||||
|      */ | ||||
|     @ExcelRequired | ||||
|     @ExcelProperty(value = "排序号") | ||||
|     private Integer orderNum; | ||||
|  | ||||
|     /** | ||||
|      * key键 | ||||
|      */ | ||||
|     @ExcelNotation(value = "测试key") | ||||
|     @ExcelProperty(value = "key键") | ||||
|     private String testKey; | ||||
|  | ||||
|     /** | ||||
|      * 值 | ||||
|      */ | ||||
|     @ExcelNotation(value = "测试value") | ||||
|     @ExcelProperty(value = "值") | ||||
|     private String value; | ||||
|  | ||||
|     /** | ||||
|      * 创建时间 | ||||
|      */ | ||||
|     @ExcelProperty(value = "创建时间") | ||||
|     private Date createTime; | ||||
|  | ||||
|     /** | ||||
|      * 创建人 | ||||
|      */ | ||||
|     @ExcelProperty(value = "创建人") | ||||
|     private Long createBy; | ||||
|  | ||||
|     /** | ||||
|      * 创建人账号 | ||||
|      */ | ||||
|     @Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy") | ||||
|     @ExcelProperty(value = "创建人账号") | ||||
|     private String createByName; | ||||
|  | ||||
|     /** | ||||
|      * 更新时间 | ||||
|      */ | ||||
|     @ExcelProperty(value = "更新时间") | ||||
|     private Date updateTime; | ||||
|  | ||||
|     /** | ||||
|      * 更新人 | ||||
|      */ | ||||
|     @ExcelProperty(value = "更新人") | ||||
|     private Long updateBy; | ||||
|  | ||||
|     /** | ||||
|      * 更新人账号 | ||||
|      */ | ||||
|     @Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "updateBy") | ||||
|     @ExcelProperty(value = "更新人账号") | ||||
|     private String updateByName; | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| package org.dromara.demo.domain.vo; | ||||
|  | ||||
| import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; | ||||
| import com.alibaba.excel.annotation.ExcelProperty; | ||||
| import org.dromara.demo.domain.TestTree; | ||||
| import io.github.linpeilie.annotations.AutoMapper; | ||||
| import lombok.Data; | ||||
|  | ||||
| import java.io.Serial; | ||||
| import java.io.Serializable; | ||||
| import java.util.Date; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * 测试树表视图对象 test_tree | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @Data | ||||
| @ExcelIgnoreUnannotated | ||||
| @AutoMapper(target = TestTree.class) | ||||
| public class TestTreeVo implements Serializable { | ||||
|  | ||||
|     @Serial | ||||
|     private static final long serialVersionUID = 1L; | ||||
|  | ||||
|     /** | ||||
|      * 主键 | ||||
|      */ | ||||
|     private Long id; | ||||
|  | ||||
|     /** | ||||
|      * 父id | ||||
|      */ | ||||
|     @ExcelProperty(value = "父id") | ||||
|     private Long parentId; | ||||
|  | ||||
|     /** | ||||
|      * 部门id | ||||
|      */ | ||||
|     @ExcelProperty(value = "部门id") | ||||
|     private Long deptId; | ||||
|  | ||||
|     /** | ||||
|      * 用户id | ||||
|      */ | ||||
|     @ExcelProperty(value = "用户id") | ||||
|     private Long userId; | ||||
|  | ||||
|     /** | ||||
|      * 树节点名 | ||||
|      */ | ||||
|     @ExcelProperty(value = "树节点名") | ||||
|     private String treeName; | ||||
|  | ||||
|     /** | ||||
|      * 创建时间 | ||||
|      */ | ||||
|     @ExcelProperty(value = "创建时间") | ||||
|     private Date createTime; | ||||
|  | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,68 @@ | ||||
| package org.dromara.demo.listener; | ||||
|  | ||||
| import cn.hutool.core.util.NumberUtil; | ||||
| import com.alibaba.excel.context.AnalysisContext; | ||||
| import org.dromara.common.core.utils.ValidatorUtils; | ||||
| import org.dromara.common.core.validate.AddGroup; | ||||
| import org.dromara.common.core.validate.EditGroup; | ||||
| import org.dromara.common.excel.core.DefaultExcelListener; | ||||
| import org.dromara.common.excel.core.DropDownOptions; | ||||
| import org.dromara.demo.domain.vo.ExportDemoVo; | ||||
|  | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * Excel带下拉框的解析处理器 | ||||
|  * | ||||
|  * @author Emil.Zhang | ||||
|  */ | ||||
| public class ExportDemoListener extends DefaultExcelListener<ExportDemoVo> { | ||||
|  | ||||
|     public ExportDemoListener() { | ||||
|         // 显示使用构造函数,否则将导致空指针 | ||||
|         super(true); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void invoke(ExportDemoVo data, AnalysisContext context) { | ||||
|         // 先校验必填 | ||||
|         ValidatorUtils.validate(data, AddGroup.class); | ||||
|  | ||||
|         // 处理级联下拉的部分 | ||||
|         String province = data.getProvince(); | ||||
|         String city = data.getCity(); | ||||
|         String area = data.getArea(); | ||||
|         // 本行用户选择的省 | ||||
|         List<String> thisRowSelectedProvinceOption = DropDownOptions.analyzeOptionValue(province); | ||||
|         if (thisRowSelectedProvinceOption.size() == 2) { | ||||
|             String provinceIdStr = thisRowSelectedProvinceOption.get(1); | ||||
|             if (NumberUtil.isNumber(provinceIdStr)) { | ||||
|                 // 严格要求数据的话可以在这里做与数据库相关的判断 | ||||
|                 // 例如判断省信息是否在数据库中存在等,建议结合RedisCache做缓存10s,减少数据库调用 | ||||
|                 data.setProvinceId(Integer.parseInt(provinceIdStr)); | ||||
|             } | ||||
|         } | ||||
|         // 本行用户选择的市 | ||||
|         List<String> thisRowSelectedCityOption = DropDownOptions.analyzeOptionValue(city); | ||||
|         if (thisRowSelectedCityOption.size() == 2) { | ||||
|             String cityIdStr = thisRowSelectedCityOption.get(1); | ||||
|             if (NumberUtil.isNumber(cityIdStr)) { | ||||
|                 data.setCityId(Integer.parseInt(cityIdStr)); | ||||
|             } | ||||
|         } | ||||
|         // 本行用户选择的县 | ||||
|         List<String> thisRowSelectedAreaOption = DropDownOptions.analyzeOptionValue(area); | ||||
|         if (thisRowSelectedAreaOption.size() == 2) { | ||||
|             String areaIdStr = thisRowSelectedAreaOption.get(1); | ||||
|             if (NumberUtil.isNumber(areaIdStr)) { | ||||
|                 data.setAreaId(Integer.parseInt(areaIdStr)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // 处理完毕以后判断是否符合规则 | ||||
|         ValidatorUtils.validate(data, EditGroup.class); | ||||
|  | ||||
|         // 添加到处理结果中 | ||||
|         getExcelResult().getList().add(data); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| package org.dromara.demo.mapper; | ||||
|  | ||||
| import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; | ||||
| import org.dromara.demo.domain.TestDemoEncrypt; | ||||
|  | ||||
| /** | ||||
|  * 测试加密功能 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  */ | ||||
| public interface TestDemoEncryptMapper extends BaseMapperPlus<TestDemoEncrypt, TestDemoEncrypt> { | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,64 @@ | ||||
| package org.dromara.demo.mapper; | ||||
|  | ||||
| import com.baomidou.mybatisplus.core.conditions.Wrapper; | ||||
| import com.baomidou.mybatisplus.core.metadata.IPage; | ||||
| import com.baomidou.mybatisplus.core.toolkit.Constants; | ||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
| import org.apache.ibatis.annotations.Param; | ||||
| import org.dromara.common.mybatis.annotation.DataColumn; | ||||
| import org.dromara.common.mybatis.annotation.DataPermission; | ||||
| import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; | ||||
| import org.dromara.demo.domain.TestDemo; | ||||
| import org.dromara.demo.domain.vo.TestDemoVo; | ||||
|  | ||||
| import java.io.Serializable; | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 测试单表Mapper接口 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| public interface TestDemoMapper extends BaseMapperPlus<TestDemo, TestDemoVo> { | ||||
|  | ||||
|     @DataPermission({ | ||||
|         @DataColumn(key = "deptName", value = "dept_id"), | ||||
|         @DataColumn(key = "userName", value = "user_id") | ||||
|     }) | ||||
|     Page<TestDemoVo> customPageList(@Param("page") Page<TestDemo> page, @Param("ew") Wrapper<TestDemo> wrapper); | ||||
|  | ||||
|     @Override | ||||
|     @DataPermission({ | ||||
|         @DataColumn(key = "deptName", value = "dept_id"), | ||||
|         @DataColumn(key = "userName", value = "user_id") | ||||
|     }) | ||||
|     default <P extends IPage<TestDemoVo>> P selectVoPage(IPage<TestDemo> page, Wrapper<TestDemo> wrapper) { | ||||
|         return selectVoPage(page, wrapper, this.currentVoClass()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @DataPermission({ | ||||
|         @DataColumn(key = "deptName", value = "dept_id"), | ||||
|         @DataColumn(key = "userName", value = "user_id") | ||||
|     }) | ||||
|     default List<TestDemoVo> selectVoList(Wrapper<TestDemo> wrapper) { | ||||
|         return selectVoList(wrapper, this.currentVoClass()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     @DataPermission(value = { | ||||
|         @DataColumn(key = "deptName", value = "dept_id"), | ||||
|         @DataColumn(key = "userName", value = "user_id") | ||||
|     }, joinStr = "AND") | ||||
|     List<TestDemo> selectByIds(@Param(Constants.COLL) Collection<? extends Serializable> idList); | ||||
|  | ||||
|     @Override | ||||
|     @DataPermission({ | ||||
|         @DataColumn(key = "deptName", value = "dept_id"), | ||||
|         @DataColumn(key = "userName", value = "user_id") | ||||
|     }) | ||||
|     int updateById(@Param(Constants.ENTITY) TestDemo entity); | ||||
|  | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| package org.dromara.demo.mapper; | ||||
|  | ||||
| import org.dromara.common.mybatis.annotation.DataColumn; | ||||
| import org.dromara.common.mybatis.annotation.DataPermission; | ||||
| import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; | ||||
| import org.dromara.demo.domain.TestTree; | ||||
| import org.dromara.demo.domain.vo.TestTreeVo; | ||||
|  | ||||
| /** | ||||
|  * 测试树表Mapper接口 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @DataPermission({ | ||||
|     @DataColumn(key = "deptName", value = "dept_id"), | ||||
|     @DataColumn(key = "userName", value = "user_id") | ||||
| }) | ||||
| public interface TestTreeMapper extends BaseMapperPlus<TestTree, TestTreeVo> { | ||||
|  | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| package org.dromara.demo.mapper; | ||||
| @ -0,0 +1,18 @@ | ||||
| package org.dromara.demo.service; | ||||
|  | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
|  | ||||
| /** | ||||
|  * 导出下拉框Excel示例 | ||||
|  * | ||||
|  * @author Emil.Zhang | ||||
|  */ | ||||
| public interface IExportExcelService { | ||||
|  | ||||
|     /** | ||||
|      * 导出下拉框 | ||||
|      * | ||||
|      * @param response / | ||||
|      */ | ||||
|     void exportWithOptions(HttpServletResponse response); | ||||
| } | ||||
| @ -0,0 +1,71 @@ | ||||
| package org.dromara.demo.service; | ||||
|  | ||||
| import org.dromara.common.mybatis.core.page.PageQuery; | ||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||
| import org.dromara.demo.domain.TestDemo; | ||||
| import org.dromara.demo.domain.bo.TestDemoBo; | ||||
| import org.dromara.demo.domain.vo.TestDemoVo; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 测试单表Service接口 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| public interface ITestDemoService { | ||||
|  | ||||
|     /** | ||||
|      * 查询单个 | ||||
|      * | ||||
|      * @return | ||||
|      */ | ||||
|     TestDemoVo queryById(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 查询列表 | ||||
|      */ | ||||
|     TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery); | ||||
|  | ||||
|     /** | ||||
|      * 自定义分页查询 | ||||
|      */ | ||||
|     TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery); | ||||
|  | ||||
|     /** | ||||
|      * 查询列表 | ||||
|      */ | ||||
|     List<TestDemoVo> queryList(TestDemoBo bo); | ||||
|  | ||||
|     /** | ||||
|      * 根据新增业务对象插入测试单表 | ||||
|      * | ||||
|      * @param bo 测试单表新增业务对象 | ||||
|      * @return | ||||
|      */ | ||||
|     Boolean insertByBo(TestDemoBo bo); | ||||
|  | ||||
|     /** | ||||
|      * 根据编辑业务对象修改测试单表 | ||||
|      * | ||||
|      * @param bo 测试单表编辑业务对象 | ||||
|      * @return | ||||
|      */ | ||||
|     Boolean updateByBo(TestDemoBo bo); | ||||
|  | ||||
|     /** | ||||
|      * 校验并删除数据 | ||||
|      * | ||||
|      * @param ids     主键集合 | ||||
|      * @param isValid 是否校验,true-删除前校验,false-不校验 | ||||
|      * @return | ||||
|      */ | ||||
|     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); | ||||
|  | ||||
|     /** | ||||
|      * 批量保存 | ||||
|      */ | ||||
|     Boolean saveBatch(List<TestDemo> list); | ||||
| } | ||||
| @ -0,0 +1,52 @@ | ||||
| package org.dromara.demo.service; | ||||
|  | ||||
| import org.dromara.demo.domain.bo.TestTreeBo; | ||||
| import org.dromara.demo.domain.vo.TestTreeVo; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * 测试树表Service接口 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| public interface ITestTreeService { | ||||
|     /** | ||||
|      * 查询单个 | ||||
|      * | ||||
|      * @return | ||||
|      */ | ||||
|     TestTreeVo queryById(Long id); | ||||
|  | ||||
|     /** | ||||
|      * 查询列表 | ||||
|      */ | ||||
|     List<TestTreeVo> queryList(TestTreeBo bo); | ||||
|  | ||||
|     /** | ||||
|      * 根据新增业务对象插入测试树表 | ||||
|      * | ||||
|      * @param bo 测试树表新增业务对象 | ||||
|      * @return | ||||
|      */ | ||||
|     Boolean insertByBo(TestTreeBo bo); | ||||
|  | ||||
|     /** | ||||
|      * 根据编辑业务对象修改测试树表 | ||||
|      * | ||||
|      * @param bo 测试树表编辑业务对象 | ||||
|      * @return | ||||
|      */ | ||||
|     Boolean updateByBo(TestTreeBo bo); | ||||
|  | ||||
|     /** | ||||
|      * 校验并删除数据 | ||||
|      * | ||||
|      * @param ids     主键集合 | ||||
|      * @param isValid 是否校验,true-删除前校验,false-不校验 | ||||
|      * @return | ||||
|      */ | ||||
|     Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid); | ||||
| } | ||||
| @ -0,0 +1,236 @@ | ||||
| package org.dromara.demo.service.impl; | ||||
|  | ||||
| import cn.hutool.core.util.RandomUtil; | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import jakarta.servlet.http.HttpServletResponse; | ||||
| import lombok.Data; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.dromara.common.core.constant.SystemConstants; | ||||
| import org.dromara.common.core.utils.StreamUtils; | ||||
| import org.dromara.common.excel.core.DropDownOptions; | ||||
| import org.dromara.common.excel.utils.ExcelUtil; | ||||
| import org.dromara.demo.domain.vo.ExportDemoVo; | ||||
| import org.dromara.demo.service.IExportExcelService; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| /** | ||||
|  * 导出下拉框Excel示例 | ||||
|  * | ||||
|  * @author Emil.Zhang | ||||
|  */ | ||||
| @Service | ||||
| @RequiredArgsConstructor | ||||
| public class ExportExcelServiceImpl implements IExportExcelService { | ||||
|  | ||||
|     @Override | ||||
|     public void exportWithOptions(HttpServletResponse response) { | ||||
|         // 创建表格数据,业务中一般通过数据库查询 | ||||
|         List<ExportDemoVo> excelDataList = new ArrayList<>(); | ||||
|         for (int i = 0; i < 3; i++) { | ||||
|             // 模拟数据库中的一条数据 | ||||
|             ExportDemoVo everyRowData = new ExportDemoVo(); | ||||
|             everyRowData.setNickName("用户-" + i); | ||||
|             everyRowData.setUserStatus(SystemConstants.NORMAL); | ||||
|             everyRowData.setGender("1"); | ||||
|             everyRowData.setPhoneNumber(String.format("175%08d", i)); | ||||
|             everyRowData.setEmail(String.format("175%08d", i) + "@163.com"); | ||||
|             everyRowData.setProvinceId(i); | ||||
|             everyRowData.setCityId(i); | ||||
|             everyRowData.setAreaId(i); | ||||
|             excelDataList.add(everyRowData); | ||||
|         } | ||||
|  | ||||
|         // 通过@ExcelIgnoreUnannotated配合@ExcelProperty合理显示需要的列 | ||||
|         // 并通过@DropDown注解指定下拉值,或者通过创建ExcelOptions来指定下拉框 | ||||
|         // 使用ExcelOptions时建议指定列index,防止出现下拉列解析不对齐 | ||||
|  | ||||
|         // 首先从数据库中查询下拉框内的可选项 | ||||
|         // 这里模拟查询结果 | ||||
|         List<DemoCityData> provinceList = getProvinceList(), | ||||
|             cityList = getCityList(provinceList), | ||||
|             areaList = getAreaList(cityList); | ||||
|         int provinceIndex = 5, cityIndex = 6, areaIndex = 7; | ||||
|  | ||||
|         DropDownOptions provinceToCity = DropDownOptions.buildLinkedOptions( | ||||
|             provinceList, | ||||
|             provinceIndex, | ||||
|             cityList, | ||||
|             cityIndex, | ||||
|             DemoCityData::getId, | ||||
|             DemoCityData::getPid, | ||||
|             everyOptions -> DropDownOptions.createOptionValue( | ||||
|                 everyOptions.getName(), | ||||
|                 everyOptions.getId() | ||||
|             ) | ||||
|         ); | ||||
|  | ||||
|         DropDownOptions cityToArea = DropDownOptions.buildLinkedOptions( | ||||
|             cityList, | ||||
|             cityIndex, | ||||
|             areaList, | ||||
|             areaIndex, | ||||
|             DemoCityData::getId, | ||||
|             DemoCityData::getPid, | ||||
|             everyOptions -> DropDownOptions.createOptionValue( | ||||
|                 everyOptions.getName(), | ||||
|                 everyOptions.getId() | ||||
|             ) | ||||
|         ); | ||||
|  | ||||
|         // 把所有的下拉框存储 | ||||
|         List<DropDownOptions> options = new ArrayList<>(); | ||||
|         options.add(provinceToCity); | ||||
|         options.add(cityToArea); | ||||
|  | ||||
|         // 到此为止所有的下拉框可选项已全部配置完毕 | ||||
|  | ||||
|         // 接下来需要将Excel中的展示数据转换为对应的下拉选 | ||||
|         List<ExportDemoVo> outList = StreamUtils.toList(excelDataList, everyRowData -> { | ||||
|             // 只需要处理没有使用@ExcelDictFormat注解的下拉框 | ||||
|             // 一般来说,可以直接在数据库查询即查询出省市县信息,这里通过模拟操作赋值 | ||||
|             everyRowData.setProvince(buildOptions(provinceList, everyRowData.getProvinceId())); | ||||
|             everyRowData.setCity(buildOptions(cityList, everyRowData.getCityId())); | ||||
|             everyRowData.setArea(buildOptions(areaList, everyRowData.getAreaId())); | ||||
|             return everyRowData; | ||||
|         }); | ||||
|  | ||||
|         ExcelUtil.exportExcel(outList, "下拉框示例", ExportDemoVo.class, response, options); | ||||
|     } | ||||
|  | ||||
|     private String buildOptions(List<DemoCityData> cityDataList, Integer id) { | ||||
|         Map<Integer, List<DemoCityData>> groupByIdMap = | ||||
|             cityDataList.stream().collect(Collectors.groupingBy(DemoCityData::getId)); | ||||
|         if (groupByIdMap.containsKey(id)) { | ||||
|             DemoCityData demoCityData = groupByIdMap.get(id).get(0); | ||||
|             return DropDownOptions.createOptionValue(demoCityData.getName(), demoCityData.getId()); | ||||
|         } else { | ||||
|             return StrUtil.EMPTY; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 模拟查询数据库操作 | ||||
|      * | ||||
|      * @return / | ||||
|      */ | ||||
|     private List<DemoCityData> getProvinceList() { | ||||
|         List<DemoCityData> provinceList = new ArrayList<>(); | ||||
|  | ||||
|         // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 | ||||
|         provinceList.add(new DemoCityData(0, null, "P100000")); | ||||
|         provinceList.add(new DemoCityData(1, null, "P200000")); | ||||
|         provinceList.add(new DemoCityData(2, null, "P300000")); | ||||
|  | ||||
|         return provinceList; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 模拟查找数据库操作,需要连带查询出省的数据 | ||||
|      * | ||||
|      * @param provinceList 模拟的父省数据 | ||||
|      * @return / | ||||
|      */ | ||||
|     private List<DemoCityData> getCityList(List<DemoCityData> provinceList) { | ||||
|         List<DemoCityData> cityList = new ArrayList<>(); | ||||
|  | ||||
|         // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 | ||||
|         cityList.add(new DemoCityData(0, 0, "C110000")); | ||||
|         cityList.add(new DemoCityData(1, 0, "C120000")); | ||||
|         cityList.add(new DemoCityData(2, 1, "C210000")); | ||||
|         cityList.add(new DemoCityData(3, 1, "C220000")); | ||||
|         cityList.add(new DemoCityData(4, 1, "C230000")); | ||||
|  | ||||
|         selectParentData(provinceList, cityList); | ||||
|  | ||||
|         return cityList; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 模拟查找数据库操作,需要连带查询出市的数据 | ||||
|      * | ||||
|      * @param cityList 模拟的父市数据 | ||||
|      * @return / | ||||
|      */ | ||||
|     private List<DemoCityData> getAreaList(List<DemoCityData> cityList) { | ||||
|         List<DemoCityData> areaList = new ArrayList<>(); | ||||
|  | ||||
|         int minCount = 500; | ||||
|         int maxCount = 10000; | ||||
|  | ||||
|         // 实际业务中一般采用数据库读取的形式,这里直接拼接创建 | ||||
|         for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { | ||||
|             areaList.add(new DemoCityData(areaList.size(), 0, String.format("A11%04d", i))); | ||||
|         } | ||||
|  | ||||
|         for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { | ||||
|             areaList.add(new DemoCityData(areaList.size(), 1, String.format("A12%04d", i))); | ||||
|         } | ||||
|  | ||||
|         for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { | ||||
|             areaList.add(new DemoCityData(areaList.size(), 2, String.format("A21%04d", i))); | ||||
|         } | ||||
|  | ||||
|         for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { | ||||
|             areaList.add(new DemoCityData(areaList.size(), 3, String.format("A22%04d", i))); | ||||
|         } | ||||
|  | ||||
|         for (int i = 0; i < RandomUtil.randomInt(minCount, maxCount); i++) { | ||||
|             areaList.add(new DemoCityData(areaList.size(), 4, String.format("A23%04d", i))); | ||||
|         } | ||||
|  | ||||
|         selectParentData(cityList, areaList); | ||||
|  | ||||
|         return areaList; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 模拟数据库的查询父数据操作 | ||||
|      * | ||||
|      * @param parentList / | ||||
|      * @param sonList    / | ||||
|      */ | ||||
|     private void selectParentData(List<DemoCityData> parentList, List<DemoCityData> sonList) { | ||||
|         Map<Integer, List<DemoCityData>> parentGroupByIdMap = | ||||
|             parentList.stream().collect(Collectors.groupingBy(DemoCityData::getId)); | ||||
|  | ||||
|         sonList.forEach(everySon -> { | ||||
|             if (parentGroupByIdMap.containsKey(everySon.getPid())) { | ||||
|                 everySon.setPData(parentGroupByIdMap.get(everySon.getPid()).get(0)); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 模拟的数据库省市县 | ||||
|      */ | ||||
|     @Data | ||||
|     private static class DemoCityData { | ||||
|         /** | ||||
|          * 数据库id字段 | ||||
|          */ | ||||
|         private Integer id; | ||||
|         /** | ||||
|          * 数据库pid字段 | ||||
|          */ | ||||
|         private Integer pid; | ||||
|         /** | ||||
|          * 数据库name字段 | ||||
|          */ | ||||
|         private String name; | ||||
|         /** | ||||
|          * MyBatisPlus连带查询父数据 | ||||
|          */ | ||||
|         private DemoCityData pData; | ||||
|  | ||||
|         public DemoCityData(Integer id, Integer pid, String name) { | ||||
|             this.id = id; | ||||
|             this.pid = pid; | ||||
|             this.name = name; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,116 @@ | ||||
| package org.dromara.demo.service.impl; | ||||
|  | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.dromara.common.core.exception.ServiceException; | ||||
| import org.dromara.common.core.utils.MapstructUtils; | ||||
| import org.dromara.common.core.utils.StringUtils; | ||||
| import org.dromara.common.mybatis.core.page.PageQuery; | ||||
| import org.dromara.common.mybatis.core.page.TableDataInfo; | ||||
| import org.dromara.demo.domain.TestDemo; | ||||
| import org.dromara.demo.domain.bo.TestDemoBo; | ||||
| import org.dromara.demo.domain.vo.TestDemoVo; | ||||
| import org.dromara.demo.mapper.TestDemoMapper; | ||||
| import org.dromara.demo.service.ITestDemoService; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * 测试单表Service业务层处理 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| @RequiredArgsConstructor | ||||
| @Service | ||||
| public class TestDemoServiceImpl implements ITestDemoService { | ||||
|  | ||||
|     private final TestDemoMapper baseMapper; | ||||
|  | ||||
|     @Override | ||||
|     public TestDemoVo queryById(Long id) { | ||||
|         return baseMapper.selectVoById(id); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public TableDataInfo<TestDemoVo> queryPageList(TestDemoBo bo, PageQuery pageQuery) { | ||||
|         LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo); | ||||
|         Page<TestDemoVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw); | ||||
|         return TableDataInfo.build(result); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 自定义分页查询 | ||||
|      */ | ||||
|     @Override | ||||
|     public TableDataInfo<TestDemoVo> customPageList(TestDemoBo bo, PageQuery pageQuery) { | ||||
|         LambdaQueryWrapper<TestDemo> lqw = buildQueryWrapper(bo); | ||||
|         Page<TestDemoVo> result = baseMapper.customPageList(pageQuery.build(), lqw); | ||||
|         return TableDataInfo.build(result); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public List<TestDemoVo> queryList(TestDemoBo bo) { | ||||
|         return baseMapper.selectVoList(buildQueryWrapper(bo)); | ||||
|     } | ||||
|  | ||||
|     private LambdaQueryWrapper<TestDemo> buildQueryWrapper(TestDemoBo bo) { | ||||
|         Map<String, Object> params = bo.getParams(); | ||||
|         LambdaQueryWrapper<TestDemo> lqw = Wrappers.lambdaQuery(); | ||||
|         lqw.like(StringUtils.isNotBlank(bo.getTestKey()), TestDemo::getTestKey, bo.getTestKey()); | ||||
|         lqw.eq(StringUtils.isNotBlank(bo.getValue()), TestDemo::getValue, bo.getValue()); | ||||
|         lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null, | ||||
|             TestDemo::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime")); | ||||
|         lqw.orderByAsc(TestDemo::getId); | ||||
|         return lqw; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Boolean insertByBo(TestDemoBo bo) { | ||||
|         TestDemo add = MapstructUtils.convert(bo, TestDemo.class); | ||||
|         validEntityBeforeSave(add); | ||||
|         boolean flag = baseMapper.insert(add) > 0; | ||||
|         if (flag) { | ||||
|             bo.setId(add.getId()); | ||||
|         } | ||||
|         return flag; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Boolean updateByBo(TestDemoBo bo) { | ||||
|         TestDemo update = MapstructUtils.convert(bo, TestDemo.class); | ||||
|         validEntityBeforeSave(update); | ||||
|         return baseMapper.updateById(update) > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 保存前的数据校验 | ||||
|      * | ||||
|      * @param entity 实体类数据 | ||||
|      */ | ||||
|     private void validEntityBeforeSave(TestDemo entity) { | ||||
|         //TODO 做一些数据校验,如唯一约束 | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { | ||||
|         if (isValid) { | ||||
|             // 做一些业务上的校验,判断是否需要校验 | ||||
|             List<TestDemo> list = baseMapper.selectByIds(ids); | ||||
|             if (list.size() != ids.size()) { | ||||
|                 throw new ServiceException("您没有删除权限!"); | ||||
|             } | ||||
|         } | ||||
|         return baseMapper.deleteByIds(ids) > 0; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Boolean saveBatch(List<TestDemo> list) { | ||||
|         return baseMapper.insertBatch(list); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,88 @@ | ||||
| package org.dromara.demo.service.impl; | ||||
|  | ||||
| import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | ||||
| import com.baomidou.mybatisplus.core.toolkit.Wrappers; | ||||
| import org.dromara.common.core.utils.MapstructUtils; | ||||
| import org.dromara.common.core.utils.StringUtils; | ||||
| import org.dromara.demo.domain.TestTree; | ||||
| import org.dromara.demo.domain.bo.TestTreeBo; | ||||
| import org.dromara.demo.domain.vo.TestTreeVo; | ||||
| import org.dromara.demo.mapper.TestTreeMapper; | ||||
| import org.dromara.demo.service.ITestTreeService; | ||||
| import lombok.RequiredArgsConstructor; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Map; | ||||
|  | ||||
| /** | ||||
|  * 测试树表Service业务层处理 | ||||
|  * | ||||
|  * @author Lion Li | ||||
|  * @date 2021-07-26 | ||||
|  */ | ||||
| // @DS("slave") // 切换从库查询 | ||||
| @RequiredArgsConstructor | ||||
| @Service | ||||
| public class TestTreeServiceImpl implements ITestTreeService { | ||||
|  | ||||
|     private final TestTreeMapper baseMapper; | ||||
|  | ||||
|     @Override | ||||
|     public TestTreeVo queryById(Long id) { | ||||
|         return baseMapper.selectVoById(id); | ||||
|     } | ||||
|  | ||||
|     // @DS("slave") // 切换从库查询 | ||||
|     @Override | ||||
|     public List<TestTreeVo> queryList(TestTreeBo bo) { | ||||
|         LambdaQueryWrapper<TestTree> lqw = buildQueryWrapper(bo); | ||||
|         return baseMapper.selectVoList(lqw); | ||||
|     } | ||||
|  | ||||
|     private LambdaQueryWrapper<TestTree> buildQueryWrapper(TestTreeBo bo) { | ||||
|         Map<String, Object> params = bo.getParams(); | ||||
|         LambdaQueryWrapper<TestTree> lqw = Wrappers.lambdaQuery(); | ||||
|         lqw.like(StringUtils.isNotBlank(bo.getTreeName()), TestTree::getTreeName, bo.getTreeName()); | ||||
|         lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null, | ||||
|             TestTree::getCreateTime, params.get("beginCreateTime"), params.get("endCreateTime")); | ||||
|         lqw.orderByAsc(TestTree::getId); | ||||
|         return lqw; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Boolean insertByBo(TestTreeBo bo) { | ||||
|         TestTree add = MapstructUtils.convert(bo, TestTree.class); | ||||
|         validEntityBeforeSave(add); | ||||
|         boolean flag = baseMapper.insert(add) > 0; | ||||
|         if (flag) { | ||||
|             bo.setId(add.getId()); | ||||
|         } | ||||
|         return flag; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Boolean updateByBo(TestTreeBo bo) { | ||||
|         TestTree update = MapstructUtils.convert(bo, TestTree.class); | ||||
|         validEntityBeforeSave(update); | ||||
|         return baseMapper.updateById(update) > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 保存前的数据校验 | ||||
|      * | ||||
|      * @param entity 实体类数据 | ||||
|      */ | ||||
|     private void validEntityBeforeSave(TestTree entity) { | ||||
|         //TODO 做一些数据校验,如唯一约束 | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) { | ||||
|         if (isValid) { | ||||
|             //TODO 做一些业务上的校验,判断是否需要校验 | ||||
|         } | ||||
|         return baseMapper.deleteByIds(ids) > 0; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| package org.dromara.demo.service.impl; | ||||
| @ -0,0 +1 @@ | ||||
| package org.dromara.demo.service; | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" ?> | ||||
| <!DOCTYPE mapper | ||||
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||||
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||||
| <mapper namespace="org.dromara.demo.mapper.TestDemoMapper"> | ||||
|  | ||||
|     <select id="customPageList" resultType="org.dromara.demo.domain.vo.TestDemoVo"> | ||||
|         SELECT * FROM test_demo ${ew.customSqlSegment} | ||||
|     </select> | ||||
|  | ||||
| </mapper> | ||||
| @ -0,0 +1,7 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" ?> | ||||
| <!DOCTYPE mapper | ||||
| PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||||
| "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||||
| <mapper namespace="org.dromara.demo.mapper.TestTreeMapper"> | ||||
|  | ||||
| </mapper> | ||||
| @ -0,0 +1,3 @@ | ||||
| java包使用 `.` 分割 resource 目录使用 `/` 分割 | ||||
| <br> | ||||
| 此文件目的 防止文件夹粘连找不到 `xml` 文件 | ||||
		Reference in New Issue
	
	Block a user