SpringAop之日志管理

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 导入的依赖均为JavaWeb界面在线配置代码生成器这篇文章,你只需将这篇文章的maven依赖导入即可。SpringAop利用注解的特性进行日志管理,只需在对应的方法上加上自己编写的注解,即可完美实现日志管理。

导入的依赖均为JavaWeb界面在线配置代码生成器这篇文章,你只需将这篇文章的maven依赖导入即可。

SpringAop利用注解的特性进行日志管理,只需在对应的方法上加上自己编写的注解,即可完美实现日志管理。

日志管理的目的是,将后台管理人员,安卓人员,第三方人员每天请求的url和是谁操作的,在哪操作,使用什么系统操作,输入的那些参数,使用什么请求等等统统记录下来。方便异常排查和应对外来的web攻击。

 

关于Controller和spring-mvc.xml使用了shiro,关于shiro方面可以参考我的如下文章,进行学习:

MP实战系列(九)之集成Shiro

shiro实战系列

步骤如下:

一、编写注解类

package com.anotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
    
    String type() default "";//日志类型
    String action() default "";//作用
    String method() default "";//请求方式

}

 

二、编写Aspect

package com.anotation;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.math.BigDecimal;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.entity.SysCompany;
import com.entity.SysUser;
import com.service.SysCompanyService;
import com.service.SysLogService;
import com.service.SysUserService;

import cn.hutool.core.date.DateUtil;
import cn.hutool.system.HostInfo;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;



public class SysLogAspect {

    @Autowired
    private SysLogService sysLogService;
    
    @Autowired
    private SysUserService userService;
    
    @Autowired
    private SysCompanyService companyService;

    /**
     * 环绕通知
     * 
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    public Object aroud(ProceedingJoinPoint joinPoint) throws Throwable {

        // 开始时间
        long beginTime = System.currentTimeMillis();

        // 执行目标方法
        Object result = joinPoint.proceed();

        // 执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        // 保存日志
        saveSysLog(joinPoint, time);
        
        return result;
    }

    /**
     * 保存日志
     * 
     * @param joinPoint
     * @param time
     */
    private void saveSysLog(ProceedingJoinPoint joinPoint, long time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        
        SysLog sysLog = method.getAnnotation(SysLog.class);
        
        com.entity.SysLog log = new  com.entity.SysLog();
        
        HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
        
        //获取session
        String userCode = (String) request.getSession().getAttribute("userCode");
        
        //获取用户信息
        EntityWrapper<SysUser> wrapper = new EntityWrapper<SysUser>();
        wrapper.eq("user_code", userCode);
        SysUser user = userService.selectOne(wrapper);
        
        //获取公司信息
        EntityWrapper<SysCompany> wrapper2 = new EntityWrapper<SysCompany>();
        wrapper2.eq("company_code", user.getCorpCode());
        SysCompany company = companyService.selectOne(wrapper2);
 
            
            if (sysLog != null) {
                
                HostInfo hostInfo = SystemUtil.getHostInfo();
                OsInfo osInfo = SystemUtil.getOsInfo();
                log.setLogType(sysLog.type());
                log.setLogTitle(sysLog.action());
                log.setRequestMethod(sysLog.method());
                log.setRequestUri(request.getRequestURI());
                log.setRemoteAddr(request.getRemoteAddr());
                log.setDeviceName(osInfo.getName());
                log.setBrowserName(request.getHeader("User-Agent"));
                log.setRequestParams(request.getQueryString());
                log.setCreateBy(user.getUserName());
                log.setCreateByName(user.getUserName());
                log.setCreateDate(DateUtil.date().toString());
                log.setServerAddr(hostInfo.getAddress());
                log.setExecuteTime(BigDecimal.valueOf(time));
                log.setIsException("否");
                log.setCorpCode(company.getCorpCode());
                log.setCorpName(company.getCompanyName());
                
            }  
            // 保存系统日志
            sysLogService.insert(log);

    }
    
    
    
   
      

}

 

