SpringBoot利用AOP机制来实现日志管理,并用线程池来实现多线程日志记录的插入

  1. 首先建立日志记录的实体类,和MySQL数据库对应,通过逆向工程生成实体类和mapper代码,以下就是我生成的三个实体类代码。
/**
 * @author 旺旺米雪饼
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class WebLog {
    private Long webLogId;

    private String description;

    private String username;

    private Date startTime;

    /**
     * 请求持续时间ms
     */
    private Integer durationTime;

    private String basePath;

    private String uri;

    private String url;

    private String method;

    private String ip;
}
public class WebLogExample {
    protected String orderByClause;

    protected boolean distinct;

    protected List<Criteria> oredCriteria;

    public WebLogExample() {
        oredCriteria = new ArrayList<Criteria>();
    }


    protected abstract static class GeneratedCriteria {
        protected List<Criterion> criteria;

        protected GeneratedCriteria() {
            super();
            criteria = new ArrayList<Criterion>();
        }


        protected void addCriterion(String condition) {
            if (condition == null) {
                throw new RuntimeException("Value for condition cannot be null");
            }
            criteria.add(new Criterion(condition));
        }

        protected void addCriterion(String condition, Object value, String property) {
            if (value == null) {
                throw new RuntimeException("Value for " + property + " cannot be null");
            }
            criteria.add(new Criterion(condition, value));
        }

        protected void addCriterion(String condition, Object value1, Object value2, String property) {
            if (value1 == null || value2 == null) {
                throw new RuntimeException("Between values for " + property + " cannot be null");
            }
            criteria.add(new Criterion(condition, value1, value2));
        }


