首先spring记录日志我所知道的有两种,一种是通过AOP,另一种是通过拦截器interceptor,我这次选择的是拦截器interceptor:
1.spring-mvc.xml文件中配置拦截器,
<!-- 装配拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**/*.do"/>
<bean class="com.zhph.sys.interceptors.LogInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
新建一个拦截器,
package com.zhph.sys.interceptors;
import com.zhph.base.utils.Utils;
import com.zhph.sys.entity.LogEntity;
import com.zhph.sys.entity.UserEntity;
import com.zhph.sys.service.LogService;
import com.zhph.sys.utils.JsonUtil;
import com.zhph.sys.utils.UserUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.Map;
/**
*日志
* Created by Administrator on 2017/3/16.
*/
public class LogInterceptor implements HandlerInterceptor {//,AfterReturningAdvice
@Autowired
LogService logService;
private Logger logger = LoggerFactory.getLogger(getClass());
/**
* 请求处理之前进行调用
* @param request
* @param httpServletResponse
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler) throws Exception {
return true;
}
/**
* 当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用,
* 所以我们可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。
* @param request
* @param httpServletResponse
* @param handler
* @param modelAndView
* @throws Exception
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception {
}
/**
* 获取Ip地址
* @param request
* @return
*/
public String getIpAddr(HttpServletRequest request) {
String ip = request.getHeader( " x-forwarded-for " );
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getHeader( " Proxy-Client-IP " );
}
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getHeader( " WL-Proxy-Client-IP " );
}
if (ip == null || ip.length() == 0 || " unknown " .equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
/**
* 将ErrorStack转化为String.
*/
public static String getStackTraceAsString(Throwable e) {
if (e == null){
return "";
}
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
/**
* 该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。
* 这个方法的主要作用是用于进行资源清理工作的
* @param request
* @param response
* @param handler
* @param e
* @throws Exception
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {
try {
HandlerMethod handler2=(HandlerMethod) handler;
Log log = handler2.getMethod().getAnnotation(Log.class);
if(null !=log){
//获取操作系统等信息
StringBuffer sb=new StringBuffer();
sb.append("操作系统名称:"+System.getProperty("os.name"));//操作系统名称
sb.append("操作系统构架"+System.getProperty("os.arch"));//操作系统构架
sb.append("操作系统版本"+System.getProperty("os.version"));//操作系统版本
LogEntity logEntity=new LogEntity();
UserEntity loginUser = UserUtils.getLoginUser();
Map<String, String[]> map = request.getParameterMap();
String jsonData = JsonUtil.getJsonByObj(map);
logEntity.setId(Utils.uuid());
logEntity.setCreateBy(loginUser.getId());
logEntity.setCreateDate(new Date());
logEntity.setType(log.operation());
logEntity.setRequestUrl(request.getRequestURI());
logEntity.setRemoteAddr(getIpAddr(request));
logEntity.setTitle(log.title());
logEntity.setUserAgent(sb.toString());
//logEntity.setRemoteAddr(request.getRemoteAddr());
logEntity.setMethod(request.getMethod());
logEntity.setParams(jsonData);
//如果controller报错,则记录异常错误
if(e != null){
logEntity.setException(getStackTraceAsString(e));
}
try {
logService.insert(logEntity);
logger.info("log create a new log ======",logEntity);
}catch (Exception e1){
logger.info("fail to save operation log ", e1);
}
}
}catch (Exception el){
el.printStackTrace();
}
}
}
3.再新建一个自定义日志注解类,
package com.zhph.sys.interceptors;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
/**
* 删除
*/
String OPERA_TYPE_DEL="0";
/**
* 新增/修改
*/
String OPERA_TYPE_EDIT="1";
/**
* 查看
*/
String OPERA_TYPE_SELECT="2";
public String operation() default Log.OPERA_TYPE_EDIT;
public String title() ;
//public String ext() default "";
}
4,现在就可以在controller层使用日志注解类了,
总结,现在这个拦截器,还有不足之处就是,如果方法报异常,能捕获到try catch不能捕获的异常
由于平时很少写博客,写的很差,请多见谅。
这里推荐下我的开源项目:
hxyFrame是一个OA办公系统,采用流行的框架springMvc+spring+mybatis+shiro+ehcache开发,还集成了权限管理(菜单权限、数据权限),完善的代码生成器,solr全文搜索引擎,activiti工作流程引擎,cas单点登陆等功能,后期还会考虑改造成Dubbo微服务化,做到模块的相对独立,使用更加灵活,努力做到快速开发OA办公系统。 感兴趣可以Watch、Start持续关注项目最新状态,加入QQ群:210315502
oschina仓库:https://git.oschina.net/huangxianyuan/hxyFrame.git
github仓库:https://github.com/huangxianyuan/hxyFrame.git