我爱编程

SpringBoot2 - 日志

2018-06-21  本文已影响0人  朱穆朗玛

构建项目

访问 http://start.spring.io

pom.xml增加Druid依赖

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid-spring-boot-starter</artifactId>
  <version>1.1.9</version>
</dependency>

配置数据源

配置application.yml

spring:
 datasource:
  type: com.alibaba.druid.pool.DruidDataSource
  driver-class-name: com.mysql.jdbc.Driver
  url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8
  username: root
  password: 123456
  #配置监控统计拦截的filters
  filters: stat,wall,log4j
  #最大活跃数
  maxActive: 20
  #初始化数量
  initialSize: 1
  #最大连接等待超时时间
  maxWait: 60000
  #打开PSCache,并指定每个连接PSCache的大小
  poolPreparedStatements: true
  maxPoolPreparedStatementPerConnectionSize: 20
  #通过connectionProperties属性打开mergeSql功能
  connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
  minldle: 1
  timeBetweenEvictionRunsMillis: 60000
  minEvictableldleTimeMillis: 300000
  validationQuery: select 1 from dual
  testWhiledle: true
  testOnBorrow: false
  testOnReturn: false
 jpa:
  properties:
   hibernate:
    show_sql: true
    format_sql: true
 mvc:
  view:
   prefix: /WEB-INF/views/
   suffix: .jsp

创建数据表结构

DROP TABLE IF EXISTS `t_logger_info`;

