spring

Spring切面编程(AOP)-记录管理系统操作日志

2022-03-16  本文已影响0人  AC编程

一、注解类

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OpLog {

    /** 参数标签 */
    String tag() default "" ;
    
    /** 参数名 */
    String name() default "";
}
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface OpLogs {
    /** 子注解 */
    OpLog[] params() ;
    
    /** 链接因子 */
    String factor() default "";
    
    /** 操作模块 */
    String module() default "";
    
    /** 动作 */
    String operation() default "";
}

二、注解使用类

    @PostMapping("add")
    @ApiOperation("新增")
    @OpLogs(module = "广告位", operation = "新增", params = {
            @OpLog(name = "name", tag = "广告位名称"),
            @OpLog(name = "code", tag = "广告位编码")
    })
    public Result<Boolean> add(@Valid @RequestBody AdvertSiteAddVO vo) {
        return Result.success(service.save(vo));
    }

三、AOP拦截类

@Aspect
@Component
@Slf4j
public class LogOperation {

    private static final String PN = "平台操作日志, ";

    @Resource
    private LogSender sender;

    /**
     * 日志切入点
     */
    @Pointcut("@annotation(com.alanchen.annon.log.OpLogs)")
    public void cut() {

    }


    /**
     * 正常执行
     * @param point 切入点
     * @throws Throwable 异常信息
     */
    @AfterReturning(value = "cut()", returning = "result")
    public void afterReturning(JoinPoint point, Result result) {
        try {
            if(ResultCode.SUCCESS.getCode() != result.getCode()) {
                return;
            }
            String user = null;
            //从Header中获取用户信息
            ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = servletRequestAttributes.getRequest();
            String userHeader = request.getHeader("user");
            String userAttribute = request.getAttribute("user") != null ? (String) request.getAttribute("user") : null;
            log.info(PN + "userHeader: " + userHeader + ", userAttribute: " + userAttribute);
            if (StrUtil.isNotEmpty(userAttribute)) {
                user = userAttribute;
            }else if(StrUtil.isNotEmpty(userHeader)){
                user = userHeader;
            }
            if (user == null) {
                log.error(PN + "不生成操作记录, 原因: header中的用户信息不存在");
                return;
            }
            try {
                user = URLDecoder.decode(user, "UTF-8");
            } catch (UnsupportedEncodingException ex) {
                log.error(PN + "不生成操作记录, 原因: 针对token信息进行URLDecode失败");
            }
            SecurityUserDTO suser = JSON.parseObject(user, SecurityUserDTO.class);
            if (SecurityUserTypeEnum.APP.equals(suser.getUserType())) {
                return;
            }

            Signature signature = point.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();
            OpLogs opLogs = method.getAnnotation(OpLogs.class);
            if (opLogs == null) {
                return;
            }
            //模块
            String module = opLogs.module();
            //操作
            String operation = opLogs.operation();
            //自定义参数
            OpLog[] params = opLogs.params();

            String op = operation + this.parseBehavior(request, params);
            String ip = ip(request);
            String uri = request.getRequestURI();

            LogAddVO vo = new LogAddVO(suser.getId(), module, op, ip, uri, LocalDateTime.now());
            sender.asyncSend(vo);
        } catch (Exception ex) {
            //捕获到异常时, 直接输出异常信息, 不在往外抛出, 防止被全局异常处理捕获
            log.error(PN + "发生异常: " + ex.getMessage() + ", 异常信息: " + ex.getStackTrace()[0].toString());
        }
    }

    /**
     * 解析行为
     * @param request   HttpServletRequest
     * @param params    子注解列表
     */
    private String parseBehavior(HttpServletRequest request, OpLog[] params) {
        StringBuffer sb = new StringBuffer();
        sb.append("[");
        String method = request.getMethod();

        //处理POST请求
        if (HttpMethod.POST.name().equals(method)) {
            sb.append(parseBehaviorPost(new CustomHttpServletRequestWrapper(request), params));
        }
        //处理PUT请求
        else if (HttpMethod.PUT.name().equals(method)) {

        }
        //处理DELETE请求
        else if (HttpMethod.DELETE.name().equals(method)) {
            sb.append(parseBehaviorDelete(new CustomHttpServletRequestWrapper(request), params));
        }
        sb.append("]");
        String buhavior = sb.toString();
        return buhavior.endsWith("[]") ? buhavior.replace("[]", "") : buhavior;
    }

