diff --git a/src/main/java/com/ycwl/basic/stats/biz/StatsBiz.java b/src/main/java/com/ycwl/basic/stats/biz/StatsBiz.java new file mode 100644 index 0000000..c823eaf --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/biz/StatsBiz.java @@ -0,0 +1,7 @@ +package com.ycwl.basic.stats.biz; + +import org.springframework.stereotype.Component; + +@Component +public class StatsBiz { +} diff --git a/src/main/java/com/ycwl/basic/stats/controller/TraceController.java b/src/main/java/com/ycwl/basic/stats/controller/TraceController.java new file mode 100644 index 0000000..61477f8 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/controller/TraceController.java @@ -0,0 +1,43 @@ +package com.ycwl.basic.stats.controller; + +import com.ycwl.basic.annotation.IgnoreToken; +import com.ycwl.basic.stats.dto.AddTraceReq; +import com.ycwl.basic.stats.service.StatsService; +import com.ycwl.basic.stats.util.StatsUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@RestController +@RequestMapping("/trace/v1") +public class TraceController { + @Autowired + private StatsService statsService; + @IgnoreToken + @PostMapping("/start") + public void startTrace(HttpServletRequest request, HttpServletResponse response) { + String traceId = request.getHeader("traceId"); + if (traceId == null || traceId.isEmpty()) { + traceId = StatsUtil.createUuid(); + response.setHeader("Set-TraceId", traceId); + } + statsService.addStats(traceId, null); + } + + @IgnoreToken + @PostMapping("/add") + public void addTrace(HttpServletRequest request, HttpServletResponse response, @RequestBody AddTraceReq req) { + String traceId = request.getHeader("traceId"); + if (traceId == null || traceId.isEmpty()) { + traceId = StatsUtil.createUuid(); + response.setHeader("Set-TraceId", traceId); + } + statsService.addRecord(traceId, req.getAction(), req.getIdentifier(), req.getParams()); + } +} diff --git a/src/main/java/com/ycwl/basic/stats/dto/AddTraceReq.java b/src/main/java/com/ycwl/basic/stats/dto/AddTraceReq.java new file mode 100644 index 0000000..739a9e0 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/dto/AddTraceReq.java @@ -0,0 +1,10 @@ +package com.ycwl.basic.stats.dto; + +import lombok.Data; + +@Data +public class AddTraceReq { + private String action; + private String identifier; + private String params; +} diff --git a/src/main/java/com/ycwl/basic/stats/entity/StatsEntity.java b/src/main/java/com/ycwl/basic/stats/entity/StatsEntity.java new file mode 100644 index 0000000..73f5729 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/entity/StatsEntity.java @@ -0,0 +1,18 @@ +package com.ycwl.basic.stats.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +@Data +@TableName("t_stats") +public class StatsEntity { + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private String traceId; + private Long memberId; + private Date createTime; +} diff --git a/src/main/java/com/ycwl/basic/stats/entity/StatsRecordEntity.java b/src/main/java/com/ycwl/basic/stats/entity/StatsRecordEntity.java new file mode 100644 index 0000000..a545256 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/entity/StatsRecordEntity.java @@ -0,0 +1,20 @@ +package com.ycwl.basic.stats.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +@Data +@TableName("t_stats_record") +public class StatsRecordEntity { + @TableId(value = "id", type = IdType.AUTO) + private Long id; + private String traceId; + private String action; + private String identifier; + private String params; + private Date createTime; +} diff --git a/src/main/java/com/ycwl/basic/stats/interceptor/StatsInterceptor.java b/src/main/java/com/ycwl/basic/stats/interceptor/StatsInterceptor.java new file mode 100644 index 0000000..c9bd0dd --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/interceptor/StatsInterceptor.java @@ -0,0 +1,63 @@ +package com.ycwl.basic.stats.interceptor; + +import com.ycwl.basic.annotation.IgnoreLogReq; +import com.ycwl.basic.constant.BaseContextHandler; +import com.ycwl.basic.stats.service.StatsService; +import com.ycwl.basic.stats.util.StatsUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.ModelAndView; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Date; +import java.util.HashSet; + +@Component +public class StatsInterceptor implements HandlerInterceptor { + @Autowired + private StatsService statsService; + + // 在请求处理前执行 + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (!(handler instanceof HandlerMethod)) { + return true; + } + HandlerMethod handlerMethod = (HandlerMethod) handler; + request.setAttribute("startTime", System.currentTimeMillis()); + String requestURI = request.getRequestURI(); + String method = request.getMethod(); + String traceId = request.getHeader("traceId"); + if (StringUtils.isEmpty(traceId)) { + return true; +// traceId = StatsUtil.createUuid(); +// response.setHeader("Set-TraceId", traceId); +// statsService.addStats(traceId, null); + } + if (handlerMethod.getMethodAnnotation(IgnoreLogReq.class) == null) { + statsService.addRecord(traceId, "REQUEST",method + " " + requestURI, null); + } + if (StringUtils.isNotEmpty(BaseContextHandler.getUserId())) { + statsService.updateStats(traceId, Long.valueOf(BaseContextHandler.getUserId())); + } + // 返回 true 继续后续流程,false 终止请求 + return true; + } + + // 控制器方法执行后,渲染视图前 + @Override + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + } + + // 请求完全完成后执行(无论是否异常) + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { +// long startTime = (Long) request.getAttribute("startTime"); +// long endTime = System.currentTimeMillis(); +// System.out.println("【AfterCompletion】请求结束,耗时:" + (endTime - startTime) + "ms"); + } +} diff --git a/src/main/java/com/ycwl/basic/stats/mapper/StatsMapper.java b/src/main/java/com/ycwl/basic/stats/mapper/StatsMapper.java new file mode 100644 index 0000000..0475309 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/mapper/StatsMapper.java @@ -0,0 +1,9 @@ +package com.ycwl.basic.stats.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ycwl.basic.stats.entity.StatsEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface StatsMapper extends BaseMapper { +} diff --git a/src/main/java/com/ycwl/basic/stats/mapper/StatsRecordMapper.java b/src/main/java/com/ycwl/basic/stats/mapper/StatsRecordMapper.java new file mode 100644 index 0000000..9d67905 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/mapper/StatsRecordMapper.java @@ -0,0 +1,9 @@ +package com.ycwl.basic.stats.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.ycwl.basic.stats.entity.StatsRecordEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface StatsRecordMapper extends BaseMapper { +} diff --git a/src/main/java/com/ycwl/basic/stats/service/StatsService.java b/src/main/java/com/ycwl/basic/stats/service/StatsService.java new file mode 100644 index 0000000..cb47cb5 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/service/StatsService.java @@ -0,0 +1,9 @@ +package com.ycwl.basic.stats.service; + +public interface StatsService { + void addStats(String traceId, Long memberId); + + void updateStats(String traceId, Long memberId); + + void addRecord(String traceId, String action, String identifier, String params); +} diff --git a/src/main/java/com/ycwl/basic/stats/service/impl/StatsServiceImpl.java b/src/main/java/com/ycwl/basic/stats/service/impl/StatsServiceImpl.java new file mode 100644 index 0000000..67fdab9 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/service/impl/StatsServiceImpl.java @@ -0,0 +1,50 @@ +package com.ycwl.basic.stats.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ycwl.basic.stats.entity.StatsEntity; +import com.ycwl.basic.stats.entity.StatsRecordEntity; +import com.ycwl.basic.stats.mapper.StatsMapper; +import com.ycwl.basic.stats.mapper.StatsRecordMapper; +import com.ycwl.basic.stats.service.StatsService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +public class StatsServiceImpl implements StatsService { + @Autowired + private StatsMapper statsMapper; + + @Autowired + private StatsRecordMapper statsRecordMapper; + + @Override + public void addStats(String traceId, Long memberId) { + StatsEntity entity = new StatsEntity(); + entity.setTraceId(traceId); + entity.setMemberId(memberId); + entity.setCreateTime(new Date()); + statsMapper.insert(entity); + } + + @Override + public void updateStats(String traceId, Long memberId) { + StatsEntity entity = new StatsEntity(); + entity.setMemberId(memberId); + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(StatsEntity::getTraceId, traceId); + statsMapper.update(entity, queryWrapper); + } + + @Override + public void addRecord(String traceId, String action, String identifier, String params) { + StatsRecordEntity entity = new StatsRecordEntity(); + entity.setTraceId(traceId); + entity.setAction(action); + entity.setIdentifier(identifier); + entity.setParams(params); + entity.setCreateTime(new Date()); + statsRecordMapper.insert(entity); + } +} diff --git a/src/main/java/com/ycwl/basic/stats/util/StatsUtil.java b/src/main/java/com/ycwl/basic/stats/util/StatsUtil.java new file mode 100644 index 0000000..616c759 --- /dev/null +++ b/src/main/java/com/ycwl/basic/stats/util/StatsUtil.java @@ -0,0 +1,9 @@ +package com.ycwl.basic.stats.util; + +import java.util.UUID; + +public class StatsUtil { + public static String createUuid() { + return UUID.randomUUID().toString().replace("-", ""); + } +}