精华内容
下载资源
问答
  • 文章目录CentOS 7安装elasticsearch6.5.4+logstash6.5.4并且使用java代码实现查询1、环境准备1.1 创建普通用户1.2 安装jdk1.3 防火墙设置2、安装elasticsearch2.1 elasticsearch配置2.2 把elasticsearch作为服务进行...

    elasticsearch+logstash并使用java代码实现日志检索


    为了项目日志不被泄露,数据展示不采用Kibana

    1、环境准备

    1.1 创建普通用户

    #创建用户
    useradd querylog
    
    #设置密码
    passwd queylog
    
    #授权sudo权限
    查找sudoers文件位置 
    whereis sudoers
    #修改文件为可编辑 
    chmod -v u+w /etc/sudoers
    #编辑文件
    vi /etc/sudoers
    #收回权限
    chmod -v u-w /etc/sudoers
    #第一次使用sudo会有提示
    
    We trust you have received the usual lecture from the local System
    Administrator. It usually boils down to these three things:
    
        #1) Respect the privacy of others.
        #2) Think before you type.
        #3) With great power comes great responsibility.
    
    用户创建完成。
    

    1.2 安装jdk

    su queylog
    cd /home/queylog
    #解压jdk-8u191-linux-x64.tar.gz 
    tar -zxvf jdk-8u191-linux-x64.tar.gz 
    sudo mv jdk1.8.0_191 /opt/jdk1.8
    #编辑/ect/profile
    vi /ect/profile
    export JAVA_HOME=/opt/jdk1.8
    export JRE_HOME=$JAVA_HOME/jre
    export CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
    export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
    #刷新配置文件
    source /ect/profile
    #查看jdk版本
    java -verion
    

    1.3 防火墙设置

    #放行指定IP
    firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="172.16.110.55"   accept" 
    #重新载入
    firewall-cmd --reload
    

    2、安装elasticsearch

    2.1 elasticsearch配置

    注意:elasticsearch要使用普通用户启动要不然会报错

    su queylog
    cd /home/queylog
    #解压elasticsearch-6.5.4.tar.gz
    tar -zxvf elasticsearch-6.5.4.tar.gz
    sudo mv elasticsearch-6.5.4 /opt/elasticsearch
    #编辑es配置文件
    vi /opt/elasticsearch/config/elasticsearch.yml 
    # 配置es的集群名称
    cluster.name: elastic
    # 修改服务地址
    network.host: 192.168.8.224
    # 修改服务端口
    http.port: 9200
    
    #切换root用户
    su root
    #修改/etc/security/limits.conf 追加以下内容
    vi /etc/security/limits.conf
    * hard nofile 655360
    * soft nofile 131072
    * hard nproc 4096
    * soft nproc 2048
    
    #编辑 /etc/sysctl.conf,追加以下内容:
    vi /etc/sysctl.conf
    vm.max_map_count=655360
    fs.file-max=655360
    
    #保存后,重新加载:
    sysctl -p
    
    #切换回普通用户
    su queylog
    #启动elasticsearch
    ./opt/elasticsearch/bin/elasticsearch
    #测试
    curl http://192.168.8.224:9200
    #控制台会打印
    {
      "name" : "L_dA6oi",
      "cluster_name" : "elasticsearch",
      "cluster_uuid" : "eS7yP6fVTvC8KMhLutOz6w",
      "version" : {
        "number" : "6.5.4",
        "build_flavor" : "default",
        "build_type" : "tar",
        "build_hash" : "d2ef93d",
        "build_date" : "2018-12-17T21:17:40.758843Z",
        "build_snapshot" : false,
        "lucene_version" : "7.5.0",
        "minimum_wire_compatibility_version" : "5.6.0",
        "minimum_index_compatibility_version" : "5.0.0"
      },
      "tagline" : "You Know, for Search"
    }
    

    2.2 把elasticsearch作为服务进行管理

    #切换root用户
    su root
    #编写服务配置文件
    vi /usr/lib/systemd/system/elasticsearch.service
    [unit]
    Description=Elasticsearch
    Documentation=http://www.elastic.co
    Wants=network-online.target
    After=network-online.target
    
    [Service]
    Environment=ES_HOME=/opt/elasticsearch
    Environment=ES_PATH_CONF=/opt/elasticsearch/config
    Environment=PID_DIR=/opt/elasticsearch/config
    EnvironmentFile=/etc/sysconfig/elasticsearch
    WorkingDirectory=/opt/elasticsearch
    User=queylog
    Group=queylog
    ExecStart=/opt/elasticsearch/bin/elasticsearch -p ${PID_DIR}/elasticsearch.pid
    
    # StandardOutput is configured to redirect to journalctl since
    # some error messages may be logged in standard output before
    # elasticsearch logging system is initialized. Elasticsearch
    # stores its logs in /var/log/elasticsearch and does not use
    # journalctl by default. If you also want to enable journalctl
    # logging, you can simply remove the "quiet" option from ExecStart.
    StandardOutput=journal
    StandardError=inherit
    
    # Specifies the maximum file descriptor number that can be opened by this process
    LimitNOFILE=65536
    
    # Specifies the maximum number of process
    LimitNPROC=4096
    
    # Specifies the maximum size of virtual memory
    LimitAS=infinity
    
    # Specifies the maximum file size
    LimitFSIZE=infinity
    
    # Disable timeout logic and wait until process is stopped
    TimeoutStopSec=0
    
    # SIGTERM signal is used to stop the Java process
    KillSignal=SIGTERM
    
    # Send the signal only to the JVM rather than its control group
    KillMode=process
    
    # Java process is never killed
    SendSIGKILL=no
    
    # When a JVM receives a SIGTERM signal it exits with code 143
    SuccessExitStatus=143
     
    [Install]
    WantedBy=multi-user.target
    
    
    vi /etc/sysconfig/elasticsearch
    
    elasticsearch    #
    #######################
    
    # Elasticsearch home directory
    ES_HOME=/opt/elasticsearch
    
    # Elasticsearch Java path
    JAVA_HOME=/home/liyijie/jdk1.8
    CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOMR/jre/lib
    
    # Elasticsearch configuration directory
    ES_PATH_CONF=/opt/elasticsearch/config
    
    # Elasticsearch PID directory
    PID_DIR=/opt/elasticsearch/config
    
    #############################
    #   Elasticsearch Service   #
    #############################
    
    # SysV init.d
    # The number of seconds to wait before checking if elasticsearch started successfully as a daemon process
    ES_STARTUP_SLEEP_TIME=5
    
    ################################
    #   Elasticsearch Properties   #
    ################################
    # Specifies the maximum file descriptor number that can be opened by this process
    # When using Systemd,this setting is ignored and the LimitNOFILE defined in
    # /usr/lib/systemd/system/elasticsearch.service takes precedence
    #MAX_OPEN_FILES=65536
    
    # The maximum number of bytes of memory that may be locked into RAM
    # Set to "unlimited" if you use the 'bootstrap.memory_lock: true' option
    # in elasticsearch.yml.
    # When using Systemd,LimitMEMLOCK must be set in a unit file such as
    # /etc/systemd/system/elasticsearch.service.d/override.conf.
    #MAX_LOCKED_MEMORY=unlimited
    
    # Maximum number of VMA(Virtual Memory Areas) a process can own
    # When using Systemd,this setting is ignored and the 'vm.max_map_count'
    # property is set at boot time in /usr/lib/sysctl.d/elasticsearch.conf
    #MAX_MAP_COUNT=262144
    
    # 重新加载服务
    systemctl daemon-reload
    #切换普通用户
    su queylog
    #启动elasticsearch
    sudo systemctl start elasticsearch
    #设置开机自启动
    sudo systemctl enable elasticsearch
    

    3、安装logstash

    3.1、logstash配置

    su queylog
    cd /home/queylog
    #解压 logstash-6.5.4.tar.gz
    tar -zxvf logstash-6.5.4.tar.gz
    sudo mv logstash-6.5.4 /opt/logstash
    #编辑es配置文件
    vi /opt/logstash/config/logstash.yml 
    xpack.monitoring.enabled: true
    xpack.monitoring.elasticsearch.username: elastic
    xpack.monitoring.elasticsearch.password: changeme
    xpack.monitoring.elasticsearch.url: ["http://192.168.8.224:9200"]
    #在bin目录下创建logstash.conf
    vi /opt/logstash/bin/logstash.conf
    input {
    # 以文件作为来源
    file {
    # 日志文件路径
    path => "/opt/tomcat/logs/catalina.out"
    start_position => "beginning" # (end, beginning)
    type=> "isp"
    }
    }
    #filter { 
    #定义数据的格式,正则解析日志(根据实际需要对日志日志过滤、收集)
    #grok {     
    #    match => { "message" => "%{IPV4:clientIP}|%{GREEDYDATA:request}|%{NUMBER:duration}"}
    #}          
    #根据需要对数据的类型转换     
    #mutate { convert => { "duration" => "integer" }}
    #}
    # 定义输出    
    output {
    elasticsearch {
    hosts => "192.168.43.211:9200" #Elasticsearch 默认端口
    index => "ind"
    document_type => "isp"
    }   
    } 
    #给该用户授权
    chown queylog:queylog /opt/logstash
    #启动logstash
    ./opt/logstash/bin/logstash -f logstash.conf 
    
    # 安装并配置启动logstash后查看es索引是否创建完成
    curl  http://192.168.8.224:9200/_cat/indices
    

    4、java代码部分

    之前在SpringBoot整合ElasticSearch与Redis的异常解决

    查阅资料,这个归纳的原因比较合理。
    原因分析:程序的其他地方使用了Netty,这里指redis。这影响在实例化传输客户端之前初始化处理器的数量。 实例化传输客户端时,我们尝试初始化处理器的数量。 由于在其他地方使用Netty,因此已经初始化并且Netty会对此进行防范,因此首次实例化会因看到的非法状态异常而失败。

    解决方案

    在SpringBoot启动类中加入:

    System.setProperty("es.set.netty.runtime.available.processors", "false");
    

    4.1、引入pom依赖

    		
    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            </dependency>
    

    4.2、修改配置文件

    spring.data.elasticsearch.cluster-name=elastic
    # restapi使用9200
    # java程序使用9300
    spring.data.elasticsearch.cluster-nodes=192.168.43.211:9300
    

    4.3、对应的接口以及实现类

    import org.springframework.data.elasticsearch.annotations.Document;
    import org.springframework.data.elasticsearch.annotations.Field;
    
    
    @Document(indexName = "ind", type = "isp")
    public class Bean {
    
    
        @Field
        private String message;
    
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    
        @Override
        public String toString() {
            return "Tomcat{" +
                    ", message='" + message + '\'' +
                    '}';
        }
    }
    
    
    
    import java.util.Map;
    
    
    public interface IElasticSearchService {
    
         Map<String, Object> search(String keywords, Integer currentPage, Integer pageSize) throws Exception ;
    
    	//特殊字符转义
         default String escape( String s) {
            StringBuilder sb = new StringBuilder();
    
            for(int i = 0; i < s.length(); ++i) {
                char c = s.charAt(i);
                if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':' || c == '^' || c == '[' || c == ']' || c == '"' || c == '{' || c == '}' || c == '~' || c == '*' || c == '?' || c == '|' || c == '&' || c == '/') {
                    sb.append('\\');
                }
    
                sb.append(c);
            }
            return sb.toString();
        }
    
    }
    
    import org.elasticsearch.index.query.BoolQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
    import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
    import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.Resource;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * ElasticSearch实现类
     */
    @Service
    public class ElasticSearchServiceImpl implements IElasticSearchService {
    
        Logger log = LoggerFactory.getLogger(ElasticSearchServiceImpl.class);
    
        @Autowired
        ElasticsearchTemplate elasticsearchTemplate;
    
        @Resource
        HighlightResultHelper highlightResultHelper;
    
        @Override
        public Map<String, Object> search(String keywords, Integer currentPage, Integer pageSize) {
            keywords= escape(keywords);
                currentPage = Math.max(currentPage - 1, 0);
    
            List<HighlightBuilder.Field> highlightFields = new ArrayList<>();
       //设置高亮 把查询到的关键字进行高亮
            HighlightBuilder.Field message = new HighlightBuilder.Field("message").fragmentOffset(80000).numOfFragments(0).requireFieldMatch(false).preTags("<span style='color:red'>").postTags("</span>");
            highlightFields.add(message);
    
            HighlightBuilder.Field[] highlightFieldsAry = highlightFields.toArray(new HighlightBuilder
                    .Field[highlightFields.size()]);
         
            //创建查询构造器
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
            //过滤  按字段权重进行搜索  查询内容不为空按关键字、摘要、其他属性权重
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            queryBuilder.withPageable(PageRequest.of(currentPage, pageSize));
            if (!MyStringUtils.isEmpty(keywords)){
                boolQueryBuilder.must(QueryBuilders.queryStringQuery(keywords).field("message"));
            }
    
            queryBuilder.withQuery(boolQueryBuilder);
    
            queryBuilder.withHighlightFields(highlightFieldsAry);
    
            log.info("查询语句:{}", queryBuilder.build().getQuery().toString());
    
            //查询
            AggregatedPage<Bean> result = elasticsearchTemplate.queryForPage(queryBuilder.build(), Bean
                    .class,highlightResultHelper);
            //解析结果
            long total = result.getTotalElements();
            int totalPage = result.getTotalPages();
            List<Bean> blogList = result.getContent();
            Map<String, Object> map = new HashMap<>();
            map.put("total", total);
            map.put("totalPage", totalPage);
            map.put("pageSize", pageSize);
            map.put("currentPage", currentPage + 1);
            map.put("blogList", blogList);
            return map;
        }
    
    import com.alibaba.fastjson.JSONObject;
    import org.apache.commons.beanutils.PropertyUtils;
    import org.elasticsearch.action.search.SearchResponse;
    import org.elasticsearch.common.text.Text;
    import org.elasticsearch.search.SearchHit;
    import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.elasticsearch.core.SearchResultMapper;
    import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
    import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
    import org.springframework.stereotype.Component;
    import org.springframework.util.StringUtils;
    
    import java.lang.reflect.InvocationTargetException;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * ElasticSearch高亮配置
     */
    @Component
    public class HighlightResultHelper implements SearchResultMapper {
    
        Logger log = LoggerFactory.getLogger(HighlightResultHelper.class);
    
    
        @Override
        public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
            List<T> results = new ArrayList<>();
            for (SearchHit hit : response.getHits()) {
                if (hit != null) {
                    T result = null;
                    if (StringUtils.hasText(hit.getSourceAsString())) {
                        result = JSONObject.parseObject(hit.getSourceAsString(), clazz);
                    }
                    // 高亮查询
                    for (HighlightField field : hit.getHighlightFields().values()) {
                        try {
                            PropertyUtils.setProperty(result, field.getName(), concat(field.fragments()));
                        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                            log.error("设置高亮字段异常:{}", e.getMessage(), e);
                        }
                    }
                    results.add(result);
                }
            }
            return new AggregatedPageImpl<T>(results, pageable, response.getHits().getTotalHits(), response
                    .getAggregations(), response.getScrollId());
        }
    
    
        public <T> T mapSearchHit(SearchHit searchHit, Class<T> clazz) {
            List<T> results = new ArrayList<>();
            for (HighlightField field : searchHit.getHighlightFields().values()) {
                T result = null;
                if (StringUtils.hasText(searchHit.getSourceAsString())) {
                    result = JSONObject.parseObject(searchHit.getSourceAsString(), clazz);
                }
                try {
                    PropertyUtils.setProperty(result, field.getName(), concat(field.fragments()));
                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                    log.error("设置高亮字段异常:{}", e.getMessage(), e);
                }
                results.add(result);
            }
            return null;
        }
    
        private String concat(Text[] texts) {
            StringBuffer sb = new StringBuffer();
            for (Text text : texts) {
                sb.append(text.toString());
            }
            return sb.toString();
        }
    }
    
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = CbeiIspApplication.class)
    public class ElasticSearchServiceTest {w
    
       private static Logger logger= LoggerFactory.getLogger(EncodePhoneAndCardTest.class);
       
      @Autowired
       private IElasticSearchService elasticSearchService;
    
      	@Test
        public ResponseVO getLog(){
           try {
           Map<String, Object> search = elasticSearchService.search("Exception", 1, 10);
             logger.info( JSON.toJSONString(search));
           } catch (Exception e) {
               e.printStackTrace();
           }
    }
    
    例如:以上就是今天要讲的内容,本文仅仅简单介绍了elasticsearch跟logstash的使用, 文章若有不当之处,欢迎评论指出~
    展开全文
  • 这两天做了个系统日志管理功能,现在来总结一下。项目中用到AOP主要是将日志记录从业务逻辑代码中划分出来,减少冗余代码和重复工作步骤...废话有点多 首先创建操作系统日志表,表结构如下: 1.创建操作日志注解...

    这两天做了个系统日志管理功能,现在来总结一下。项目中用到AOP主要是将日志记录从业务逻辑代码中划分出来,减少冗余代码和重复工作步骤...废话有点多

    首先创建操作系统日志表,表结构如下:

    1.创建操作日志注解类Log.java

    package com.daqing.financial.hrauth.annotation;
    
    
    import com.daqing.financial.hrauth.enums.OperationType;
    import com.daqing.financial.hrauth.enums.OperationUnit;
    
    import java.lang.annotation.*;
    
    /**
     * @author Rogers
     * 操作日志注解
     * @create 2020-07-03
     */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Log {
    
        /**
         * 方法描述,可使用占位符获取参数:{{tel}}
         */
        String detail() default "";
    
        /**
         * 日志等级:自己定,此处分为1-9
         */
        int level() default 0;
    
        /**
         * 操作类型(enum):主要是select,insert,update,delete
         */
        OperationType operationType() default OperationType.UNKNOWN;
    
        /**
         * 被操作的对象(此处使用enum):可以是任何对象,如表名(user),或者是工具(redis)
         */
        OperationUnit operationUnit() default OperationUnit.UNKNOWN;
    
    
    }
    
    
    

    2.创建切面类记录操作系统日志(此处的获取登录用户信息是根据request请求中的token获取到user_id,从而得到所有用户信息)

    package com.daqing.financial.hrauth.aspect;
    
    import com.alibaba.fastjson.JSONObject;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.daqing.financial.hrauth.annotation.Log;
    import com.daqing.financial.hrauth.service.TokenService;
    import com.daqing.financial.hrauth.service.UserLoginService;
    import com.daqing.framework.domain.hrms.Token;
    import com.daqing.framework.domain.hrms.UserEntity;
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @ClassName SysLogAspect
     * @Description 操作日志切面
     * @Date 2020/9/30 
     * @Version 1.0
     */
    @Slf4j
    @Aspect
    @Component
    public class SysLogAspect {
    
        @Resource
        private Operation operation;
        @Autowired
        private TokenService tokenService;
        @Autowired
        private UserLoginService userLoginService;
        /**
         * 此处的切点是注解的方式,也可以用包名的方式达到相同的效果
         * '@Pointcut("execution(* com.wwj.springboot.service.impl.*.*(..))")'
         */
        @Pointcut("@annotation(com.daqing.financial.hrauth.annotation.Log)")
        public void operationLog() {
        }
    
    
        /**
         * 环绕增强,相当于MethodInterceptor
         */
        @Around("operationLog()")
        public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
            Object res = null;
            long time = System.currentTimeMillis();
            try {
                res = joinPoint.proceed();
                time = System.currentTimeMillis() - time;
                return res;
            } finally {
                try {
                    //User systemUser = (User) SecurityUtils.getSubject().getPrincipal();
                    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                    String token = request.getHeader("token");
                    Token userToken = tokenService.getOne(new QueryWrapper<Token>().eq("token", token));
                    UserEntity systemUser = userLoginService.getOne(new QueryWrapper<UserEntity>().eq("id",userToken.getUserId()));
                    operation.addOperationLog(joinPoint,res,time,systemUser);
                    //方法执行完成后增加日志
    //                addOperationLog(joinPoint, res, time);
                } catch (Exception e) {
                    log.error("LogAspect 操作失败:" + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    
    
        /**
         * 对当前登录用户和占位符处理
         *
         * @param argNames   方法参数名称数组
         * @param args       方法参数数组
         * @param annotation 注解信息
         * @return 返回处理后的描述
         */
        private String getDetail(String[] argNames, Object[] args, Log annotation) {
            //获得登录用户信息
            //User systemUser = (User) SecurityUtils.getSubject().getPrincipal();
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            UserEntity systemUser = (UserEntity) request.getUserPrincipal();
    
            Map<Object, Object> map = new HashMap<>(4);
            for (int i = 0; i < argNames.length; i++) {
                map.put(argNames[i], args[i]);
            }
    
            String detail = annotation.detail();
            try {
                detail = "'" + systemUser.getAccount() + "'=》" + annotation.detail();
                for (Map.Entry<Object, Object> entry : map.entrySet()) {
                    Object k = entry.getKey();
                    Object v = entry.getValue();
                    detail = detail.replace("{{" + k + "}}", JSONObject.toJSONString(v));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return detail;
        }
    
        @Before("operationLog()")
        public void doBeforeAdvice(JoinPoint joinPoint) {
    //        System.out.println("进入方法前执行.....");
        }
    
        /**
         * 处理完请求,返回内容
         *
         * @param ret
         */
        @AfterReturning(returning = "ret", pointcut = "operationLog()")
        public void doAfterReturning(Object ret) {
    //        System.out.println("方法的返回值 : " + ret);
        }
    
        /**
         * 后置异常通知
         */
        @AfterThrowing("operationLog()")
        public void throwss(JoinPoint jp) {
    //        System.out.println("方法异常时执行.....");
        }
    
    
        /**
         * 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
         */
        @After("operationLog()")
        public void after(JoinPoint jp) {
    //        System.out.println("方法最后执行.....");
        }
    
    
        /**
         * 获取客户端ip地址
         *
         * @param request
         * @return
         */
        public static String getClientIp(HttpServletRequest request) {
            String ip = request.getHeader("x-forwarded-for");
            if (ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ip == null || ip.trim() == "" || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }
            // 多个路由时,取第一个非unknown的ip
            final String[] arr = ip.split(",");
            for (final String str : arr) {
                if (!"unknown".equalsIgnoreCase(str)) {
                    ip = str;
                    break;
                }
            }
            return ip;
        }
    
    }
    

    3.操作日志类Operation.java

    package com.daqing.financial.hrauth.aspect;
    
    import com.alibaba.fastjson.JSONObject;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import com.daqing.financial.hrauth.annotation.Log;
    import com.daqing.financial.hrauth.dao.SystemLogMapper;
    import com.daqing.financial.hrauth.service.TokenService;
    import com.daqing.financial.hrauth.service.UserLoginService;
    import com.daqing.financial.hrauth.util.IpUtils;
    import com.daqing.framework.domain.hrms.SystemLog;
    import com.daqing.framework.domain.hrms.Token;
    import com.daqing.framework.domain.hrms.UserEntity;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.annotation.Resource;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    /**
     * @ClassName Operation
     * @Description 操作日志类
     * @Date 2020/9/29 10:06
     * @Version 1.0
     */
    @Slf4j
    @Component
    public class Operation {
    
        @Resource
        private SystemLogMapper systemLogMapper;
        @Autowired
        private TokenService tokenService;
        @Autowired
        private UserLoginService userLoginService;
        @Async
        public void addOperationLog(JoinPoint joinPoint, Object res, long time, UserEntity systemUser) {
    //        synchronized (SysLogAspect.class) {//获得登录用户信息
    //        User systemUser = (User) SecurityUtils.getSubject().getPrincipal();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            SystemLog operationLog = new SystemLog();
            //获取内网地址IpUtils.intranetIp()
            //获取外网地址IpUtils.internetIp()
    //        operationLog.setIpAddressLan("");
    //        operationLog.setIpAddressWan("");
            operationLog.setIpAddressLan(IpUtils.intranetIp());
            //获取不到外网IP设置内网IP
            if (StringUtils.isBlank(IpUtils.internetIp())) {
                operationLog.setIpAddressWan(IpUtils.intranetIp());
            } else {
                operationLog.setIpAddressWan(IpUtils.internetIp());
            }
    //        operationLog.setRunTime(time);
            //operationLog.setRunTime(0L);
            operationLog.setReturnValue(JSONObject.toJSONString(res));
            operationLog.setId(UUID.randomUUID().toString());
            operationLog.setArgs(JSONObject.toJSONString(joinPoint.getArgs()));
            operationLog.setCreateTime(new Date());
            operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
            operationLog.setUserId(systemUser.getId() + "");
            operationLog.setUserName(systemUser.getAccount());
            Log annotation = signature.getMethod().getAnnotation(Log.class);
            if (annotation != null) {
                operationLog.setLogLevel(annotation.level());
                operationLog.setLogDescribe(getDetail(((MethodSignature) joinPoint.getSignature()).getParameterNames(), joinPoint.getArgs(), annotation));
                operationLog.setOperationType(annotation.operationType().getValue());
                operationLog.setOperationUnit(annotation.operationUnit().getValue());
            }
    
            //这里保存日志
    //        log.info("######记录日志:{}######", operationLog.toString());
            int b = systemLogMapper.insert(operationLog);
            log.info("######记录日志:{}######", operationLog.toString());
            if (b<= 0) {
                log.error("#####新增###记录日志失败:{}####", operationLog);
            }
    //        }
        }
    
        /**
         * 对当前登录用户和占位符处理
         *
         * @param argNames   方法参数名称数组
         * @param args       方法参数数组
         * @param annotation 注解信息
         * @return 返回处理后的描述
         */
        private String getDetail(String[] argNames, Object[] args, Log annotation) {
            //获得登录用户信息
            //User systemUser = (User) SecurityUtils.getSubject().getPrincipal();
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String token = request.getHeader("token");
            Token userToken = tokenService.getOne(new QueryWrapper<Token>().eq("token", token));
            UserEntity systemUser = userLoginService.getOne(new QueryWrapper<UserEntity>().eq("id",userToken.getUserId()));
    
            Map<Object, Object> map = new HashMap<>(4);
            for (int i = 0; i < argNames.length; i++) {
                map.put(argNames[i], args[i]);
            }
    
            String detail = annotation.detail();
            try {
                detail = "'" + systemUser.getAccount() + "'=》" + annotation.detail();
                for (Map.Entry<Object, Object> entry : map.entrySet()) {
                    Object k = entry.getKey();
                    Object v = entry.getValue();
                    detail = detail.replace("{{" + k + "}}", JSONObject.toJSONString(v));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return detail;
        }
    }
    

    主要的三个业务逻辑类写完了,下面再记录一些细节的类,包括引用到的java类和工具类等...

    1.SystemLogMapper类

    package com.daqing.financial.hrauth.dao;
    
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.daqing.framework.domain.hrms.SystemLog;
    import org.apache.ibatis.annotations.Mapper;
    
    /**
     * @ClassName SystemLogMapper
     * @Description 用户动作记录
     * @Date 2020/9/30
     * @Version 1.0
     */
    @Mapper
    public interface SystemLogMapper extends BaseMapper<SystemLog> {
    }
    
    

    2.枚举类enums,主要有三个,分别是BusinessType(日志操作类型),OperationType(操作类型),OperationUnit(被操作的单元)

    package com.daqing.financial.hrauth.enums;
    
    /**
     * 日志操作类型
     */
    public enum BusinessType
    {
        /**
         * 其它
         */
        OTHER,
        /**
         * 新增
         */
        INSERT,
        /**
         * 修改
         */
        UPDATE,
        /**
         * 删除
         */
        DELETE,
        /**
         * 查询
         */
        SELECT,
        /**
         * 导出
         */
        EXPORT,
        /**
         * 导入
         */
        IMPORT;
    
        public static String getMsg(BusinessType type){
            String result = null;
            switch (type) {
                case INSERT:
                    result = "新增";
                    break;
                case UPDATE:
                    result = "修改";
                    break;
                case DELETE:
                    result = "删除";
                    break;
                case SELECT:
                    result = "查询";
                    break;
                case EXPORT:
                    result = "导出";
                    break;
                case IMPORT:
                    result = "导入";
                    break;
                case OTHER:
                    result = "其它";
                    break;
                default:
                    break;
            }
            return result;
        }
    }
    
    package com.daqing.financial.hrauth.enums;
    
    public enum OperationType {
    
        /**
         * 操作类型
         */
        UNKNOWN("UNKNOWN"),
        DELETE("DELETE"),
        SELECT("SELECT"),
        UPDATE("UPDATE"),
        INSERT("INSERT");
    
        private String value;
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        OperationType(String s) {
            this.value = s;
        }
    
    
        public static String getMsg(BusinessType type){
            String result = null;
            switch (type) {
                case INSERT:
                    result = "新增";
                    break;
                case UPDATE:
                    result = "修改";
                    break;
                case DELETE:
                    result = "删除";
                    break;
                case SELECT:
                    result = "查询";
                    break;
                case OTHER:
                    result = "其它";
                    break;
                default:
                    break;
            }
            return result;
        }
    }
    
    package com.daqing.financial.hrauth.enums;
    
    public enum OperationUnit {
        /**
         * 被操作的单元
         */
        UNKNOWN("unknown"),
        USER("user"),
        LOG("log"),
        PERMISSION("permission"),
        ROLE("role"),
        DEVICE("device"),
        WITHDRAW("withdraw"),
        ATRUSER("atrUser"),
        ASSERT("ASSERT"),
        COIN("coin"),
        NOTICE("notice"),
        DATASTATISTIC("datastatistic"),
        BlockGroup("blockGroup"),
        C2C("c2c"),
        USERROLE("userRole");
    
        private String value;
    
        OperationUnit(String value) {
            this.value = value;
        }
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
    }
    

    3.操作日志类SystemLog.java

    package com.daqing.framework.domain.hrms;
    
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import com.fasterxml.jackson.annotation.JsonFormat;
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.AllArgsConstructor;
    import lombok.Builder;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    import java.util.Date;
    
    /**
     * @ClassName SystemLog
     * @Description 操作日志
     * @Date 2020/9/29 14:30
     * @Version 1.0
     */
    
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    @Data
    @TableName("sys_action_log")
    @ApiModel("操作日志")
    public class SystemLog {
        @TableId(value = "id", type = IdType.UUID)
        private String id;
        /**
         * 创建时间
         */
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    //    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    //    @TableField(fill = FieldFill.INSERT_UPDATE)
        @ApiModelProperty("创建时间")
        private Date createTime;
        /**
         * 日志等级
         */
        @ApiModelProperty("日志等级")
        private Integer logLevel;
        /**
         * 被操作的对象
         */
        @ApiModelProperty("被操作的对象")
        private String operationUnit;
        /**
         * 方法名
         */
        @ApiModelProperty("method")
        private String method;
        /**
         * 参数
         */
        @ApiModelProperty("参数")
        private String args;
        /**
         * 操作人id
         */
        @ApiModelProperty("操作人id")
        private String userId;
        /**
         * 操作人
         */
        @ApiModelProperty("操作人")
        private String userName;
        /**
         * 日志描述
         */
        @ApiModelProperty("日志描述")
        private String logDescribe;
        /**
         * 操作类型
         */
        @ApiModelProperty("操作类型")
        private String operationType;
        /**
         * 方法运行时间
         */
        @ApiModelProperty("方法运行时间")
        @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
        private Long runTime;
        /**
         * 方法返回值
         */
        @ApiModelProperty("方法返回值")
        private String returnValue;
        /**
         * 内网IP地址
         */
        @ApiModelProperty("内网IP地址")
        private String ipAddressLan;
    
        /**
         * 外网IP地址
         */
        @ApiModelProperty("外网IP地址")
        private String ipAddressWan;
    }
    

    4.Ip工具类 IpUtils

    package com.daqing.financial.hrauth.util;
    
    import java.net.Inet4Address;
    import java.net.InetAddress;
    import java.net.NetworkInterface;
    import java.util.Enumeration;
    
    /**
     * @ClassName IpUtils
     * @Description Ip工具类,获取ip
     * @Date 2020/9/30
     * @Version 1.0
     */
    public class IpUtils {
        /***
         * 获取外网IP
         * @return
         */
        public static String internetIp() {
            try {
    
                Enumeration<NetworkInterface> networks = NetworkInterface.getNetworkInterfaces();
                InetAddress inetAddress = null;
                Enumeration<InetAddress> inetAddresses = null;
                while (networks.hasMoreElements()) {
                    inetAddresses = networks.nextElement().getInetAddresses();
                    while (inetAddresses.hasMoreElements()) {
                        inetAddress = inetAddresses.nextElement();
                        if (inetAddress != null
                                && inetAddress instanceof Inet4Address
                                && !inetAddress.isSiteLocalAddress()
                                && !inetAddress.isLoopbackAddress()
                                && inetAddress.getHostAddress().indexOf(":") == -1) {
                            return inetAddress.getHostAddress();
                        }
                    }
                }
    
                return null;
    
            } catch (Exception e) {
    
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 获取内网IP
         *
         * @return
         */
        public static String intranetIp() {
            try {
                return InetAddress.getLocalHost().getHostAddress();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        /**
         * 获取服务启动host
         * @return
         */
        public static String getHost(){
            return internetIp()==null?intranetIp():internetIp();
        }
    }
    

    最后,添加注解即可

        @GetMapping("/list")
        @Log(detail = "员工列表",level = 3,operationUnit = OperationUnit.ROLE,operationType = OperationType.INSERT)
        //@RequiresPermissions("hrms:employee:info")
        public ResponseResult list(@RequestParam("page") Integer page,
                                   @RequestParam("size") Integer size,
                                   @Valid EmployeeEntity employee) {
            PageUtils data = employeeService.queryPage(page, size, employee);
            return new ResponseResult<PageUtils>().SUCCESS(data);
        }

    效果如下:

    展开全文
  • 二,代码实现 基于注解的Aop日志记录 1.Log实体类 package com.ideal.manage.guest.bean.log; import javax.persistence.*; import java.io.Serializable; import java.util.Date; /** * @...

    一,功能点

    实现管理员操作数据的记录。效果如下

    二,代码实现

    基于注解的Aop日志记录

    1.Log实体类

    package com.ideal.manage.guest.bean.log;
    
    import javax.persistence.*;
    import java.io.Serializable;
    import java.util.Date;
    
    /**
     * @apiNote 日志
     * @author Yaming
     * @since 2019-01-24
     */
    @Entity
    @Table(name = "visitor_sys_log")
    public class Log implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @Id
        @GeneratedValue(strategy= GenerationType.IDENTITY)
        private Long id;
    
        private String content;
    
        private String description;
    
        private String ip;
    
        private String module;
    
        private String username;
    
        private Date createAt;
    
        private Date updateAt;
    
        private Integer able;
    
    
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public String getDescription() {
            return description;
        }
    
        public void setDescription(String description) {
            this.description = description;
        }
    
        public String getIp() {
            return ip;
        }
    
        public void setIp(String ip) {
            this.ip = ip;
        }
    
        public String getModule() {
            return module;
        }
    
        public void setModule(String module) {
            this.module = module;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public static long getSerialVersionUID() {
            return serialVersionUID;
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public Date getCreateAt() {
            return createAt;
        }
    
        public void setCreateAt(Date createAt) {
            this.createAt = createAt;
        }
    
        public Date getUpdateAt() {
            return updateAt;
        }
    
        public void setUpdateAt(Date updateAt) {
            this.updateAt = updateAt;
        }
    
        public Integer getAble() {
            return able;
        }
    
        public void setAble(Integer able) {
            this.able = able;
        }
    }

    2.定义注解

    package com.ideal.manage.guest.annotation;
    
    import java.lang.annotation.*;
    
    /**
     * @author Hao
     * @create 2017-03-29
     */
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Log {
        /**模块*/
        String module() default "";
    
        /**描述*/
        String description() default "";
    }

    3.定义切面

    package com.ideal.manage.guest.aop;
    
    
    import com.ideal.manage.guest.annotation.Log;
    import com.ideal.manage.guest.service.log.LogService;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import java.lang.reflect.Method;
    
    /**
     * 日志切面处理类
     *
     * @author Yaming
     * @create 2019-01-24
     */
    @Aspect
    @Component
    public class LogAspect {
    
        @Autowired
        private LogService logService;
    
        /**
         * 日志切入点
         */
        @Pointcut("@annotation(com.ideal.manage.guest.annotation.Log)")
        public void logPointCut(){}
    
        @AfterReturning(pointcut = "logPointCut()")
        public void doAfter(JoinPoint joinPoint){
            /**
             * 解析Log注解
             */
            String methodName = joinPoint.getSignature().getName();
            Method method = currentMethod(joinPoint,methodName);
            Log log = method.getAnnotation(Log.class);
            logService.put(joinPoint,methodName,log.module(),log.description());
        }
    
        /**
         * 获取当前执行的方法
         *
         * @param joinPoint  连接点
         * @param methodName 方法名称
         * @return 方法
         */
        private Method currentMethod(JoinPoint joinPoint, String methodName) {
            /**
             * 获取目标类的所有方法,找到当前要执行的方法
             */
            Method[] methods = joinPoint.getTarget().getClass().getMethods();
            Method resultMethod = null;
            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    resultMethod = method;
                    break;
                }
            }
            return resultMethod;
        }
    
    }

    4.业务处理:LogService

    package com.ideal.manage.guest.service.log;
    
    import com.alibaba.fastjson.JSONObject;
    
    
    import com.ideal.manage.guest.bean.DTO.PageDto;
    import com.ideal.manage.guest.bean.log.Log;
    
    import com.ideal.manage.guest.config.shiro.MyShiroRealm;
    import com.ideal.manage.guest.repository.framework.MySpecification;
    import com.ideal.manage.guest.repository.framework.SpecificationOperator;
    import com.ideal.manage.guest.repository.log.LogRepository;
    import com.ideal.manage.guest.util.Const;
    import com.ideal.manage.guest.util.HttpRequests;
    import com.ideal.manage.guest.util.IPUtils;
    
    /*import org.apache.ibatis.javassist.*;
    import org.apache.ibatis.javassist.bytecode.CodeAttribute;
    import org.apache.ibatis.javassist.bytecode.LocalVariableAttribute;
    import org.apache.ibatis.javassist.bytecode.MethodInfo;*/
    import javassist.*;
    import javassist.bytecode.CodeAttribute;
    import javassist.bytecode.LocalVariableAttribute;
    import javassist.bytecode.MethodInfo;
    import org.apache.shiro.SecurityUtils;
    import org.aspectj.lang.JoinPoint;
    import org.springframework.beans.factory.annotation.Autowired;
    
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageRequest;
    import org.springframework.data.domain.Pageable;
    import org.springframework.data.domain.Sort;
    import org.springframework.stereotype.Service;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.StringUtils;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    /**
     * <p>
     *  服务实现类
     * </p>
     *
     * @author
     * @since 2017-09-05
     */
    @Service
    public class LogService{
    
        private static final String LOG_CONTENT = "[类名]:%s,[方法]:%s,[参数]:%s,[IP]:%s";
    
        private String username;
    
        @Autowired
        private LogRepository logRepository;
    
        public String initUsername(String username) {
            if(!StringUtils.isEmpty(username)){
                this.username = username;
            }
            return this.username;
        }
    
    
        public void put(JoinPoint joinPoint, String methodName, String module, String description) {
            try {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                Log log = new Log();
                //username = ((JwtClient) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername();
                // 获取当前登录用户
                MyShiroRealm.ShiroUser shiroUser = (MyShiroRealm.ShiroUser) SecurityUtils.getSubject().getPrincipal();
    //          User user = userRepository.findOne(shiroUser.getId());
                username = shiroUser.getUsername();
                if (StringUtils.isEmpty(username)) {
                    username = Const.USERNAME_IN_CONTEXT != null ? Const.USERNAME_IN_CONTEXT : "未知用户";
                }
    
                String ip = IPUtils.getIpAddr(request);
                log.setUsername(username);
                log.setModule(module);
                log.setDescription(description);
                log.setIp(ip);
                log.setContent(operateContent(joinPoint, methodName, ip, request));
                log.setAble(1);
                //insert(log);
                logRepository.save(log);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /*public Page<Log> page(LogRequest request, Page<Log> page) {
            if(request == null){
                request = new LogRequest();
            }
            request.setIsDeleted(Config.ABLE_CONFIG.ABLE);
            List<Log> logs = baseMapper.page(request,page);
            page.setRecords(logs);
            return page;
        }*/
    
        /**
         * 查询所有日志
         * @param pageNum
         * @param request
         * @return
         */
        public PageDto findAll(int pageNum, HttpServletRequest request) {
            Sort sort = new Sort(Sort.Direction.DESC, "updateAt");
            List<SpecificationOperator> operators = HttpRequests.getParametersStartingWith(request, "Q_");
            //增加删除标识的过滤
            SpecificationOperator isValid = new SpecificationOperator("able", "1", "EQ");
            operators.add(isValid);
            MySpecification<Log> mySpecifications = new MySpecification<>(operators);
            Pageable pageable = new PageRequest(pageNum, 10, sort);
            Page<Log> page = logRepository.findAll(mySpecifications, pageable);
            //设置PageDto
            List<Log> parameters = page.getContent();
            long total = page.getTotalElements();
            PageDto pageDto = new PageDto();
            pageDto.setRows(parameters);
            pageDto.setTotal(total);
            return pageDto;
        }
    
    
        public String operateContent(JoinPoint joinPoint, String methodName, String ip, HttpServletRequest request) throws ClassNotFoundException, NotFoundException {
            String className = joinPoint.getTarget().getClass().getName();
            Object[] params = joinPoint.getArgs();
            String classType = joinPoint.getTarget().getClass().getName();
            Class<?> clazz = Class.forName(classType);
            String clazzName = clazz.getName();
            Map<String,Object > nameAndArgs = getFieldsName(this.getClass(), clazzName, methodName,params);
            StringBuffer bf = new StringBuffer();
            if (!CollectionUtils.isEmpty(nameAndArgs)){
                Iterator it = nameAndArgs.entrySet().iterator();
                while (it.hasNext()){
                    Map.Entry entry = (Map.Entry) it.next();
                    String key = (String) entry.getKey();
                    String value = JSONObject.toJSONString(entry.getValue());
                    bf.append(key).append("=");
                    bf.append(value).append("&");
                }
            }
            if (StringUtils.isEmpty(bf.toString())){
                bf.append(request.getQueryString());
            }
            return String.format(LOG_CONTENT, className, methodName, bf.toString(), ip);
        }
    
        private Map<String,Object> getFieldsName(Class cls, String clazzName, String methodName, Object[] args) throws NotFoundException {
            Map<String,Object > map=new HashMap<String,Object>();
    
            ClassPool pool = ClassPool.getDefault();
            ClassClassPath classPath = new ClassClassPath(cls);
            pool.insertClassPath(classPath);
    
            CtClass cc = pool.get(clazzName);
            CtMethod cm = cc.getDeclaredMethod(methodName);
            MethodInfo methodInfo = cm.getMethodInfo();
            CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
            LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
            if (attr == null) {
                // exception
                return map;
            }
            int pos = Modifier.isStatic(cm.getModifiers()) ? 0 : 1;
            for (int i = 0; i < cm.getParameterTypes().length; i++){
                map.put( attr.variableName(i + pos),args[i]);//paramNames即参数名
            }
            return map;
        }
    }

    5.dao

    package com.ideal.manage.guest.repository.log;
    import com.ideal.manage.guest.bean.log.Log;
    import com.ideal.manage.guest.repository.framework.BaseRepository;
    
    /**
     * <p>
      *  Mapper 接口
     * </p>
     *
     * @author Yankee
     * @since 2017-09-05
     */
    
    public interface LogRepository extends BaseRepository<Log,String> {
    
        /**
         * 查询分页
         * @param request
         * @param page
         * @return
         */
        //List<Log> page(@Param("re") LogRequest request, Pagination page);
    }

    三,使用注解在需要的地方记录日志

    @Log(module = "设备管理",description = "添加设备")
        public Integer saveEquipment(Equipment equipment) {
            equipment.setAble(1);
            Equipment resultEquipment = equipmentRepository.save(equipment);
            if(resultEquipment == null){
                return StateUtil.RESULT_FAILED;
            }
            return StateUtil.RESULT_SUCCESS;
        }

     

    转载于:https://www.cnblogs.com/inspred/p/10385005.html

    展开全文
  • Java快速开发平台源码 用户权限管理系统源码一个轻量级的Java快速开发平台,能快速开发项目并交付【接私活利器】 友好的代码结构及注释,便于阅读及二次开发 实现前后端分离,通过token进行数据交互,前端再也不用...

    Java快速开发平台源码 用户权限管理系统源码

    一个轻量级的Java快速开发平台,能快速开发项目并交付【接私活利器】 友好的代码结构及注释,便于阅读及二次开发 实现前后端分离,通过token进行数据交互,前端再也不用关注后端技术 灵活的权限控制,可控制到页面或按钮,满足绝大部分的权限需求 页面交互使用Vue2.x,极大的提高了开发效率 引入quartz定时任务,可动态完成任务的添加、修改、删除、暂停、恢复及日志查看等功能 引入API模板,根据token作为登录令牌,极大的方便了APP接口开发 引入Hibernate Validator校验框架,轻松实现后端校验 引入云存储服务,已支持:七牛云、阿里云、腾讯云等 引入swagger文档支持,方便编写API接口文档 引入路由机制,刷新页面会停留在当前页 强大的代码生成机制,可在线生成entity、xml、dao、service、html、js、sql代码,减少70%以上的开发任务

    先关注,在转发,然后私信发送 HM 可以领取ASP.NET-HiMall3.0多用户B2B2C商城源码一套,记得私信发送 HM 领取源码,需要了解其他的请私信小编。

    数据权限设计思想

    • 管理员管理、角色管理、部门管理,可操作本部门及子部门数据
    • 菜单管理、定时任务、参数管理、系统日志,没有数据权限
    • 业务功能,按照用户数据权限,查询、操作数据【没有本部门数据权限,也能查询本人数据】

    技术选型:

    • 核心框架:Spring Boot 2.1
    • 安全框架:Apache Shiro 1.3
    • 视图框架:Spring MVC 5.1
    • 持久层框架:MyBatis 3.5
    • 定时器:Quartz 2.3
    • 数据库连接池:Druid 1.1
    • 日志管理:SLF4J 1.7、Log4j
    • 页面交互:Vue2.x

    一,管理员

    50d7eb64d45463ff1b616fa3ad613907.png

    二,部门管理

    f1d6e4580ea818e44bca1fbcfd4757ed.png

    三,角色管理

    d2cb0c0acd96445ff75f0560252ec367.png

    四,菜单管理

    5c6fc12df0271db09cbf3cb6d6e98bd2.png

    五,字典管理

    4d3dfd9e8d098744f68a596d18eb5107.png

    六,文件上传

    6dcf33fe29ed21a1db975ed23ffff427.png

    七,系统日志

    d6edd9dd0b944cc2b8ed4a43bdbf910f.png

    八,代码生成

    872da004e6c3533597f3066d5e9b34e8.png

    先关注,在转发,然后私信发送 HM 可以领取ASP.NET-HiMall3.0多用户B2B2C商城源码一套,记得私信发送 HM 领取源码,需要了解其他的请私信小编。

    展开全文
  • 二,代码实现(springboot项目) 只需要在resources目录下新建:logback-spring.xml文件。具体每个文件多大自己设置。 <configuration> <!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名,%i索...
  • java日志管理

    千次阅读 2018-09-07 10:12:47
    log4j和logback都是具体的日志实现框架,slf4j是一个接口层框架,slf4j-log4j,slf4j-logback则是针对log4j和logback的桥接框架。使用slf4j,就可以随意切换日志框架,而不用修改代码。 高并发系统日志记录 多...
  • 目录搭建日志系统1 创建项目2 添加依赖3创建配置文件4新建实体5新建service及实现类6新建控制器在Java代码中获取日志信息1新建实体类2修改Log实体类3修改service实现类 搭建日志系统 绝大多数项目在后台管理中都有...
  • aop + annotation + lombok实现java日志收集管理 在日常的开发中,日志模块应该是我们接触比较多的。 梳理一下的如何使用aop+annotation实现一个简单的日志。 话不多说,直接上代码: 引入依赖 <!-- 引入 aop --&...
  • Spring boot内部使用Commons Logging来记录日志,但也兼容一些主流日志框架实现,例如java.util.logging,Log4J2以及Logback。本篇介绍springboot整合第三方日志框架以及lombok。
  • Servlet实现日志管理

    千次阅读 2017-08-27 23:08:19
    //本文主要实现学员日志管理功能,表单以及前端等样式代码省略,主要servlet方法实现的功能的如下: package com.softeem.dao; import java.util.List; public interface BaseDAO { public boolean save(T t);...
  • Spring AOP实现日志管理

    2019-07-06 17:06:01
    Java面对对象语言中要实现日志管理功能时,是比较麻烦的。在此,引入了Spring框架中的AOP思想,AOP的主要作用是可以横向插入可重复代码日志管理),在面向对象语言中是无法做到的,它是面向对象的一种延伸。而...
  • 实现代码二、贯穿任务(物流管理系统)任务1-1升级实体类为可序列化的类,以便在文件中保存或网络中传递。DataBase.javaLogRec.javaMatchedLogRec.javaTransport.javaMatchedTransport.java任务1-2 实现匹配的日志信息...
  • 使用HandlerInterceptor拦截器,可以拦截请求,实现通用的日志管理操作 一、添加拦截器类 在"src/main/java"代码文件夹的"org.xs.demo1"的包下新建"LogInterceptor.java"类: /** * Copyright © 2012-2014...
  • 下面主要介绍两种常用的拦截器:一、基于URL实现的拦截器:关键代码:path.matches(Const.NO_INTERCEPTOR_PATH 就是基于正则匹配的url。二、基于注解的拦截器①创建注解:②创建拦截器:三、把拦截器添...
  • 大二下学期,用Javajavadbf4.1jar包辅助开发的数据库管理系统课程设计,模仿了Java的 从.java到.class再到类加载执行的过程对SQL语句进行先编译再执行,时间有限,,只有一 星期时间,细节方面没考虑很多,代码也...
  • 学生日志管理系统一、功能介绍二、功能代码1、定义学生类2、定义日志类3、定义一个日志系统类三、演示效果图 一、功能介绍 学生日志内容管理系统,日志信息主要包含日志编号,今日学习内容,掌握程度,疑问,日志...
  • 它是一种快速、可扩展的、设计内在就是分布式的,分区的和可复制的提交日志服务。  Kafka是一个分布式的、支持分区的(partition)、多副本(replica),基于zookeeper协调的分布式消息系统,它的最大的特性就是...
  • 最近一个项目客户要求能够监控用户对系统的详细操作步骤,比如某人在某时间删除了某个模块的某条数据,经过一番斟酌,决定用struts2的拦截器功能实现日志管理系统,因为系统是旧系统(SSH架构)了,用struts2就可以...
  • 通过Java API调用水壶核心代码,并基于Spring Boot提供简易的Web管理界面。 特色 Java API调用水壶核心代码 任务并行执行 网络管理任务 展示 界面用Bootstrap3和jQuery简单撸了下。 仪表板 查看任务执行情况 任务 ...
  • 之前一直写.net,没玩过spring,一直没用过aop(面向切面编程)这类功能,当然不是说.net里面没有这类框架,企业库就可以微软企业库官网开始上代码:注解定义package com.jiankunking.common;import java.lang....
  • 利用Java实现C/S模式的大学班级内日常事务管理系统(PC版,应用于校内网有线网络访问,暂不开发移动端),使用swings技术完成如下基本功能需求: 班级公告通知 文稿匿名传阅投票 文件共享(上传、下载) 即时...
  • 本次javaweb实习基于目前流行的企业级框架Spring 、Spring MVC、MyBatis(SSM)和前端技术JQuery的图书管理系统,主要功能包括:图书查询、图书管理、图书编辑、读者管理、图书的借阅与归还以及借还日志记录等。...
  • 来执行特殊处理的小程序,无需依赖任何容器,简单独立,方便部署扩展,一般应用场景是小工具、业务应用的拆分、快速开发实施、小白用户(简化部署实施)等二、代码部分1. 启动脚本&部署脚本app_startup.bat内容@...
  • 包含文件在线操作,工作日志,多班次考勤,CRM,ERP进销存,项目管理,EHR,拖拽式生成问卷,日程,笔记,工作计划,行政办公,薪资模块,动态表单,摘要,公告模块,企业论坛,云售后模块,生产模块,系统同步模块...
  • Java实现单例的难点

    2021-01-21 17:15:50
    单例模式常用于日志记录、工厂、窗口管理器和平台组件管理等。我认为要尽量避免使用单例模式,因为一旦实现很难改变或重载,而且会造成编写测试用例困难、代码结构糟糕等问题。另外,下面文章中的单例模式是不安全的...
  • 第一步定义两个注解: Java代码 package com.annotation; import java.lang.annotation.*; /** *自定义注解 拦截Controller */ @Target({ElementType.PARAMETER, Ele...
  • 一、效果 二、技术应用: ...三、上代码---我的博客只上干货!!!! Log实体对象类.java package *****.***.***.modules.sys.log.entity; import java.io.Serializable; import java.util.Dat...
  • JAVA代码-Spring AOP

    2019-07-31 16:46:56
    2.日志管理;3.安全验证 AOP底层的实现是通过JAVA的动态代理方式,当然Spring还有静态代理方式,主要是调用业务逻辑。 我们需要解释清楚何为动态代理,举例说明,在一个类的某一个方法中前后加如日志记录、权限...
  • Java代码实现部分,比较有意思,也具参考性。像坐标控制、旋转矩阵、定时器、生成图像、数据初始化、矩阵乘法、坐标旋转、判断是否是顺时针方向排列、鼠标按下、放开时的动作等,都可在本源码中得以体现。 Java...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 445
精华内容 178
关键字:

日志管理java代码实现

java 订阅