Commit d32a3558 by fsn

日志记录添加业务日志记录,并改为线程池记录方式

parent 4904f5a5
package com.stylefeng.guns.common.annotion.log;
import java.lang.annotation.*;
/**
* 标记需要做业务日志的方法
*
* @author fengshuonan
* @date 2017-03-31 12:46
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface BussinessLog {
String value() default "";
}
package com.stylefeng.guns.common.annotion.log;
import java.lang.annotation.*;
/**
* 标记保存编辑操作之前的controller方法
*
* @author fengshuonan
* @date 2017-03-31 9:37
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface LogBefore {
}
......@@ -4,8 +4,8 @@ import com.stylefeng.guns.common.constant.tips.ErrorTip;
import com.stylefeng.guns.common.exception.BizExceptionEnum;
import com.stylefeng.guns.common.exception.BussinessException;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.log.factory.LogTaskFactory;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.support.HttpKit;
import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.CredentialsException;
......@@ -16,8 +16,9 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.naming.NoPermissionException;
import static com.stylefeng.guns.core.support.HttpKit.getIp;
import static com.stylefeng.guns.core.support.HttpKit.getRequest;
/**
* 全局的的异常拦截器(拦截所有的控制器)(带有@RequestMapping注解的方法上都会拦截)
......@@ -39,8 +40,8 @@ public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorTip notFount(BussinessException e) {
LogManager.exceptionLog(ShiroKit.getUser().getId(), e);
HttpKit.getRequest().setAttribute("tip", e.getMessage());
LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
getRequest().setAttribute("tip", e.getMessage());
return new ErrorTip(e.getCode(), e.getMessage());
}
......@@ -53,8 +54,8 @@ public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorTip notFount(RuntimeException e) {
LogManager.exceptionLog(ShiroKit.getUser().getId(), e);
HttpKit.getRequest().setAttribute("tip", "服务器未知运行时异常");
LogManager.me().executeLog(LogTaskFactory.exceptionLog(ShiroKit.getUser().getId(), e));
getRequest().setAttribute("tip", "服务器未知运行时异常");
return new ErrorTip(BizExceptionEnum.SERVER_ERROR);
}
......@@ -78,8 +79,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(DisabledAccountException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public String accountLocked(DisabledAccountException e, Model model) {
String username = HttpKit.getRequest().getParameter("username");
LogManager.loginLog(username,"账号被冻结");
String username = getRequest().getParameter("username");
LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号被冻结", getIp()));
model.addAttribute("tips", "账号被冻结");
return "/login.html";
}
......@@ -92,8 +93,8 @@ public class GlobalExceptionHandler {
@ExceptionHandler(CredentialsException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public String credentials(CredentialsException e, Model model) {
String username = HttpKit.getRequest().getParameter("username");
LogManager.loginLog(username,"账号密码错误");
String username = getRequest().getParameter("username");
LogManager.me().executeLog(LogTaskFactory.loginLog(username, "账号密码错误", getIp()));
model.addAttribute("tips", "账号密码错误");
return "/login.html";
}
......@@ -107,7 +108,7 @@ public class GlobalExceptionHandler {
@ResponseStatus(HttpStatus.UNAUTHORIZED)
@ResponseBody
public ErrorTip credentials(NoPermissionException e, Model model) {
HttpKit.getRequest().setAttribute("tip", "权限异常");
getRequest().setAttribute("tip", "权限异常");
return new ErrorTip(BizExceptionEnum.NO_PERMITION);
}
......
package com.stylefeng.guns.core.aop;
import com.stylefeng.guns.common.annotion.log.BussinessLog;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.log.factory.LogTaskFactory;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.support.StrKit;
......@@ -28,7 +30,7 @@ public class LogAop {
private Logger log = Logger.getLogger(this.getClass());
@Pointcut("execution(* com.stylefeng.guns..service.*.*(..))")
@Pointcut(value = "@annotation(com.stylefeng.guns.common.annotion.log.BussinessLog)")
public void cutService() {
}
......@@ -50,6 +52,10 @@ public class LogAop {
String className = point.getTarget().getClass().getName();
Object[] params = point.getArgs();
//获取操作名称
BussinessLog annotation = method.getAnnotation(BussinessLog.class);
String bussinessName = annotation.value();
StringBuilder sb = new StringBuilder();
for (Object param : params) {
sb.append(param);
......@@ -59,7 +65,7 @@ public class LogAop {
String msg = ToolUtil.format("[时间]:{} [类名]:{} [方法]:{} [参数]:{}", DateUtil.getTime(), className, methodName, sb.toString());
msg = StrKit.removeSuffix(msg, "& ");
log.info(msg);
LogManager.bussinessLog(user.getId(),className,methodName,msg);
LogManager.me().executeLog(LogTaskFactory.bussinessLog(user.getId(),bussinessName,className,methodName,msg));
return point.proceed();
}
}
\ No newline at end of file
package com.stylefeng.guns.core.log;
import java.util.HashMap;
/**
* 方法名和具体日志记录名称的映射管理
*
* @author fengshuonan
* @date 2017-03-30 19:22
*/
public class ConcreteLogNameHolder {
private HashMap<String, String> mapping = new HashMap<>();
private void init(){
mapping.put("setAuthority","分配角色权限");
}
private ConcreteLogNameHolder() {
init();
}
private static ConcreteLogNameHolder holder = new ConcreteLogNameHolder();
public static ConcreteLogNameHolder me(){
return holder;
}
public String get(String key){
return mapping.get(key);
}
}
package com.stylefeng.guns.core.log;
import com.stylefeng.guns.common.constant.state.LogType;
import com.stylefeng.guns.core.db.Db;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.persistence.dao.LoginLogMapper;
import com.stylefeng.guns.persistence.dao.OperationLogMapper;
import com.stylefeng.guns.persistence.model.LoginLog;
import com.stylefeng.guns.persistence.model.OperationLog;
import org.apache.log4j.Logger;
import java.util.TimerTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* 日志管理器
......@@ -17,54 +12,22 @@ import org.apache.log4j.Logger;
*/
public class LogManager {
private static Logger logger = Logger.getLogger(LogManager.class);
private static LoginLogMapper loginLogMapper = Db.getMapper(LoginLogMapper.class);
private static OperationLogMapper operationLogMapper = Db.getMapper(OperationLogMapper.class);
//日志记录操作延时
private final int OPERATE_DELAY_TIME = 10;
public static void loginLog(Integer userId) {
LoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null);
try {
loginLogMapper.insert(loginLog);
} catch (Exception e) {
logger.error("创建登录日志异常!", e);
}
}
//异步操作记录日志的线程池
private ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
public static void loginLog(String username, String msg) {
LoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN_FAIL, null, "账号:" + username + "," + msg);
try {
loginLogMapper.insert(loginLog);
} catch (Exception e) {
logger.error("创建登录失败异常!", e);
}
private LogManager() {
}
public static void exitLog(Integer userId) {
LoginLog loginLog = LogFactory.createLoginLog(LogType.EXIT, userId, null);
try {
loginLogMapper.insert(loginLog);
} catch (Exception e) {
logger.error("创建退出日志异常!", e);
}
}
public static LogManager logManager = new LogManager();
public static void bussinessLog(Integer userId, String clazzName, String methodName, String msg) {
OperationLog operationLog = LogFactory.createOperationLog(LogType.BUSSINESS, userId, clazzName, methodName, msg);
try {
operationLogMapper.insert(operationLog);
} catch (Exception e) {
logger.error("创建业务日志异常!", e);
}
public static LogManager me() {
return logManager;
}
public static void exceptionLog(Integer userId, Exception exception) {
String msg = ToolUtil.getExceptionMsg(exception);
OperationLog operationLog = LogFactory.createOperationLog(LogType.EXCEPTION, userId, null, null, msg);
try {
operationLogMapper.insert(operationLog);
} catch (Exception e) {
logger.error("创建异常日志异常!", e);
public void executeLog(TimerTask task) {
executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
}
}
}
package com.stylefeng.guns.core.log;
import com.stylefeng.guns.core.util.SpringContextHolder;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;
/**
* 被修改的bean临时存放的地方
*
* @author fengshuonan
* @date 2017-03-31 11:19
*/
@Component
@Scope(scopeName = WebApplicationContext.SCOPE_SESSION)
public class LogObjectHolder {
private Object object = null;
public void set(Object obj) {
this.object = obj;
}
public Object get() {
return object;
}
public static LogObjectHolder me(){
LogObjectHolder bean = SpringContextHolder.getBean(LogObjectHolder.class);
return bean;
}
}
package com.stylefeng.guns.core.log;
package com.stylefeng.guns.core.log.factory;
import com.stylefeng.guns.common.constant.state.LogSucceed;
import com.stylefeng.guns.common.constant.state.LogType;
import com.stylefeng.guns.core.support.HttpKit;
import com.stylefeng.guns.persistence.model.LoginLog;
import com.stylefeng.guns.persistence.model.OperationLog;
......@@ -22,15 +21,15 @@ public class LogFactory {
* @author fengshuonan
* @Date 2017/3/30 18:45
*/
public static OperationLog createOperationLog(LogType logType, Integer userId, String clazzName, String methodName, String msg) {
public static OperationLog createOperationLog(LogType logType, Integer userId, String bussinessName, String clazzName, String methodName, String msg, LogSucceed succeed) {
OperationLog operationLog = new OperationLog();
operationLog.setLogtype(logType.getMessage());
operationLog.setLogname(ConcreteLogNameHolder.me().get(methodName));
operationLog.setLogname(bussinessName);
operationLog.setUserid(userId);
operationLog.setClassname(clazzName);
operationLog.setMethod(methodName);
operationLog.setCreatetime(new Date());
operationLog.setSucceed(LogSucceed.SUCCESS.getMessage());
operationLog.setSucceed(succeed.getMessage());
operationLog.setMessage(msg);
return operationLog;
}
......@@ -41,13 +40,13 @@ public class LogFactory {
* @author fengshuonan
* @Date 2017/3/30 18:46
*/
public static LoginLog createLoginLog(LogType logType, Integer userId, String msg) {
public static LoginLog createLoginLog(LogType logType, Integer userId, String msg,String ip) {
LoginLog loginLog = new LoginLog();
loginLog.setLogname(logType.getMessage());
loginLog.setUserid(userId);
loginLog.setCreatetime(new Date());
loginLog.setSucceed(LogSucceed.SUCCESS.getMessage());
loginLog.setIp(HttpKit.getRequest().getRemoteHost());
loginLog.setIp(ip);
loginLog.setMessage(msg);
return loginLog;
}
......
package com.stylefeng.guns.core.log.factory;
import com.stylefeng.guns.common.constant.state.LogSucceed;
import com.stylefeng.guns.common.constant.state.LogType;
import com.stylefeng.guns.core.db.Db;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.persistence.dao.LoginLogMapper;
import com.stylefeng.guns.persistence.dao.OperationLogMapper;
import com.stylefeng.guns.persistence.model.LoginLog;
import com.stylefeng.guns.persistence.model.OperationLog;
import org.apache.log4j.Logger;
import java.util.TimerTask;
/**
* 日志操作任务创建工厂
*
* @author fengshuonan
* @date 2016年12月6日 下午9:18:27
*/
public class LogTaskFactory {
private static Logger logger = Logger.getLogger(LogManager.class);
private static LoginLogMapper loginLogMapper = Db.getMapper(LoginLogMapper.class);
private static OperationLogMapper operationLogMapper = Db.getMapper(OperationLogMapper.class);
public static TimerTask loginLog(Integer userId, String ip) {
return new TimerTask() {
@Override
public void run() {
try {
LoginLog loginLog = LogFactory.createLoginLog(LogType.LOGIN, userId, null, ip);
loginLogMapper.insert(loginLog);
} catch (Exception e) {
logger.error("创建登录日志异常!", e);
}
}
};
}
public static TimerTask loginLog(String username, String msg, String ip) {
return new TimerTask() {
@Override
public void run() {
LoginLog loginLog = LogFactory.createLoginLog(
LogType.LOGIN_FAIL, null, "账号:" + username + "," + msg, ip);
try {
loginLogMapper.insert(loginLog);
} catch (Exception e) {
logger.error("创建登录失败异常!", e);
}
}
};
}
public static TimerTask exitLog(Integer userId,String ip) {
return new TimerTask() {
@Override
public void run() {
LoginLog loginLog = LogFactory.createLoginLog(LogType.EXIT, userId, null,ip);
try {
loginLogMapper.insert(loginLog);
} catch (Exception e) {
logger.error("创建退出日志异常!", e);
}
}
};
}
public static TimerTask bussinessLog(Integer userId, String bussinessName, String clazzName, String methodName, String msg) {
return new TimerTask() {
@Override
public void run() {
OperationLog operationLog = LogFactory.createOperationLog(
LogType.BUSSINESS, userId, bussinessName, clazzName, methodName, msg, LogSucceed.SUCCESS);
try {
operationLogMapper.insert(operationLog);
} catch (Exception e) {
logger.error("创建业务日志异常!", e);
}
}
};
}
public static TimerTask exceptionLog(Integer userId, Exception exception) {
return new TimerTask() {
@Override
public void run() {
String msg = ToolUtil.getExceptionMsg(exception);
OperationLog operationLog = LogFactory.createOperationLog(
LogType.EXCEPTION, userId, "", null, null, msg, LogSucceed.FAIL);
try {
operationLogMapper.insert(operationLog);
} catch (Exception e) {
logger.error("创建异常日志异常!", e);
}
}
};
}
}
/**
* Copyright (c) 2015-2016, Chill Zhuang 庄骞 (smallchill@163.com).
*
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
*
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
......@@ -15,22 +15,42 @@
*/
package com.stylefeng.guns.core.support;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class HttpKit {
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
public static String getIp(){
return HttpKit.getRequest().getRemoteHost();
}
public class HttpKit {
/**
* 获取所有请求的值
*/
public static Map<String, String> getRequestParameters() {
HashMap<String, String> values = new HashMap<>();
HttpServletRequest request = HttpKit.getRequest();
Enumeration enums = request.getParameterNames();
while ( enums.hasMoreElements()){
String paramName = (String) enums.nextElement();
String paramValue = request.getParameter(paramName);
values.put(paramName, paramValue);
}
return values;
}
/**
* 获取 HttpServletRequest
......
package com.stylefeng.guns.core.util;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 对比两个对象的变化的工具类
*
* @author fengshuonan
* @Date 2017/3/31 10:36
*/
public class Contrast {
//记录每个修改字段的分隔符
public static final String separator = ";;;";
public static String contrastObj(Object pojo1, Object pojo2) {
String str = "";
try {
Class clazz = pojo1.getClass();
Field[] fields = pojo1.getClass().getDeclaredFields();
int i = 1;
for (Field field : fields) {
if ("serialVersionUID".equals(field.getName())) {
continue;
}
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
Method getMethod = pd.getReadMethod();
Object o1 = getMethod.invoke(pojo1);
Object o2 = getMethod.invoke(pojo2);
if (o1 == null || o2 == null) {
continue;
}
if (!o1.toString().equals(o2.toString())) {
if (i != 1) {
str += separator;
}
str += "字段名称" + field.getName() + ",旧值:" + o1 + ",新值:" + o2;
i++;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return str;
}
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ package com.stylefeng.guns.modular.system.controller;
import com.stylefeng.guns.common.controller.BaseController;
import com.stylefeng.guns.common.node.MenuNode;
import com.stylefeng.guns.core.log.LogManager;
import com.stylefeng.guns.core.log.factory.LogTaskFactory;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.modular.system.dao.MenuDao;
......@@ -16,6 +17,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
import static com.stylefeng.guns.core.support.HttpKit.getIp;
/**
* 登录控制器
*
......@@ -71,7 +74,7 @@ public class LoginController extends BaseController {
ShiroUser shiroUser = ShiroKit.getUser();
super.getSession().setAttribute("shiroUser", shiroUser);
LogManager.loginLog(shiroUser.getId());
LogManager.me().executeLog(LogTaskFactory.loginLog(shiroUser.getId(), getIp()));
return REDIRECT + "/";
}
......@@ -81,7 +84,7 @@ public class LoginController extends BaseController {
*/
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logOut() {
LogManager.exitLog(ShiroKit.getUser().getId());
LogManager.me().executeLog(LogTaskFactory.exitLog(ShiroKit.getUser().getId(), getIp()));
ShiroKit.getSubject().logout();
super.getSession().invalidate();
return REDIRECT + "/login";
......
......@@ -8,6 +8,8 @@ import com.stylefeng.guns.common.controller.BaseController;
import com.stylefeng.guns.common.exception.BizExceptionEnum;
import com.stylefeng.guns.common.exception.BussinessException;
import com.stylefeng.guns.common.node.ZTreeNode;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.util.Contrast;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.modular.system.dao.MenuDao;
import com.stylefeng.guns.modular.system.warpper.MenuWarpper;
......@@ -48,7 +50,6 @@ public class MenuController extends BaseController {
*/
@RequestMapping("")
public String index() {
return PREFIX + "menu.html";
}
......@@ -61,7 +62,7 @@ public class MenuController extends BaseController {
}
/**
* 跳转到菜单列表列表页面
* 跳转到菜单详情列表页面
*/
@RequestMapping(value = "/menu_edit/{menuId}")
public String menuEdit(@PathVariable Integer menuId, Model model) {
......@@ -69,6 +70,9 @@ public class MenuController extends BaseController {
throw new BussinessException(BizExceptionEnum.REQUEST_NULL);
}
Menu menu = this.menuMapper.selectById(menuId);
LogObjectHolder.me().set(menu);
model.addAttribute(menu);
return PREFIX + "menu_edit.html";
}
......@@ -121,6 +125,11 @@ public class MenuController extends BaseController {
if (result.hasErrors()) {
throw new BussinessException(BizExceptionEnum.REQUEST_NULL);
}
Object obj1 = LogObjectHolder.me().get();
Object obj2 = menu;
System.out.println(Contrast.contrastObj(obj1,obj2));
this.menuMapper.updateById(menu);
return SUCCESS_TIP;
}
......
package com.stylefeng.guns.modular.system.service.impl;
import com.stylefeng.guns.common.annotion.log.BussinessLog;
import com.stylefeng.guns.core.util.Convert;
import com.stylefeng.guns.modular.system.dao.RoleDao;
import com.stylefeng.guns.modular.system.service.IRoleService;
......@@ -20,6 +21,7 @@ public class RoleServiceImpl implements IRoleService {
RelationMapper relationMapper;
@Override
@BussinessLog("分配角色权限")
@Transactional(readOnly = false)
public void setAuthority(Integer roleId, String ids) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment