澳门新蒲京娱乐

图片 6
HTTP协议简介详解

5的简单步骤

Aspect基于spingmvc自定义表明完结操作记录,操作日志记录

  现在做的种类中用到了日志记录效能,整理了1晃,发出去,也是做个记录:连锁jar包百度云下载

1.存在的意思

 
所日志记录,正是记录全体的操作,使管理者对这么些系统的流转了若指掌,同时假诺系统出现了难题,也得以精晓找到难题的四方。

  一.自定义表明类  SystemControllerLog.java

2. 分界面突显

 图片 1

  图片 2图片 3

三. 首要代码深入分析(提供二种方法)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 自定义注解 拦截Controller
 * 
 * @author Administrator
 *
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemControllerLog {
    /**
     * 描述业务操作 例:Xxx管理-执行Xxx操作
     * @return
     */
    String description() default "";
}

  3.1 方法一 使用aop实现

图片 4

 

源码介绍:

01.首先在承接保险你的条件不利的情景下(作者用的是ssh)

0二.BussAnnotation.java  (自定义评释)

图片 5图片 6

package cn.bdqn.annotation;

/**
 * 自定义注解(用于记录日志)
 */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface BussAnnotation {
    // 模块名
    String moduleName();
    // 操作内容 
    String option();
}

View Code

0叁.LogBeforeAdvice.java (前置巩固)—首要记录的点子

图片 7图片 8

package cn.bdqn.aop;
/**
 * aop前置增强结合自定义注解实现记录日志
 */
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.struts2.ServletActionContext;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.bdqn.annotation.BussAnnotation;
import cn.bdqn.base.BaseService;
import cn.bdqn.entity.PSUser;
import cn.bdqn.entity.PsLogs;
import cn.bdqn.service.IPsLogsService;

public class LogBeforeAdvice implements MethodBeforeAdvice{

     public void before(Method method, Object[] args, Object target)   
                throws Throwable {  
            // 拿到我们的service对象
            ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
            IPsLogsService bean = (IPsLogsService)context.getBean("pslsi");
            //注解,拿到类型的元数据
            BussAnnotation ol = method.getAnnotation(BussAnnotation.class);
            if (ol!=null) {
                 System.out.println(ol.moduleName()+"\t"+ol.option());
                 //判断是否
                 PSUser user=(PSUser)ServletActionContext.getRequest().getSession().getAttribute("loginuserinfo");
                 PsLogs logs=new PsLogs();
                 if(user==null){//在登录的时候记录登录信息
                     String userCode = ServletActionContext.getRequest().getParameter("userCode");//登录界面的值
                     System.out.println(userCode);
                     //赋值并保存
                     SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                     Date date = sdf.parse(sdf.format(new Date()));
                     logs.setOperateInfo(ol.option());
                     logs.setOperateDatetime(date);
                     logs.setUserCode(userCode);
                     ((BaseService<PsLogs>) bean).save(logs);
                 }else{//登录后,直接记录我们自定义注解中指定的信息
                     //赋值并保存
                     SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                     Date date = sdf.parse(sdf.format(new Date()));
                     logs.setOperateInfo(ol.option());
                     logs.setOperateDatetime(date);
                     logs.setUserCode(user.getUserCode());
                     ((BaseService<PsLogs>) bean).save(logs);

                 }
            }

        }    

}

View Code

0四.XXXAction.java (Action类中应用自定义注明完毕记录)

图片 9图片 10

        /*
     * 用于登录
     */
    @BussAnnotation(moduleName="用户登录",option="登录")
    public String login() {

          //关键代码

       return SUCCESS;
    }

View Code

05.applicationContext.xml (配置aop)

图片 11图片 12

<!-- aop结合自定义注解实现日志记录 -->
    <bean name="logBefore" class="cn.bdqn.aop.LogBeforeAdvice"></bean>
    <aop:config proxy-target-class="true">
        <aop:pointcut expression="execution(* *..action.*.*(..))"
            id="pointcut" />
        <aop:advisor advice-ref="logBefore" pointcut-ref="pointcut" />
    </aop:config>

View Code

View Code

  3.二 方法2  使用过滤器完毕

图片 13

源码介绍:

01.FunctionFilter.java (过滤器)—首要记录的法子

图片 14图片 15

package cn.bdqn.filter;
/** 
 * 用于记录操作日志的过滤器类(方法二)
 */
import java.io.IOException;
import java.util.Date;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 */
import cn.bdqn.entity.PSFunction;
import cn.bdqn.entity.PSRole;
import cn.bdqn.entity.PSUser;
import cn.bdqn.entity.PsLogs;
import cn.bdqn.service.IPsLogsService;


