增加访问日志的 dubbo 实现

This commit is contained in:
YunaiV 2020-04-20 19:55:39 +08:00
parent e36b32a97d
commit bdff67b7b3
37 changed files with 635 additions and 56 deletions

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>common</artifactId>
<groupId>cn.iocoder.mall</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mall-spring-boot-starter-web</artifactId>
<dependencies>
<!-- Spring 核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,131 @@
package cn.iocoder.mall.web.handler;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.exception.ServiceException;
import cn.iocoder.common.framework.util.ExceptionUtil;
import cn.iocoder.common.framework.util.HttpUtil;
import cn.iocoder.common.framework.util.MallUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.system.api.SystemLogService;
import cn.iocoder.mall.system.api.dto.systemlog.AccessLogAddDTO;
import cn.iocoder.mall.system.api.dto.systemlog.ExceptionLogAddDTO;
import com.alibaba.fastjson.JSON;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Metrics;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.util.Assert;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolationException;
import java.util.Date;
@ControllerAdvice
public class GlobalExceptionHandler {
// /**
// * 异常总数 Metrics
// */
// private static final Counter EXCEPTION_COUNTER = Metrics.counter("mall.exception.total");
private Logger logger = LoggerFactory.getLogger(getClass());
@Value("${spring.application.name}")
private String applicationName;
@Reference(validation = "true", version = "${dubbo.consumer.AdminAccessLogService.version:1.0.0}")
private SystemLogService systemLogService;
// 逻辑异常
@ResponseBody
@ExceptionHandler(value = ServiceException.class)
public CommonResult serviceExceptionHandler(HttpServletRequest req, ServiceException ex) {
logger.debug("[serviceExceptionHandler]", ex);
return CommonResult.error(ex.getCode(), ex.getMessage());
}
// Spring MVC 参数不正确
@ResponseBody
@ExceptionHandler(value = MissingServletRequestParameterException.class)
public CommonResult missingServletRequestParameterExceptionHandler(HttpServletRequest req, MissingServletRequestParameterException ex) {
logger.warn("[missingServletRequestParameterExceptionHandler]", ex);
return CommonResult.error(SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getCode(), SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getMessage() + ":" + ex.getMessage());
}
@ResponseBody
@ExceptionHandler(value = ConstraintViolationException.class)
public CommonResult constraintViolationExceptionHandler(HttpServletRequest req, ConstraintViolationException ex) {
logger.info("[constraintViolationExceptionHandler]", ex);
// TODO 芋艿后续要想一个更好的方式
// 拼接详细报错
StringBuilder detailMessage = new StringBuilder("\n\n详细错误如下");
ex.getConstraintViolations().forEach(constraintViolation -> detailMessage.append("\n").append(constraintViolation.getMessage()));
return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getMessage()
+ detailMessage.toString());
}
// TODO 芋艿应该还有其它的异常需要进行翻译
@ResponseBody
@ExceptionHandler(value = Exception.class)
public CommonResult exceptionHandler(HttpServletRequest req, Exception e) {
logger.error("[exceptionHandler]", e);
// 插入异常日志
ExceptionLogAddDTO exceptionLog = new ExceptionLogAddDTO();
try {
// 增加异常计数 metrics
EXCEPTION_COUNTER.increment();
// 初始化 exceptionLog
initExceptionLog(exceptionLog, req, e);
// 执行插入 exceptionLog
addExceptionLog(exceptionLog);
} catch (Throwable th) {
logger.error("[exceptionHandler][插入访问日志({}) 发生异常({})", JSON.toJSONString(exceptionLog), ExceptionUtils.getRootCauseMessage(th));
}
// 返回 ERROR CommonResult
return CommonResult.error(SysErrorCodeEnum.SYS_ERROR.getCode(), SysErrorCodeEnum.SYS_ERROR.getMessage());
}
private void initExceptionLog(ExceptionLogAddDTO exceptionLog, HttpServletRequest request, Exception e) {
// 设置用户编号
exceptionLog.setUserId(MallUtil.getUserId(request));
if (exceptionLog.getUserId() == null) {
exceptionLog.setUserId(AccessLogAddDTO.USER_ID_NULL);
}
exceptionLog.setUserType(MallUtil.getUserType(request));
// 设置异常字段
exceptionLog.setExceptionName(e.getClass().getName());
exceptionLog.setExceptionMessage(ExceptionUtil.getMessage(e));
exceptionLog.setExceptionRootCauseMessage(ExceptionUtil.getRootCauseMessage(e));
exceptionLog.setExceptionStackTrace(ExceptionUtil.getStackTrace(e));
StackTraceElement[] stackTraceElements = e.getStackTrace();
Assert.notEmpty(stackTraceElements, "异常 stackTraceElements 不能为空");
StackTraceElement stackTraceElement = stackTraceElements[0];
exceptionLog.setExceptionClassName(stackTraceElement.getClassName());
exceptionLog.setExceptionFileName(stackTraceElement.getFileName());
exceptionLog.setExceptionMethodName(stackTraceElement.getMethodName());
exceptionLog.setExceptionLineNumber(stackTraceElement.getLineNumber());
// 设置其它字段
exceptionLog.setTraceId(MallUtil.getTraceId())
.setApplicationName(applicationName)
.setUri(request.getRequestURI()) // TODO 提升如果想要优化可以使用 Swagger @ApiOperation 注解
.setQueryString(HttpUtil.buildQueryString(request))
.setMethod(request.getMethod())
.setUserAgent(HttpUtil.getUserAgent(request))
.setIp(HttpUtil.getIp(request))
.setExceptionTime(new Date());
}
@Async
public void addExceptionLog(ExceptionLogAddDTO exceptionLog) {
systemLogService.addExceptionLog(exceptionLog);
}
}

