自动配置类参数完善;日志表增加日志类型细化操作;增加预留字段比较新旧值数据存储;
This commit is contained in:
@@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.utils.LogUtils;
|
||||
|
||||
/**
|
||||
@@ -35,7 +36,7 @@ public class LogoutFilter extends org.apache.shiro.web.filter.authc.LogoutFilter
|
||||
//try/catch added for SHIRO-298:
|
||||
try {
|
||||
// 记录用户退出日志
|
||||
LogUtils.saveLog(ServletUtils.getRequest(), "系统退出");
|
||||
LogUtils.saveLog(ServletUtils.getRequest(), "系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
// 退出登录
|
||||
subject.logout();
|
||||
} catch (SessionException ise) {
|
||||
|
||||
@@ -5,12 +5,15 @@ package com.jeesite.common.shiro.realm;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
|
||||
import com.jeesite.common.codec.EncodeUtils;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.modules.sys.entity.EmpUser;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.service.EmpUserService;
|
||||
import com.jeesite.modules.sys.service.UserService;
|
||||
@@ -55,13 +58,13 @@ public class AuthorizingRealm extends com.jeesite.common.shiro.realm.BaseAuthori
|
||||
userService.updateUserLoginInfo(user);
|
||||
|
||||
// 记录用户登录日志
|
||||
LogUtils.saveLog(ServletUtils.getRequest(), "系统登录");
|
||||
LogUtils.saveLog(ServletUtils.getRequest(), "系统登录", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLogoutSuccess(User logoutUser) {
|
||||
public void onLogoutSuccess(User logoutUser, HttpServletRequest request) {
|
||||
// 记录用户退出日志
|
||||
LogUtils.saveLog(logoutUser, null, null, null, "系统退出");
|
||||
LogUtils.saveLog(logoutUser, request, null, null, "系统退出", Log.TYPE_LOGIN_LOGOUT);
|
||||
}
|
||||
|
||||
public void setUserService(UserService userService) {
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.config.web;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.alibaba.druid.support.http.StatViewServlet;
|
||||
import com.alibaba.druid.support.http.WebStatFilter;
|
||||
|
||||
/**
|
||||
* Servlet 配置
|
||||
* @author ThinkGem
|
||||
* @version 2017年11月30日
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name="druid.stat.enabled", havingValue="true", matchIfMissing=true)
|
||||
public class DruidStatConfig {
|
||||
|
||||
/**
|
||||
* 注册DruidFilter拦截
|
||||
*/
|
||||
@Bean
|
||||
public FilterRegistrationBean duridFilter() {
|
||||
FilterRegistrationBean bean = new FilterRegistrationBean();
|
||||
bean.setFilter(new WebStatFilter());
|
||||
bean.addInitParameter("exclusions", "*.css,*.js,*.png,"
|
||||
+ "*.jpg,*.gif,*.jpeg,*.bmp,*.ico,*.swf,*.psd,*.htc,*.htm,*.html,"
|
||||
+ "*.crx,*.xpi,*.exe,*.ipa,*.apk,*.otf,*.eot,*.svg,*.ttf,*.woff,"
|
||||
+ "/druid/*");
|
||||
bean.addUrlPatterns("/*");
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册DruidServlet
|
||||
*/
|
||||
@Bean
|
||||
public ServletRegistrationBean druidServlet() {
|
||||
ServletRegistrationBean bean = new ServletRegistrationBean();
|
||||
bean.setServlet(new StatViewServlet());
|
||||
bean.addUrlMappings("/druid/*");
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.config.web.interceptor;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.modules.sys.interceptor.LogInterceptor;
|
||||
|
||||
/**
|
||||
* 后台管理日志记录拦截器
|
||||
* @author ThinkGem
|
||||
* @version 2018年1月10日
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ConditionalOnProperty(name="web.interceptor.log.enabled", havingValue="true", matchIfMissing=true)
|
||||
public class LogInterceptorConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
InterceptorRegistration registration = registry.addInterceptor(new LogInterceptor());
|
||||
String apps = Global.getProperty("web.interceptor.log.addPathPatterns");
|
||||
String epps = Global.getProperty("web.interceptor.log.excludePathPatterns");
|
||||
for (String uri : StringUtils.split(apps, ",")){
|
||||
if (StringUtils.isNotBlank(uri)){
|
||||
registration.addPathPatterns(StringUtils.trim(uri));
|
||||
}
|
||||
}
|
||||
for (String uri : StringUtils.split(epps, ",")){
|
||||
if (StringUtils.isNotBlank(uri)){
|
||||
registration.excludePathPatterns(StringUtils.trim(epps));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.config.web.interceptor;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.modules.sys.interceptor.MobileInterceptor;
|
||||
|
||||
/**
|
||||
* 前台自动切换到手机视图拦截器
|
||||
* @author ThinkGem
|
||||
* @version 2018年1月10日
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ConditionalOnProperty(name="web.interceptor.mobile.enabled", havingValue="true", matchIfMissing=false)
|
||||
public class MobileViewInterceptorConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
InterceptorRegistration registration = registry.addInterceptor(new MobileInterceptor());
|
||||
String apps = Global.getProperty("web.interceptor.mobile.addPathPatterns");
|
||||
String epps = Global.getProperty("web.interceptor.mobile.excludePathPatterns");
|
||||
for (String uri : StringUtils.split(apps, ",")){
|
||||
if (StringUtils.isNotBlank(uri)){
|
||||
registration.addPathPatterns(StringUtils.trim(uri));
|
||||
}
|
||||
}
|
||||
for (String uri : StringUtils.split(epps, ",")){
|
||||
if (StringUtils.isNotBlank(uri)){
|
||||
registration.excludePathPatterns(StringUtils.trim(epps));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Binary file not shown.
@@ -1,243 +1,255 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.sys.entity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
import com.jeesite.common.collect.MapUtils;
|
||||
import com.jeesite.common.entity.BaseEntity;
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.common.shiro.realm.LoginInfo;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
/**
|
||||
* 操作日志Entity
|
||||
* @author ThinkGem
|
||||
* @version 2017-03-19
|
||||
*/
|
||||
@Table(name="${_prefix}sys_log", alias="a", columns={
|
||||
@Column(includeEntity=BaseEntity.class),
|
||||
@Column(name="id", attrName="id", label="编码", isPK=true),
|
||||
@Column(name="log_type", attrName="logType", label="日志类型"),
|
||||
@Column(name="log_title", attrName="logTitle", label="日志标题", queryType=QueryType.LIKE),
|
||||
@Column(name="create_by", attrName="createBy.userCode", label="创建者", isUpdate=false),
|
||||
@Column(name="create_by_name", attrName="createBy.userName", label="创建者名称", queryType=QueryType.LIKE),
|
||||
@Column(name="create_date", attrName="createDate", label="创建时间", isUpdate=false, isQuery=false),
|
||||
@Column(name="request_uri", attrName="requestUri", label="请求URI", queryType=QueryType.LIKE),
|
||||
@Column(name="request_method", attrName="requestMethod", label="操作方式"),
|
||||
@Column(name="request_params", attrName="requestParams", label="操作提交的数据", queryType=QueryType.LIKE),
|
||||
@Column(name="biz_key", attrName="bizKey", label="业务主键"),
|
||||
@Column(name="biz_type", attrName="bizType", label="业务类型"),
|
||||
@Column(name="remote_addr", attrName="remoteAddr", label="操作IP地址"),
|
||||
@Column(name="server_addr", attrName="serverAddr", label="请求服务器地址"),
|
||||
@Column(name="exception_info", attrName="exceptionInfo", label="异常信息"),
|
||||
@Column(name="user_agent", attrName="userAgent", label="用户代理"),
|
||||
@Column(name="device_name", attrName="deviceName", label="设备名称/操作系统", queryType=QueryType.LIKE),
|
||||
@Column(name="browser_name", attrName="browserName", label="浏览器名称", queryType=QueryType.LIKE),
|
||||
}, orderBy="a.create_date DESC"
|
||||
)
|
||||
public class Log extends DataEntity<Log> {
|
||||
|
||||
// 日志类型(1:接入日志;2:错误日志)
|
||||
public static final String TYPE_ACCESS = "1";
|
||||
public static final String TYPE_EXCEPTION = "2";
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String logType; // 日志类型
|
||||
private String logTitle; // 日志标题
|
||||
private String requestUri; // 请求URI
|
||||
private String requestMethod; // 操作方式
|
||||
private String requestParams; // 操作提交的数据
|
||||
private String bizKey; // 业务主键
|
||||
private String bizType; // 业务类型
|
||||
private String remoteAddr; // 操作IP地址
|
||||
private String serverAddr; // 请求服务器地址
|
||||
private String exceptionInfo; // 异常信息
|
||||
private String userAgent; // 用户代理
|
||||
private String deviceName; // 设备名称/操作系统
|
||||
private String browserName; // 浏览器名称
|
||||
|
||||
private Map<String, String[]> paramsMap; // 操作提交的数据,临时存储用
|
||||
|
||||
public Log() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public Log(String id){
|
||||
super(id);
|
||||
}
|
||||
|
||||
@NotBlank(message="日志类型不能为空")
|
||||
@Length(min=0, max=1, message="日志类型长度不能超过 1 个字符")
|
||||
public String getLogType() {
|
||||
return logType;
|
||||
}
|
||||
|
||||
public void setLogType(String logType) {
|
||||
this.logType = logType;
|
||||
}
|
||||
|
||||
@NotBlank(message="日志标题不能为空")
|
||||
@Length(min=0, max=500, message="日志标题长度不能超过 500 个字符")
|
||||
public String getLogTitle() {
|
||||
return logTitle;
|
||||
}
|
||||
|
||||
public void setLogTitle(String logTitle) {
|
||||
this.logTitle = logTitle;
|
||||
}
|
||||
|
||||
@Length(min=0, max=255, message="请求URI长度不能超过 255 个字符")
|
||||
public String getRequestUri() {
|
||||
LoginInfo p = UserUtils.getLoginInfo();
|
||||
if (p != null && "1".equals(p.getParam("l"))){
|
||||
return null;
|
||||
}
|
||||
return requestUri;
|
||||
}
|
||||
|
||||
public void setRequestUri(String requestUri) {
|
||||
this.requestUri = requestUri;
|
||||
}
|
||||
|
||||
@Length(min=0, max=10, message="操作方式长度不能超过 10 个字符")
|
||||
public String getRequestMethod() {
|
||||
return requestMethod;
|
||||
}
|
||||
|
||||
public void setRequestMethod(String requestMethod) {
|
||||
this.requestMethod = requestMethod;
|
||||
}
|
||||
|
||||
public String getRequestParams() {
|
||||
return requestParams;
|
||||
}
|
||||
|
||||
public void setRequestParams(String requestParams) {
|
||||
this.requestParams = requestParams;
|
||||
}
|
||||
|
||||
@Length(min=0, max=64, message="业务主键长度不能超过 64 个字符")
|
||||
public String getBizKey() {
|
||||
return bizKey;
|
||||
}
|
||||
|
||||
public void setBizKey(String bizKey) {
|
||||
this.bizKey = bizKey;
|
||||
}
|
||||
|
||||
@Length(min=0, max=64, message="业务类型长度不能超过 64 个字符")
|
||||
public String getBizType() {
|
||||
return bizType;
|
||||
}
|
||||
|
||||
public void setBizType(String bizType) {
|
||||
this.bizType = bizType;
|
||||
}
|
||||
|
||||
@NotBlank(message="操作IP地址不能为空")
|
||||
@Length(min=0, max=255, message="操作IP地址长度不能超过 255 个字符")
|
||||
public String getRemoteAddr() {
|
||||
return remoteAddr;
|
||||
}
|
||||
|
||||
public void setRemoteAddr(String remoteAddr) {
|
||||
this.remoteAddr = remoteAddr;
|
||||
}
|
||||
|
||||
@NotBlank(message="请求服务器地址不能为空")
|
||||
@Length(min=0, max=255, message="请求服务器地址长度不能超过 255 个字符")
|
||||
public String getServerAddr() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
public void setServerAddr(String serverAddr) {
|
||||
this.serverAddr = serverAddr;
|
||||
}
|
||||
|
||||
public String getExceptionInfo() {
|
||||
return exceptionInfo;
|
||||
}
|
||||
|
||||
public void setExceptionInfo(String exceptionInfo) {
|
||||
this.exceptionInfo = exceptionInfo;
|
||||
}
|
||||
|
||||
@Length(min=0, max=500, message="用户代理长度不能超过 500 个字符")
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
@Length(min=0, max=100, message="设备名称/操作系统长度不能超过 100 个字符")
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public void setDeviceName(String deviceName) {
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
|
||||
@Length(min=0, max=100, message="浏览器名称长度不能超过 100 个字符")
|
||||
public String getBrowserName() {
|
||||
return browserName;
|
||||
}
|
||||
|
||||
public void setBrowserName(String browserName) {
|
||||
this.browserName = browserName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求参数
|
||||
* @param paramMap
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void setRequestParams(Map paramsMap){
|
||||
if (paramsMap == null){
|
||||
return;
|
||||
}
|
||||
if (this.paramsMap == null){
|
||||
this.paramsMap = MapUtils.newHashMap();
|
||||
}
|
||||
StringBuilder params = new StringBuilder();
|
||||
for (Map.Entry<String, String[]> param : ((Map<String, String[]>)paramsMap).entrySet()){
|
||||
params.append(("".equals(params.toString()) ? "" : "&") + param.getKey() + "=");
|
||||
String paramValue = (param.getValue() != null && param.getValue().length > 0 ? param.getValue()[0] : "");
|
||||
params.append(StringUtils.abbr(StringUtils.endsWithIgnoreCase(param.getKey(), "password") ? "*" : paramValue, 1000));
|
||||
this.paramsMap.put(param.getKey(), param.getValue());
|
||||
}
|
||||
this.requestParams = params.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据名称获取参数(只有先执行setParams(Map)后才有效)
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public String getRequestParam(String name) {
|
||||
if (paramsMap == null){
|
||||
return null;
|
||||
}
|
||||
String[] values = (String[])paramsMap.get(name);
|
||||
return values != null && values.length > 0 ? values[0] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilder.toString(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.sys.entity;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
|
||||
import com.jeesite.common.collect.MapUtils;
|
||||
import com.jeesite.common.entity.BaseEntity;
|
||||
import com.jeesite.common.entity.DataEntity;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.query.QueryType;
|
||||
import com.jeesite.common.shiro.realm.LoginInfo;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
/**
|
||||
* 操作日志Entity
|
||||
* @author ThinkGem
|
||||
* @version 2017-03-19
|
||||
*/
|
||||
@Table(name="${_prefix}sys_log", alias="a", columns={
|
||||
@Column(includeEntity=BaseEntity.class),
|
||||
@Column(name="id", attrName="id", label="编码", isPK=true),
|
||||
@Column(name="log_type", attrName="logType", label="日志类型"),
|
||||
@Column(name="log_title", attrName="logTitle", label="日志标题", queryType=QueryType.LIKE),
|
||||
@Column(name="create_by", attrName="createBy.userCode", label="创建者", isUpdate=false),
|
||||
@Column(name="create_by_name", attrName="createBy.userName", label="创建者名称", queryType=QueryType.LIKE),
|
||||
@Column(name="create_date", attrName="createDate", label="创建时间", isUpdate=false, isQuery=false),
|
||||
@Column(name="request_uri", attrName="requestUri", label="请求URI", queryType=QueryType.LIKE),
|
||||
@Column(name="request_method", attrName="requestMethod", label="操作方式"),
|
||||
@Column(name="request_params", attrName="requestParams", label="操作提交的数据", queryType=QueryType.LIKE),
|
||||
@Column(name="biz_key", attrName="bizKey", label="业务主键"),
|
||||
@Column(name="biz_type", attrName="bizType", label="业务类型"),
|
||||
@Column(name="remote_addr", attrName="remoteAddr", label="操作IP地址"),
|
||||
@Column(name="server_addr", attrName="serverAddr", label="请求服务器地址"),
|
||||
@Column(name="is_exception", attrName="isException", label="是否异常"),
|
||||
@Column(name="exception_info", attrName="exceptionInfo", label="异常信息"),
|
||||
@Column(name="user_agent", attrName="userAgent", label="用户代理"),
|
||||
@Column(name="device_name", attrName="deviceName", label="设备名称/操作系统", queryType=QueryType.LIKE),
|
||||
@Column(name="browser_name", attrName="browserName", label="浏览器名称", queryType=QueryType.LIKE),
|
||||
}, orderBy="a.create_date DESC"
|
||||
)
|
||||
public class Log extends DataEntity<Log> {
|
||||
|
||||
// 日志类型(access:接入日志;update:修改日志;select:查询日志;loginLogout:登录登出;)
|
||||
public static final String TYPE_ACCESS = "access";
|
||||
public static final String TYPE_UPDATE = "update";
|
||||
public static final String TYPE_SELECT = "select";
|
||||
public static final String TYPE_LOGIN_LOGOUT = "loginLogout";
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String logType; // 日志类型
|
||||
private String logTitle; // 日志标题
|
||||
private String requestUri; // 请求URI
|
||||
private String requestMethod; // 操作方式
|
||||
private String requestParams; // 操作提交的数据
|
||||
private String bizKey; // 业务主键
|
||||
private String bizType; // 业务类型
|
||||
private String remoteAddr; // 操作IP地址
|
||||
private String serverAddr; // 请求服务器地址
|
||||
private String isException; // 是否有异常
|
||||
private String exceptionInfo; // 异常信息
|
||||
private String userAgent; // 用户代理
|
||||
private String deviceName; // 设备名称/操作系统
|
||||
private String browserName; // 浏览器名称
|
||||
|
||||
private Map<String, String[]> paramsMap; // 操作提交的数据,临时存储用
|
||||
|
||||
public Log() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public Log(String id){
|
||||
super(id);
|
||||
}
|
||||
|
||||
@NotBlank(message="日志类型不能为空")
|
||||
@Length(min=0, max=1, message="日志类型长度不能超过 1 个字符")
|
||||
public String getLogType() {
|
||||
return logType;
|
||||
}
|
||||
|
||||
public void setLogType(String logType) {
|
||||
this.logType = logType;
|
||||
}
|
||||
|
||||
@NotBlank(message="日志标题不能为空")
|
||||
@Length(min=0, max=500, message="日志标题长度不能超过 500 个字符")
|
||||
public String getLogTitle() {
|
||||
return logTitle;
|
||||
}
|
||||
|
||||
public void setLogTitle(String logTitle) {
|
||||
this.logTitle = logTitle;
|
||||
}
|
||||
|
||||
@Length(min=0, max=255, message="请求URI长度不能超过 255 个字符")
|
||||
public String getRequestUri() {
|
||||
LoginInfo p = UserUtils.getLoginInfo();
|
||||
if (p != null && "1".equals(p.getParam("l"))){
|
||||
return null;
|
||||
}
|
||||
return requestUri;
|
||||
}
|
||||
|
||||
public void setRequestUri(String requestUri) {
|
||||
this.requestUri = requestUri;
|
||||
}
|
||||
|
||||
@Length(min=0, max=10, message="操作方式长度不能超过 10 个字符")
|
||||
public String getRequestMethod() {
|
||||
return requestMethod;
|
||||
}
|
||||
|
||||
public void setRequestMethod(String requestMethod) {
|
||||
this.requestMethod = requestMethod;
|
||||
}
|
||||
|
||||
public String getRequestParams() {
|
||||
return requestParams;
|
||||
}
|
||||
|
||||
public void setRequestParams(String requestParams) {
|
||||
this.requestParams = requestParams;
|
||||
}
|
||||
|
||||
@Length(min=0, max=64, message="业务主键长度不能超过 64 个字符")
|
||||
public String getBizKey() {
|
||||
return bizKey;
|
||||
}
|
||||
|
||||
public void setBizKey(String bizKey) {
|
||||
this.bizKey = bizKey;
|
||||
}
|
||||
|
||||
@Length(min=0, max=64, message="业务类型长度不能超过 64 个字符")
|
||||
public String getBizType() {
|
||||
return bizType;
|
||||
}
|
||||
|
||||
public void setBizType(String bizType) {
|
||||
this.bizType = bizType;
|
||||
}
|
||||
|
||||
@NotBlank(message="操作IP地址不能为空")
|
||||
@Length(min=0, max=255, message="操作IP地址长度不能超过 255 个字符")
|
||||
public String getRemoteAddr() {
|
||||
return remoteAddr;
|
||||
}
|
||||
|
||||
public void setRemoteAddr(String remoteAddr) {
|
||||
this.remoteAddr = remoteAddr;
|
||||
}
|
||||
|
||||
@NotBlank(message="请求服务器地址不能为空")
|
||||
@Length(min=0, max=255, message="请求服务器地址长度不能超过 255 个字符")
|
||||
public String getServerAddr() {
|
||||
return serverAddr;
|
||||
}
|
||||
|
||||
public void setServerAddr(String serverAddr) {
|
||||
this.serverAddr = serverAddr;
|
||||
}
|
||||
|
||||
public String getIsException() {
|
||||
return isException;
|
||||
}
|
||||
|
||||
public void setIsException(String isException) {
|
||||
this.isException = isException;
|
||||
}
|
||||
|
||||
public String getExceptionInfo() {
|
||||
return exceptionInfo;
|
||||
}
|
||||
|
||||
public void setExceptionInfo(String exceptionInfo) {
|
||||
this.exceptionInfo = exceptionInfo;
|
||||
}
|
||||
|
||||
@Length(min=0, max=500, message="用户代理长度不能超过 500 个字符")
|
||||
public String getUserAgent() {
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
public void setUserAgent(String userAgent) {
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
@Length(min=0, max=100, message="设备名称/操作系统长度不能超过 100 个字符")
|
||||
public String getDeviceName() {
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
public void setDeviceName(String deviceName) {
|
||||
this.deviceName = deviceName;
|
||||
}
|
||||
|
||||
@Length(min=0, max=100, message="浏览器名称长度不能超过 100 个字符")
|
||||
public String getBrowserName() {
|
||||
return browserName;
|
||||
}
|
||||
|
||||
public void setBrowserName(String browserName) {
|
||||
this.browserName = browserName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求参数
|
||||
* @param paramMap
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void setRequestParams(Map paramsMap){
|
||||
if (paramsMap == null){
|
||||
return;
|
||||
}
|
||||
if (this.paramsMap == null){
|
||||
this.paramsMap = MapUtils.newHashMap();
|
||||
}
|
||||
StringBuilder params = new StringBuilder();
|
||||
for (Map.Entry<String, String[]> param : ((Map<String, String[]>)paramsMap).entrySet()){
|
||||
params.append(("".equals(params.toString()) ? "" : "&") + param.getKey() + "=");
|
||||
String paramValue = (param.getValue() != null && param.getValue().length > 0 ? param.getValue()[0] : "");
|
||||
params.append(StringUtils.abbr(StringUtils.endsWithIgnoreCase(param.getKey(), "password") ? "*" : paramValue, 1000));
|
||||
this.paramsMap.put(param.getKey(), param.getValue());
|
||||
}
|
||||
this.requestParams = params.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据名称获取参数(只有先执行setParams(Map)后才有效)
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public String getRequestParam(String name) {
|
||||
if (paramsMap == null){
|
||||
return null;
|
||||
}
|
||||
String[] values = (String[])paramsMap.get(name);
|
||||
return values != null && values.length > 0 ? values[0] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ReflectionToStringBuilder.toString(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +1,71 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.sys.interceptor;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.lang.TimeUtils;
|
||||
import com.jeesite.common.service.BaseService;
|
||||
import com.jeesite.modules.sys.utils.LogUtils;
|
||||
|
||||
/**
|
||||
* 日志拦截器
|
||||
* @author ThinkGem
|
||||
* @version 2014-8-19
|
||||
*/
|
||||
public class LogInterceptor extends BaseService implements HandlerInterceptor {
|
||||
|
||||
private static final ThreadLocal<Long> startTimeThreadLocal =
|
||||
new NamedThreadLocal<Long>("ThreadLocal StartTime");
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
if (logger.isDebugEnabled()){
|
||||
long beginTime = System.currentTimeMillis();//1、开始时间
|
||||
startTimeThreadLocal.set(beginTime); //线程绑定变量(该数据只有当前请求的线程可见)
|
||||
logger.debug("开始计时: {} URI: {}", new SimpleDateFormat("hh:mm:ss.SSS")
|
||||
.format(beginTime), request.getRequestURI());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
ModelAndView modelAndView) throws Exception {
|
||||
if (modelAndView != null){
|
||||
logger.info("ViewName: " + modelAndView.getViewName() + " <<<<<<<<< " + request.getRequestURI() + " >>>>>>>>> " + handler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
|
||||
// 保存日志
|
||||
LogUtils.saveLog(request, handler, ex, null);
|
||||
|
||||
// 打印JVM信息。
|
||||
if (logger.isDebugEnabled()){
|
||||
long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)
|
||||
long endTime = System.currentTimeMillis(); //2、结束时间
|
||||
logger.debug("计时结束: {} 用时: {} URI: {} 最大内存: {}m 已分配内存: {}m 已分配内存中的剩余空间: {}m 最大可用内存: {}m",
|
||||
DateUtils.formatDate(endTime, "hh:mm:ss.SSS"), TimeUtils.formatDateAgo(endTime - beginTime),
|
||||
request.getRequestURI(), Runtime.getRuntime().maxMemory()/1024/1024, Runtime.getRuntime().totalMemory()/1024/1024, Runtime.getRuntime().freeMemory()/1024/1024,
|
||||
(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024);
|
||||
startTimeThreadLocal.remove(); //用完之后销毁线程变量数据
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.sys.interceptor;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.core.NamedThreadLocal;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.jeesite.common.lang.DateUtils;
|
||||
import com.jeesite.common.lang.TimeUtils;
|
||||
import com.jeesite.common.service.BaseService;
|
||||
import com.jeesite.modules.sys.utils.LogUtils;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
/**
|
||||
* 日志拦截器
|
||||
* @author ThinkGem
|
||||
* @version 2014-8-19
|
||||
*/
|
||||
public class LogInterceptor extends BaseService implements HandlerInterceptor {
|
||||
|
||||
private static final ThreadLocal<Long> startTimeThreadLocal =
|
||||
new NamedThreadLocal<Long>("ThreadLocal StartTime");
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler) throws Exception {
|
||||
if (logger.isDebugEnabled()){
|
||||
long beginTime = System.currentTimeMillis();//1、开始时间
|
||||
startTimeThreadLocal.set(beginTime); //线程绑定变量(该数据只有当前请求的线程可见)
|
||||
logger.debug("开始计时: {} URI: {}", new SimpleDateFormat("hh:mm:ss.SSS")
|
||||
.format(beginTime), request.getRequestURI());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
|
||||
ModelAndView modelAndView) throws Exception {
|
||||
if (modelAndView != null){
|
||||
logger.info("ViewName: " + modelAndView.getViewName() + " <<<<<<<<< " + request.getRequestURI() + " >>>>>>>>> " + handler);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler, Exception ex) throws Exception {
|
||||
|
||||
// 保存日志
|
||||
LogUtils.saveLog(UserUtils.getUser(), request, handler, ex, null, null);
|
||||
|
||||
// 打印JVM信息。
|
||||
if (logger.isDebugEnabled()){
|
||||
long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)
|
||||
long endTime = System.currentTimeMillis(); //2、结束时间
|
||||
logger.debug("计时结束: {} 用时: {} URI: {} 最大内存: {}m 已分配内存: {}m 已分配内存中的剩余空间: {}m 最大可用内存: {}m",
|
||||
DateUtils.formatDate(endTime, "hh:mm:ss.SSS"), TimeUtils.formatDateAgo(endTime - beginTime),
|
||||
request.getRequestURI(), Runtime.getRuntime().maxMemory()/1024/1024, Runtime.getRuntime().totalMemory()/1024/1024, Runtime.getRuntime().freeMemory()/1024/1024,
|
||||
(Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024);
|
||||
startTimeThreadLocal.remove(); //用完之后销毁线程变量数据
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,210 +1,197 @@
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.sys.utils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.entity.BaseEntity;
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.MapperHelper;
|
||||
import com.jeesite.common.network.IpUtils;
|
||||
import com.jeesite.common.utils.SpringUtils;
|
||||
import com.jeesite.common.web.http.ServletUtils;
|
||||
import com.jeesite.common.web.http.UserAgentUtils;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.service.LogService;
|
||||
import com.jeesite.modules.sys.service.MenuService;
|
||||
import com.jeesite.modules.sys.utils.UserUtils;
|
||||
|
||||
import eu.bitwalker.useragentutils.UserAgent;
|
||||
|
||||
/**
|
||||
* 字典工具类
|
||||
* @author ThinkGem
|
||||
* @version 2014-11-7
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
/**
|
||||
* 静态内部类,延迟加载,懒汉式,线程安全的单例模式
|
||||
*/
|
||||
private static final class Static {
|
||||
private static LogService logService = SpringUtils.getBean(LogService.class);
|
||||
private static MenuService menuService = SpringUtils.getBean(MenuService.class);
|
||||
}
|
||||
|
||||
// 参数名获取工具(尝试获取标注为@ModelAttribute注解的方法,第一个参数名一般为主键名)
|
||||
private static ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*/
|
||||
public static void saveLog(String title){
|
||||
saveLog(null, null, null, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*/
|
||||
public static void saveLog(HttpServletRequest request, String title){
|
||||
saveLog(request, null, null, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*/
|
||||
public static void saveLog(HttpServletRequest request, Object handler, Exception ex, String title){
|
||||
saveLog(null, request, handler, ex, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*/
|
||||
public static void saveLog(User user, HttpServletRequest request, Object handler, Exception ex, String title){
|
||||
if (user == null){
|
||||
user = UserUtils.getUser();
|
||||
}
|
||||
if (request == null){
|
||||
request = ServletUtils.getRequest();
|
||||
}
|
||||
if (request != null && user != null && StringUtils.isNotBlank(user.getUserCode())){
|
||||
Log log = new Log();
|
||||
log.setLogTitle(title);
|
||||
Throwable throwable = ex != null ? ex : ExceptionUtils.getThrowable(request);
|
||||
log.setLogType(throwable == null ? Log.TYPE_ACCESS : Log.TYPE_EXCEPTION);
|
||||
log.setServerAddr(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort());
|
||||
log.setRemoteAddr(IpUtils.getRemoteAddr(request));
|
||||
UserAgent userAgent = UserAgentUtils.getUserAgent(request);
|
||||
log.setDeviceName(userAgent.getOperatingSystem().getName());
|
||||
log.setBrowserName(userAgent.getBrowser().getName());
|
||||
log.setUserAgent(request.getHeader("User-Agent"));
|
||||
log.setRequestUri(StringUtils.abbr(request.getRequestURI(), 255));
|
||||
log.setRequestParams(request.getParameterMap());
|
||||
log.setRequestMethod(request.getMethod());
|
||||
if (Global.isUseCorpModel()){
|
||||
log.setCorpCode(user.getCorpCode());
|
||||
log.setCorpName(user.getCorpName());
|
||||
}
|
||||
log.setCurrentUser(user);
|
||||
log.preInsert();
|
||||
|
||||
// 异步保存日志
|
||||
new SaveLogThread(log, handler, throwable).start();
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 保存日志线程
|
||||
*/
|
||||
public static class SaveLogThread extends Thread{
|
||||
|
||||
private Log log;
|
||||
private Object handler;
|
||||
private Throwable throwable;
|
||||
|
||||
public SaveLogThread(Log log, Object handler, Throwable throwable){
|
||||
super(SaveLogThread.class.getSimpleName());
|
||||
this.log = log;
|
||||
this.handler = handler;
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// 获取日志标题
|
||||
if (StringUtils.isBlank(log.getLogTitle())){
|
||||
String permission = "";
|
||||
if (handler instanceof HandlerMethod){
|
||||
HandlerMethod hm = ((HandlerMethod)handler);
|
||||
Method m = hm.getMethod();
|
||||
// 获取权限字符串
|
||||
RequiresPermissions rp = m.getAnnotation(RequiresPermissions.class);
|
||||
permission = (rp != null ? StringUtils.join(rp.value(), ",") : "");
|
||||
|
||||
// 尝试获取BaseEntity的设置的主键值
|
||||
for (Class<?> type : m.getParameterTypes()){
|
||||
try {
|
||||
// 判断是否是BaseEntity的子类
|
||||
Class<?> superClass = type.getSuperclass();
|
||||
while(superClass != null && superClass != BaseEntity.class){
|
||||
superClass = superClass.getSuperclass();
|
||||
};
|
||||
// 如果是BaseEntity的子类,则获取主键名
|
||||
if (superClass != null){
|
||||
Table t = type.getAnnotation(Table.class);
|
||||
for (Column c : t.columns()){
|
||||
if (c.isPK()){
|
||||
try {
|
||||
String attrName = MapperHelper.getAttrName(c);
|
||||
if (attrName != null){
|
||||
log.setBizKey(log.getRequestParam(attrName));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试获取标注为@ModelAttribute注解的方法,第一个参数名一般为主键名
|
||||
if (StringUtils.isBlank(log.getBizKey())){
|
||||
for (Method me : hm.getBeanType().getMethods()){
|
||||
ModelAttribute ma = AnnotationUtils.findAnnotation(me, ModelAttribute.class);
|
||||
if(ma != null){
|
||||
String[] ps = pnd.getParameterNames(me);
|
||||
if(ps != null && ps.length > 0){
|
||||
log.setBizKey(StringUtils.abbr(log.getRequestParam(ps[0]), 64));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最后尝试获取参数为id的值
|
||||
if (StringUtils.isBlank(log.getBizKey())){
|
||||
log.setBizKey(log.getRequestParam("id"));
|
||||
}
|
||||
|
||||
}
|
||||
log.setLogTitle(Static.menuService.getMenuNamePath(log.getRequestUri(), permission));
|
||||
}
|
||||
if (StringUtils.isBlank(log.getLogTitle())){
|
||||
if (StringUtils.contains(log.getRequestParams(), "taskCommandInfo=")){
|
||||
log.setLogTitle("我的任务-任务办理");
|
||||
}else{
|
||||
log.setLogTitle("未知操作");
|
||||
}
|
||||
}
|
||||
// 如果有异常,设置异常信息(将异常对象转换为字符串)
|
||||
log.setExceptionInfo(ExceptionUtils.getStackTraceAsString(throwable));
|
||||
// 如果无地址并无异常日志,则不保存信息
|
||||
if (StringUtils.isBlank(log.getRequestUri()) && StringUtils.isBlank(log.getExceptionInfo())){
|
||||
return;
|
||||
}
|
||||
// 保存日志信息
|
||||
log.setIsNewRecord(true);
|
||||
Static.logService.insertLog(log);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
|
||||
*/
|
||||
package com.jeesite.modules.sys.utils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.ibatis.mapping.SqlCommandType;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||
import org.springframework.core.ParameterNameDiscoverer;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
|
||||
import com.jeesite.common.config.Global;
|
||||
import com.jeesite.common.entity.BaseEntity;
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
import com.jeesite.common.lang.ObjectUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
import com.jeesite.common.mybatis.annotation.Column;
|
||||
import com.jeesite.common.mybatis.annotation.Table;
|
||||
import com.jeesite.common.mybatis.mapper.MapperHelper;
|
||||
import com.jeesite.common.network.IpUtils;
|
||||
import com.jeesite.common.utils.SpringUtils;
|
||||
import com.jeesite.common.web.http.UserAgentUtils;
|
||||
import com.jeesite.modules.sys.entity.Log;
|
||||
import com.jeesite.modules.sys.entity.User;
|
||||
import com.jeesite.modules.sys.service.LogService;
|
||||
import com.jeesite.modules.sys.service.MenuService;
|
||||
|
||||
import eu.bitwalker.useragentutils.UserAgent;
|
||||
|
||||
/**
|
||||
* 字典工具类
|
||||
* @author ThinkGem
|
||||
* @version 2014-11-7
|
||||
*/
|
||||
public class LogUtils {
|
||||
|
||||
/**
|
||||
* 静态内部类,延迟加载,懒汉式,线程安全的单例模式
|
||||
*/
|
||||
private static final class Static {
|
||||
private static LogService logService = SpringUtils.getBean(LogService.class);
|
||||
private static MenuService menuService = SpringUtils.getBean(MenuService.class);
|
||||
}
|
||||
|
||||
// 参数名获取工具(尝试获取标注为@ModelAttribute注解的方法,第一个参数名一般为主键名)
|
||||
private static ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*/
|
||||
public static void saveLog(HttpServletRequest request, String logTitle, String logType){
|
||||
saveLog(UserUtils.getUser(), request, null, null, logTitle, logType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存日志
|
||||
*/
|
||||
public static void saveLog(User user, HttpServletRequest request, Object handler, Exception ex, String logTitle, String logType){
|
||||
if (user == null || StringUtils.isBlank(user.getUserCode()) || request == null){
|
||||
return;
|
||||
}
|
||||
Log log = new Log();
|
||||
log.setLogTitle(logTitle);
|
||||
log.setLogType(logType);
|
||||
if (StringUtils.isBlank(log.getLogType())){
|
||||
String sqlCommandTypes = ObjectUtils.toString(request.getAttribute(SqlCommandType.class.getName()));
|
||||
if (StringUtils.inString(","+sqlCommandTypes+",", ",INSERT,", ",UPDATE,", ",DELETE,")){
|
||||
log.setLogType(Log.TYPE_UPDATE);
|
||||
}else if (StringUtils.inString(","+sqlCommandTypes+",", ",SELECT,")){
|
||||
log.setLogType(Log.TYPE_SELECT);
|
||||
}else{
|
||||
log.setLogType(Log.TYPE_ACCESS);
|
||||
}
|
||||
}
|
||||
log.setServerAddr(request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort());
|
||||
log.setRemoteAddr(IpUtils.getRemoteAddr(request));
|
||||
UserAgent userAgent = UserAgentUtils.getUserAgent(request);
|
||||
log.setDeviceName(userAgent.getOperatingSystem().getName());
|
||||
log.setBrowserName(userAgent.getBrowser().getName());
|
||||
log.setUserAgent(request.getHeader("User-Agent"));
|
||||
log.setRequestUri(StringUtils.abbr(request.getRequestURI(), 255));
|
||||
log.setRequestParams(request.getParameterMap());
|
||||
log.setRequestMethod(request.getMethod());
|
||||
if (Global.isUseCorpModel()){
|
||||
log.setCorpCode(user.getCorpCode());
|
||||
log.setCorpName(user.getCorpName());
|
||||
}
|
||||
log.setCurrentUser(user);
|
||||
log.preInsert();
|
||||
|
||||
// 获取异常对象
|
||||
Throwable throwable = null;
|
||||
if (ex != null){
|
||||
throwable = ExceptionUtils.getThrowable(request);
|
||||
}
|
||||
|
||||
// 异步保存日志
|
||||
new SaveLogThread(log, handler, throwable).start();
|
||||
}
|
||||
/**
|
||||
* 保存日志线程
|
||||
*/
|
||||
public static class SaveLogThread extends Thread{
|
||||
|
||||
private Log log;
|
||||
private Object handler;
|
||||
private Throwable throwable;
|
||||
|
||||
public SaveLogThread(Log log, Object handler, Throwable throwable){
|
||||
super(SaveLogThread.class.getSimpleName());
|
||||
this.log = log;
|
||||
this.handler = handler;
|
||||
this.throwable = throwable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// 获取日志标题
|
||||
if (StringUtils.isBlank(log.getLogTitle())){
|
||||
String permission = "";
|
||||
if (handler instanceof HandlerMethod){
|
||||
HandlerMethod hm = ((HandlerMethod)handler);
|
||||
Method m = hm.getMethod();
|
||||
// 获取权限字符串
|
||||
RequiresPermissions rp = m.getAnnotation(RequiresPermissions.class);
|
||||
permission = (rp != null ? StringUtils.join(rp.value(), ",") : "");
|
||||
|
||||
// 尝试获取BaseEntity的设置的主键值
|
||||
for (Class<?> type : m.getParameterTypes()){
|
||||
try {
|
||||
// 判断是否是BaseEntity的子类
|
||||
Class<?> superClass = type.getSuperclass();
|
||||
while(superClass != null && superClass != BaseEntity.class){
|
||||
superClass = superClass.getSuperclass();
|
||||
};
|
||||
// 如果是BaseEntity的子类,则获取主键名
|
||||
if (superClass != null){
|
||||
Table t = type.getAnnotation(Table.class);
|
||||
for (Column c : t.columns()){
|
||||
if (c.isPK()){
|
||||
try {
|
||||
String attrName = MapperHelper.getAttrName(c);
|
||||
if (attrName != null){
|
||||
log.setBizKey(log.getRequestParam(attrName));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试获取标注为@ModelAttribute注解的方法,第一个参数名一般为主键名
|
||||
if (StringUtils.isBlank(log.getBizKey())){
|
||||
for (Method me : hm.getBeanType().getMethods()){
|
||||
ModelAttribute ma = AnnotationUtils.findAnnotation(me, ModelAttribute.class);
|
||||
if(ma != null){
|
||||
String[] ps = pnd.getParameterNames(me);
|
||||
if(ps != null && ps.length > 0){
|
||||
log.setBizKey(StringUtils.abbr(log.getRequestParam(ps[0]), 64));
|
||||
log.setBizType(me.getReturnType().getSimpleName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.setLogTitle(Static.menuService.getMenuNamePath(log.getRequestUri(), permission));
|
||||
}
|
||||
if (StringUtils.isBlank(log.getLogTitle())){
|
||||
log.setLogTitle("未知操作");
|
||||
}
|
||||
// 如果有异常,设置异常信息(将异常对象转换为字符串)
|
||||
log.setExceptionInfo(throwable != null ? Global.YES : Global.NO);
|
||||
log.setExceptionInfo(ExceptionUtils.getStackTraceAsString(throwable));
|
||||
// 如果无地址并无异常日志,则不保存信息
|
||||
if (StringUtils.isBlank(log.getRequestUri()) && StringUtils.isBlank(log.getExceptionInfo())){
|
||||
return;
|
||||
}
|
||||
// 保存日志信息
|
||||
log.setIsNewRecord(true);
|
||||
Static.logService.insertLog(log);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,9 +56,6 @@ jdbc:
|
||||
# 最大连接数
|
||||
maxActive: 20
|
||||
|
||||
# 表名前缀
|
||||
tablePrefix: js_
|
||||
|
||||
# # 多数数据源名称列表,调用方式:DataSourceHolder.setDataSourceName("ds2")
|
||||
# dataSourceNames: ds2
|
||||
#
|
||||
@@ -69,13 +66,23 @@ jdbc:
|
||||
# url: jdbc:oracle:thin:@127.0.0.1:1521/orcl
|
||||
# username: jeesite
|
||||
# password: jeesite
|
||||
# encryptUsername: false
|
||||
# encryptPassword: true
|
||||
# testSql: ~
|
||||
# encrypt:
|
||||
# username: false
|
||||
# password: true
|
||||
# pool:
|
||||
# init: 1
|
||||
# minIdle: 3
|
||||
# maxActive: 20
|
||||
|
||||
# 表名前缀
|
||||
tablePrefix: js_
|
||||
|
||||
# Druid连接池监控
|
||||
druid:
|
||||
stat:
|
||||
enabled: true
|
||||
|
||||
# Redis 配置
|
||||
redis:
|
||||
|
||||
@@ -353,11 +360,25 @@ web:
|
||||
# 后台管理日志记录拦截器
|
||||
log:
|
||||
enabled: true
|
||||
addPathPatterns: >
|
||||
${adminPath}/**
|
||||
excludePathPatterns: >
|
||||
${adminPath}/index,
|
||||
${adminPath}/login,
|
||||
${adminPath}/**/listData,
|
||||
${adminPath}/**/treeData,
|
||||
${adminPath}/file/**,
|
||||
${adminPath}/tags/*,
|
||||
${adminPath}/sys/log/**,
|
||||
${adminPath}/sys/online/count
|
||||
|
||||
# 前台自动切换到手机视图拦截器
|
||||
mobile:
|
||||
enabled: false
|
||||
|
||||
addPathPatterns: >
|
||||
${frontPath}/**
|
||||
excludePathPatterns: ~
|
||||
|
||||
# 静态文件后缀,过滤静态文件,以提高访问性能。
|
||||
staticFile: .css,.js,.map,.png,.jpg,.gif,.jpeg,.bmp,.ico,.swf,.psd,.htc,.crx,.xpi,.exe,.ipa,.apk,.otf,.eot,.svg,.ttf,.woff,.woff2
|
||||
|
||||
|
||||
@@ -15,5 +15,6 @@
|
||||
<logger name="com.jeesite.common.io.FileUtils" level="INFO" />
|
||||
<logger name="com.jeesite.common.cache.JedisUtils" level="INFO" />
|
||||
<logger name="com.jeesite.common.web.view.JstlView" level="INFO" />
|
||||
<logger name="com.jeesite.modules.job.service.JobService" level="INFO" />
|
||||
|
||||
</included>
|
||||
Reference in New Issue
Block a user