From a6751c22be6d055b320c9a4b26b7490c02dbfe4f Mon Sep 17 00:00:00 2001 From: JEECG <445654970@qq.com> Date: Sun, 14 Sep 2025 10:41:25 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90v3.8.3=E3=80=91=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/CommonController.java | 41 +++++++----------- .../system/controller/LoginController.java | 43 +++++++++++++------ 2 files changed, 45 insertions(+), 39 deletions(-) diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java index d975bf019..4429eb66f 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/CommonController.java @@ -13,7 +13,10 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Lazy; import org.springframework.util.AntPathMatcher; import org.springframework.util.FileCopyUtils; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.servlet.HandlerMapping; @@ -213,9 +216,7 @@ public class CommonController { if(oConvertUtils.isEmpty(imgPath) || CommonConstant.STRING_NULL.equals(imgPath)){ return; } - // 其余处理略 - InputStream inputStream = null; - OutputStream outputStream = null; + try { imgPath = imgPath.replace("..", "").replace("../",""); if (imgPath.endsWith(SymbolConstant.COMMA)) { @@ -236,33 +237,21 @@ public class CommonController { // 设置强制下载不打开 response.setContentType("application/force-download"); response.addHeader("Content-Disposition", "attachment;fileName=" + new String(file.getName().getBytes("UTF-8"),"iso-8859-1")); - inputStream = new BufferedInputStream(new FileInputStream(filePath)); - outputStream = response.getOutputStream(); - byte[] buf = new byte[1024]; - int len; - while ((len = inputStream.read(buf)) > 0) { - outputStream.write(buf, 0, len); + + // 结合 StreamingResponseBody 的流式写法 + try (InputStream inputStream = new BufferedInputStream(new FileInputStream(file)); + OutputStream outputStream = response.getOutputStream()) { + byte[] buf = new byte[8192]; + int len; + while ((len = inputStream.read(buf)) != -1) { + outputStream.write(buf, 0, len); + } + outputStream.flush(); } - response.flushBuffer(); } catch (IOException e) { log.error("预览文件失败" + e.getMessage()); response.setStatus(404); e.printStackTrace(); - } finally { - if (inputStream != null) { - try { - inputStream.close(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } - if (outputStream != null) { - try { - outputStream.close(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } } } diff --git a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java index 3f998066e..48ee02c18 100644 --- a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java +++ b/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/LoginController.java @@ -31,6 +31,7 @@ import org.jeecg.modules.system.service.impl.SysBaseApiImpl; import org.jeecg.modules.system.util.RandImageUtil; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; @@ -38,6 +39,9 @@ import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** @@ -67,9 +71,12 @@ public class LoginController { private BaseCommonService baseCommonService; @Autowired private JeecgBaseConfig jeecgBaseConfig; - private final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890"; - + /** + * 线程池用于异步发送纪要 + */ + public static ExecutorService cachedThreadPool = new ShiroThreadPoolExecutor(0, 1024, 60L, TimeUnit.SECONDS, new SynchronousQueue<>()); + @Operation(summary="登录接口") @RequestMapping(value = "/login", method = RequestMethod.POST) public Result login(@RequestBody SysLoginModel sysLoginModel, HttpServletRequest request){ @@ -192,23 +199,33 @@ public class LoginController { String username = JwtUtil.getUsername(token); LoginUser sysUser = sysBaseApi.getUserByName(username); if(sysUser!=null) { - //update-begin--Author:wangshuai Date:20200714 for:登出日志没有记录人员 - baseCommonService.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null,sysUser); - //update-end--Author:wangshuai Date:20200714 for:登出日志没有记录人员 - log.info(" 用户名: "+sysUser.getRealname()+",退出成功! "); - //清空用户登录Token缓存 - redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token); - //清空用户登录Shiro权限缓存 - redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId()); - //清空用户的缓存信息(包括部门信息),例如sys:cache:user:: - redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername())); - //调用shiro的logout + asyncClearLogoutCache(token, sysUser); // 异步清理 SecurityUtils.getSubject().logout(); return Result.ok("退出登录成功!"); }else { return Result.error("Token无效!"); } } + + /** + * 清理用户缓存 + * + * @param token + * @param sysUser + */ + private void asyncClearLogoutCache(String token, LoginUser sysUser) { + cachedThreadPool.execute(()->{ + //清空用户登录Token缓存 + redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token); + //清空用户登录Shiro权限缓存 + redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId()); + //清空用户的缓存信息(包括部门信息),例如sys:cache:user:: + redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername())); + baseCommonService.addLog("用户名: "+sysUser.getRealname()+",退出成功!", CommonConstant.LOG_TYPE_1, null, sysUser); + log.info("【退出成功操作】异步处理,退出后,清理用户缓存: "+sysUser.getRealname()); + }); + } + /** * 获取访问量