View File

@ -0,0 +1,31 @@
package cn.iocoder.mall.web.handler;
import cn.iocoder.common.framework.util.MallUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@ControllerAdvice
public class GlobalResponseBodyHandler implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
if (returnType.getMethod() == null) {
return false;
}
return returnType.getMethod().getReturnType() == CommonResult.class;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
MallUtil.setCommonResult(((ServletServerHttpRequest) request).getServletRequest(), (CommonResult) body);
return body;
}
}

View File

@ -0,0 +1,102 @@
package cn.iocoder.mall.web.interceptor;
import cn.iocoder.common.framework.util.HttpUtil;
import cn.iocoder.common.framework.util.MallUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.system.api.SystemLogService;
import cn.iocoder.mall.system.api.dto.systemlog.AccessLogAddDTO;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
/**
* 访问日志拦截器
*/
@Component
public class AccessLogInterceptor extends HandlerInterceptorAdapter {
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 开始时间
*/
private static final ThreadLocal<Date> START_TIME = new ThreadLocal<>();
@Reference(validation = "true", version = "${dubbo.consumer.AdminAccessLogService.version:1.0.0}")
private SystemLogService systemAccessLogService;
@Value("${spring.application.name}")
private String applicationName;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 记录当前时间
START_TIME.set(new Date());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
AccessLogAddDTO accessLog = new AccessLogAddDTO();
try {
// 初始化 accessLog
initAccessLog(accessLog, request);
// 执行插入 accessLog
addAccessLog(accessLog);
// TODO 提升暂时不考虑 ELK 的方案而是基于 MySQL 存储如果访问日志比较多需要定期归档
} catch (Throwable th) {
logger.error("[afterCompletion][插入访问日志({}) 发生异常({})", JSON.toJSONString(accessLog), ExceptionUtils.getRootCauseMessage(th));
} finally {
clear();
}
}
private void initAccessLog(AccessLogAddDTO accessLog, HttpServletRequest request) {
// 设置用户编号
accessLog.setUserId(MallUtil.getUserId(request));
if (accessLog.getUserId() == null) {
accessLog.setUserId(AccessLogAddDTO.USER_ID_NULL);
}
accessLog.setUserType(MallUtil.getUserType(request));
// 设置访问结果
CommonResult result = MallUtil.getCommonResult(request);
Assert.isTrue(result != null, "result 必须非空");
accessLog.setErrorCode(result.getCode())
.setErrorMessage(result.getMessage());
// 设置其它字段
accessLog.setTraceId(MallUtil.getTraceId())
.setApplicationName(applicationName)
.setUri(request.getRequestURI()) // TODO 提升如果想要优化可以使用 Swagger @ApiOperation 注解
.setQueryString(HttpUtil.buildQueryString(request))
.setMethod(request.getMethod())
.setUserAgent(HttpUtil.getUserAgent(request))
.setIp(HttpUtil.getIp(request))
.setStartTime(START_TIME.get())
.setResponseTime((int) (System.currentTimeMillis() - accessLog.getStartTime().getTime())); // 默认响应时间设为 0
}
@Async // 异步入库
public void addAccessLog(AccessLogAddDTO accessLog) {
try {
systemAccessLogService.addAccessLog(accessLog);
} catch (Throwable th) {
logger.error("[addAccessLog][插入访问日志({}) 发生异常({})", JSON.toJSONString(accessLog), ExceptionUtils.getRootCauseMessage(th));
}
}
private static void clear() {
START_TIME.remove();
}
}