        public Criteria andUriEqualTo(String value) {
            addCriterion("uri =", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriNotEqualTo(String value) {
            addCriterion("uri <>", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriGreaterThan(String value) {
            addCriterion("uri >", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriGreaterThanOrEqualTo(String value) {
            addCriterion("uri >=", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriLessThan(String value) {
            addCriterion("uri <", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriLessThanOrEqualTo(String value) {
            addCriterion("uri <=", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriLike(String value) {
            addCriterion("uri like", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriNotLike(String value) {
            addCriterion("uri not like", value, "uri");
            return (Criteria) this;
        }

        public Criteria andUriIn(List<String> values) {
            addCriterion("uri in", values, "uri");
            return (Criteria) this;
        }

        public Criteria andUriNotIn(List<String> values) {
            addCriterion("uri not in", values, "uri");
            return (Criteria) this;
        }

        public Criteria andUriBetween(String value1, String value2) {
            addCriterion("uri between", value1, value2, "uri");
            return (Criteria) this;
        }

        public Criteria andUriNotBetween(String value1, String value2) {
            addCriterion("uri not between", value1, value2, "uri");
            return (Criteria) this;
        }

        public Criteria andUrlIsNull() {
            addCriterion("url is null");
            return (Criteria) this;
        }

        public Criteria andUrlIsNotNull() {
            addCriterion("url is not null");
            return (Criteria) this;
        }

        public Criteria andUrlEqualTo(String value) {
            addCriterion("url =", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlNotEqualTo(String value) {
            addCriterion("url <>", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlGreaterThan(String value) {
            addCriterion("url >", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlGreaterThanOrEqualTo(String value) {
            addCriterion("url >=", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlLessThan(String value) {
            addCriterion("url <", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlLessThanOrEqualTo(String value) {
            addCriterion("url <=", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlLike(String value) {
            addCriterion("url like", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlNotLike(String value) {
            addCriterion("url not like", value, "url");
            return (Criteria) this;
        }

        public Criteria andUrlIn(List<String> values) {
            addCriterion("url in", values, "url");
            return (Criteria) this;
        }

        public Criteria andUrlNotIn(List<String> values) {
            addCriterion("url not in", values, "url");
            return (Criteria) this;
        }

        public Criteria andUrlBetween(String value1, String value2) {
            addCriterion("url between", value1, value2, "url");
            return (Criteria) this;
        }

        public Criteria andUrlNotBetween(String value1, String value2) {
            addCriterion("url not between", value1, value2, "url");
            return (Criteria) this;
        }

        public Criteria andMethodIsNull() {
            addCriterion("method is null");
            return (Criteria) this;
        }

        public Criteria andMethodIsNotNull() {
            addCriterion("method is not null");
            return (Criteria) this;
        }

        public Criteria andMethodEqualTo(String value) {
            addCriterion("method =", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodNotEqualTo(String value) {
            addCriterion("method <>", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodGreaterThan(String value) {
            addCriterion("method >", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodGreaterThanOrEqualTo(String value) {
            addCriterion("method >=", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodLessThan(String value) {
            addCriterion("method <", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodLessThanOrEqualTo(String value) {
            addCriterion("method <=", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodLike(String value) {
            addCriterion("method like", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodNotLike(String value) {
            addCriterion("method not like", value, "method");
            return (Criteria) this;
        }

        public Criteria andMethodIn(List<String> values) {
            addCriterion("method in", values, "method");
            return (Criteria) this;
        }

        public Criteria andMethodNotIn(List<String> values) {
            addCriterion("method not in", values, "method");
            return (Criteria) this;
        }

        public Criteria andMethodBetween(String value1, String value2) {
            addCriterion("method between", value1, value2, "method");
            return (Criteria) this;
        }

        public Criteria andMethodNotBetween(String value1, String value2) {
            addCriterion("method not between", value1, value2, "method");
            return (Criteria) this;
        }

        public Criteria andIpIsNull() {
            addCriterion("ip is null");
            return (Criteria) this;
        }

        public Criteria andIpIsNotNull() {
            addCriterion("ip is not null");
            return (Criteria) this;
        }

        public Criteria andIpEqualTo(String value) {
            addCriterion("ip =", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpNotEqualTo(String value) {
            addCriterion("ip <>", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpGreaterThan(String value) {
            addCriterion("ip >", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpGreaterThanOrEqualTo(String value) {
            addCriterion("ip >=", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpLessThan(String value) {
            addCriterion("ip <", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpLessThanOrEqualTo(String value) {
            addCriterion("ip <=", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpLike(String value) {
            addCriterion("ip like", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpNotLike(String value) {
            addCriterion("ip not like", value, "ip");
            return (Criteria) this;
        }

        public Criteria andIpIn(List<String> values) {
            addCriterion("ip in", values, "ip");
            return (Criteria) this;
        }

        public Criteria andIpNotIn(List<String> values) {
            addCriterion("ip not in", values, "ip");
            return (Criteria) this;
        }

        public Criteria andIpBetween(String value1, String value2) {
            addCriterion("ip between", value1, value2, "ip");
            return (Criteria) this;
        }

        public Criteria andIpNotBetween(String value1, String value2) {
            addCriterion("ip not between", value1, value2, "ip");
            return (Criteria) this;
        }
    }

    public static class Criteria extends GeneratedCriteria {

        protected Criteria() {
            super();
        }
    }

    public static class Criterion {
        private String condition;

        private Object value;

        private Object secondValue;

        private boolean noValue;

        private boolean singleValue;

        private boolean betweenValue;

        private boolean listValue;

        private String typeHandler;

        public String getCondition() {
            return condition;
        }

        public Object getValue() {
            return value;
        }

        public Object getSecondValue() {
            return secondValue;
        }

        public boolean isNoValue() {
            return noValue;
        }

        public boolean isSingleValue() {
            return singleValue;
        }

        public boolean isBetweenValue() {
            return betweenValue;
        }

        public boolean isListValue() {
            return listValue;
        }

        public String getTypeHandler() {
            return typeHandler;
        }

        protected Criterion(String condition) {
            super();
            this.condition = condition;
            this.typeHandler = null;
            this.noValue = true;
        }

        protected Criterion(String condition, Object value, String typeHandler) {
            super();
            this.condition = condition;
            this.value = value;
            this.typeHandler = typeHandler;
            if (value instanceof List<?>) {
                this.listValue = true;
            } else {
                this.singleValue = true;
            }
        }

        protected Criterion(String condition, Object value) {
            this(condition, value, null);
        }

        protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
            super();
            this.condition = condition;
            this.value = value;
            this.secondValue = secondValue;
            this.typeHandler = typeHandler;
            this.betweenValue = true;
        }

        protected Criterion(String condition, Object value, Object secondValue) {
            this(condition, value, secondValue, null);
        }
    }
}
/**
 * @author 旺旺米雪饼
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class WebLogWithBLOBs extends WebLog {
    private String parameter;

    private String result;

}

 2.实体类所对应的mapper.java文件:

/**
 * @author 旺旺米雪饼
 */
public interface WebLogMapper {
    long countByExample(WebLogExample example);

    int deleteByExample(WebLogExample example);

    int deleteByPrimaryKey(Long webLogId);

    int insert(WebLogWithBLOBs record);

    int insertSelective(WebLogWithBLOBs record);

    List<WebLogWithBLOBs> selectByExampleWithBLOBs(WebLogExample example);

    List<WebLog> selectByExample(WebLogExample example);

    WebLogWithBLOBs selectByPrimaryKey(Long webLogId);

    int updateByExampleSelective(@Param("record") WebLogWithBLOBs record, @Param("example") WebLogExample example);

    int updateByExampleWithBLOBs(@Param("record") WebLogWithBLOBs record, @Param("example") WebLogExample example);

    int updateByExample(@Param("record") WebLog record, @Param("example") WebLogExample example);

    int updateByPrimaryKeySelective(WebLogWithBLOBs record);

    int updateByPrimaryKeyWithBLOBs(WebLogWithBLOBs record);

    int updateByPrimaryKey(WebLog record);
    int insertBatch(@Param("webLogList") List<WebLog> webLogList);
}

3.所对应的WebLogMapper.xml文件为:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjfu.mapper.WebLogMapper">
  <resultMap id="BaseResultMap" type="com.bjfu.entity.WebLog">
    <id column="web_log_id" jdbcType="BIGINT" property="webLogId" />
    <result column="description" jdbcType="VARCHAR" property="description" />
    <result column="username" jdbcType="VARCHAR" property="username" />
    <result column="start_time" jdbcType="TIMESTAMP" property="startTime" />
    <result column="duration_time" jdbcType="INTEGER" property="durationTime" />
    <result column="base_path" jdbcType="VARCHAR" property="basePath" />
    <result column="uri" jdbcType="VARCHAR" property="uri" />
    <result column="url" jdbcType="VARCHAR" property="url" />
    <result column="method" jdbcType="VARCHAR" property="method" />
    <result column="ip" jdbcType="VARCHAR" property="ip" />
  </resultMap>
  <resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="com.bjfu.entity.WebLogWithBLOBs">
    <result column="parameter" jdbcType="LONGVARCHAR" property="parameter" />
    <result column="result" jdbcType="LONGVARCHAR" property="result" />
  </resultMap>
  <sql id="Example_Where_Clause">
    <where>
      <foreach collection="oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  <sql id="Update_By_Example_Where_Clause">
    <where>
      <foreach collection="example.oredCriteria" item="criteria" separator="or">
        <if test="criteria.valid">
          <trim prefix="(" prefixOverrides="and" suffix=")">
            <foreach collection="criteria.criteria" item="criterion">
              <choose>
                <when test="criterion.noValue">
                  and ${criterion.condition}
                </when>
                <when test="criterion.singleValue">
                  and ${criterion.condition} #{criterion.value}
                </when>
                <when test="criterion.betweenValue">
                  and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
                </when>
                <when test="criterion.listValue">
                  and ${criterion.condition}
                  <foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
                    #{listItem}
                  </foreach>
                </when>
              </choose>
            </foreach>
          </trim>
        </if>
      </foreach>
    </where>
  </sql>
  <sql id="Base_Column_List">
    web_log_id, description, username, start_time, duration_time, base_path, uri, url, 
    method, ip
  </sql>
  <sql id="Blob_Column_List">
    parameter, result
  </sql>
  <select id="selectByExampleWithBLOBs" parameterType="com.bjfu.entity.WebLogExample" resultMap="ResultMapWithBLOBs">
    select
    <if test="distinct">
      distinct
    </if>
    <include refid="Base_Column_List" />
    ,
    <include refid="Blob_Column_List" />
    from web_log
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>
  <select id="selectByExample" parameterType="com.bjfu.entity.WebLogExample" resultMap="BaseResultMap">
    select
    <if test="distinct">
      distinct
    </if>
    <include refid="Base_Column_List" />
    from web_log
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null">
      order by ${orderByClause}
    </if>
  </select>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="ResultMapWithBLOBs">
    select 
    <include refid="Base_Column_List" />
    ,
    <include refid="Blob_Column_List" />
    from web_log
    where web_log_id = #{webLogId,jdbcType=BIGINT}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    delete from web_log
    where web_log_id = #{webLogId,jdbcType=BIGINT}
  </delete>
  <delete id="deleteByExample" parameterType="com.bjfu.entity.WebLogExample">
    delete from web_log
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </delete>
  <insert id="insert" parameterType="com.bjfu.entity.WebLogWithBLOBs">
    <selectKey keyProperty="webLogId" order="AFTER" resultType="java.lang.Long">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into web_log (description, username, start_time, 
      duration_time, base_path, uri, 
      url, method, ip, parameter, 
      result)
    values (#{description,jdbcType=VARCHAR}, #{username,jdbcType=VARCHAR}, #{startTime,jdbcType=TIMESTAMP}, 
      #{durationTime,jdbcType=INTEGER}, #{basePath,jdbcType=VARCHAR}, #{uri,jdbcType=VARCHAR}, 
      #{url,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR}, #{ip,jdbcType=VARCHAR}, #{parameter,jdbcType=LONGVARCHAR}, 
      #{result,jdbcType=LONGVARCHAR})
  </insert>
  <insert id="insertBatch">
    insert into web_log (description, username, start_time,
    duration_time, base_path, uri,
    url, method, ip, parameter,
    result)
    values
    <foreach collection="webLogList" item="item" separator=",">
      (#{item.description,jdbcType=VARCHAR}, #{item.username,jdbcType=VARCHAR}, #{item.startTime,jdbcType=TIMESTAMP},
      #{item.durationTime,jdbcType=TIMESTAMP}, #{item.basePath,jdbcType=VARCHAR}, #{item.uri,jdbcType=VARCHAR},
      #{item.url,jdbcType=VARCHAR}, #{item.method,jdbcType=VARCHAR}, #{item.ip,jdbcType=VARCHAR}, #{item.parameter,jdbcType=VARCHAR},
      #{item.result,jdbcType=VARCHAR})
    </foreach>
  </insert>
  <insert id="insertSelective" parameterType="com.bjfu.entity.WebLogWithBLOBs">
    <selectKey keyProperty="webLogId" order="AFTER" resultType="java.lang.Long">
      SELECT LAST_INSERT_ID()
    </selectKey>
    insert into web_log
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="description != null">
        description,
      </if>
      <if test="username != null">
        username,
      </if>
      <if test="startTime != null">
        start_time,
      </if>
      <if test="durationTime != null">
        duration_time,
      </if>
      <if test="basePath != null">
        base_path,
      </if>
      <if test="uri != null">
        uri,
      </if>
      <if test="url != null">
        url,
      </if>
      <if test="method != null">
        method,
      </if>
      <if test="ip != null">
        ip,
      </if>
      <if test="parameter != null">
        parameter,
      </if>
      <if test="result != null">
        result,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="description != null">
        #{description,jdbcType=VARCHAR},
      </if>
      <if test="username != null">
        #{username,jdbcType=VARCHAR},
      </if>
      <if test="startTime != null">
        #{startTime,jdbcType=TIMESTAMP},
      </if>
      <if test="durationTime != null">
        #{durationTime,jdbcType=INTEGER},
      </if>
      <if test="basePath != null">
        #{basePath,jdbcType=VARCHAR},
      </if>
      <if test="uri != null">
        #{uri,jdbcType=VARCHAR},
      </if>
      <if test="url != null">
        #{url,jdbcType=VARCHAR},
      </if>
      <if test="method != null">
        #{method,jdbcType=VARCHAR},
      </if>
      <if test="ip != null">
        #{ip,jdbcType=VARCHAR},
      </if>
      <if test="parameter != null">
        #{parameter,jdbcType=LONGVARCHAR},
      </if>
      <if test="result != null">
        #{result,jdbcType=LONGVARCHAR},
      </if>
    </trim>
  </insert>
  <select id="countByExample" parameterType="com.bjfu.entity.WebLogExample" resultType="java.lang.Long">
    select count(*) from web_log
    <if test="_parameter != null">
      <include refid="Example_Where_Clause" />
    </if>
  </select>
  <update id="updateByExampleSelective" parameterType="map">
    update web_log
    <set>
      <if test="record.webLogId != null">
        web_log_id = #{record.webLogId,jdbcType=BIGINT},
      </if>
      <if test="record.description != null">
        description = #{record.description,jdbcType=VARCHAR},
      </if>
      <if test="record.username != null">
        username = #{record.username,jdbcType=VARCHAR},
      </if>
      <if test="record.startTime != null">
        start_time = #{record.startTime,jdbcType=TIMESTAMP},
      </if>
      <if test="record.durationTime != null">
        duration_time = #{record.durationTime,jdbcType=INTEGER},
      </if>
      <if test="record.basePath != null">
        base_path = #{record.basePath,jdbcType=VARCHAR},
      </if>
      <if test="record.uri != null">
        uri = #{record.uri,jdbcType=VARCHAR},
      </if>
      <if test="record.url != null">
        url = #{record.url,jdbcType=VARCHAR},
      </if>
      <if test="record.method != null">
        method = #{record.method,jdbcType=VARCHAR},
      </if>
      <if test="record.ip != null">
        ip = #{record.ip,jdbcType=VARCHAR},
      </if>
      <if test="record.parameter != null">
        parameter = #{record.parameter,jdbcType=LONGVARCHAR},
      </if>
      <if test="record.result != null">
        result = #{record.result,jdbcType=LONGVARCHAR},
      </if>
    </set>
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  <update id="updateByExampleWithBLOBs" parameterType="map">
    update web_log
    set web_log_id = #{record.webLogId,jdbcType=BIGINT},
      description = #{record.description,jdbcType=VARCHAR},
      username = #{record.username,jdbcType=VARCHAR},
      start_time = #{record.startTime,jdbcType=TIMESTAMP},
      duration_time = #{record.durationTime,jdbcType=INTEGER},
      base_path = #{record.basePath,jdbcType=VARCHAR},
      uri = #{record.uri,jdbcType=VARCHAR},
      url = #{record.url,jdbcType=VARCHAR},
      method = #{record.method,jdbcType=VARCHAR},
      ip = #{record.ip,jdbcType=VARCHAR},
      parameter = #{record.parameter,jdbcType=LONGVARCHAR},
      result = #{record.result,jdbcType=LONGVARCHAR}
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  <update id="updateByExample" parameterType="map">
    update web_log
    set web_log_id = #{record.webLogId,jdbcType=BIGINT},
      description = #{record.description,jdbcType=VARCHAR},
      username = #{record.username,jdbcType=VARCHAR},
      start_time = #{record.startTime,jdbcType=TIMESTAMP},
      duration_time = #{record.durationTime,jdbcType=INTEGER},
      base_path = #{record.basePath,jdbcType=VARCHAR},
      uri = #{record.uri,jdbcType=VARCHAR},
      url = #{record.url,jdbcType=VARCHAR},
      method = #{record.method,jdbcType=VARCHAR},
      ip = #{record.ip,jdbcType=VARCHAR}
    <if test="_parameter != null">
      <include refid="Update_By_Example_Where_Clause" />
    </if>
  </update>
  <update id="updateByPrimaryKeySelective" parameterType="com.bjfu.entity.WebLogWithBLOBs">
    update web_log
    <set>
      <if test="description != null">
        description = #{description,jdbcType=VARCHAR},
      </if>
      <if test="username != null">
        username = #{username,jdbcType=VARCHAR},
      </if>
      <if test="startTime != null">
        start_time = #{startTime,jdbcType=TIMESTAMP},
      </if>
      <if test="durationTime != null">
        duration_time = #{durationTime,jdbcType=INTEGER},
      </if>
      <if test="basePath != null">
        base_path = #{basePath,jdbcType=VARCHAR},
      </if>
      <if test="uri != null">
        uri = #{uri,jdbcType=VARCHAR},
      </if>
      <if test="url != null">
        url = #{url,jdbcType=VARCHAR},
      </if>
      <if test="method != null">
        method = #{method,jdbcType=VARCHAR},
      </if>
      <if test="ip != null">
        ip = #{ip,jdbcType=VARCHAR},
      </if>
      <if test="parameter != null">
        parameter = #{parameter,jdbcType=LONGVARCHAR},
      </if>
      <if test="result != null">
        result = #{result,jdbcType=LONGVARCHAR},
      </if>
    </set>
    where web_log_id = #{webLogId,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKeyWithBLOBs" parameterType="com.bjfu.entity.WebLogWithBLOBs">
    update web_log
    set description = #{description,jdbcType=VARCHAR},
      username = #{username,jdbcType=VARCHAR},
      start_time = #{startTime,jdbcType=TIMESTAMP},
      duration_time = #{durationTime,jdbcType=INTEGER},
      base_path = #{basePath,jdbcType=VARCHAR},
      uri = #{uri,jdbcType=VARCHAR},
      url = #{url,jdbcType=VARCHAR},
      method = #{method,jdbcType=VARCHAR},
      ip = #{ip,jdbcType=VARCHAR},
      parameter = #{parameter,jdbcType=LONGVARCHAR},
      result = #{result,jdbcType=LONGVARCHAR}
    where web_log_id = #{webLogId,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.bjfu.entity.WebLog">
    update web_log
    set description = #{description,jdbcType=VARCHAR},
      username = #{username,jdbcType=VARCHAR},
      start_time = #{startTime,jdbcType=TIMESTAMP},
      duration_time = #{durationTime,jdbcType=INTEGER},
      base_path = #{basePath,jdbcType=VARCHAR},
      uri = #{uri,jdbcType=VARCHAR},
      url = #{url,jdbcType=VARCHAR},
      method = #{method,jdbcType=VARCHAR},
      ip = #{ip,jdbcType=VARCHAR}
    where web_log_id = #{webLogId,jdbcType=BIGINT}
  </update>
</mapper>

 4.用aop实现日志记录,Joinpoint(连接点)为webLog方法,Pointcut为项目的controller包。

/**
 * @author 旺旺米雪饼
 */
@Aspect
@Component
@Order(1)
@Slf4j
public class WebLogAspect {
    /**
     * 定义切点表达式,指定通知功能被应用的范围
     */
    @Pointcut("execution(public * com.bjfu.controller.*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
    }

    /**
     * value切入点位置
     * returning 自定义的变量,标识目标方法的返回值,自定义变量名必须和通知方法的形参一样
     * 特点:在目标方法之后执行的,能够获取到目标方法的返回值,可以根据这个返回值做不同的处理
     */
    @AfterReturning(value = "webLog()", returning = "ret")
    public void doAfterReturning(Object ret) throws Throwable {
    }

    /**
     * 通知包裹了目标方法,在目标方法调用之前和之后执行自定义的行为
     * ProceedingJoinPoint切入点可以获取切入点方法上的名字、参数、注解和对象
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        //获取当前请求对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        // TODO 从这里拿token
        HttpServletRequest request = attributes.getRequest();
        //记录请求信息
        WebLogWithBLOBs webLog = new WebLogWithBLOBs();
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        long endTime = System.currentTimeMillis();
        String urlStr = request.getRequestURL().toString();
        webLog.setBasePath(urlStr);
        webLog.setIp(IpUtil.getIpAddr(request));
        webLog.setMethod(request.getMethod());
        Object parameter = getParameter(method, joinPoint.getArgs());
        if (parameter != null) {
            webLog.setParameter(parameter.toString());
        }
        //前面是前置通知,后面是后置通知
        Object result = joinPoint.proceed();
        if (result != null) {
            webLog.setResult(result.toString());
        }
        webLog.setDurationTime((int) (endTime - startTime));
        webLog.setStartTime(new Date(startTime));
        webLog.setUri(request.getRequestURI());
        webLog.setUrl(request.getRequestURL().toString());

        // String token = jwtUtil.getToken(request);
        // if (!StringUtils.isEmpty(token)) {
        //    webLog.setUsername(jwtUtil.getId(token));
        // }
//        String userId = jwtUtil.getId(jwtUtil.getToken(request));
//        webLog.setUsername(userId);
//        log.info("{}", JSONUtil.parse(webLog));

        // 数据插入到队列
        asyncTask.insertIntoQueue(webLog);
        log.info("监听到数据{}", webLog);
        return result;
    }

    @Autowired
    private AsyncTask asyncTask;

    /**
     * 根据方法和传入的参数获取请求参数
     */
    private Object getParameter(Method method, Object[] args) {
        List<Object> argList = new ArrayList<>();
        Parameter[] parameters = method.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            //将RequestBody注解修饰的参数作为请求参数
            RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
            if (requestBody != null) {
                argList.add(args[i]);
            }
            //将RequestParam注解修饰的参数作为请求参数
            RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
            if (requestParam != null) {
                Map<String, Object> map = new HashMap<>();
                String key = parameters[i].getName();
                if (!StringUtils.isEmpty(requestParam.value())) {
                    key = requestParam.value();
                }
                map.put(key, args[i]);
                argList.add(map);
            }
        }
        if (argList.size() == 0) {
            return null;
        } else if (argList.size() == 1) {
            return argList.get(0);
        } else {
            return argList;
        }
    }
}

 5.定义一个线程池,将插入日志操作交由其他线程去做:设置一个定时器,每将十秒将操作日志记录在一个队列中,再通过LogPersistenceServiceImpl业务类实现插入操作,线程池对队列的操作可能会并发,我用synchronized关键字修饰在方法上来保证对Queue<WebLog> DATA_QUEUE队列的操作原子性。

/**
 * @author 旺旺米雪饼
 */
@Slf4j
@Component
public class AsyncTask {

    /**
     * 线程池对队列的操作可能并发,需要用synchronized保证队列内存可见性
     */
//    public final static Queue<WebLog> DATA_QUEUE = new LinkedBlockingQueue<>();
    public final static Queue<WebLog> DATA_QUEUE = new LinkedList<>();
    private final List<WebLog> logList = new ArrayList<>();
    @Autowired
    private LogPersistenceServiceImpl logPersistenceServiceImpl;

    private synchronized void commitLogPool() {
        while (DATA_QUEUE.peek() != null) {
            int size = DATA_QUEUE.size();
            logList.clear();
            for (int i = 0; i < size; i++) {
                logList.add(DATA_QUEUE.poll());
            }
            int affectRows = logPersistenceServiceImpl.insertBatch(logList);
            logList.clear();
            log.info("共有{}条日志插入成功", affectRows);
        }

    }

    @Async("asyncExecutor")
    public synchronized void insertIntoQueue(WebLog webLog) {
        log.info("线程池接收到数据");
        DATA_QUEUE.offer(webLog);
    }

    /**
     * 每10秒将用户的擦欧哦日志刷新到数据库
     */
    @Scheduled(cron = "0/10 * * * * ? ")
    public void timer() {
        log.info("用户的操作日志刷新到数据库,共有条记录{}", logList.size());
        //spring timer定时提交任务
        commitLogPool();
    }
}

6.同样, 线程池定义如下:定义了核心线程数,最大线程数,空闲线程存活时间,并且采用ThreadPoolTaskExecutor();方式建立线程。

/**
 * 启用 Spring 的异步方法执行功能
 *
 * @author 旺旺米雪饼
 */
@EnableAsync
@Configuration
public class ExecutorConfig {


    // new ThreadPoolTaskExecutor();
    /**
     * 核心线程数量,默认16
     */
    private final static int CORE_POOL_SIZE = 16;

    /**
     * 最大线程数量,默认Integer.MAX_VALUE;
     */
    private final static int MAX_POLL_SIZE = 32;

    /**
     * 空闲线程存活时间
     */
    private final static int KEEP_ALIVE_SECONDS = 60;

    /**
     * 线程阻塞队列容量,默认Integer.MAX_VALUE
     */
    private final static int QUEUE_CAPACITY = 10;

    /**
     * 是否允许核心线程超时
     */
    private final static boolean ALLOW_CORE_THREAD_TIMEOUT = false;


    @Bean("asyncExecutor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 配置核心线程数量
        executor.setCorePoolSize(CORE_POOL_SIZE);
        // 配置最大线程数
        executor.setMaxPoolSize(MAX_POLL_SIZE);

        // 配置队列容量
        executor.setQueueCapacity(QUEUE_CAPACITY);
        // 配置空闲线程存活时间
        executor.setKeepAliveSeconds(KEEP_ALIVE_SECONDS);

        executor.setAllowCoreThreadTimeOut(ALLOW_CORE_THREAD_TIMEOUT);

        // 设置拒绝策略,直接在execute方法的调用线程中运行被拒绝的任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());

        // 执行初始化
        executor.initialize();
        return executor;
    }
}

7.业务类实现接口:

/**
 * @author 旺旺米雪饼
 * 日志表操作业务类
 */
@Service
public class LogPersistenceServiceImpl {
    @Resource
    private WebLogMapper webLogMapper;

    public int insertBatch(List<WebLog> webLogList) {
        return webLogMapper.insertBatch(webLogList);
    }
}

 别忘了在application中加@EnableAsync和@EnableScheduling注解。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值