public class FunctionFilter implements Filter {
    public void destroy() {

    }
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        System.out.println("用于记录操作日志的过滤器类");
        HttpServletRequest req=(HttpServletRequest)request;
        String url=req.getRequestURI();
        System.out.println(url);
        //过滤掉所有静态资源,不做处理
        if (url.endsWith(".js")) {
            chain.doFilter(request, response);
        } 
        if (url.endsWith(".css")) {
            chain.doFilter(request, response);
        } 
        if (url.endsWith(".html")) {
            chain.doFilter(request, response);
        } 
        if (url.endsWith(".txt")) {
            chain.doFilter(request, response);
        } 
        if (url.endsWith(".gif")) {
            chain.doFilter(request, response);
        } 
        if (url.endsWith(".jpg") || url.endsWith(".jpeg")) {
            chain.doFilter(request, response);
        } 
        if (url.endsWith(".png")) {
            chain.doFilter(request, response);
        }
        int pos=url.indexOf("?");
        if (pos>-1) {
            url=url.substring(0,pos); 
        }
        int actionindex=url.indexOf(".action");
        if(actionindex>-1){
            url=url.substring(0,actionindex);
        }
        int of = url.indexOf("/", 2);
        url=url.substring(of+1);

        System.out.println("url地址:"+url);
        //判断是否登录
        PSUser user=(PSUser)req.getSession().getAttribute("loginuserinfo");
        if(url.endsWith("login")||url.equals("")){
                chain.doFilter(request, response);
        }else if(user!=null){
            for (PSRole role : user.getRole()) {
                for (PSFunction function : role.getPsFunctions()) {
                    if(function.getFuncUrl().equals(url)){
                        PsLogs log=new PsLogs();
                        log.setOperateDatetime(new Date());
                        log.setOperateInfo(function.getFunctionName());
                        log.setUserCode(user.getUserCode());
                        //获取spring的上下文容器
                        ApplicationContext contex=new ClassPathXmlApplicationContext("applicationContext.xml");
                        //获取spring容器中定义的IRoleService对象实例用于查询角色信息
                        IPsLogsService logsService = contex.getBean(IPsLogsService.class,"pslsi");
                        logsService.save(log);
                        chain.doFilter(request, response);
                    }
                }
        }
        }else{
            HttpServletResponse resp=(HttpServletResponse) response;
            resp.setCharacterEncoding("utf-8");
            resp.getWriter().write("<script type='text/javascript'>alert('您没有该权限')</script>");
        }
    }


    public void init(FilterConfig arg0) throws ServletException {

    }

}

View Code

02.web.xml

图片 16图片 17

       <!-- 配置记录日志的过滤器(方法二) -->
     <filter>
        <filter-name>functionfilter</filter-name>
        <filter-class>cn.filter.FunctionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>functionfilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping> 

View Code  

  二.日志管理类 SystemLogAspect.java

  3.3 方法三  使用拦截器完结

源码介绍:

0壹.BussAnnotation.java  (自定义注脚)

图片 18图片 19

package cn.bdqn.annotation;

/**
 * 自定义注解(用于记录日志)
 */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface BussAnnotation {
    // 模块名
    String moduleName();
    // 操作内容 
    String option();
}

View Code

02.OperateLogIntercepter.java (自定义拦截器)—重要记录的方法

图片 20图片 21

package cn.bdqn.interceptor;
/**
 * 记录日志的拦截器(方法三)
 */

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.bdqn.annotation.BussAnnotation;
import cn.bdqn.base.BaseService;
import cn.bdqn.entity.PSUser;
import cn.bdqn.entity.PsLogs;
import cn.bdqn.service.IPsLogsService;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

public class OperateLogIntercepter extends AbstractInterceptor{

    private static final long serialVersionUID = 1L;

    private static final Log log=LogFactory.getLog(OperateLogIntercepter.class);


    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        /*Object bean = SpringContextHelper.getBean("psLogsService");*/

        System.out.println("日志拦截器已经开始启动");
        //获得service实例
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        IPsLogsService bean = (IPsLogsService)context.getBean("pslsi");

