因为项目需求,需要保存项目日志。项目的并发量不大,所以这里直接通过flume保存到oracle
源码地址: https://github.com/jaxlove/fks/tree/master/src/main/java/com
日志系统设置:
url:以select、save、update、remove开头。
通过filter记录请求功的url。格式为json格式,字段包括channel(来源渠道web、wap、app等)、operate_type(操作类型)、first_model(菜单第一模块)、second_model(菜单第二模块)、data(url传递的参数)、ip(请求者ip)、account_id(用户账号id)、time(时间,有系统自动生成),url(请求的url地址)、remark(自定义备注)
表结构相同。
flume配置:
由于flume没有直接sink到oracle的jar包,这里自己自定义sink,偷懒,直接通过mybatis保存到数据库。。。
flume在conf里配置设置
a1.sinks.k1.type = com.myflume.OracleSink
a1.sinks.k1.jdbc_url = jdbc:oracle:thin:@ip:port:实例名
a1.sinks.k1.jdbc_username = username
a1.sinks.k1.jdbc_password = password
#设置多少跳数据提交一次。数据量大,数据精度要求不高可以设置高一点
a1.sinks.k1.jdbc_batchsize = 5
#需要保存的表名
a1.sinks.k1.jdbc_tablename =tablename
java代码的实现说明:
1、获取日志的 { 与 } 之间的数据,将其转为json。
2、json的key必须和table的字段相同。只有这样才能保存,否则该字段不会入库。
3、由于java无法识别日志过多的数据格式,所以只能保存数字与字符串类型。同样数据也必须设置为相同类型。否则会报错。
以下是代码:
com.myflume.OracleSink
package com.myflume;
import com.common.SpringContextHolder;
import com.service.LogInfoService;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.flume.*;
import org.apache.flume.conf.Configurable;
import org.apache.flume.sink.AbstractSink;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 自定义sink
*
* @author wdj on 2018/6/8
*/
public class OracleSink extends AbstractSink implements Configurable{
private Logger logger = LoggerFactory.getLogger(getClass());
private Integer tryCount = 0;
//MAX_TRY_COUNT 次尝试提交之后若数据个数还未达到batchSize,则试着提交
private final Integer MAX_TRY_COUNT = 2;
private String jdbcurl;
private String username;
private String password;
private Integer batchSize;
private String tablename;
private DataSource dataSource;
LogInfoService logInfoService;
private List
com.service.LogInfoService
package com.service;
import com.dao.LogInfoDao;
import com.entity.ColumnDataBean;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
/**
* description
*
* @author wdj on 2018/6/9
*/
@Service
public class LogInfoService {
@Resource
LogInfoDao logInfoDao;
public void save(String tablename,List> datas){
//除了id所有列
List> columnList = logInfoDao.getColumn(tablename.toUpperCase());
//使用linkedHashMap保存原有的顺序
Map columns = new LinkedHashMap();
for (Map stringStringMap : columnList) {
columns.put(stringStringMap.get("COLUMN_NAME"),getJdbcType(stringStringMap.get("DATA_TYPE")));
}
List dataMap = new ArrayList<>();
for (Map data : datas) {
data =transformUpperCase(data);
Map map = new LinkedHashMap();
for (String s : columns.keySet()) {
ColumnDataBean dataBean = new ColumnDataBean();
dataBean.setValue(data.get(s));
dataBean.setType(columns.get(s));
//保存字段值,及字段类型
map.put(s,dataBean);
}
dataMap.add(map);
}
logInfoDao.save(tablename,dataMap);
}
/**
* 将map的key转为大写
* @param orgMap
* @return
*/
public Map transformUpperCase(Map orgMap) {
Map resultMap = new HashMap<>();
if (orgMap == null || orgMap.isEmpty()) {
return resultMap;
}
Set keySet = orgMap.keySet();
for (String key : keySet) {
String newKey = key.toUpperCase();
resultMap.put(newKey, orgMap.get(key));
}
return resultMap;
}
/**
* 根据数据库类型,获取jdbcType,粗略版
* @param dataSourceType
* @return
*/
public String getJdbcType(String dataSourceType){
if(StringUtils.isBlank(dataSourceType)){
return "VARCHAR";//默认字符串
}else if(dataSourceType.indexOf("TIMESTAMP")>-1){
return "TIMESTAMP";
}else if(dataSourceType.indexOf("CHAR")>-1){
return "VARCHAR";
}else if(dataSourceType.indexOf("NUMBER")>-1){
return "NUMERIC";
}else{
return "VARCHAR";
}
}
}
ColumnDataBean就俩个参数,private Object value;private String type;不粘代码了。(PS一下,本来打算直接用map的。但是在dao的save方法里,通过c[VALUE]和c[KEY]只能获取map中固定的一个,不知道是为什么)
dao实现的xml
<mapper namespace="com.dao.LogInfoDao"> <select id="getColumn" resultType="map"> select COLUMN_NAME,DATA_TYPE from USER_TAB_COLUMNS WHERE TABLE_NAME=#{tablename} and COLUMN_NAME !='ID' select> <insert id="save"> insert into ${tablename} select * from <foreach collection="data" item="d" open="(" close=")" separator="union all"> select sys_guid(), <foreach collection="d" index="k" item="c" separator=","> #{c.value,jdbcType=${c.type}} as ${k} foreach> from dual foreach> insert> mapper>
over!byebye,继续努力!