增加访问日志的 dubbo 实现
This commit is contained in:
parent
e36b32a97d
commit
bdff67b7b3
29
common/mall-spring-boot-starter-web/pom.xml
Normal file
29
common/mall-spring-boot-starter-web/pom.xml
Normal 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>
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.web;
|
@ -16,6 +16,7 @@
|
||||
<module>mall-spring-boot</module>
|
||||
<module>common-dependencies</module>
|
||||
<module>mall-spring-boot-starter-swagger</module>
|
||||
<module>mall-spring-boot-starter-web</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -18,6 +18,11 @@
|
||||
<artifactId>system-rest</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>system-rpc</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
@ -11,7 +11,7 @@ public class SystemApplication {
|
||||
* 设置需要读取的配置文件的名字。
|
||||
* 基于 {@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) {
|
||||
// 设置环境变量
|
||||
|
@ -1,3 +1,7 @@
|
||||
spring:
|
||||
# Application 的配置项
|
||||
application:
|
||||
name: admin-application
|
||||
# Profile 的配置项
|
||||
profiles:
|
||||
active: test
|
||||
|
@ -1 +0,0 @@
|
||||
package cn.iocoder.mall.system.biz.bo;
|
@ -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.dataobject.account.AccountDO;
|
@ -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.dataobject.admin.AdminDO;
|
@ -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.dataobject.oauth2.OAuth2AccessTokenDO;
|
@ -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);
|
||||
|
||||
}
|
@ -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.user.UserAuthenticateBO;
|
@ -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()));
|
||||
// }
|
||||
|
||||
}
|
@ -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.vo.CommonResult;
|
||||
import cn.iocoder.mall.system.api.dto.systemlog.AccessLogAddDTO;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.Date;
|
||||
@ -13,10 +13,16 @@ import java.util.Date;
|
||||
* 访问日志 DO
|
||||
*/
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Accessors(chain = true)
|
||||
@TableName("access_log")
|
||||
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;
|
||||
/**
|
||||
* 用户编号.
|
||||
* 账号编号
|
||||
*
|
||||
* 当管理员为空时,该值为 {@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;
|
||||
/**
|
@ -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;
|
||||
|
||||
}
|
@ -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.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.dataobject.account.AccountDO;
|
||||
import cn.iocoder.mall.system.biz.dto.account.AccountCreateDTO;
|
@ -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.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.dataobject.admin.AdminDO;
|
||||
import cn.iocoder.mall.system.biz.service.admin.AdminService;
|
@ -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.util.ServiceExceptionUtil;
|
@ -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.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.util.ValidationUtil;
|
||||
import cn.iocoder.mall.system.biz.bo.account.AccountBO;
|
||||
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.OAuth2RefreshTokenMapper;
|
||||
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.OAuth2UsernameAuthenticateDTO;
|
||||
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.Value;
|
||||
import org.springframework.stereotype.Service;
|
@ -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);
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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.user.UserAuthenticateBO;
|
||||
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.dataobject.user.UserDO;
|
||||
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.user.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
@ -12,6 +12,19 @@ import java.util.Date;
|
||||
@Accessors(chain = true)
|
||||
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
|
||||
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;
|
||||
/**
|
||||
* TODO 晚点测试下 swagger 的表现
|
||||
* 访问令牌
|
||||
*/
|
||||
private Token token;
|
||||
|
||||
|
@ -11,5 +11,20 @@
|
||||
|
||||
<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>
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -0,0 +1 @@
|
||||
package cn.iocoder.mall.system.rpc.request;
|
@ -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;
|
||||
|
||||
}
|
@ -11,5 +11,30 @@
|
||||
|
||||
<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>
|
||||
|
@ -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);
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
14
system/system-rpc/src/main/resources/rpc-local.yaml
Normal file
14
system/system-rpc/src/main/resources/rpc-local.yaml
Normal 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 服务注册中心的地址
|
14
system/system-rpc/src/main/resources/rpc-test.yaml
Normal file
14
system/system-rpc/src/main/resources/rpc-test.yaml
Normal 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 服务注册中心的地址
|
17
system/system-rpc/src/main/resources/rpc.yaml
Normal file
17
system/system-rpc/src/main/resources/rpc.yaml
Normal 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
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user