        Class<? extends Object> actionClass=invocation.getAction().getClass();
        String methodName=invocation.getProxy().getMethod();
        //获取当前方法
        Method currentMethod=actionClass.getMethod(methodName);
        boolean flag = currentMethod.isAnnotationPresent(BussAnnotation.class);
        if(flag){
            BussAnnotation ol=currentMethod.getAnnotation(BussAnnotation.class);
            PsLogs logs=new PsLogs();
            PSUser user=(PSUser)ServletActionContext.getRequest().getSession().getAttribute("loginuserinfo");
            if(user==null){//在登录的时候记录登录信息
                String userCode = ServletActionContext.getRequest().getParameter("userCode");
                System.out.println(userCode);
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = sdf.parse(sdf.format(new Date()));
                logs.setOperateInfo(ol.option());
                logs.setOperateDatetime(date);
                logs.setUserCode(userCode);
                ((BaseService<PsLogs>) bean).save(logs);
            }else{//登录后,直接记录我们自定义注解中指定的信息
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = sdf.parse(sdf.format(new Date()));
                logs.setOperateInfo(ol.option());
                logs.setOperateDatetime(date);
                logs.setUserCode(user.getUserCode());
                ((BaseService<PsLogs>) bean).save(logs);

            }

        }
        return invocation.invoke();
    }

    public static Log getLog() {
        return log;
    }
}

View Code

0三.XXXAction.java (Action类中运用自定义申明完成记录)

图片 22图片 23

        /*
     * 用于登录
     */
    @BussAnnotation(moduleName="用户登录",option="登录")
    public String login() throws Exception {

            //主要代码

          return SUCCESS;

    }

View Code

0四.struts.xml (使用拦截器)

图片 24图片 25

               <!-- 拦截器 -->
        <interceptors>
            <!-- 声明记录日志拦截器 -->
            <interceptor name="logs" class="cn.interceptor.OperateLogIntercepter"></interceptor>
            <!-- 配置一个拦截器栈 -->
            <interceptor-stack name="myStack">
                <!-- <interceptor-ref name="logs"></interceptor-ref> -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!--默认使用这个拦截器栈 -->
        <default-interceptor-ref name="myStack"></default-interceptor-ref>

View Code

 

  图片 26图片 27

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import com.zw.annotation.SystemControllerLog;
import com.zw.aop.SystemLogAspect;
import com.zw.model.Logs;
import com.zw.model.User;
import com.zw.service.LogsService;
import com.zw.util.AcquireIp;
import com.zw.util.DateUtils;

/**
 * 系统日志切面类
 * */