三、在spring-mvc.xml配置aop

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:c="http://www.springframework.org/schema/c" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:ehcache="http://www.springmodules.org/schema/ehcache"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd  
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd  
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd  
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd  
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd  
        http://www.springmodules.org/schema/ehcache http://www.springmodules.org/schema/cache/springmodules-ehcache.xsd">
    <aop:aspectj-autoproxy />
    <!-- Controller包(自动注入) -->
    <context:component-scan base-package="com.controller"/>

    <!-- 将 springSwaggerConfig加载到spring容器 -->  
    <bean class="com.mangofactory.swagger.configuration.SpringSwaggerConfig" />  

    <mvc:default-servlet-handler/>
    
    <bean class="com.listener.InitDataListener"/>  

     <!-- FastJson注入 -->
    <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
     
            <bean id="fastJsonHttpMessageConverter"
                  class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                     
                        <value>text/html;charset=UTF-8</value>
                        <value>application/json;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>
    <!-- 上传限制 -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 上传文件大小限制为31M,31*1024*1024 -->
        <property name="maxUploadSize" value="32505856"/>
    </bean>
    
    <!-- shiro 验证注解start -->
        <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
            <property name="proxyTargetClass" value="true" />
        </bean>
    
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
            <property name="securityManager" ref="securityManager"/>
        </bean>
    
    <!-- 异常处理 -->
   <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="org.apache.shiro.authz.UnauthorizedException">/error/unauthorized</prop>
                <prop key="org.apache.shiro.authz.UnauthenticatedException">/error/unlogined</prop>
            </props>
        </property>
    </bean>
     

 
 <!-- 切面 -->
<bean id="sysLogAspect" class="com.anotation.SysLogAspect"></bean>

<aop:config>
    <aop:aspect ref="sysLogAspect">
        <aop:pointcut expression="@annotation(com.anotation.SysLog)" id="sysLogPointcut"/>
        <aop:around method="aroud" pointcut-ref="sysLogPointcut"/>
    </aop:aspect>
</aop:config>
</beans>

 

四、在对应的Controller方法上加上注解即可

