Browse Source

支持异常情况报告功能,包括大量访问请求、异常数据输入

master
zhouyl 1 year ago
parent
commit
059c91ec32
  1. 93
      tp-admin/src/main/java/com/inscloudtech/web/controller/system/SysExceptionReportController.java
  2. 61
      tp-common/src/main/java/com/inscloudtech/common/core/domain/event/ExceptionReportEvent.java
  3. 55
      tp-common/src/main/java/com/inscloudtech/common/core/domain/event/RequestLogEvent.java
  4. 83
      tp-common/src/main/java/com/inscloudtech/common/filter/RequestLoggingFilter.java
  5. 4
      tp-common/src/main/java/com/inscloudtech/common/utils/ServletUtils.java
  6. 11
      tp-framework/src/main/java/com/inscloudtech/framework/config/FilterConfig.java
  7. 11
      tp-framework/src/main/java/com/inscloudtech/framework/web/exception/GlobalExceptionHandler.java
  8. 80
      tp-system/src/main/java/com/inscloudtech/system/domain/SysExceptionReport.java
  9. 77
      tp-system/src/main/java/com/inscloudtech/system/domain/SysRequestLog.java
  10. 21
      tp-system/src/main/java/com/inscloudtech/system/mapper/SysExceptionReportMapper.java
  11. 23
      tp-system/src/main/java/com/inscloudtech/system/mapper/SysRequestLogMapper.java
  12. 17
      tp-system/src/main/java/com/inscloudtech/system/service/ISysExceptionReportService.java
  13. 29
      tp-system/src/main/java/com/inscloudtech/system/service/SysRequestLogService.java
  14. 24
      tp-system/src/main/java/com/inscloudtech/system/service/impl/SysExceptionReportServiceImpl.java
  15. 86
      tp-system/src/main/java/com/inscloudtech/system/service/impl/SysRequestLogServiceImpl.java

93
tp-admin/src/main/java/com/inscloudtech/web/controller/system/SysExceptionReportController.java

@ -0,0 +1,93 @@
package com.inscloudtech.web.controller.system;
/***/
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.inscloudtech.common.annotation.Log;
import com.inscloudtech.common.annotation.RepeatSubmit;
import com.inscloudtech.common.core.domain.PageQuery;
import com.inscloudtech.common.core.domain.R;
import com.inscloudtech.common.core.page.TableDataInfo;
import com.inscloudtech.common.enums.BusinessType;
import com.inscloudtech.system.domain.SysExceptionReport;
import com.inscloudtech.system.domain.SysRequestLog;
import com.inscloudtech.system.service.ISysExceptionReportService;
import com.inscloudtech.system.service.SysRequestLogService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* 异常情况报告
*
* @author zfcf
* @date 2024-08-28
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/functional/exceptionReport")
public class SysExceptionReportController {
private final ISysExceptionReportService iSysExceptionReportService;
private final SysRequestLogService sysRequestLogService;
/**
* 分页查询
* @param
* @param
* @return
*/
@GetMapping("/page" )
public TableDataInfo<SysExceptionReport> page(PageQuery pageQuery, SysExceptionReport sysExceptionReport) {
Page page = new Page();
page.setSize(pageQuery.getPageSize());
page.setCurrent(pageQuery.getPageNum());
Page result = iSysExceptionReportService.page(page, Wrappers.query(sysExceptionReport));
TableDataInfo dataInfo = new TableDataInfo();
dataInfo.setTotal(result.getTotal());
dataInfo.setRows(result.getRecords());
return dataInfo;
}
/**
* 修改异常情况报告已读
* @param
* @return R
*/
@Log(title = "异常情况报告", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping
public R updateById(@RequestBody SysExceptionReport report) {
return R.ok(iSysExceptionReportService.updateById(report));
}
/**
* 修改异常情况报告阈值
* @param
* @return R
*/
@Log(title = "异常情况报告", businessType = BusinessType.UPDATE)
@RepeatSubmit()
@PutMapping
public R updateYz(@RequestBody SysRequestLog sysRequestLog) {
sysRequestLogService.updateYz(sysRequestLog);
return R.ok();
}
/**
* 获取异常情况报告阈值
*
*/
@GetMapping("/getYzInfo")
public R getInfo() {
return R.ok(sysRequestLogService.getYzInfo());
}
}

61
tp-common/src/main/java/com/inscloudtech/common/core/domain/event/ExceptionReportEvent.java

@ -0,0 +1,61 @@
package com.inscloudtech.common.core.domain.event;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 操作日志事件
*
* @author inscloudtech
*/
@Data
public class ExceptionReportEvent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 日志主键
*/
private Long operId;
/**
* 请求方法
*/
private String method;
/**
* 请求方式
*/
private String requestMethod;
/**
* 操作人员
*/
private String operName;
/**
* 请求url
*/
private String operUrl;
/**
* 操作地址
*/
private String operIp;
/**
* 操作地点
*/
private String operLocation;
/**
* 请求参数
*/
private String msg;
}

55
tp-common/src/main/java/com/inscloudtech/common/core/domain/event/RequestLogEvent.java

@ -0,0 +1,55 @@
package com.inscloudtech.common.core.domain.event;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 操作日志事件
*
* @author inscloudtech
*/
@Data
public class RequestLogEvent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 日志主键
*/
private Long operId;
/**
* 请求方式
*/
private String requestMethod;
/**
* 操作人员
*/
private String operName;
/**
* 请求url
*/
private String operUrl;
/**
* 操作地址
*/
private String operIp;
/**
* 操作地点
*/
private String operLocation;
/**
* 请求参数
*/
private String operParam;
}

83
tp-common/src/main/java/com/inscloudtech/common/filter/RequestLoggingFilter.java

@ -0,0 +1,83 @@
package com.inscloudtech.common.filter;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.inscloudtech.common.core.domain.event.RequestLogEvent;
import com.inscloudtech.common.core.domain.model.LoginUser;
import com.inscloudtech.common.helper.LoginHelper;
import com.inscloudtech.common.utils.JsonUtils;
import com.inscloudtech.common.utils.ServletUtils;
import com.inscloudtech.common.utils.StringUtils;
import com.inscloudtech.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
@Slf4j
public class RequestLoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
ServletRequest requestWrapper = null;
if (request instanceof HttpServletRequest
&& StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE)) {
requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
}
handleLog(request);
// 记录请求信息
chain.doFilter(ObjectUtil.defaultIfNull(requestWrapper, request), response);
}
@Override
public void destroy() {
}
protected void handleLog(ServletRequest request) {
try {
HttpServletRequest servletRequest = (HttpServletRequest) request;
String requestURI = servletRequest.getRequestURI();
String method = servletRequest.getMethod();
Map<String, String> paramMap = ServletUtils.getParamMap(servletRequest);
String operParam = "";
if(MapUtil.isNotEmpty(paramMap)){
operParam = StringUtils.substring(JsonUtils.toJsonString(paramMap), 0, 2000);
}
String ip = ServletUtils.getClientIPByRequest(servletRequest);
RequestLogEvent requestLog = new RequestLogEvent();
requestLog.setOperIp(ip);
requestLog.setOperUrl(StringUtils.substring(requestURI, 0, 255));
requestLog.setRequestMethod(method);
requestLog.setOperParam(operParam);
String authorization = servletRequest.getHeader("authorization");
if(StrUtil.isNotEmpty(authorization)){
authorization = authorization.replace("Bearer","").trim();
LoginUser user = LoginHelper.getLoginUser(authorization);
requestLog.setOperName(user.getUsername());
}
SpringUtils.context().publishEvent(requestLog);
} catch (Exception exp) {
// 记录本地异常日志
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
}

4
tp-common/src/main/java/com/inscloudtech/common/utils/ServletUtils.java

@ -172,6 +172,10 @@ public class ServletUtils extends ServletUtil {
return getClientIP(getRequest());
}
public static String getClientIPByRequest(HttpServletRequest servletRequest) {
return getClientIP(servletRequest);
}
/**
* 内容编码
*

11
tp-framework/src/main/java/com/inscloudtech/framework/config/FilterConfig.java

@ -1,6 +1,7 @@
package com.inscloudtech.framework.config;
import com.inscloudtech.common.filter.RepeatableFilter;
import com.inscloudtech.common.filter.RequestLoggingFilter;
import com.inscloudtech.common.filter.XssFilter;
import com.inscloudtech.common.utils.StringUtils;
import com.inscloudtech.framework.config.properties.XssProperties;
@ -52,4 +53,14 @@ public class FilterConfig {
return registration;
}
@Bean
public FilterRegistrationBean requestLoggingFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RequestLoggingFilter());
registration.addUrlPatterns("/*");
registration.setName("requestLoggingFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
return registration;
}
}

11
tp-framework/src/main/java/com/inscloudtech/framework/web/exception/GlobalExceptionHandler.java

@ -6,10 +6,14 @@ import cn.dev33.satoken.exception.NotRoleException;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpStatus;
import com.inscloudtech.common.core.domain.R;
import com.inscloudtech.common.core.domain.event.ExceptionReportEvent;
import com.inscloudtech.common.core.domain.event.RequestLogEvent;
import com.inscloudtech.common.exception.DemoModeException;
import com.inscloudtech.common.exception.ServiceException;
import com.inscloudtech.common.exception.base.BaseException;
import com.inscloudtech.common.utils.ServletUtils;
import com.inscloudtech.common.utils.StreamUtils;
import com.inscloudtech.common.utils.spring.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
@ -137,6 +141,13 @@ public class GlobalExceptionHandler {
public R<Void> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) {
String requestURI = request.getRequestURI();
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI);
ExceptionReportEvent reportEvent = new ExceptionReportEvent();
reportEvent.setOperUrl(requestURI);
String ip = ServletUtils.getClientIPByRequest(request);
reportEvent.setOperIp(ip);
reportEvent.setMsg(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
SpringUtils.context().publishEvent(reportEvent);
return R.fail(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), e.getValue()));
}

80
tp-system/src/main/java/com/inscloudtech/system/domain/SysExceptionReport.java

@ -0,0 +1,80 @@
package com.inscloudtech.system.domain;
import com.baomidou.mybatisplus.annotation.SqlCondition;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* 异常情况报告对象 sys_exception_report
*
* @author inscloudtech
* @date 2024-09-06
*/
@Data
@TableName("sys_exception_report")
public class SysExceptionReport{
private static final long serialVersionUID=1L;
/**
* 日志主键
*/
@TableId(value = "oper_id")
private Long operId;
/**
* 方法名称
*/
private String method;
/**
* 请求方式
*/
private String requestMethod;
/**
* 操作人员
*/
private String operName;
/**
* 请求URL
*/
@TableField(condition = SqlCondition.LIKE)
private String operUrl;
/**
* 主机地址
*/
private String operIp;
/**
* 操作地点
*/
private String operLocation;
/**
* 请求参数
*/
private String operParam;
/**
* 返回参数
*/
private String jsonResult;
/**
* 大量访问请求/异常数据输入
*/
private String type;
/**
* 错误消息
*/
private String msg;
/**
* 操作时间
*/
private Date operTime;
/**
* 单位时间请求次数
*/
private Integer requestCount;
}

77
tp-system/src/main/java/com/inscloudtech/system/domain/SysRequestLog.java

@ -0,0 +1,77 @@
package com.inscloudtech.system.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.util.Date;
/**
* 访问日志记录对象 sys_request_log
*
* @author inscloudtech
* @date 2024-09-06
*/
@Data
@TableName("sys_request_log")
public class SysRequestLog {
private static final long serialVersionUID=1L;
/**
* 日志主键
*/
@TableId(value = "oper_id")
private Long operId;
/**
* 方法名称
*/
private String method;
/**
* 请求方式
*/
private String requestMethod;
/**
* 操作人员
*/
private String operName;
/**
* 请求URL
*/
private String operUrl;
/**
* 主机地址
*/
private String operIp;
/**
* 操作地点
*/
private String operLocation;
/**
* 请求参数
*/
private String operParam;
/**
* 操作时间
*/
private Date operTime;
/**
* 预警时间阈值(分钟)
*/
@TableField(exist = false)
private Integer alterTime;
/**
* 预警请求次数阈值
*/
@TableField(exist = false)
private Integer requestCount;
/**
* 单位时间请求次数
*/
@TableField(exist = false)
private Integer count;
}

21
tp-system/src/main/java/com/inscloudtech/system/mapper/SysExceptionReportMapper.java

@ -0,0 +1,21 @@
package com.inscloudtech.system.mapper;
import com.inscloudtech.common.core.mapper.BaseMapperPlus;
import com.inscloudtech.system.domain.SysExceptionReport;
import com.inscloudtech.system.domain.SysRequestLog;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 测试包管理Mapper接口
*
* @author inscloudtech
* @date 2024-08-08
*/
public interface SysExceptionReportMapper extends BaseMapperPlus<SysExceptionReportMapper, SysExceptionReport, SysExceptionReport> {
}

23
tp-system/src/main/java/com/inscloudtech/system/mapper/SysRequestLogMapper.java

@ -0,0 +1,23 @@
package com.inscloudtech.system.mapper;
import com.inscloudtech.common.core.mapper.BaseMapperPlus;
import com.inscloudtech.system.domain.SysRequestLog;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 测试包管理Mapper接口
*
* @author inscloudtech
* @date 2024-08-08
*/
public interface SysRequestLogMapper extends BaseMapperPlus<SysRequestLogMapper, SysRequestLog, SysRequestLog> {
@Select("select oper_url operUrl,count(*) count from sys_request_log WHERE oper_time BETWEEN NOW() - INTERVAL > #{alterTime} MINUTE AND NOW()" +
" GROUP BY oper_url HAVING count > #{requestCount}")
List<SysRequestLog> getAlertURl(@Param("alterTime") int alterTime, @Param("requestCount") int requestCount);
}

17
tp-system/src/main/java/com/inscloudtech/system/service/ISysExceptionReportService.java

@ -0,0 +1,17 @@
package com.inscloudtech.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.inscloudtech.system.domain.SysExceptionReport;
import com.inscloudtech.system.domain.SysRequestLog;
/**
*
*
* @author inscloudtech
* @date 2024-08-08
*/
public interface ISysExceptionReportService extends IService<SysExceptionReport> {
}

29
tp-system/src/main/java/com/inscloudtech/system/service/SysRequestLogService.java

@ -0,0 +1,29 @@
package com.inscloudtech.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.inscloudtech.common.core.domain.PageQuery;
import com.inscloudtech.common.core.page.TableDataInfo;
import com.inscloudtech.system.domain.SysRequestLog;
import com.inscloudtech.system.domain.ToolManage;
import com.inscloudtech.system.domain.vo.DownloadToolRequest;
import com.inscloudtech.system.domain.vo.ToolManageVo;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.List;
/**
*
*
* @author inscloudtech
* @date 2024-08-08
*/
public interface SysRequestLogService extends IService<SysRequestLog> {
void updateYz(SysRequestLog sysRequestLog);
SysRequestLog getYzInfo();
}

24
tp-system/src/main/java/com/inscloudtech/system/service/impl/SysExceptionReportServiceImpl.java

@ -0,0 +1,24 @@
package com.inscloudtech.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.inscloudtech.common.core.domain.event.ExceptionReportEvent;
import com.inscloudtech.system.domain.SysExceptionReport;
import com.inscloudtech.system.mapper.SysExceptionReportMapper;
import com.inscloudtech.system.service.ISysExceptionReportService;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import java.util.Date;
public class SysExceptionReportServiceImpl extends ServiceImpl<SysExceptionReportMapper, SysExceptionReport> implements ISysExceptionReportService {
@Async
@EventListener
public void recordOper(ExceptionReportEvent reportEvent) {
SysExceptionReport report = BeanUtil.toBean(reportEvent, SysExceptionReport.class);
report.setType("异常数据输入");
report.setOperTime(new Date());
baseMapper.insert(report);
}
}

86
tp-system/src/main/java/com/inscloudtech/system/service/impl/SysRequestLogServiceImpl.java

@ -0,0 +1,86 @@
package com.inscloudtech.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.inscloudtech.common.core.domain.event.RequestLogEvent;
import com.inscloudtech.common.utils.ip.AddressUtils;
import com.inscloudtech.system.domain.SysExceptionReport;
import com.inscloudtech.system.domain.SysRequestLog;
import com.inscloudtech.system.mapper.SysRequestLogMapper;
import com.inscloudtech.system.service.ISysExceptionReportService;
import com.inscloudtech.system.service.SysRequestLogService;
import lombok.AllArgsConstructor;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
*
* @author zfcf
* @date 2024-08-28
*/
@Service
@AllArgsConstructor
public class SysRequestLogServiceImpl extends ServiceImpl<SysRequestLogMapper, SysRequestLog> implements SysRequestLogService {
private final ISysExceptionReportService exceptionReportService;
/**
* 预警时间阈值(分钟)
*/
private Integer alterTime = 1;
/**
* 预警请求次数阈值
*/
private Integer requestCount = 10;
@Async
@EventListener
public void recordOper(RequestLogEvent requestLogEvent) {
SysRequestLog requestLog = BeanUtil.toBean(requestLogEvent, SysRequestLog.class);
requestLog.setOperLocation(AddressUtils.getRealAddressByIP(requestLog.getOperIp()));
requestLog.setOperTime(new Date());
baseMapper.insert(requestLog);
List<SysRequestLog> alertURlList = baseMapper.getAlertURl(alterTime,requestCount);
if(CollectionUtil.isNotEmpty(alertURlList)){
List<SysExceptionReport> addList = new ArrayList<>();
for (SysRequestLog sysRequestLog : alertURlList) {
SysExceptionReport report = new SysExceptionReport();
report.setOperUrl(sysRequestLog.getOperUrl());
report.setRequestCount(sysRequestLog.getRequestCount());
report.setType("大量访问请求");
addList.add(report);
}
exceptionReportService.saveBatch(addList);
}
}
@Override
public void updateYz(SysRequestLog sysRequestLog) {
if(sysRequestLog.getAlterTime() != null){
alterTime = sysRequestLog.getAlterTime();
}
if(sysRequestLog.getRequestCount() != null){
requestCount = sysRequestLog.getRequestCount();
}
}
@Override
public SysRequestLog getYzInfo() {
SysRequestLog sysRequestLog = new SysRequestLog();
sysRequestLog.setAlterTime(alterTime);
sysRequestLog.setRequestCount(requestCount);
return sysRequestLog;
}
}
Loading…
Cancel
Save