View File

@ -0,0 +1 @@
package cn.iocoder.mall.web;

View File

@ -16,6 +16,7 @@
<module>mall-spring-boot</module> <module>mall-spring-boot</module>
<module>common-dependencies</module> <module>common-dependencies</module>
<module>mall-spring-boot-starter-swagger</module> <module>mall-spring-boot-starter-swagger</module>
<module>mall-spring-boot-starter-web</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>

View File

@ -18,6 +18,11 @@
<artifactId>system-rest</artifactId> <artifactId>system-rest</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-rpc</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies> </dependencies>

View File

@ -11,7 +11,7 @@ public class SystemApplication {
* 设置需要读取的配置文件的名字 * 设置需要读取的配置文件的名字
* 基于 {@link org.springframework.boot.context.config.ConfigFileApplicationListener#CONFIG_NAME_PROPERTY} 实现 * 基于 {@link org.springframework.boot.context.config.ConfigFileApplicationListener#CONFIG_NAME_PROPERTY} 实现
*/ */
private static final String CONFIG_NAME_VALUE = "biz,rest,application"; private static final String CONFIG_NAME_VALUE = "biz,rest,rpc,application";
public static void main(String[] args) { public static void main(String[] args) {
// 设置环境变量 // 设置环境变量

View File

@ -1,3 +1,7 @@
spring: spring:
# Application 的配置项
application: application:
name: admin-application name: admin-application
# Profile 的配置项
profiles:
active: test

View File

@ -1 +0,0 @@
package cn.iocoder.mall.system.biz.bo;

View File

@ -1,4 +1,4 @@
package cn.iocoder.mall.system.biz.convert; package cn.iocoder.mall.system.biz.convert.account;
import cn.iocoder.mall.system.biz.bo.account.AccountBO; import cn.iocoder.mall.system.biz.bo.account.AccountBO;
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO; import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;

View File

@ -1,4 +1,4 @@
package cn.iocoder.mall.system.biz.convert; package cn.iocoder.mall.system.biz.convert.admin;
import cn.iocoder.mall.system.biz.bo.admin.AdminBO; import cn.iocoder.mall.system.biz.bo.admin.AdminBO;
import cn.iocoder.mall.system.biz.dataobject.admin.AdminDO; import cn.iocoder.mall.system.biz.dataobject.admin.AdminDO;

View File

@ -1,4 +1,4 @@
package cn.iocoder.mall.system.biz.convert; package cn.iocoder.mall.system.biz.convert.oauth2;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO; import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO; import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO;

View File

@ -0,0 +1,15 @@
package cn.iocoder.mall.system.biz.convert.systemlog;
import cn.iocoder.mall.system.biz.dataobject.system.AccessLogDO;
import cn.iocoder.mall.system.biz.dto.system.AccessLogAddDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SystemLogConvert {
SystemLogConvert INSTANCE = Mappers.getMapper(SystemLogConvert.class);
AccessLogDO convert(AccessLogAddDTO accessLogAddDTO);
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.mall.system.biz.convert; package cn.iocoder.mall.system.biz.convert.user;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO; import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.user.UserAuthenticateBO; import cn.iocoder.mall.system.biz.bo.user.UserAuthenticateBO;

View File

@ -0,0 +1,15 @@
package cn.iocoder.mall.system.biz.dao.system;
import cn.iocoder.mall.system.biz.dataobject.system.AccessLogDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface AccessLogMapper extends BaseMapper<AccessLogDO> {
// default IPage<AccessLogDO> selectPage(AccessLogPageDTO accessLogPageDTO) {
// return selectPage(new Page<>(accessLogPageDTO.getPageNo(), accessLogPageDTO.getPageSize()),
// new QueryWrapperX<AccessLogDO>().eqIfPresent("user_id", accessLogPageDTO.getUserId()));
// }
}

View File

@ -1,10 +1,10 @@
package cn.iocoder.mall.admin.dataobject; package cn.iocoder.mall.system.biz.dataobject.system;
import cn.iocoder.common.framework.dataobject.BaseDO; import cn.iocoder.common.framework.dataobject.BaseDO;
import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.system.api.dto.systemlog.AccessLogAddDTO;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
import java.util.Date; import java.util.Date;
@ -13,10 +13,16 @@ import java.util.Date;
* 访问日志 DO * 访问日志 DO
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true) @Accessors(chain = true)
@TableName("access_log") @TableName("access_log")
public class AccessLogDO extends BaseDO { public class AccessLogDO extends BaseDO {
/**
* 账号编号 -
*/
public static final Integer ACCOUNT_ID_NULL = 0;
/** /**
* 编号 * 编号
*/ */
@ -28,11 +34,11 @@ public class AccessLogDO extends BaseDO {
*/ */
private String traceId; private String traceId;
/** /**
* 用户编号. * 账号编号
* *
* 当管理员为空时该值为 {@link AccessLogAddDTO#USER_ID_NULL} * 空值 {@link #ACCOUNT_ID_NULL}
*/ */
private Integer userId; private Integer accountId;
/** /**
* 用户类型 * 用户类型
*/ */
@ -40,7 +46,7 @@ public class AccessLogDO extends BaseDO {
/** /**
* 应用名 * 应用名
* *
* 目前读取 spring.application.name * 目前读取 `spring.application.name` 配置项
*/ */
private String applicationName; private String applicationName;
/** /**

View File

@ -0,0 +1,45 @@
package cn.iocoder.mall.system.biz.dto.system;
import javax.validation.constraints.NotNull;
import java.util.Date;
/**
* 访问日志添加 DTO
*/
public class AccessLogAddDTO {
/**
* 用户编号 -
*/
public static final Integer ACCOUNT_ID_NULL = 0;
@NotNull(message = "链路追踪编号不能为空")
private String traceId;
/**
* 账号编号
*/
private Integer accountId;
@NotNull(message = "应用名不能为空")
private String applicationName;
@NotNull(message = "访问地址不能为空")
private String uri;
@NotNull(message = "请求参数不能为空")
private String queryString;
@NotNull(message = "http 请求方法不能为空")
private String method;
@NotNull(message = "User-Agent 不能为空")
private String userAgent;
@NotNull(message = "ip 不能为空")
private String ip;
@NotNull(message = "请求时间不能为空")
private Date startTime;
@NotNull(message = "响应时长不能为空")
private Integer responseTime;
@NotNull(message = "错误码不能为空")
private Integer errorCode;
/**
* 错误提示
*/
private String errorMessage;
}

View File

@ -1,8 +1,8 @@
package cn.iocoder.mall.system.biz.service.account.impl; package cn.iocoder.mall.system.biz.service.account;
import cn.iocoder.common.framework.constant.CommonStatusEnum; import cn.iocoder.common.framework.constant.CommonStatusEnum;
import cn.iocoder.mall.system.biz.bo.account.AccountBO; import cn.iocoder.mall.system.biz.bo.account.AccountBO;
import cn.iocoder.mall.system.biz.convert.AccountConvert; import cn.iocoder.mall.system.biz.convert.account.AccountConvert;
import cn.iocoder.mall.system.biz.dao.account.AccountMapper; import cn.iocoder.mall.system.biz.dao.account.AccountMapper;
import cn.iocoder.mall.system.biz.dataobject.account.AccountDO; import cn.iocoder.mall.system.biz.dataobject.account.AccountDO;
import cn.iocoder.mall.system.biz.dto.account.AccountCreateDTO; import cn.iocoder.mall.system.biz.dto.account.AccountCreateDTO;

View File

@ -1,7 +1,7 @@
package cn.iocoder.mall.system.biz.service.admin.impl; package cn.iocoder.mall.system.biz.service.admin;
import cn.iocoder.mall.system.biz.bo.admin.AdminBO; import cn.iocoder.mall.system.biz.bo.admin.AdminBO;
import cn.iocoder.mall.system.biz.convert.AdminConvert; import cn.iocoder.mall.system.biz.convert.admin.AdminConvert;
import cn.iocoder.mall.system.biz.dao.admin.AdminMapper; import cn.iocoder.mall.system.biz.dao.admin.AdminMapper;
import cn.iocoder.mall.system.biz.dataobject.admin.AdminDO; import cn.iocoder.mall.system.biz.dataobject.admin.AdminDO;
import cn.iocoder.mall.system.biz.service.admin.AdminService; import cn.iocoder.mall.system.biz.service.admin.AdminService;

View File

@ -1,4 +1,4 @@
package cn.iocoder.mall.system.biz.service.oauth2.impl; package cn.iocoder.mall.system.biz.service.oauth2;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum; import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil; import cn.iocoder.common.framework.util.ServiceExceptionUtil;

View File

@ -1,11 +1,11 @@
package cn.iocoder.mall.system.biz.service.oauth2.impl; package cn.iocoder.mall.system.biz.service.oauth2;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum; import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil; import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.util.ValidationUtil; import cn.iocoder.common.framework.util.ValidationUtil;
import cn.iocoder.mall.system.biz.bo.account.AccountBO; import cn.iocoder.mall.system.biz.bo.account.AccountBO;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO; import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.convert.OAuth2Convert; import cn.iocoder.mall.system.biz.convert.oauth2.OAuth2Convert;
import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2AccessTokenMapper; import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2AccessTokenMapper;
import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2RefreshTokenMapper; import cn.iocoder.mall.system.biz.dao.oauth2.OAuth2RefreshTokenMapper;
import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO; import cn.iocoder.mall.system.biz.dataobject.oauth2.OAuth2AccessTokenDO;
@ -14,8 +14,6 @@ import cn.iocoder.mall.system.biz.dto.account.AccountCreateDTO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2MobileCodeAuthenticateDTO; import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2MobileCodeAuthenticateDTO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO; import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2UsernameAuthenticateDTO;
import cn.iocoder.mall.system.biz.service.account.AccountService; import cn.iocoder.mall.system.biz.service.account.AccountService;
import cn.iocoder.mall.system.biz.service.oauth2.OAuth2MobileCodeService;
import cn.iocoder.mall.system.biz.service.oauth2.OAuth2Service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;

View File

@ -0,0 +1,9 @@
package cn.iocoder.mall.system.biz.service.system;
import cn.iocoder.mall.system.biz.dto.system.AccessLogAddDTO;
public interface SystemLogService {
void addAccessLog(AccessLogAddDTO accessLogAddDTO);
}

View File

@ -0,0 +1,28 @@
package cn.iocoder.mall.system.biz.service.system;
import cn.iocoder.mall.system.biz.convert.systemlog.SystemLogConvert;
import cn.iocoder.mall.system.biz.dao.system.AccessLogMapper;
import cn.iocoder.mall.system.biz.dataobject.system.AccessLogDO;
import cn.iocoder.mall.system.biz.dto.system.AccessLogAddDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
@Service
public class SystemLogServiceImpl implements SystemLogService {
@Autowired
private AccessLogMapper accessLogMapper;
@Override
public void addAccessLog(AccessLogAddDTO accessLogAddDTO) {
AccessLogDO logDO = SystemLogConvert.INSTANCE.convert(accessLogAddDTO);
if (logDO.getAccountId() == null) {
logDO.setAccountId(AccessLogDO.ACCOUNT_ID_NULL);
}
logDO.setCreateTime(new Date());
accessLogMapper.insert(logDO);
}
}

View File

@ -1,14 +1,13 @@
package cn.iocoder.mall.system.biz.service.user.impl; package cn.iocoder.mall.system.biz.service.user;
import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO; import cn.iocoder.mall.system.biz.bo.ouath2.OAuth2AccessTokenBO;
import cn.iocoder.mall.system.biz.bo.user.UserAuthenticateBO; import cn.iocoder.mall.system.biz.bo.user.UserAuthenticateBO;
import cn.iocoder.mall.system.biz.bo.user.UserBO; import cn.iocoder.mall.system.biz.bo.user.UserBO;
import cn.iocoder.mall.system.biz.convert.UserConvert; import cn.iocoder.mall.system.biz.convert.user.UserConvert;
import cn.iocoder.mall.system.biz.dao.user.UserMapper; import cn.iocoder.mall.system.biz.dao.user.UserMapper;
import cn.iocoder.mall.system.biz.dataobject.user.UserDO; import cn.iocoder.mall.system.biz.dataobject.user.UserDO;
import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2MobileCodeAuthenticateDTO; import cn.iocoder.mall.system.biz.dto.oatuh2.OAuth2MobileCodeAuthenticateDTO;
import cn.iocoder.mall.system.biz.service.oauth2.OAuth2Service; import cn.iocoder.mall.system.biz.service.oauth2.OAuth2Service;
import cn.iocoder.mall.system.biz.service.user.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;

View File

@ -12,6 +12,19 @@ import java.util.Date;
@Accessors(chain = true) @Accessors(chain = true)
public class AdminsOAuth2AuthenticateResponse { public class AdminsOAuth2AuthenticateResponse {
@ApiModel("管理员")
@Data
public static class Admin {
@ApiModelProperty(value = "管理员编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "真实名字", required = true, example = "小王")
private String name;
}
@ApiModel("访问令牌")
@Data @Data
public static class Token { public static class Token {
@ -26,23 +39,12 @@ public class AdminsOAuth2AuthenticateResponse {
} }
@Data
public static class Admin {
@ApiModelProperty(value = "管理员编号", required = true, example = "1")
private Integer id;
@ApiModelProperty(value = "真实名字", required = true, example = "小王")
private String name;
}
/** /**
* TODO 晚点测试下 swagger 的表现 * 管理员
*/ */
private Admin admin; private Admin admin;
/** /**
* TODO 晚点测试下 swagger 的表现 * 访问令牌
*/ */
private Token token; private Token token;

View File

@ -11,5 +11,20 @@
<artifactId>system-rpc-api</artifactId> <artifactId>system-rpc-api</artifactId>
<dependencies>
<!-- Mall 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>common-framework</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
</dependencies>
</project> </project>

View File

@ -0,0 +1,10 @@
package cn.iocoder.mall.system.rpc.api;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.system.rpc.request.system.AccessLogAddRequest;
public interface SystemLogRPC {
CommonResult<Boolean> addAccessLog(AccessLogAddRequest accessLogAddRequest);
}

View File

@ -0,0 +1 @@
package cn.iocoder.mall.system.rpc.request;

View File

@ -0,0 +1,42 @@
package cn.iocoder.mall.system.rpc.request.system;
import javax.validation.constraints.NotNull;
import java.util.Date;
public class AccessLogAddRequest {
/**
* 用户编号 -
*/
public static final Integer ACCOUNT_ID_NULL = 0;
@NotNull(message = "链路追踪编号不能为空")
private String traceId;
/**
* 账号编号
*/
private Integer accountId;
@NotNull(message = "应用名不能为空")
private String applicationName;
@NotNull(message = "访问地址不能为空")
private String uri;
@NotNull(message = "请求参数不能为空")
private String queryString;
@NotNull(message = "http 请求方法不能为空")
private String method;
@NotNull(message = "User-Agent 不能为空")
private String userAgent;
@NotNull(message = "ip 不能为空")
private String ip;
@NotNull(message = "请求时间不能为空")
private Date startTime;
@NotNull(message = "响应时长不能为空")
private Integer responseTime;
@NotNull(message = "错误码不能为空")
private Integer errorCode;
/**
* 错误提示
*/
private String errorMessage;
}

View File

@ -11,5 +11,30 @@
<artifactId>system-rpc</artifactId> <artifactId>system-rpc</artifactId>
<dependencies>
<!-- Mall 相关 -->
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-rpc-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>cn.iocoder.mall</groupId>
<artifactId>system-biz</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- RPC 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!-- Registry 和 Config 相关 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project> </project>

View File

@ -0,0 +1,15 @@
package cn.iocoder.mall.system.rpc.convert;
import cn.iocoder.mall.system.biz.dto.system.AccessLogAddDTO;
import cn.iocoder.mall.system.rpc.request.system.AccessLogAddRequest;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@Mapper
public interface SystemLogConvert {
SystemLogConvert INSTANCE = Mappers.getMapper(SystemLogConvert.class);
AccessLogAddDTO convert(AccessLogAddRequest accessLogAddRequest);
}

View File

@ -0,0 +1,25 @@
package cn.iocoder.mall.system.rpc.rpc;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.system.biz.dto.system.AccessLogAddDTO;
import cn.iocoder.mall.system.biz.service.system.SystemLogService;
import cn.iocoder.mall.system.rpc.api.SystemLogRPC;
import cn.iocoder.mall.system.rpc.convert.SystemLogConvert;
import cn.iocoder.mall.system.rpc.request.system.AccessLogAddRequest;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service(version = "dubbo.provider.SystemLogRPC.version", validation = "true")
public class SystemLogRPCImpl implements SystemLogRPC {
@Autowired
private SystemLogService systemLogService;
@Override
public CommonResult<Boolean> addAccessLog(AccessLogAddRequest accessLogAddRequest) {
AccessLogAddDTO accessLogAddDTO = SystemLogConvert.INSTANCE.convert(accessLogAddRequest);
systemLogService.addAccessLog(accessLogAddDTO);
return CommonResult.success(true);
}
}

View File

@ -0,0 +1,14 @@
spring:
# Spring Cloud 配置项
cloud:
nacos:
# Spring Cloud Nacos Discovery 配置项
discovery:
server-addr: s1.iocoder.cn:8848 # Nacos 服务器地址
namespace: local # Nacos 命名空间
# Dubbo 配置项
dubbo:
# Dubbo 注册中心
registry:
address: spring-cloud://s1.iocoder.cn:8848 # 指定 Dubbo 服务注册中心的地址

View File

@ -0,0 +1,14 @@
spring:
# Spring Cloud 配置项
cloud:
nacos:
# Spring Cloud Nacos Discovery 配置项
discovery:
server-addr: s1.iocoder.cn:8848 # Nacos 服务器地址
namespace: test # Nacos 命名空间
# Dubbo 配置项
dubbo:
# Dubbo 注册中心
registry:
address: spring-cloud://s1.iocoder.cn:8848 # 指定 Dubbo 服务注册中心的地址

View File

@ -0,0 +1,17 @@
# Dubbo 配置项
dubbo:
# Spring Cloud Alibaba Dubbo 专属配置
cloud:
subscribed-services: '' # 设置订阅的应用列表,默认为 * 订阅所有应用
# Dubbo 提供者的协议
protocol:
name: dubbo
port: -1
# Dubbo 提供服务的扫描基础包
scan:
base-packages: cn.iocoder.mall.system.rpc.rpc
# Dubbo 服务提供者的配置
provider:
filter: -exception
SystemLogRPC:
version: 1.0.0

View File

@ -1,19 +0,0 @@
package cn.iocoder.mall.admin.dao;
import cn.iocoder.common.framework.mybatis.QueryWrapperX;
import cn.iocoder.mall.system.api.dto.systemlog.AccessLogPageDTO;
import cn.iocoder.mall.admin.dataobject.AccessLogDO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Repository;
@Repository
public interface AccessLogMapper extends BaseMapper<AccessLogDO> {
default IPage<AccessLogDO> selectPage(AccessLogPageDTO accessLogPageDTO) {
return selectPage(new Page<>(accessLogPageDTO.getPageNo(), accessLogPageDTO.getPageSize()),
new QueryWrapperX<AccessLogDO>().eqIfPresent("user_id", accessLogPageDTO.getUserId()));
}
}