/**
     * 账号登录
     * @param request
     * @return
     */
    @PostMapping(value = "/login",produces="application/json;charset=utf-8")
    @SysLog(type="后台系统",action="登录功能",method="POST")
    @ApiOperation(value="登录",httpMethod="POST",notes="登录")
    public JSONObject login(@RequestParam String username, @RequestParam String password, HttpSession session,HttpServletResponse response) {
        //接收前台参数
        logger.info("用户名:"+username);
        logger.info("密码:"+password);
        //调用查询逻辑
        EntityWrapper<SysUser> wrapper = new EntityWrapper<SysUser>();
        wrapper.eq("login_code", username);
        SysUser user = userService.selectOne(wrapper);
        
        JSONObject json = new JSONObject();
        
        if(user != null && "0".equals(user.getStatus())) {
            //获取当前用户
            Subject subject = SecurityUtils.getSubject();  
            
            //根据前台传的用户名和密码进行认证
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);         
      
            try {
                //认证通过
                subject.login(token); 
            
                String encode = Base64.encode(user.getUserCode());
                
                //Cookie有效期默认为8小时
                int time=28800;
                
                //将Cookie加密为16进制字符串
                CookieUtils.setCookie(response,  "userCode", encode, time);

                user.setLastLoginDate(DateUtil.date());
                userService.updateById(user);
                
                //将userCode放入session中保存
                session.setAttribute("userCode", user.getUserCode());
                
                json.put("token", subject.getSession().getId());
                json.put(CommonEnum.RETURN_CODE, "000000");
                json.put(CommonEnum.RETURN_MSG, "登录成功");
            } catch (IncorrectCredentialsException e) {
                json.put(CommonEnum.RETURN_CODE, "111111");
                json.put(CommonEnum.RETURN_MSG, "用户名或密码错误");
            }catch (Exception e) {
                json.put(CommonEnum.RETURN_CODE, "222222");
                json.put(CommonEnum.RETURN_MSG, "特殊异常");
            }
        }else {
            json.put(CommonEnum.RETURN_CODE, "500");
            json.put(CommonEnum.RETURN_MSG, "用户不存在");
        }    
        
        return json;

    }

 

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
2月前
|
Prometheus 监控 Java
日志收集和Spring 微服务监控的最佳实践
在微服务架构中,日志记录与监控对系统稳定性、问题排查和性能优化至关重要。本文介绍了在 Spring 微服务中实现高效日志记录与监控的最佳实践,涵盖日志级别选择、结构化日志、集中记录、服务ID跟踪、上下文信息添加、日志轮转,以及使用 Spring Boot Actuator、Micrometer、Prometheus、Grafana、ELK 堆栈等工具进行监控与可视化。通过这些方法,可提升系统的可观测性与运维效率。
318 1
日志收集和Spring 微服务监控的最佳实践
|
2月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
540 5
|
8月前
|
存储 Java 文件存储
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— logback.xml 配置文件解析
本文解析了 `logback.xml` 配置文件的详细内容,包括日志输出格式、存储路径、控制台输出及日志级别等关键配置。通过定义 `LOG_PATTERN` 和 `FILE_PATH`,设置日志格式与存储路径;利用 `&lt;appender&gt;` 节点配置控制台和文件输出,支持日志滚动策略(如文件大小限制和保存时长);最后通过 `&lt;logger&gt;` 和 `&lt;root&gt;` 定义日志级别与输出方式。此配置适用于精细化管理日志输出,满足不同场景需求。
2126 1
|
8月前
|
Java 微服务 Spring
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——使用Logger在项目中打印日志
本文介绍了如何在项目中使用Logger打印日志。通过SLF4J和Logback,可设置不同日志级别(如DEBUG、INFO、WARN、ERROR)并支持占位符输出动态信息。示例代码展示了日志在控制器中的应用,说明了日志配置对问题排查的重要性。附课程源码下载链接供实践参考。
1010 0
|
8月前
|
SQL Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录—— application.yml 中对日志的配置
在 Spring Boot 项目中,`application.yml` 文件用于配置日志。通过 `logging.config` 指定日志配置文件(如 `logback.xml`),实现日志详细设置。`logging.level` 可定义包的日志输出级别,例如将 `com.itcodai.course03.dao` 包设为 `trace` 级别,便于开发时查看 SQL 操作。日志级别从高到低为 ERROR、WARN、INFO、DEBUG,生产环境建议调整为较高级别以减少日志量。本课程采用 yml 格式,因其层次清晰,但需注意格式要求。
807 0
|
8月前
|
Java API 开发者
微服务——SpringBoot使用归纳——Spring Boot使用slf4j进行日志记录——slf4j 介绍
在软件开发中,`System.out.println()`常被用于打印信息,但大量使用会增加资源消耗。实际项目推荐使用slf4j结合logback输出日志,效率更高。Slf4j(Simple Logging Facade for Java)是一个日志门面,允许开发者通过统一方式记录日志,无需关心具体日志系统。它支持灵活切换日志实现(如log4j或logback),且具备简洁占位符和日志级别判断等优势。阿里巴巴《Java开发手册》强制要求使用slf4j,以保证日志处理方式的统一性和维护性。使用时只需通过`LoggerFactory`创建日志实例即可。
628 0
|
4月前
|
机器学习/深度学习 XML Java
【spring boot logback】日志logback格式解析
在 Spring Boot 中,Logback 是默认的日志框架,它支持灵活的日志格式配置。通过配置 logback.xml 文件,可以定义日志的输出格式、日志级别、日志文件路径等。
791 5
|
消息中间件 存储 Java
手动实现 Spring Boot 日志链路追踪:提升调试效率的利器
【8月更文挑战第8天】在复杂的分布式系统中,日志是诊断问题、追踪系统行为的重要工具。然而,随着微服务架构的普及,服务间的调用链路错综复杂,传统的日志记录方式往往难以快速定位问题源头。今天,我们将探讨如何在不依赖外部组件(如Zipkin、Sleuth等)的情况下,手动实现Spring Boot应用的日志链路追踪,让日志定位更加便捷高效。
649 1
|
存储 SQL Java
Spring Boot使用slf4j进行日志记录
本节课主要对 slf4j 做了一个简单的介绍,并且对 Spring Boot 中如何使用 slf4j 输出日志做了详细的说明,着重分析了 logback.xml 文件中对日志相关信息的配置,包括日志的不同级别...
|
10月前
|
开发框架 运维 监控
Spring Boot中的日志框架选择
在Spring Boot开发中,日志管理至关重要。常见的日志框架有Logback、Log4j2、Java Util Logging和Slf4j。选择合适的日志框架需考虑性能、灵活性、社区支持及集成配置。本文以Logback为例,演示了如何记录不同级别的日志消息,并强调合理配置日志框架对提升系统可靠性和开发效率的重要性。
412 5