From 6f00ab30d8012488bdb845f9ce6bfc12832fdc33 Mon Sep 17 00:00:00 2001 From: anthonyywj2 <353682448@qq.com> Date: Mon, 12 Dec 2022 10:10:13 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=B3=BB=E7=BB=9F=E6=93=8D?= =?UTF-8?q?=E4=BD=9C=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/glxp/api/admin/annotation/Log.java | 40 ++++ .../com/glxp/api/admin/aspect/LogAspect.java | 191 ++++++++++++++++++ .../glxp/api/admin/config/RuoYiConfig.java | 52 +++++ .../api/admin/constant/BusinessStatus.java | 18 ++ .../glxp/api/admin/constant/BusinessType.java | 56 +++++ .../com/glxp/api/admin/constant/Constant.java | 34 ++++ .../glxp/api/admin/constant/OperatorType.java | 21 ++ .../controller/auth/AuthAdminController.java | 3 + .../controller/auth/LoginController.java | 9 +- .../controller/auth/SysUserController.java | 4 +- .../monitor/SysLogininforController.java | 63 ++++++ .../monitor/SysOperlogController.java | 64 ++++++ .../dao/monitor/SysLogininforMapper.java | 31 +++ .../admin/dao/monitor/SysOperLogMapper.java | 28 +++ .../api/admin/entity/monitor/OperLogDTO.java | 102 ++++++++++ .../admin/entity/monitor/SysLogininfor.java | 68 +++++++ .../api/admin/entity/monitor/SysOperLog.java | 109 ++++++++++ .../req/monitor/SysLogininforRequest.java | 21 ++ .../admin/req/monitor/SysOperLogRequest.java | 34 ++++ .../monitor/ISysLogininforService.java | 35 ++++ .../service/monitor/ISysOperLogService.java | 46 +++++ .../service/monitor/LogininforService.java | 12 ++ .../admin/service/monitor/OperLogService.java | 13 ++ .../impl/SysLogininforServiceImpl.java | 113 +++++++++++ .../monitor/impl/SysOperLogServiceImpl.java | 90 +++++++++ .../com/glxp/api/admin/util/AddressUtils.java | 58 ++++++ .../com/glxp/api/admin/util/JsonUtils.java | 110 ++++++++++ .../com/glxp/api/admin/util/MessageUtils.java | 26 +++ .../com/glxp/api/admin/util/ServletUtils.java | 173 ++++++++++++++++ .../com/glxp/api/admin/util/SpringUtils.java | 63 ++++++ .../mapper/monitor/SysLogininforMapper.xml | 79 ++++++++ .../mapper/monitor/SysOperLogMapper.xml | 107 ++++++++++ 32 files changed, 1870 insertions(+), 3 deletions(-) create mode 100644 api-admin/src/main/java/com/glxp/api/admin/annotation/Log.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/aspect/LogAspect.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/config/RuoYiConfig.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/constant/BusinessStatus.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/constant/BusinessType.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/constant/OperatorType.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysLogininforController.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysOperlogController.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysLogininforMapper.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysOperLogMapper.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/entity/monitor/OperLogDTO.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysLogininfor.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysOperLog.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysLogininforRequest.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysOperLogRequest.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysLogininforService.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysOperLogService.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/service/monitor/LogininforService.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/service/monitor/OperLogService.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysLogininforServiceImpl.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysOperLogServiceImpl.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/util/AddressUtils.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/util/JsonUtils.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/util/MessageUtils.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/util/ServletUtils.java create mode 100644 api-admin/src/main/java/com/glxp/api/admin/util/SpringUtils.java create mode 100644 api-admin/src/main/resources/mybatis/mapper/monitor/SysLogininforMapper.xml create mode 100644 api-admin/src/main/resources/mybatis/mapper/monitor/SysOperLogMapper.xml diff --git a/api-admin/src/main/java/com/glxp/api/admin/annotation/Log.java b/api-admin/src/main/java/com/glxp/api/admin/annotation/Log.java new file mode 100644 index 00000000..f7dfafdb --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/annotation/Log.java @@ -0,0 +1,40 @@ +package com.glxp.api.admin.annotation; + + +import com.glxp.api.admin.constant.BusinessType; +import com.glxp.api.admin.constant.OperatorType; + +import java.lang.annotation.*; + +/** + * 自定义操作日志记录注解 + */ +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface Log { + /** + * 模块 + */ + String title() default ""; + + /** + * 功能 + */ + BusinessType businessType() default BusinessType.OTHER; + + /** + * 操作人类别 + */ + OperatorType operatorType() default OperatorType.MANAGE; + + /** + * 是否保存请求的参数 + */ + boolean isSaveRequestData() default true; + + /** + * 是否保存响应的参数 + */ + boolean isSaveResponseData() default true; +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/aspect/LogAspect.java b/api-admin/src/main/java/com/glxp/api/admin/aspect/LogAspect.java new file mode 100644 index 00000000..00c42c88 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/aspect/LogAspect.java @@ -0,0 +1,191 @@ +package com.glxp.api.admin.aspect; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjectUtil; +import com.glxp.api.admin.annotation.Log; +import com.glxp.api.admin.constant.BusinessStatus; +import com.glxp.api.admin.entity.monitor.OperLogDTO; +import com.glxp.api.admin.service.monitor.OperLogService; +import com.glxp.api.admin.util.JsonUtils; +import com.glxp.api.admin.util.ServletUtils; +import com.glxp.api.admin.util.SpringUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.http.HttpMethod; +import org.springframework.stereotype.Component; +import org.springframework.validation.BindingResult; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Collection; +import java.util.Map; + +/** + * 操作日志记录处理 + */ +@Slf4j +@Aspect +@Component +public class LogAspect { + + /** + * 排除敏感属性字段 + */ + public static final String[] EXCLUDE_PROPERTIES = {"password", "oldPassword", "newPassword", "confirmPassword"}; + + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) { + handleLog(joinPoint, controllerLog, null, jsonResult); + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) { + handleLog(joinPoint, controllerLog, e, null); + } + + protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) { + try { + + // *========数据库日志=========*// + OperLogDTO operLog = new OperLogDTO(); + operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); + // 请求的地址 + String ip = ServletUtils.getClientIP(); + operLog.setOperIp(ip); + operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); +// operLog.setOperName(LoginHelper.getUsername()); + + if (e != null) { + operLog.setStatus(BusinessStatus.FAIL.ordinal()); + operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); + } + // 设置方法名称 + String className = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + operLog.setMethod(className + "." + methodName + "()"); + // 设置请求方式 + operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); + // 处理设置注解上的参数 + getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); + // 保存数据库 + SpringUtils.getBean(OperLogService.class).recordOper(operLog); + } catch (Exception exp) { + // 记录本地异常日志 + log.error("==前置通知异常=="); + log.error("异常信息:{}", exp.getMessage()); + exp.printStackTrace(); + } + } + + /** + * 获取注解中对方法的描述信息 用于Controller层注解 + * + * @param log 日志 + * @param operLog 操作日志 + * @throws Exception + */ + public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogDTO operLog, Object jsonResult) throws Exception { + // 设置action动作 + operLog.setBusinessType(log.businessType().ordinal()); + // 设置标题 + operLog.setTitle(log.title()); + // 设置操作人类别 + operLog.setOperatorType(log.operatorType().ordinal()); + // 是否需要保存request,参数和值 + if (log.isSaveRequestData()) { + // 获取参数的信息,传入到数据库中。 + setRequestValue(joinPoint, operLog); + } + // 是否需要保存response,参数和值 + if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) { + operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 2000)); + } + } + + /** + * 获取请求的参数,放到log中 + * + * @param operLog 操作日志 + * @throws Exception 异常 + */ + private void setRequestValue(JoinPoint joinPoint, OperLogDTO operLog) throws Exception { + String requestMethod = operLog.getRequestMethod(); + if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { + String params = argsArrayToString(joinPoint.getArgs()); + operLog.setOperParam(StringUtils.substring(params, 0, 2000)); + } else { + Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); + operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000)); + } + } + + /** + * 参数拼装 + */ + private String argsArrayToString(Object[] paramsArray) { + StringBuilder params = new StringBuilder(); + if (paramsArray != null && paramsArray.length > 0) { + for (Object o : paramsArray) { + if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) { + try { + String str = JsonUtils.toJsonString(o); + Dict dict = JsonUtils.parseMap(str); + if (MapUtil.isNotEmpty(dict)) { + MapUtil.removeAny(dict, EXCLUDE_PROPERTIES); + str = JsonUtils.toJsonString(dict); + } + params.append(str).append(" "); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + return params.toString().trim(); + } + + /** + * 判断是否需要过滤的对象。 + * + * @param o 对象信息。 + * @return 如果是需要过滤的对象,则返回true;否则返回false。 + */ + @SuppressWarnings("rawtypes") + public boolean isFilterObject(final Object o) { + Class clazz = o.getClass(); + if (clazz.isArray()) { + return clazz.getComponentType().isAssignableFrom(MultipartFile.class); + } else if (Collection.class.isAssignableFrom(clazz)) { + Collection collection = (Collection) o; + for (Object value : collection) { + return value instanceof MultipartFile; + } + } else if (Map.class.isAssignableFrom(clazz)) { + Map map = (Map) o; + for (Object value : map.entrySet()) { + Map.Entry entry = (Map.Entry) value; + return entry.getValue() instanceof MultipartFile; + } + } + return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse + || o instanceof BindingResult; + } +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/config/RuoYiConfig.java b/api-admin/src/main/java/com/glxp/api/admin/config/RuoYiConfig.java new file mode 100644 index 00000000..a9acf770 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/config/RuoYiConfig.java @@ -0,0 +1,52 @@ +package com.glxp.api.admin.config; + +import lombok.Data; +import lombok.Getter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 读取项目相关配置 + */ + +@Data +@Component +@ConfigurationProperties(prefix = "ruoyi") +public class RuoYiConfig { + + /** + * 项目名称 + */ + private String name; + + /** + * 版本 + */ + private String version; + + /** + * 版权年份 + */ + private String copyrightYear; + + /** + * 实例演示开关 + */ + private boolean demoEnabled; + + /** + * 缓存懒加载 + */ + private boolean cacheLazy; + + /** + * 获取地址开关 + */ + @Getter + private static boolean addressEnabled; + + public void setAddressEnabled(boolean addressEnabled) { + RuoYiConfig.addressEnabled = addressEnabled; + } + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/constant/BusinessStatus.java b/api-admin/src/main/java/com/glxp/api/admin/constant/BusinessStatus.java new file mode 100644 index 00000000..32ff41c9 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/constant/BusinessStatus.java @@ -0,0 +1,18 @@ +package com.glxp.api.admin.constant; + +/** + * 操作状态 + * + * @author ruoyi + */ +public enum BusinessStatus { + /** + * 成功 + */ + SUCCESS, + + /** + * 失败 + */ + FAIL, +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/constant/BusinessType.java b/api-admin/src/main/java/com/glxp/api/admin/constant/BusinessType.java new file mode 100644 index 00000000..4448f18b --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/constant/BusinessType.java @@ -0,0 +1,56 @@ +package com.glxp.api.admin.constant; + +/** + * 业务操作类型 + */ +public enum BusinessType { + /** + * 其它 + */ + OTHER, + + /** + * 新增 + */ + INSERT, + + /** + * 修改 + */ + UPDATE, + + /** + * 删除 + */ + DELETE, + + /** + * 授权 + */ + GRANT, + + /** + * 导出 + */ + EXPORT, + + /** + * 导入 + */ + IMPORT, + + /** + * 强退 + */ + FORCE, + + /** + * 生成代码 + */ + GENCODE, + + /** + * 清空数据 + */ + CLEAN, +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/constant/Constant.java b/api-admin/src/main/java/com/glxp/api/admin/constant/Constant.java index a39e549e..7f59763c 100644 --- a/api-admin/src/main/java/com/glxp/api/admin/constant/Constant.java +++ b/api-admin/src/main/java/com/glxp/api/admin/constant/Constant.java @@ -105,4 +105,38 @@ public class Constant { public static final String YES = "Y"; + public static final String UTF8 = "UTF-8"; + + public static final String GBK = "GBK"; + + /** + * 通用失败标识 + */ + public static final String FAIL = "1"; + /** + * 通用成功标识 + */ + public static final String SUCCESS = "0"; + + /** + * 登录成功 + */ + public static final String LOGIN_SUCCESS = "Success"; + + /** + * 注销 + */ + public static final String LOGOUT = "Logout"; + + /** + * 注册 + */ + public static final String REGISTER = "Register"; + + /** + * 登录失败 + */ + public static final String LOGIN_FAIL = "Error"; + + } diff --git a/api-admin/src/main/java/com/glxp/api/admin/constant/OperatorType.java b/api-admin/src/main/java/com/glxp/api/admin/constant/OperatorType.java new file mode 100644 index 00000000..f36dabfc --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/constant/OperatorType.java @@ -0,0 +1,21 @@ +package com.glxp.api.admin.constant; + +/** + * 操作人类别 + */ +public enum OperatorType { + /** + * 其它 + */ + OTHER, + + /** + * 后台用户 + */ + MANAGE, + + /** + * 手机端用户 + */ + MOBILE +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/controller/auth/AuthAdminController.java b/api-admin/src/main/java/com/glxp/api/admin/controller/auth/AuthAdminController.java index 2e940aa6..c07c9080 100644 --- a/api-admin/src/main/java/com/glxp/api/admin/controller/auth/AuthAdminController.java +++ b/api-admin/src/main/java/com/glxp/api/admin/controller/auth/AuthAdminController.java @@ -2,6 +2,8 @@ package com.glxp.api.admin.controller.auth; import com.github.pagehelper.PageInfo; import com.glxp.api.admin.annotation.AuthRuleAnnotation; +import com.glxp.api.admin.annotation.Log; +import com.glxp.api.admin.constant.BusinessType; import com.glxp.api.admin.entity.auth.AuthAdmin; import com.glxp.api.admin.entity.auth.AuthRole; import com.glxp.api.admin.entity.auth.AuthRoleAdmin; @@ -239,6 +241,7 @@ public class AuthAdminController { * * @return */ + @Log(title = "用户管理", businessType = BusinessType.DELETE) @AuthRuleAnnotation("admin/auth/admin/delete") @PostMapping("/admin/auth/admin/delete") public BaseResponse delete(@RequestBody AuthAdminSaveRequest authAdminSaveRequest) { diff --git a/api-admin/src/main/java/com/glxp/api/admin/controller/auth/LoginController.java b/api-admin/src/main/java/com/glxp/api/admin/controller/auth/LoginController.java index bd878978..75303c99 100644 --- a/api-admin/src/main/java/com/glxp/api/admin/controller/auth/LoginController.java +++ b/api-admin/src/main/java/com/glxp/api/admin/controller/auth/LoginController.java @@ -1,6 +1,7 @@ package com.glxp.api.admin.controller.auth; import cn.hutool.core.util.StrUtil; +import com.glxp.api.admin.constant.Constant; import com.glxp.api.admin.controller.BaseController; import com.glxp.api.admin.dao.auth.AuthLicenseDao; import com.glxp.api.admin.entity.auth.AuthCheckEntity; @@ -18,6 +19,7 @@ import com.glxp.api.admin.service.auth.*; import com.glxp.api.admin.service.info.CompanyService; import com.glxp.api.admin.service.inventory.InvSubWarehouseService; import com.glxp.api.admin.service.inventory.InvWarehouseService; +import com.glxp.api.admin.service.monitor.LogininforService; import com.glxp.api.admin.util.*; import com.glxp.api.common.enums.ResultEnum; import com.glxp.api.common.res.BaseResponse; @@ -52,6 +54,8 @@ public class LoginController extends BaseController { @Autowired private AuthAdminService authAdminService; + @Resource + private LogininforService logininforService; @Resource private AuthCheckService authCheckService; @@ -92,7 +96,6 @@ public class LoginController extends BaseController { if (authAdmin.getUserFlag() == 0) { throw new JsonException(ResultEnum.DATA_NOT, "该用户已被禁用!"); } - if (StrUtil.isNotEmpty(loginRequest.getImei())) { DeviceKeyEntity deviceKeyEntity = deviceKeyService.findDeviceByImei(loginRequest.getImei()); if (deviceKeyEntity == null) { @@ -102,7 +105,6 @@ public class LoginController extends BaseController { } else if (deviceKeyEntity.getIsCheck() == 2) { return ResultVOUtils.error(412, "该设备被拒绝登录,请联系管理员!"); } - } // 更新登录状态 @@ -128,6 +130,9 @@ public class LoginController extends BaseController { loginResponse.setToken(token); loginResponse.setDept(authAdmin.getDept()); loginResponse.setDeptName(authAdmin.getDeptName()); + + logininforService.recordLogininfor(authAdmin.getEmployeeName(), Constant.LOGIN_SUCCESS, "登录成功!", request); + return ResultVOUtils.success(loginResponse); } diff --git a/api-admin/src/main/java/com/glxp/api/admin/controller/auth/SysUserController.java b/api-admin/src/main/java/com/glxp/api/admin/controller/auth/SysUserController.java index 5b6b447d..dc7d4d5c 100644 --- a/api-admin/src/main/java/com/glxp/api/admin/controller/auth/SysUserController.java +++ b/api-admin/src/main/java/com/glxp/api/admin/controller/auth/SysUserController.java @@ -5,6 +5,8 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.github.pagehelper.PageInfo; +import com.glxp.api.admin.annotation.Log; +import com.glxp.api.admin.constant.BusinessType; import com.glxp.api.admin.controller.BaseController; import com.glxp.api.admin.entity.auth.AuthAdmin; import com.glxp.api.admin.entity.auth.AuthRoleAdmin; @@ -144,7 +146,7 @@ public class SysUserController extends BaseController { return ResultVOUtils.success("授权成功!"); } - + @Log(title = "用户管理", businessType = BusinessType.INSERT) @PostMapping("/save") public BaseResponse save(@RequestBody @Valid AuthAdminSaveRequest authAdminSaveRequest, BindingResult bindingResult) { diff --git a/api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysLogininforController.java b/api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysLogininforController.java new file mode 100644 index 00000000..7cdc7838 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysLogininforController.java @@ -0,0 +1,63 @@ +package com.glxp.api.admin.controller.monitor; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.github.pagehelper.PageInfo; +import com.glxp.api.admin.annotation.Log; +import com.glxp.api.admin.constant.BusinessType; +import com.glxp.api.admin.controller.BaseController; +import com.glxp.api.admin.entity.monitor.SysLogininfor; +import com.glxp.api.admin.req.monitor.SysLogininforRequest; +import com.glxp.api.admin.res.PageSimpleResponse; +import com.glxp.api.admin.service.monitor.ISysLogininforService; +import com.glxp.api.common.res.BaseResponse; +import com.glxp.api.common.util.ResultVOUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Arrays; +import java.util.List; + +/** + * 系统访问记录 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/monitor/logininfor") +public class SysLogininforController extends BaseController { + + private final ISysLogininforService logininforService; + + /** + * 获取系统访问记录列表 + */ + @SaCheckPermission("monitor:logininfor:list") + @GetMapping("/list") + public BaseResponse list(SysLogininforRequest sysLogininforRequest) { + + List selectLogininforList = logininforService.selectLogininforList(sysLogininforRequest); + PageInfo pageInfo; + pageInfo = new PageInfo<>(selectLogininforList); + PageSimpleResponse pageSimpleResponse = new PageSimpleResponse<>(); + pageSimpleResponse.setTotal(pageInfo.getTotal()); + pageSimpleResponse.setList(selectLogininforList); + return ResultVOUtils.success(pageSimpleResponse); + } + + + /** + * 批量删除登录日志 + * + * @param infoIds 日志ids + */ + @SaCheckPermission("monitor:logininfor:remove") + @Log(title = "登录日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{infoIds}") + public BaseResponse remove(@PathVariable Long[] infoIds) { + int i = logininforService.deleteLogininforByIds(Arrays.asList(infoIds)); + return ResultVOUtils.success("删除成功!"); + } + + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysOperlogController.java b/api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysOperlogController.java new file mode 100644 index 00000000..d44e3eb3 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/controller/monitor/SysOperlogController.java @@ -0,0 +1,64 @@ +package com.glxp.api.admin.controller.monitor; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.github.pagehelper.PageInfo; +import com.glxp.api.admin.annotation.Log; +import com.glxp.api.admin.constant.BusinessType; +import com.glxp.api.admin.controller.BaseController; +import com.glxp.api.admin.entity.info.DeviceKeyEntity; +import com.glxp.api.admin.entity.monitor.SysOperLog; +import com.glxp.api.admin.req.monitor.SysOperLogRequest; +import com.glxp.api.admin.res.PageSimpleResponse; +import com.glxp.api.admin.service.monitor.ISysOperLogService; +import com.glxp.api.common.res.BaseResponse; +import com.glxp.api.common.util.ResultVOUtils; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 操作日志记录 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/monitor/operlog") +public class SysOperlogController extends BaseController { + + private final ISysOperLogService operLogService; + + /** + * 获取操作日志记录列表 + */ + @Log(title = "操作日志", businessType = BusinessType.OTHER) + @SaCheckPermission("monitor:operlog:list") + @GetMapping("/list") + public BaseResponse list(SysOperLogRequest sysOperLogRequest) { + + List selectOperLogList = operLogService.selectOperLogList(sysOperLogRequest); + PageInfo pageInfo; + pageInfo = new PageInfo<>(selectOperLogList); + PageSimpleResponse pageSimpleResponse = new PageSimpleResponse<>(); + pageSimpleResponse.setTotal(pageInfo.getTotal()); + pageSimpleResponse.setList(selectOperLogList); + return ResultVOUtils.success(pageSimpleResponse); + } + + + /** + * 批量删除操作日志记录 + * + * @param operIds 日志ids + */ + @Log(title = "操作日志", businessType = BusinessType.DELETE) + @SaCheckPermission("monitor:operlog:remove") + @DeleteMapping("/{operIds}") + public BaseResponse remove(@PathVariable Long[] operIds) { + + int i = operLogService.deleteOperLogByIds(operIds); + return ResultVOUtils.success("删除成功!"); + } + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysLogininforMapper.java b/api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysLogininforMapper.java new file mode 100644 index 00000000..2f4461f2 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysLogininforMapper.java @@ -0,0 +1,31 @@ +package com.glxp.api.admin.dao.monitor; + +import com.glxp.api.admin.entity.monitor.SysLogininfor; +import com.glxp.api.admin.req.monitor.SysLogininforRequest; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 系统访问日志情况信息 数据层 + */ +@Mapper +public interface SysLogininforMapper { + + + int insert(SysLogininfor sysLogininfor); + + int deleteBatchIds(@Param("infoIds") List infoIds); + + List selectLogininforList(SysLogininforRequest logininforRequest); + + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + void insertLogininfor(SysLogininfor logininfor); + + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysOperLogMapper.java b/api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysOperLogMapper.java new file mode 100644 index 00000000..b0b78313 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/dao/monitor/SysOperLogMapper.java @@ -0,0 +1,28 @@ +package com.glxp.api.admin.dao.monitor; + + +import com.glxp.api.admin.entity.monitor.SysOperLog; +import com.glxp.api.admin.req.monitor.SysOperLogRequest; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 操作日志 数据层 + */ +@Mapper +public interface SysOperLogMapper { + + List selectList(SysOperLogRequest sysOperLogRequest); + + int insert(SysOperLog sysOperLog); + + int deleteBatchIds(@Param("ids") List ids); + + int delete(Long id); + + SysOperLog selectById(Long id); + + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/OperLogDTO.java b/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/OperLogDTO.java new file mode 100644 index 00000000..fc6c4a4b --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/OperLogDTO.java @@ -0,0 +1,102 @@ +package com.glxp.api.admin.entity.monitor; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +/** + * 通用操作日志实体 + */ + +@Data +public class OperLogDTO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 日志主键 + */ + private Long operId; + + /** + * 操作模块 + */ + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + private Integer businessType; + + /** + * 业务类型数组 + */ + private Integer[] businessTypes; + + /** + * 请求方法 + */ + private String method; + + /** + * 请求方式 + */ + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + private Integer operatorType; + + /** + * 操作人员 + */ + private String operName; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 请求url + */ + private String operUrl; + + /** + * 操作地址 + */ + private String operIp; + + /** + * 操作地点 + */ + private String operLocation; + + /** + * 请求参数 + */ + private String operParam; + + /** + * 返回参数 + */ + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + private Integer status; + + /** + * 错误消息 + */ + private String errorMsg; + + /** + * 操作时间 + */ + private Date operTime; + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysLogininfor.java b/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysLogininfor.java new file mode 100644 index 00000000..74563fb8 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysLogininfor.java @@ -0,0 +1,68 @@ +package com.glxp.api.admin.entity.monitor; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 系统访问记录表 sys_logininfor + */ + +@Data +public class SysLogininfor implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * ID + */ + private Long infoId; + + /** + * 用户账号 + */ + private String userName; + + /** + * 登录状态 0成功 1失败 + */ + private String status; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + /** + * 提示消息 + */ + private String msg; + + /** + * 访问时间 + */ + private Date loginTime; + + /** + * 请求参数 + */ + private Map params = new HashMap<>(); + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysOperLog.java b/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysOperLog.java new file mode 100644 index 00000000..3d63ac2f --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/entity/monitor/SysOperLog.java @@ -0,0 +1,109 @@ +package com.glxp.api.admin.entity.monitor; + +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 操作日志记录表 oper_log + */ + +@Data +public class SysOperLog implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 日志主键 + */ + private Long operId; + + /** + * 操作模块 + */ + private String title; + + /** + * 业务类型(0其它 1新增 2修改 3删除) + */ + private Integer businessType; + + /** + * 业务类型数组 + */ + private Integer[] businessTypes; + + /** + * 请求方法 + */ + private String method; + + /** + * 请求方式 + */ + private String requestMethod; + + /** + * 操作类别(0其它 1后台用户 2手机端用户) + */ + private Integer operatorType; + + /** + * 操作人员 + */ + private String operName; + + /** + * 部门名称 + */ + private String deptName; + + /** + * 请求url + */ + private String operUrl; + + /** + * 操作地址 + */ + private String operIp; + + /** + * 操作地点 + */ + private String operLocation; + + /** + * 请求参数 + */ + private String operParam; + + /** + * 返回参数 + */ + private String jsonResult; + + /** + * 操作状态(0正常 1异常) + */ + private Integer status; + + /** + * 错误消息 + */ + private String errorMsg; + + /** + * 操作时间 + */ + private Date operTime; + + /** + * 请求参数 + */ + private Map params = new HashMap<>(); + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysLogininforRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysLogininforRequest.java new file mode 100644 index 00000000..25157324 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysLogininforRequest.java @@ -0,0 +1,21 @@ +package com.glxp.api.admin.req.monitor; + +import com.glxp.api.admin.req.ListPageRequest; +import lombok.Data; + +import java.util.Date; + +@Data +public class SysLogininforRequest extends ListPageRequest { + + private Long infoId; + + private String userName; + + private String status; + + private String ipaddr; + + private String loginLocation; + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysOperLogRequest.java b/api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysOperLogRequest.java new file mode 100644 index 00000000..fa80dac2 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/req/monitor/SysOperLogRequest.java @@ -0,0 +1,34 @@ +package com.glxp.api.admin.req.monitor; + +import com.glxp.api.admin.req.ListPageRequest; +import lombok.Data; + +import java.util.Date; + +@Data +public class SysOperLogRequest extends ListPageRequest { + + private Long operId; + + private String title; + + private Integer businessType; + + private String method; + + private String requestMethod; + + private Integer operatorType; + + private String operName; + + private String deptName; + + private String operUrl; + + private String operIp; + + private Integer status; + + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysLogininforService.java b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysLogininforService.java new file mode 100644 index 00000000..79879425 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysLogininforService.java @@ -0,0 +1,35 @@ +package com.glxp.api.admin.service.monitor; + + +import com.glxp.api.admin.entity.monitor.SysLogininfor; +import com.glxp.api.admin.req.monitor.SysLogininforRequest; + +import java.util.List; + +/** + * 系统访问日志情况信息 服务层 + * + * @author Lion Li + */ +public interface ISysLogininforService { + + + List selectLogininforList(SysLogininforRequest logininforRequest); + + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + void insertLogininfor(SysLogininfor logininfor); + + + /** + * 批量删除系统登录日志 + * + * @param infoIds 需要删除的登录日志ID + * @return 结果 + */ + int deleteLogininforByIds(List infoIds); + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysOperLogService.java b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysOperLogService.java new file mode 100644 index 00000000..723714a7 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/ISysOperLogService.java @@ -0,0 +1,46 @@ +package com.glxp.api.admin.service.monitor; + + +import com.glxp.api.admin.entity.monitor.SysOperLog; +import com.glxp.api.admin.req.monitor.SysOperLogRequest; + +import java.util.List; + +/** + * 操作日志 服务层 + */ +public interface ISysOperLogService { + + + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + void insertOperlog(SysOperLog operLog); + + /** + * 查询系统操作日志集合 + * + * @param operLog 操作日志对象 + * @return 操作日志集合 + */ + List selectOperLogList(SysOperLogRequest sysOperLogRequest); + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + int deleteOperLogByIds(Long[] operIds); + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + SysOperLog selectOperLogById(Long operId); + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/monitor/LogininforService.java b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/LogininforService.java new file mode 100644 index 00000000..3b9a5300 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/LogininforService.java @@ -0,0 +1,12 @@ +package com.glxp.api.admin.service.monitor; + +import javax.servlet.http.HttpServletRequest; + +/** + * 通用 系统访问日志 + */ +public interface LogininforService { + + void recordLogininfor(String username, String status, String message, + HttpServletRequest request, Object... args); +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/monitor/OperLogService.java b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/OperLogService.java new file mode 100644 index 00000000..8cab4bf8 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/OperLogService.java @@ -0,0 +1,13 @@ +package com.glxp.api.admin.service.monitor; + +import com.glxp.api.admin.entity.monitor.OperLogDTO; +import org.springframework.scheduling.annotation.Async; + +/** + * 通用 操作日志 + */ +public interface OperLogService { + + @Async + void recordOper(OperLogDTO operLogDTO); +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysLogininforServiceImpl.java b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysLogininforServiceImpl.java new file mode 100644 index 00000000..5d25517c --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysLogininforServiceImpl.java @@ -0,0 +1,113 @@ +package com.glxp.api.admin.service.monitor.impl; + +import cn.hutool.http.useragent.UserAgent; +import cn.hutool.http.useragent.UserAgentUtil; +import com.github.pagehelper.PageHelper; +import com.glxp.api.admin.constant.Constant; +import com.glxp.api.admin.dao.monitor.SysLogininforMapper; +import com.glxp.api.admin.entity.monitor.SysLogininfor; +import com.glxp.api.admin.req.monitor.SysLogininforRequest; +import com.glxp.api.admin.service.monitor.ISysLogininforService; +import com.glxp.api.admin.service.monitor.LogininforService; +import com.glxp.api.admin.util.AddressUtils; +import com.glxp.api.admin.util.ServletUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.util.Date; +import java.util.List; + +/** + * 系统访问日志情况信息 服务层处理 + */ +@RequiredArgsConstructor +@Slf4j +@Service +public class SysLogininforServiceImpl implements ISysLogininforService, LogininforService { + + private final SysLogininforMapper baseMapper; + + /** + * 记录登录信息 + * + * @param username 用户名 + * @param status 状态 + * @param message 消息 + * @param args 列表 + */ + @Async + @Override + public void recordLogininfor(final String username, final String status, final String message, + HttpServletRequest request, final Object... args) { + final UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent")); + final String ip = ServletUtils.getClientIP(request); + + String address = AddressUtils.getRealAddressByIP(ip); + StringBuilder s = new StringBuilder(); + s.append(getBlock(ip)); + s.append(address); + s.append(getBlock(username)); + s.append(getBlock(status)); + s.append(getBlock(message)); + // 打印信息到日志 + log.info(s.toString(), args); + // 获取客户端操作系统 + String os = userAgent.getOs().getName(); + // 获取客户端浏览器 + String browser = userAgent.getBrowser().getName(); + // 封装对象 + SysLogininfor logininfor = new SysLogininfor(); + logininfor.setUserName(username); + logininfor.setIpaddr(ip); + logininfor.setLoginLocation(address); + logininfor.setBrowser(browser); + logininfor.setOs(os); + logininfor.setMsg(message); + // 日志状态 + if (StringUtils.equalsAny(status, Constant.LOGIN_SUCCESS, Constant.LOGOUT, Constant.REGISTER)) { + logininfor.setStatus(Constant.SUCCESS); + } else if (Constant.LOGIN_FAIL.equals(status)) { + logininfor.setStatus(Constant.FAIL); + } + // 插入数据 + insertLogininfor(logininfor); + } + + private String getBlock(Object msg) { + if (msg == null) { + msg = ""; + } + return "[" + msg.toString() + "]"; + } + + @Override + public List selectLogininforList(SysLogininforRequest logininfor) { + if (logininfor.getPage() != null) { + int offset = (logininfor.getPage() - 1) * logininfor.getLimit(); + PageHelper.offsetPage(offset, logininfor.getLimit()); + } + return baseMapper.selectLogininforList(logininfor); + } + + /** + * 新增系统登录日志 + * + * @param logininfor 访问日志对象 + */ + @Override + public void insertLogininfor(SysLogininfor logininfor) { + logininfor.setLoginTime(new Date()); + baseMapper.insert(logininfor); + } + + @Override + public int deleteLogininforByIds(List infoIds) { + return baseMapper.deleteBatchIds(infoIds); + } + + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysOperLogServiceImpl.java b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysOperLogServiceImpl.java new file mode 100644 index 00000000..8cf496cf --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/service/monitor/impl/SysOperLogServiceImpl.java @@ -0,0 +1,90 @@ +package com.glxp.api.admin.service.monitor.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.StrUtil; +import com.github.pagehelper.PageHelper; +import com.glxp.api.admin.dao.monitor.SysOperLogMapper; +import com.glxp.api.admin.entity.monitor.OperLogDTO; +import com.glxp.api.admin.entity.monitor.SysOperLog; +import com.glxp.api.admin.req.monitor.SysOperLogRequest; +import com.glxp.api.admin.service.monitor.ISysOperLogService; +import com.glxp.api.admin.service.monitor.OperLogService; +import com.glxp.api.admin.util.AddressUtils; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * 操作日志 服务层处理 + */ +@RequiredArgsConstructor +@Service +public class SysOperLogServiceImpl implements ISysOperLogService, OperLogService { + + private final SysOperLogMapper baseMapper; + + /** + * 操作日志记录 + * + * @param operLogDTO 操作日志信息 + */ + @Async + @Override + public void recordOper(final OperLogDTO operLogDTO) { + SysOperLog operLog = BeanUtil.toBean(operLogDTO, SysOperLog.class); + // 远程查询操作地点 + operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp())); + insertOperlog(operLog); + } + + @Override + public List selectOperLogList(SysOperLogRequest sysOperLogRequest) { + if (sysOperLogRequest.getPage() != null) { + int offset = (sysOperLogRequest.getPage() - 1) * sysOperLogRequest.getLimit(); + PageHelper.offsetPage(offset, sysOperLogRequest.getLimit()); + } + return baseMapper.selectList(sysOperLogRequest); + } + + /** + * 新增操作日志 + * + * @param operLog 操作日志对象 + */ + @Override + public void insertOperlog(SysOperLog operLog) { + operLog.setOperTime(new Date()); + baseMapper.insert(operLog); + } + + + /** + * 批量删除系统操作日志 + * + * @param operIds 需要删除的操作日志ID + * @return 结果 + */ + @Override + public int deleteOperLogByIds(Long[] operIds) { + return baseMapper.deleteBatchIds(Arrays.asList(operIds)); + } + + /** + * 查询操作日志详细 + * + * @param operId 操作ID + * @return 操作日志对象 + */ + @Override + public SysOperLog selectOperLogById(Long operId) { + return baseMapper.selectById(operId); + } + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/util/AddressUtils.java b/api-admin/src/main/java/com/glxp/api/admin/util/AddressUtils.java new file mode 100644 index 00000000..b28f0c66 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/util/AddressUtils.java @@ -0,0 +1,58 @@ +package com.glxp.api.admin.util; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.net.NetUtil; +import cn.hutool.http.HtmlUtil; +import cn.hutool.http.HttpUtil; +import com.glxp.api.admin.config.RuoYiConfig; +import com.glxp.api.admin.constant.Constant; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.tomcat.util.bcel.Const; + +/** + * 获取地址类 + */ +@Slf4j +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class AddressUtils { + + // IP地址查询 + public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp"; + + // 未知地址 + public static final String UNKNOWN = "XX XX"; + + public static String getRealAddressByIP(String ip) { + String address = UNKNOWN; + if (StringUtils.isBlank(ip)) { + return address; + } + // 内网不查询 + ip = "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : HtmlUtil.cleanHtmlTag(ip); + if (NetUtil.isInnerIP(ip)) { + return "内网IP"; + } + if (RuoYiConfig.isAddressEnabled()) { + try { + String rspStr = HttpUtil.createGet(IP_URL) + .body("ip=" + ip + "&json=true", Constant.GBK) + .execute() + .body(); + if (StringUtils.isEmpty(rspStr)) { + log.error("获取地理位置异常 {}", ip); + return UNKNOWN; + } + Dict obj = JsonUtils.parseMap(rspStr); + String region = obj.getStr("pro"); + String city = obj.getStr("city"); + return String.format("%s %s", region, city); + } catch (Exception e) { + log.error("获取地理位置异常 {}", ip); + } + } + return UNKNOWN; + } +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/util/JsonUtils.java b/api-admin/src/main/java/com/glxp/api/admin/util/JsonUtils.java new file mode 100644 index 00000000..a02af7cd --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/util/JsonUtils.java @@ -0,0 +1,110 @@ +package com.glxp.api.admin.util; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.MismatchedInputException; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * JSON 工具类 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class JsonUtils { + + private static final ObjectMapper OBJECT_MAPPER = SpringUtils.getBean(ObjectMapper.class); + + public static ObjectMapper getObjectMapper() { + return OBJECT_MAPPER; + } + + public static String toJsonString(Object object) { + if (ObjectUtil.isNull(object)) { + return null; + } + try { + return OBJECT_MAPPER.writeValueAsString(object); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, Class clazz) { + if (StringUtils.isEmpty(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(byte[] bytes, Class clazz) { + if (ArrayUtil.isEmpty(bytes)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(bytes, clazz); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static T parseObject(String text, TypeReference typeReference) { + if (StringUtils.isBlank(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, typeReference); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static Dict parseMap(String text) { + if (StringUtils.isBlank(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class)); + } catch (MismatchedInputException e) { + // 类型不匹配说明不是json + return null; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static List parseArrayMap(String text) { + if (StringUtils.isBlank(text)) { + return null; + } + try { + return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, Dict.class)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static List parseArray(String text, Class clazz) { + if (StringUtils.isEmpty(text)) { + return new ArrayList<>(); + } + try { + return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/util/MessageUtils.java b/api-admin/src/main/java/com/glxp/api/admin/util/MessageUtils.java new file mode 100644 index 00000000..e43c3f51 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/util/MessageUtils.java @@ -0,0 +1,26 @@ +package com.glxp.api.admin.util; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.context.MessageSource; +import org.springframework.context.i18n.LocaleContextHolder; + +/** + * 获取i18n资源文件 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class MessageUtils { + + private static final MessageSource MESSAGE_SOURCE = SpringUtils.getBean(MessageSource.class); + + /** + * 根据消息键和参数 获取消息 委托给spring messageSource + * + * @param code 消息键 + * @param args 参数 + * @return 获取国际化翻译值 + */ + public static String message(String code, Object... args) { + return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale()); + } +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/util/ServletUtils.java b/api-admin/src/main/java/com/glxp/api/admin/util/ServletUtils.java new file mode 100644 index 00000000..0a29c3ef --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/util/ServletUtils.java @@ -0,0 +1,173 @@ +package com.glxp.api.admin.util; + +import cn.hutool.core.convert.Convert; +import cn.hutool.extra.servlet.ServletUtil; +import cn.hutool.http.HttpStatus; +import com.glxp.api.admin.constant.Constant; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.MediaType; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +/** + * 客户端工具类 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class ServletUtils extends ServletUtil { + + /** + * 获取String参数 + */ + public static String getParameter(String name) { + return getRequest().getParameter(name); + } + + /** + * 获取String参数 + */ + public static String getParameter(String name, String defaultValue) { + return Convert.toStr(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name) { + return Convert.toInt(getRequest().getParameter(name)); + } + + /** + * 获取Integer参数 + */ + public static Integer getParameterToInt(String name, Integer defaultValue) { + return Convert.toInt(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name) { + return Convert.toBool(getRequest().getParameter(name)); + } + + /** + * 获取Boolean参数 + */ + public static Boolean getParameterToBool(String name, Boolean defaultValue) { + return Convert.toBool(getRequest().getParameter(name), defaultValue); + } + + /** + * 获取request + */ + public static HttpServletRequest getRequest() { + return getRequestAttributes().getRequest(); + } + + /** + * 获取response + */ + public static HttpServletResponse getResponse() { + return getRequestAttributes().getResponse(); + } + + /** + * 获取session + */ + public static HttpSession getSession() { + return getRequest().getSession(); + } + + public static ServletRequestAttributes getRequestAttributes() { + RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); + return (ServletRequestAttributes) attributes; + } + + /** + * 将字符串渲染到客户端 + * + * @param response 渲染对象 + * @param string 待渲染的字符串 + */ + public static void renderString(HttpServletResponse response, String string) { + try { + response.setStatus(HttpStatus.HTTP_OK); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding(StandardCharsets.UTF_8.toString()); + response.getWriter().print(string); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 是否是Ajax异步请求 + * + * @param request + */ + public static boolean isAjaxRequest(HttpServletRequest request) { + + String accept = request.getHeader("accept"); + if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) { + return true; + } + + String xRequestedWith = request.getHeader("X-Requested-With"); + if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) { + return true; + } + + String uri = request.getRequestURI(); + if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) { + return true; + } + + String ajax = request.getParameter("__ajax"); + return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml"); + } + + public static String getClientIP() { + return getClientIP(getRequest()); + } + + /** + * 内容编码 + * + * @param str 内容 + * @return 编码后的内容 + */ + public static String urlEncode(String str) { + try { + return URLEncoder.encode(str, Constant.UTF8); + } catch (UnsupportedEncodingException e) { + return StringUtils.EMPTY; + } + } + + /** + * 内容解码 + * + * @param str 内容 + * @return 解码后的内容 + */ + public static String urlDecode(String str) { + try { + return URLDecoder.decode(str, Constant.UTF8); + } catch (UnsupportedEncodingException e) { + return StringUtils.EMPTY; + } + } + +} diff --git a/api-admin/src/main/java/com/glxp/api/admin/util/SpringUtils.java b/api-admin/src/main/java/com/glxp/api/admin/util/SpringUtils.java new file mode 100644 index 00000000..161e7572 --- /dev/null +++ b/api-admin/src/main/java/com/glxp/api/admin/util/SpringUtils.java @@ -0,0 +1,63 @@ +package com.glxp.api.admin.util; + +import cn.hutool.extra.spring.SpringUtil; +import org.springframework.aop.framework.AopContext; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.stereotype.Component; + +/** + * spring工具类 + */ +@Component +public final class SpringUtils extends SpringUtil { + + /** + * 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true + * + * @param name + * @return boolean + */ + public static boolean containsBean(String name) { + return getBeanFactory().containsBean(name); + } + + /** + * 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 + * 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { + return getBeanFactory().isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException { + return getBeanFactory().getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { + return getBeanFactory().getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) { + return (T) AopContext.currentProxy(); + } + +} diff --git a/api-admin/src/main/resources/mybatis/mapper/monitor/SysLogininforMapper.xml b/api-admin/src/main/resources/mybatis/mapper/monitor/SysLogininforMapper.xml new file mode 100644 index 00000000..185b760b --- /dev/null +++ b/api-admin/src/main/resources/mybatis/mapper/monitor/SysLogininforMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO sys_logininfor( `user_name`, `status`, ipaddr, `login_location`, browser, `os`, msg + , login_time) + values (#{userName}, + #{status}, #{ipaddr}, + #{loginLocation}, #{browser}, #{os}, #{msg}, #{loginTime}) + + + + delete + from sys_logininfor + where info_id = #{id} + + + + + delete + from sys_logininfor + where info_id in + + #{item} + + + + + diff --git a/api-admin/src/main/resources/mybatis/mapper/monitor/SysOperLogMapper.xml b/api-admin/src/main/resources/mybatis/mapper/monitor/SysOperLogMapper.xml new file mode 100644 index 00000000..7b12a898 --- /dev/null +++ b/api-admin/src/main/resources/mybatis/mapper/monitor/SysOperLogMapper.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO sys_oper_log(`oper_id`, `title`, business_type, `method`, `request_method`, operator_type + , oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, + error_msg, oper_time) + values ( #{operId}, + #{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName} + , #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status} + , #{errorMsg}, #{operTime}) + + + + delete + from sys_oper_log + where oper_id = #{id} + + + + + delete + from sys_oper_log + where oper_id in + + #{item} + + + + +