@Aspect
@Component
public class SystemLogAspect {
private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);

    private static final ThreadLocal<Date> beginTimeThreadLocal =
            new NamedThreadLocal<Date>("ThreadLocal beginTime");

    private static final ThreadLocal<Logs> logThreadLocal = 
            new NamedThreadLocal<Logs>("ThreadLocal log");

    private static final ThreadLocal<User> currentUser=new NamedThreadLocal<>("ThreadLocal authUser");

    @Resource
    private HttpServletRequest request;

    @Resource(name="logsServiceImpl")
    private LogsService logsService;
    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * Controller层切点 注解拦截
     */
    @Pointcut("@annotation(com.ht.annotation.SystemControllerLog)")
    public void controllerAspect(){}

    /**
     * 方法规则拦截
     */
    @Pointcut("execution(* com.ht.controller.*.*(..))")
    public void controllerPointerCut(){}

    /**
     * 前置通知 用于拦截Controller层记录用户的操作的开始时间
     * @param joinPoint 切点
     * @throws InterruptedException 
     */
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) throws InterruptedException{
        Date beginTime=new Date();
        beginTimeThreadLocal.set(beginTime);
        //debug模式下 显式打印开始时间用于调试
        if (logger.isDebugEnabled()){
            logger.debug("开始计时: {}  URI: {}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
                .format(beginTime), request.getRequestURI());
        }

        //读取session中的用户 
        HttpSession session = request.getSession();       

        User authUser = (User) session.getAttribute("user");
        currentUser.set(authUser);
    }

    /**
     * 后置通知 用于拦截Controller层记录用户的操作
     * @param joinPoint 切点
     */
    @After("controllerAspect()")
    public void doAfter(JoinPoint joinPoint) {
        User User = currentUser.get();
        //登入login操作 前置通知时用户未校验 所以session中不存在用户信息
        if(User == null){
            HttpSession session = request.getSession();       
            User = (User) session.getAttribute("user");    
            if(User==null){
                return;
            }
        }

        Object [] args = joinPoint.getArgs();
        System.out.println(args);

        String title="";
        String type="info";                          //日志类型(info:入库,error:错误)
        String remoteAddr=AcquireIp.getIP(request);//请求的IP
        String requestUri=request.getRequestURI();//请求的Uri
        String method=request.getMethod();          //请求的方法类型(post/get)
        Map<String,String[]> params=request.getParameterMap(); //请求提交的参数

        try {
            title=getControllerMethodDescription2(joinPoint);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // debu模式下打印JVM信息。
        long beginTime = beginTimeThreadLocal.get().getTime();//得到线程绑定的局部变量(开始时间)  
        long endTime = System.currentTimeMillis();     //2、结束时间  
        if (logger.isDebugEnabled()){
            Object[] obj = new Object[7];
            obj[0] = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(endTime);
            obj[1] = request.getRequestURI();
            obj[2] = DateUtils.formatDateTime(endTime - beginTime);
            obj[3] = Runtime.getRuntime().maxMemory()/1024/1024;
            obj[4] = Runtime.getRuntime().totalMemory()/1024/1024;
            obj[5] = Runtime.getRuntime().freeMemory()/1024/1024;
            obj[6] = (Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024;
            logger.debug("计时结束:{}  URI: {}  耗时: {}   最大内存: {}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m",obj);
        }

        //获取数据
        Logs log = new Logs();
        log.setTitle(title);
        log.setType(type);
        log.setRemoteAddr(remoteAddr);
        log.setRequestUri(requestUri);
        log.setMethod(method);
        log.setMapToParams(params);
        log.setUserId(String.valueOf(User.getId()));
        Date operateDate=beginTimeThreadLocal.get();
        log.setOperateDate(operateDate);
        log.setTimeout(DateUtils.formatDateTime(endTime - beginTime));

        //1.直接执行保存操作
        //this.logService.createSystemLog(log);

        //2.优化:异步保存日志
        //new SaveLogThread(log, logService).start();

        //3.再优化:通过线程池来执行日志保存
        threadPoolTaskExecutor.execute(new SaveLogThread(log, logsService));
        logThreadLocal.set(log);
    }

    /**
     *  异常通知 
     * @param joinPoint
     * @param e
     */
    @AfterThrowing(pointcut = "controllerAspect()", throwing = "e")  
    public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
        Logs logs = logThreadLocal.get();
        if(logs != null){
            logs.setType("error");
            logs.setException(e.toString());
            new UpdateLogThread(logs, logsService).start();            
        }
    }

    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     * 
     * @param joinPoint 切点
     * @return 方法描述
     */
    public static String getControllerMethodDescription2(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        SystemControllerLog controllerLog = method
                .getAnnotation(SystemControllerLog.class);
        String discription = controllerLog.description();
        return discription;
    }

    /**
     * 保存日志线程
     * 
     * @author l
     *
     */
    private static class SaveLogThread implements Runnable {
        private Logs logs;
        private LogsService logsService;

        public SaveLogThread(Logs logs, LogsService logsService) {
            this.logs = logs;
            this.logsService = logsService;
        }

        @Override
        public void run() {
            logsService.insert(logs);
        }
    }

    /**
     * 日志更新线程
     * 
     * @author l
     *
     */
    private static class UpdateLogThread extends Thread {
        private Logs logs;
        private LogsService logsService;

        public UpdateLogThread(Logs logs, LogsService logsService) {
            super(UpdateLogThread.class.getSimpleName());
            this.logs = logs;
            this.logsService = logsService;
        }

        @Override
        public void run() {
            this.logsService.insert(logs);
        }
    }
}

View Code

  3.spring的xml添加

xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd

图片 28

  启用申明,扫描controller层

 <!-- 启动对@AspectJ注解的支持 -->  
    <aop:aspectj-autoproxy/> 

<!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器  -->  
    <context:component-scan base-package="com.zw"></context:component-scan>

  安排日志

  <!-- 配置日志 -->
        <bean id ="threadPoolTaskExecutor"  class ="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" >
            <property name ="corePoolSize" value ="5" /> <!--核心线程数 -->
            <property name ="keepAliveSeconds" value ="3000" /> <!-- 某线程空闲超过这个时间,就回收该线程 -->
            <property name ="maxPoolSize" value ="10" />     <!--最大线程数 -->
            <property name ="queueCapacity" value ="1000" />  <!-- 队列大小 -->
            <property name= "rejectedExecutionHandler" >
                <!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 -->
                <!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 -->
                <!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
                <!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 -->
                <bean class = "java.util.concurrent.ThreadPoolExecutor$DiscardPolicy"   />
            </property>
        </bean>

  四.Controller中运用自定义表明

图片 29

相关文章

No Comments, Be The First!
近期评论
    功能
    网站地图xml地图