Files
UserBaseService/src/main/java/com/yunhai/userbase/controller/api/BaseController.java
T
chenxing b226a567b8
ci-userbase-service / build-and-push (push) Successful in 41s
ci
2026-08-10 21:44:03 +08:00

141 lines
6.2 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.yunhai.userbase.controller.api;
import com.yunhai.platform.utils.model.BoaUser;
import com.yunhai.userbase.config.Config;
import com.yunhai.userbase.enums.*;
import com.yunhai.userbase.utils.*;
import com.bestsch.utils.DException;
import org.springframework.web.multipart.MultipartFile;
import lombok.var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.RedirectView;
import java.util.*;
import java.util.function.Supplier;
@RestController
@RequestMapping(value = Config.API_PATH +"/base/")
public class BaseController {
@Autowired
private RedisUtil redisUtil;
/**
* 一般hashMap初始化大小
*/
public static final int initialCapacity = 6;
/**
* 通用上传允许的子目录(与 MyWebAppConfigurer.addResourceHandlers 的资源映射一一对应)。<br>
* 注:html 因 FileUtil 的危险后缀黑名单被禁止通过此接口上传,故未列入,避免存储可被浏览器执行的 HTML 引发 XSS。
*/
private static final Set<String> ALLOWED_UPLOAD_TYPES = new HashSet<>(Arrays.asList("image", "file", "icon", "word"));
@GetMapping("GetUserInfo")
public Object getUserInfo(BoaUser authUserWithDept){
return authUserWithDept;
}
//返回系统枚举2
@GetMapping("GetSysDict")
public Map getSysDict(BoaUser authUserWithDept){
Map<String, List> resultMap = new HashMap<>(7);
resultMap.put("grouptype", IEnum.toSimpleMapList(GroupTypeEnum.class, "k", "v"));
resultMap.put("gender", IEnum.toSimpleMapList(GenderEnum.class, "k", "v"));
resultMap.put("client", IEnum.toSimpleMapList(ClientEnum.class, "k", "v"));
resultMap.put("integ", IEnum.toSimpleMapList(IntegEnum.class, "k", "v"));
resultMap.put("status", IEnum.toSimpleMapList(StatusEnum.class, "k", "v"));
resultMap.put("sysrole", IEnum.toSimpleMapList(SysRoleEnum.class, "k", "v"));
resultMap.put("mode", IEnum.toSimpleMapList(SysModeEnum.class, "k", "v"));
return resultMap;
}
/**
* 手动管理 Redis Hash 缓存的示例(@Cacheable 注解无法满足的场景)。<br>
* 适用场景:需要把一个对象的多个字段按 Hash 结构存储,<br>
* 可单独读写/更新某个字段,而不像 @Cacheable 那样把整个对象序列化成一个大 value。<br>
* 访问路径:GET {Config.API_PATH}/base/ManualHashCacheDemo。<br>
* 注:手动缓存依赖 Redis;Redis 不可用时 RedisUtil 已内部捕获异常,操作失败但不影响接口本身。
*
* @return 本次演示各步骤的结果快照
*/
@GetMapping("ManualHashCacheDemo")
public Map<String, Object> manualHashCacheDemo() {
Map<String, Object> result = new HashMap<>(8);
String hashKey = "demo:user:1001";
// 1) 写入整张 hash(带 TTL):适合一次性缓存一个对象的多个属性
Map<String, Object> profile = new HashMap<>(4);
profile.put("name", "yunhai");
profile.put("age", 18);
profile.put("role", "admin");
redisUtil.hmset(hashKey, profile, 300);
// 2) 只更新其中一个字段,无需整体覆盖
redisUtil.hset(hashKey, "role", "superadmin");
// 3) 读取单个字段
result.put("roleAfterUpdate", redisUtil.hget(hashKey, "role"));
// 4) 读取整张 hash
result.put("wholeHash", redisUtil.hmget(hashKey));
// 5) 判断字段是否存在
result.put("hasAgeField", redisUtil.hHasKey(hashKey, "age"));
// 6) Cache-Aside(复用下方私有方法):字段不存在时回源并写回 Hash
Object nickname = getHashFieldWithFallback(hashKey, "nickname", () -> "yunhai-nick");
result.put("nickname", nickname);
// 7) 删除某个字段
redisUtil.hdel(hashKey, "age");
result.put("afterDelAge", redisUtil.hmget(hashKey));
return result;
}
@GetMapping("RedirectTo/{id}")
public RedirectView RedirectTo(BoaUser authUserWithDept, @PathVariable(name = "id") String id) {
String url= OtherUtil.hexToString(id);
return new RedirectView(url,true);
}
/**
* 通用文件上传接口(一个接口覆盖所有类型,无需按类型拆分)。<br>
* type 决定存储子目录,与 MyWebAppConfigurer.addResourceHandlers 的 /upload/{type}/** 映射一一对应,<br>
* 上传成功后可直接用返回的 URL 访问,无需再改资源映射配置。<br>
* 访问路径:POST {Config.API_PATH}/base/UploadFile(multipart/form-data)。<br>
* 支持 type:image / file / icon / word(html 被 FileUtil 黑名单禁止上传)。<br>
*
* @param file 上传文件(必填,单文件上限 50MB,见 application.yml 的 multipart 配置)
* @param type 存储子目录类型,默认 image
* @return 文件对外可访问的 Web URL
*/
@PostMapping("UploadFile")
public String uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam(value = "type", defaultValue = "image") String type) {
if (!ALLOWED_UPLOAD_TYPES.contains(type)) {
throw new DException("不支持的上传类型: " + type + ",可选: image/file/icon/word");
}
// FileUtil.upload 内部已处理空文件校验、危险后缀黑名单、目录创建与访问 URL 拼接
return FileUtil.upload(file, type);
}
/**
* 私有方法(可复用):演示 Hash 结构的 Cache-Aside(缓存旁路)模式。<br>
* 先从 Redis Hash 读字段;读不到则回源(此处用 fallback 模拟数据库查询),再把结果写回 Hash。<br>
*
* @param hashKey hash 键
* @param field 字段名
* @param fallback 回源加载器(真实场景替换为查数据库/远程调用)
* @return 字段值
*/
private Object getHashFieldWithFallback(String hashKey, String field, Supplier<Object> fallback) {
if (redisUtil.hHasKey(hashKey, field)) {
return redisUtil.hget(hashKey, field);
}
Object value = fallback.get();
if (value != null) {
redisUtil.hset(hashKey, field, value);
}
return value;
}
}