1,spring配置文件
<bean class="com.able.aop.LogAspect" id="logAspect"/>
<aop:config>
<aop:aspect id="serviceMonitor" ref="logAspect">
<aop:pointcut expression="execution(* com.able.controller.*.*(..))" id="servicePointcut" />
<aop:around method="doAroundMethodLog" pointcut-ref="servicePointcut"/>
</aop:aspect>
</aop:config>
2,日志拦截类
public class LogAspect {
private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
@Autowired
private HttpServletRequest request;
@Autowired
private UserOperatLogService userOperatLogService;
@Autowired
private TokenService tokenService;
/**
* 标注该方法体为环绕通知,当目标方法执行时执行该方法体
*/
public Object doAroundMethodLog(ProceedingJoinPoint jp) throws Throwable{
StopWatch stopWatch = new StopWatch(); //记录方法执行耗时
stopWatch.start();
Object retVal = null;
try{
retVal = jp.proceed();
}catch (Throwable e){
e.printStackTrace();
logger.error(e.getMessage());
retVal = new ResponseEntity(new RestResult(e.getMessage(),false), HttpStatus.OK);
}finally {
stopWatch.stop();
insertOpertLog(jp, stopWatch);
}
return retVal;
}
private void insertOpertLog(ProceedingJoinPoint jp, StopWatch stopWatch) {
Class<? extends Object> classD=jp.getTarget().getClass();
String className = classD.getName();
MethodSignature joinPointObject = (MethodSignature) jp.getSignature();
Method method = joinPointObject.getMethod();
String methodName = method.getName();
if(!jp.getTarget().getClass().isAnnotationPresent(NoLog.class)&&!method.isAnnotationPresent(NoLog.class)){
String params = parseParames(jp.getArgs()); //解析目标方法体的参数
UserOperatLog userOperatLog=new UserOperatLog();
userOperatLog.setIpAddr(request.getRemoteAddr());
userOperatLog.setActionUrl(request.getRequestURI());
userOperatLog.setTimeLong(stopWatch.getTotalTimeMillis()+"");
ShiroUser shiroUser = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
if(shiroUser!=null){
userOperatLog.setUserId(shiroUser.getZhsId());
userOperatLog.setUserName(shiroUser.getRealName());
}else{
String tokenCode=request.getParameter("tokenCode")==null?"":request.getParameter("tokenCode");
if(tokenCode!=null && !"".equals(tokenCode)){
Token token = new Token();
token.setTokenCode(tokenCode);
List<Token> list =tokenService.selectBySelective(token);
if(list != null && list.size() > 0){
token=list.get(0);
userOperatLog.setUserId(token.getUserId());
userOperatLog.setUserName(token.getRealName());
}
}
}
Function fd = null;
Operate md = null;
if(classD.isAnnotationPresent(Function.class)){
fd = classD.getAnnotation(Function.class);
}
if(method.isAnnotationPresent(Operate.class)){
md =method.getAnnotation(Operate.class);
}
if(fd!=null){
userOperatLog.setMean(fd.value());
userOperatLog.setModule(fd.moduleName());
userOperatLog.setSubModule(fd.subModuleName());
}
if(md!=null){
userOperatLog.setFunction(md.value());
}
userOperatLog.setParamData(params);
userOperatLog.setCreateTime(DateUtil.getTimeStamp());
logger.info("业务处理"+",模块:["+(fd!=null?fd.moduleName():"")+"],操作:["+(md!=null?md.value():"")+"],调用类名称:["+className+"],调用方法名称:["+methodName+"],参数为:" + params + ";耗时" + stopWatch.getTotalTimeMillis() + "毫秒");
userOperatLogService.insertBySelective(userOperatLog);
//userOperatLogService.testasy();
logger.info("执行完毕=======");
}
}
3,自定义注解三个
功能模块注解
/**
* 每个类的功能描述
* @author zhangqh
* @date 2016-8-2 下午01:03:59
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface Function {
String value() default "";
String moduleName() default "";
String subModuleName() default "";
}
操作方法注解
/**
* 方法描述
* @author zhangqh
* @date 2016-8-2 下午12:55:25
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Operate {
String value() default "";
}
不需要记录日志的注解
/**
* 免记录日志注解标识
* @author wjhu
* @date 2016-8-2 下午01:03:59
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
public @interface NoLog {
}
4,controller中记录操作日志的使用
/**
* @Function注解为对应的操作日志模块
* @author zhangqh
*
*/
@Controller
@RequestMapping("/test")
@Function(value ="测试模块",moduleName = "测试模块",subModuleName = "")
public class test {
/**
* 会记录对应的操作说明
*/
@Operate(value="操作")
public void aa(){
}
/**
* 使用@NoLog注解就不是记录该方法的操作日志了
*/
@NoLog
public void bb(){
}
}
提示:如果记录日志要持久化到数据库的话,建议入库操作加上异步操作这样对性能会提升不少
spring对异步调用方法支持也比较好 配置也比较简单,只需要要在配置文件中加入
<!-- 支持异步加载 -->
<task:annotation-driven/>
就可以了,然后使用的方法上加上@Async就可以了