    private String parseBehaviorDelete(CustomHttpServletRequestWrapper requestWrapper, OpLog[] params) {
        StringBuffer sb = new StringBuffer();
        Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
        if (parameterMap != null || parameterMap.size() != 0) {
            Iterator<Map.Entry<String, String[]>> iterator = parameterMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String[]> next = iterator.next();
                for (int i=0; i<params.length; i++) {
                    OpLog param = params[i];
                    //参数标签
                    String tag = param.tag();
                    //参数值
                    String name = param.name();
                    if (name.equalsIgnoreCase(next.getKey())) {
                        String[] value = next.getValue();
                        sb.append(tag).append(": ").append(value[0]);
                        if (i < (params.length - 1)) {
                            sb.append(", ");
                        }
                    }
                }
            }
        }
        return sb.toString();
    }

    private String parseBehaviorPost(CustomHttpServletRequestWrapper requestWrapper, OpLog[] params) {
        StringBuffer sb = new StringBuffer();
        String body = requestWrapper.getBody();
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSONUtil.parseObj(body);
            Iterator<Map.Entry<String, Object>> iterator = jsonObject.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, Object> next = iterator.next();
                for (int i=0; i<params.length; i++) {
                    OpLog param = params[i];
                    //参数标签
                    String tag = param.tag();
                    //参数值
                    String name = param.name();
                    if (name.equalsIgnoreCase(next.getKey())) {
                        sb.append(tag).append(": ").append(next.getValue());
                        if (i < (params.length - 1)) {
                            sb.append(", ");
                        }
                    }
                }
            }
        }
        return sb.toString();
    }

    /**
     * 获取ip
     * @param request
     * @return
     */
    private String ip(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        String comma = ",";
        String localhost = "127.0.0.1";
        if (ip.contains(comma)) {
            ip = ip.split(",")[0];
        }
        if (localhost.equals(ip)) {
            // 获取本机真正的ip地址
            try {
                ip = InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                log.error(e.getMessage(), e);
            }
        }
        return ip;
    }
}

四、MQ记录操作日志

@Slf4j
@Component
public class LogSender {

    private static final String PN = "运营平台操作记录发送, ";

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Value("${rocketmq.topic.sysLog}")
    private String topic;

    /**
     * 发送消息(异步)
     */
    public void asyncSend(LogAddVO vo) {
        String msg = JSONObject.toJSONString(vo);
        rocketMQTemplate.asyncSend(topic, msg, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info(PN + "消息发送成功, result: {}", sendResult);
            }

            @Override
            public void onException(Throwable e) {
                log.error(PN + "消息发送失败");
                e.printStackTrace();
            }
        });
    }
}

五、操作日志记录表

@Data
@NoArgsConstructor
@AllArgsConstructor
@SuppressWarnings("serial")
@TableName("t_sys_log")
public class Log{

    /** 操作用户ID */
    private Long userId;
    
    /** 操作用户名 */
    private String userName;
    
    /** 操作用户手机号 */
    private String userMobile;
    
    /** 角色ID */
    private String roleId;
    
    /** 角色名 */
    private String roleName;
    
    /** 一级菜单ID */
    private Long menu1Id;
    
    /** 一级菜单 */
    private String menu1;
    
    /** 二级菜单ID */
    private Long menu2Id;
    
    /** 二级菜单 */
    private String menu2;
    
    /** 操作 */
    private String op;
    
    /** 操作模块 */
    private String opMod;
    
    /** 操作IP地址 */
    private String ip;
}

六、HttpServletRequestWrapper

@Slf4j
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private final String body;
    private final Map<String, String> headers;

    public CustomHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        body = buildBody(request);
        headers = buildHeaders(request);
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
            @Override
            public boolean isReady() {
                return false;
            }
            @Override
            public void setReadListener(ReadListener readListener) {
            }
            @Override
            public int read() {
                return byteArrayInputStream.read();
            }
        };
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    /**
     * 重写 setHeader
     * @param name      header name
     * @param value     header value
     */
    public void setHeader(String name, String value){
        headers.put(name, value);
    }

    public String getHeader(String name) {
        String headerValue = headers.get(name);
        if (headerValue != null){
            return headerValue;
        }
        return ((HttpServletRequest) getRequest()).getHeader(name);
    }

    public Enumeration<String> getHeaderNames() {
        Set<String> set = new HashSet<>(headers.keySet());
        Enumeration<String> e = ((HttpServletRequest) getRequest()).getHeaderNames();
        while (e.hasMoreElements()) {
            String n = e.nextElement();
            set.add(n);
        }
        return Collections.enumeration(set);
    }

    public String getBody() {
        return this.body;
    }

    private String buildBody(HttpServletRequest request) {
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                char[] charBuffer = new char[1024];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return stringBuilder.toString();
    }

    private Map<String, String> buildHeaders(HttpServletRequest request) {
        Map<String, String> headers = new HashMap<>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            headers.put(headerName, headerValue);
        }
        return headers;
    }
}
上一篇下一篇

猜你喜欢

热点阅读