CREATE TABLE `t_logger_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `client_ip` varchar(50) DEFAULT NULL COMMENT '客户端请求ip',
  `uri` varchar(200) DEFAULT NULL COMMENT '客户端请求路径',
  `log_type` varchar(50) DEFAULT NULL COMMENT '终端请求方式:普通请求,ajax请求',
  `log_method` varchar(50) DEFAULT NULL COMMENT '请求方式method:get,post',
  `param_data` varchar(500) DEFAULT NULL COMMENT '请求参数内容json',
  `session_id` varchar(100) DEFAULT NULL COMMENT '请求接口唯一session标识',
  `log_time` varchar(100) DEFAULT NULL COMMENT '请求时间',
  `return_time` varchar(50) DEFAULT NULL COMMENT '接口返回时间',
  `return_data` varchar(500) DEFAULT NULL COMMENT '接口返回数据json',
  `http_status_code` varchar(10) DEFAULT NULL COMMENT '接口返回状态代码',
  `time_consuming` int DEFAULT NULL COMMENT '耗时',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

创建实体

package com.gala.log.entity;

import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Table(name = "t_logger_info")
public class LoggerInfo {

    private Long id; // 主键
    private String clientIp; // 客户端请求ip
    private String uri; // 客户端请求路径
    private String logType; // 终端请求方式:普通请求ajax请求
    private String logMethod; // 请求方式method:getpost
    private String paramData; // 请求参数内容json
    private String sessionId; // 请求接口唯一session标识
    private String logTime; // 请求时间
    private String returnTime; // 接口返回时间
    private String returnData; // 接口返回数据json
    private String httpStatusCode; // 接口返回状态代码
    private Integer timeConsuming; // 耗时

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getClientIp() {
        return clientIp;
    }

    public void setClientIp(String clientIp) {
        this.clientIp = clientIp;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public String getLogType() {
        return logType;
    }

    public void setLogType(String logType) {
        this.logType = logType;
    }

    public String getLogMethod() {
        return logMethod;
    }

    public void setLogMethod(String logMethod) {
        this.logMethod = logMethod;
    }

    public String getParamData() {
        return paramData;
    }

    public void setParamData(String paramData) {
        this.paramData = paramData;
    }

    public String getSessionId() {
        return sessionId;
    }

    public void setSessionId(String sessionId) {
        this.sessionId = sessionId;
    }

    public String getLogTime() {
        return logTime;
    }

    public void setLogTime(String logTime) {
        this.logTime = logTime;
    }

    public String getReturnTime() {
        return returnTime;
    }

    public void setReturnTime(String returnTime) {
        this.returnTime = returnTime;
    }

    public String getReturnData() {
        return returnData;
    }

    public void setReturnData(String returnData) {
        this.returnData = returnData;
    }

    public String getHttpStatusCode() {
        return httpStatusCode;
    }

    public void setHttpStatusCode(String httpStatusCode) {
        this.httpStatusCode = httpStatusCode;
    }

    public Integer getTimeConsuming() {
        return timeConsuming;
    }

    public void setTimeConsuming(Integer timeConsuming) {
        this.timeConsuming = timeConsuming;
    }

}

创建JPA

package com.gala.log.jpa;

import java.io.Serializable;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;

import com.gala.log.entity.LoggerInfo;

public interface LoggerInfoDao extends JpaRepository<LoggerInfo, Long>, JpaSpecificationExecutor<LoggerInfo>, Serializable {

}

创建日志拦截器

自定义SpringMVC拦截器需要实现HandlerIntercptor接口,并且实现内部的三个方法。

package com.gala.jpa.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class LoggerInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
    }
}

拦截器内无法通过SpringBean的方式注入LoggerDao

工具类WebApplicationContextUtils可以通过HttpServletRequest请求对象的上下文(ServetCotext)获取Spring管理的Bean

private <T> T getDAO(Class<T> clazz,HttpServletRequest request) {
        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return factory.getBean(clazz);
    }

记录请求日志

加入FastJson、HttpServet依赖

<dependency>
  <groupId>org.apache.tomcat.embed</groupId>
  <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
</dependency>
        
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>fastjson</artifactId>
  <version>1.2.47</version>
</dependency>
  1. 在preHandle方法内创建LoggerEntity实体,并记录一些必要参数后将实体写入到当前请求对象HttpServletRequest内
@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 创建日志实体
        LoggerInfo logger = new LoggerInfo();
        // 获取请求sessionId
        String sessionId = request.getRequestedSessionId();
        // 请求路径
        String url = request.getRequestURI();
        // 获取请求参数信息
        String paramData = JSON.toJSONString(request.getParameterMap(), SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
        // 设置客户端IP
        logger.setClientIp(LoggerUtils.getCliectIp(request));
        // 设置请求方法
        logger.setLogMethod(request.getMethod());
        // 设置请求类型
        logger.setLogType(LoggerUtils.getRequestType(request));
        // 设置请求参数内容
        logger.setParamData(paramData);
        // 设置请求地址
        logger.setUri(url);
        // 设置sessionId
        logger.setSessionId(sessionId);
        // 设置请求开始时间
        request.setAttribute(LOGGER_SEND_TIME, System.currentTimeMillis());
        request.setAttribute(LOGGER_ENTITY, logger);
        
        return true;
    }
  1. 当用户发送请求时在进入SpringMVC的控制器之前会进入preHandle方法,接着会进入对应springMVC控制器方法的方法,在最后渲染视图即将返回前台的时候开始执行afterCompletion方法。
@Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        //获取请求错误码
        int status = response.getStatus();
        //当前时间
        long currentTime = System.currentTimeMillis();
        //请求开始时间
        long time = Long.valueOf(request.getAttribute(LOGGER_SEND_TIME).toString());
        //获取本次请求日志实体
        LoggerInfo loggerEntity = (LoggerInfo) request.getAttribute(LOGGER_ENTITY);
        //设置请求时间差
        loggerEntity.setTimeConsuming(Integer.valueOf((currentTime - time)+""));
        //设置返回时间
        loggerEntity.setReturnTime(currentTime + "");
        //设置返回错误码
        loggerEntity.setHttpStatusCode(status+"");
        //设置返回值
        loggerEntity.setReturnData(JSON.toJSONString(request.getAttribute(LoggerUtils.LOGGER_RETURN),
                SerializerFeature.DisableCircularReferenceDetect,
                SerializerFeature.WriteMapNullValue));
        //执行将日志写入数据库
        LoggerInfoDao loggerDAO = getDAO(LoggerInfoDao.class,request);
        loggerDAO.save(loggerEntity);
    }

编写控制器

package com.gala.log.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.gala.log.util.LoggerUtils;

@RestController
@RequestMapping(value = "/index")
public class IndexController {

    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public JSONObject login(HttpServletRequest request, String name) throws Exception {
        JSONObject obj = new JSONObject();
        obj.put("msg", "用户:" + name + ",登录成功。");
        // 将返回值写入到请求对象中
        request.setAttribute(LoggerUtils.LOGGER_RETURN, obj);
        return obj;
    }

}

配置拦截器

package com.gala.log;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import com.gala.log.interceptor.LoggerInterceptor;

@Configuration
public class LoggerConfguration implements WebMvcConfigurer {

    /**
     * 将拦截器配置到SpringBoot中
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoggerInterceptor()).addPathPatterns("/**");
    }

}

运行项目

访问地址:http://127.0.0.1:8080/index/login?name=admin

上一篇 下一篇

猜你喜欢

热点阅读