`
wj196
  • 浏览: 297785 次
  • 性别: Icon_minigender_2
  • 来自: 北京
社区版块
存档分类
最新评论

AOP实现Controller日志输出,返回结果

阅读更多
因为经常要给别人写一些接口,查询已发生的问题,如果日志记录的不清楚,难以找到问题,所以想做个东西,把别人请求的东西和接口响应后的结果在info日志中记录,经过尝试很多方法才达到目的,做一下记录,以便查找。

拦截器方式: 拦截器可以截取到很多信息,但是对于Controller的返回信息有限制,如果结果放在ModelAndView中,可以取到;如果是@ResponseBody的结果,没有找到方法取得,如果有人可以解决此问题,也请大家可以分享下。
/**
 * 
 */
package com.test.utils.web.interceptor;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;


/** 
 * @Description: 这里用一句话描述这个类的作用
 * @see: MVCRequestInterceptor 此处填写需要参考的类
 * @version 2016年12月13日 下午4:45:52 
 * @author wangqj
 */
public class MVCRequestInterceptor extends ApplicationLogging implements HandlerInterceptor {
	 
    private static final ObjectMapper mapper = new ObjectMapper();
    private NamedThreadLocal<Long>  startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-startTimed");  
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        
        info("##############################【一个MVC完整请求开始】##############################");
        
        info("*******************MVC业务处理开始**********************");
        try {
            long timed = System.currentTimeMillis();
            startTimeThreadLocal.set(timed);
            
            String requestURL = request.getRequestURI();
            info("当前请求的URL:【{}】", requestURL);
            info("执行目标方法: {}", handler);
            
            Map<String, ?> params = request.getParameterMap();
            if (!params.isEmpty()) {
                info("当前请求参数打印:");
                print(request.getParameterMap(), "参数");
            }
        } catch (Exception e) {
            error("MVC业务处理-拦截器异常:", e);
        }
        info("*******************MVC业务处理结束**********************");
        
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        
        info("*******************一个MVC 视图渲染开始**********************");
        
        try {
        	 long timeend = System.currentTimeMillis();
            info("执行业务逻辑代码耗时:【{}】", timeend - startTimeThreadLocal.get());
            String requestURL = request.getRequestURI();
            info("当前请求的URL:【{}】", requestURL);
          
            if (modelAndView != null) {
                info("即将返回到MVC视图:{}", modelAndView.getViewName());
                
                if (modelAndView.getView() != null) {
                    info("返回到MVC视图内容类型ContentType:{}", modelAndView.getView().getContentType());
                }
                
                if (!modelAndView.getModel().isEmpty()) {
                    
                    info("返回到MVC视图{}数据打印如下:", modelAndView.getViewName());
                    print(modelAndView.getModel(), "返回数据");
                }
            }else{
            	  info("返回到MVC视图{}数据打印如下:", "数据暂时无法打印");
            	 
            	
//            	if(handler.getClass().isAssignableFrom(HandlerMethod.class)){
//            		HandlerMethod handlerMethod=(HandlerMethod) handler;   
//            		info("aa{}",handlerMethod.getMethodParameters());
////            		System.out.println(handlerMethod.getMethodAnnotation(annotationType)());
//            		System.out.println(handlerMethod.getMethod());
//            		System.out.println(handlerMethod.getMethod().getParameters());
//            		System.out.println(handlerMethod.getReturnValueType(""));
//            		Object a= handlerMethod.getBean();
//            		info("aa{}",a.toString());
//            		 MethodParameter[] methodParameters = handlerMethod.getMethodParameters();
//            		    for(MethodParameter methodParameter : methodParameters){
//            		    System.out.println(methodParameter.getParameterName());
//            		    }
//            		    
//            		    System.out.println(handlerMethod.getMethod().getName());    
//            		    System.out.println(handlerMethod.getMethod().getReturnType());  
////            		    handlerMethod.
////            		System.out.println(handlerMethod.);
//            	}
//            	int bufferSize = response.getBufferSize();
//            	byte[] data = new byte[bufferSize];
//            	ServletOutputStream outputStream = response.getOutputStream();
//            	int len = 0 ;
//            	InputStream in =  new ByteArrayInputStream(new ByteArrayOutputStream(outputStream))
//            	outputStream.write(data);
//            	outputStream.flush();
            	// ByteArrayOutputStream out =  outputStream;
//            	  ByteArrayInputStream in = new ByteArrayInputStream(outputStream.toByteArray());
//            	          byte[] bs = new byte[1024];  
//            	           int len = in.read(bs);  
//            	            for (int i = 0; i < len; i++) {  
//            	              System.out.println(bs[i]);  
//            	           }  
//            	info("aaa"+wr.toString());
            	
            	
            }
        } catch (Exception e) {
            error("MVC 视图渲染-拦截器异常:", e);
        }
        
        info("*******************一个MVC 视图渲染结束**********************");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        
        try {
            String requestURL = request.getRequestURI();
            info("MVC返回请求完成URL:【{}】", requestURL);
            long timeend = System.currentTimeMillis();
            info("MVC返回请求完成耗时:【{}】", timeend - startTimeThreadLocal.get());
            if (ex != null) {
                info("MVC返回请求发生异常:", ex.getMessage());
                error("异常信息如下:", ex);
            }
        } catch (Exception e) {
            error("MVC完成返回-拦截器异常:", e);
        }
        
        info("##############################【一个MVC完整请求完成】##############################");
    }
    
    private void print(Map<String, ?> map, String prefix) {
        if (map != null) {
            Set<String> keys = map.keySet();
            Iterator<String> iter = keys.iterator();
            while (iter.hasNext()) {
                
                String name = iter.next();
                if (name.contains("org.springframework.validation.BindingResult")) {
                    continue;
                }
                
                String value = "";
                try {
                	if(null!=map.get(name)){
                	   value = mapper.writeValueAsString(map.get(name));
                	}
                  
                } catch (Exception e) {
                    error("转换参数【{}】发生异常:", name, e);
                }
                info("{} \"{}\": {}", prefix, name, value);
            }
        }
    }
    
 
}



spring切面实现,实现方式:可以拿到所有Controller的结果,但是如果是作为跳转的String,返回结果在ModelAndView的,输出是String的url,并不熟ModelAndView的结果,
而其他的结果,return的结果就是输出结果。


/**
 * 
 */
package com.test.utils.web.interceptor;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @Description: 这里用一句话描述这个类的作用
 * @see: LogAspect 此处填写需要参考的类
 * @version 2016年12月14日 下午1:09:53
 * @author wangqj
 */
public class LogAspect  {
	private final Logger logger = LoggerFactory.getLogger(this.getClass());
	private static final ObjectMapper mapper = new ObjectMapper();
	private String requestPath = null; // 请求地址
	private Map<String, ?> inputParamMap = null; // 传入参数
	private Map<String, Object> outputParamMap = null; // 存放输出结果
	private long startTimeMillis = 0; // 开始时间
	private long endTimeMillis = 0; // 结束时间
	private String method ="";
	
	
	/**
	 * @Title:doBeforeInServiceLayer
	 * @Description: 方法调用前触发
	 *               记录开始时间
	 * @author shaojian.yu
	 * @date 2014年11月2日 下午4:45:53
	 * @param joinPoint
	 */
	public void doBefore(JoinPoint joinPoint) {
		startTimeMillis = System.currentTimeMillis(); // 记录方法开始执行的时间
		info("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$【一个MVC完整请求开始 Log】$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");

	}

	/**
	 * @Title:doAfterInServiceLayer
	 * @Description: 方法调用后触发
	 *               记录结束时间
	 * @author shaojian.yu
	 * @date 2014年11月2日 下午4:46:21
	 * @param joinPoint
	 */
 
	public void doAfter(JoinPoint joinPoint) {
		endTimeMillis = System.currentTimeMillis(); // 记录方法执行完成的时间
		this.printOptLog();
		info("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$【一个MVC完整请求结束 Log】$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
	}

	/**
	 * @Title:doAround
	 * @Description: 环绕触发
	 * @author shaojian.yu
	 * @date 2014年11月3日 下午1:58:45
	 * @param pjp
	 * @return
	 * @throws Throwable
	 */
 
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		/**
		 * 1.获取request信息
		 * 2.根据request获取session
		 * 3.从session中取出登录用户信息
		 */
		RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes sra = (ServletRequestAttributes) ra;
		HttpServletRequest request = sra.getRequest();

		// 获取输入参数
		inputParamMap = request.getParameterMap();
		// 获取请求地址
		requestPath = request.getRequestURI();
		method =  request.getMethod();
		//info("当前请求的URL:【{}】", requestPath);
	    //info("执行目标方法: {}", method);
	    //print(inputParamMap, "请求参数");

		// 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
		outputParamMap = new HashMap<String, Object>();
		Object result = pjp.proceed();// result的值就是被拦截方法的返回值
		outputParamMap.put("result", result);
//		print(outputParamMap, "返回参数");
//		info("MVC返回请求完成耗时:【{}】", startTimeMillis - endTimeMillis);

		return result;
	}

	
	public JoinPoint afterReturning(JoinPoint joinpoint, Object returnValue) {

		// 此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象
		Object[] args = joinpoint.getArgs();
		logger.info("目标参数列表:");
		if (args != null) {
			for (Object obj : args) {
				logger.info(obj + ",");
			}
			System.out.println();
		}
		logger.info("被拦截方法调用之后调用此方法,输出此语句");
		logger.info("方法调用成功后返回结果:" + returnValue);
		return joinpoint;
	}

	public JoinPoint afterThrowing(JoinPoint joinpoint) {
		joinpoint.getArgs();// 此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象
		logger.info("被拦截方法调用之后调用此方法,输出此语句");
		return joinpoint;
	}
	
	private void print(Map<String, ?> map, String prefix) {
		if (map != null) {
			Set<String> keys = map.keySet();
			Iterator<String> iter = keys.iterator();
			while (iter.hasNext()) {

				String name = iter.next();
				if (name.contains("org.springframework.validation.BindingResult")) {
					continue;
				}

				String value = "";
				try {
					value = mapper.writeValueAsString(map.get(name));
				} catch (Exception e) {
					error("转换参数【{}】发生异常:", name, e);
				}
				info("{} \"{}\": {}", prefix, name, value);
			}
		}
	}

	
	protected final void error(String msg, Object... objects) {
		logger.error(msg, objects);
	}

	protected final void info(String msg, Object... objects) {
		logger.info(msg, objects);
	}
	/**
	 * @Title:printOptLog
	 * @Description: 输出日志
	 * @author shaojian.yu
	 * @date 2014年11月2日 下午4:47:09
	 */
	 private void printOptLog() {
	   info("当前请求路径:【{}】", requestPath); 
	   info("当前执行目标方法:【{}】", method); 
	   
	   info("【当前请求参数】");
	   if (!inputParamMap.isEmpty()) {
           print(inputParamMap, "请求参数:");
       }
		 
	   info("【当前返回参数】");
	   if (!outputParamMap.isEmpty()) {
           print(outputParamMap, "返回参数:");
       }
	   String startTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(startTimeMillis);
	   String endTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").format(endTimeMillis);
	   info("当前操作响应开始时间:{}", startTime); 
	   info("当前操作响应结束时间:{}", endTime); 
	   long optTime =  endTimeMillis-startTimeMillis;
	   info("当前操作响应时间:【{}】ms", optTime); 
	 
	 
	 }
}




方法拦截器:

/**
 * 
 */
package com.test.utils.web.interceptor;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.test.utils.lang.ParameterNameUtils;


/**
 * <b>function:</b> Spring 接口调用拦截器,主要拦截com.xxx.*.sdk.client对外接口
 * @author hoojo
 * @createDate 2016-11-24 下午5:39:57
 * @file ExecutionApiLogMethodInterceptor.java
 * @package com.xxx.eduyun.sdk.framework
 * @project eduyun-sdk-service
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class LogMethodInterceptor implements MethodInterceptor {

    private Logger log = LoggerFactory.getLogger(LogMethodInterceptor.class);
    private static final ObjectMapper mapper = new ObjectMapper();
    
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

        info("************************************【接口调用拦截开始】*************************************");
        String targetName = invocation.getThis().getClass().getSimpleName();
        Method method = invocation.getMethod();
        String methodName = method.getName();
        
        info("系统开始执行方法:{}.{}", targetName, methodName);
        
        info("【{}.{}】方法参数打印如下:", targetName, methodName);
        Object[] args = invocation.getArguments();
        
        //printArgs(args, method, invocation.getThis().getClass());
        printArgs(args, method);
        
        try {
            long timestart = System.currentTimeMillis();
            
            Object result = invocation.proceed();

            long timeend = System.currentTimeMillis();
            
            info("【{}.{}】方法执行完成,耗时:【{}】", targetName, methodName, timeend - timestart);
            info("【{}.{}】方法执行返回结果:{}", targetName, methodName, result);
            
            info("【{}.{}】方法返回数据打印如下:", targetName, methodName);
            printResult(result);
            info("************************************【接口调用拦截结束*】************************************");
            
            return result;
        } catch (Throwable throwable) {
            error("外部接口调用方法【{}.{}】异常:", targetName, methodName, throwable);
            
            info("************************************【接口异常拦截结束】*************************************");
            throw throwable;
        }
    }
    
    private void printArgs(Object[] args, Method method) {
        try {
            
            String[] argNames = null;
            try {
                argNames = ParameterNameUtils.getMethodParamNames(method);
            } catch (Exception e) {
                error("获取参数名称异常:", e);
            }
            
            if (args != null) {
                for (int i = 0; i < args.length; i++) {
                    String argName = "";
                    if (argNames != null && argNames.length >= i) {
                        argName = argNames[i];
                    }
                    
                    if (args[i] != null) {
                        String value = "";
                        try {
                            value = mapper.writeValueAsString(args[i]);
                        } catch (Exception e) {
                            error("转换参数 \"{}\" 发生异常:", argName, e);
                        }
                        info("【参数 \"{}\" 】:({})", argName, value);
                    } else {
                        info("参数 \"{}\":NULL", argName);
                    }
                }
            }
        } catch (Exception e) {
            error("【接口调用拦截器】打印方法执行参数异常:", e);
        }
    }
    
    private void printResult(Object result) {
        if (result != null) {
            try {
                info("【返回数据】:({})", mapper.writeValueAsString(result));
            } catch (Exception e) {
                error("返回数据打印异常:", e);
            }
        } else {
            info("【返回数据】:NULL");
        }
    }
    
    protected final void error(String msg, Object... objects) {
        log.error(msg, objects);
    }

    protected final void info(String msg, Object... objects) {
        log.info(msg, objects);
    }
}



/**
 * 
 */
package com.test.utils.lang;


import java.io.InputStream;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

import org.springframework.asm.ClassReader;
import org.springframework.asm.ClassVisitor;
import org.springframework.asm.ClassWriter;
import org.springframework.asm.Label;
import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Opcodes;
import org.springframework.asm.Type;

/**
 * <b>function:</b> 获取方法参加名称
 * @createDate 2016-11-25 下午3:40:33
 * @file ParameterNameUtils.java
 * @package com.xxx.flipclass.sdk.client.utils
 * @project flipclass-sdk-client
 * @version 1.0
 */
public abstract class ParameterNameUtils {

    /**
     * 获取指定类指定方法的参数名
     *
     * @param clazz 要获取参数名的方法所属的类
     * @param method 要获取参数名的方法
     * @return 按参数顺序排列的参数名列表,如果没有参数,则返回null
     */
    public static String[] getMethodParamNames(Class<?> clazz, final Method method) throws Exception {
        
        try {
            
            final String[] paramNames = new String[method.getParameterTypes().length];
            String className = clazz.getName();
            
            int lastDotIndex = className.lastIndexOf(".");
            className = className.substring(lastDotIndex + 1) + ".class";
            InputStream is = clazz.getResourceAsStream(className);
            
            final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
            ClassReader cr = new ClassReader(is);
            
            cr.accept(new ClassVisitor(Opcodes.ASM4, cw) {
                @Override
                public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
                    final Type[] args = Type.getArgumentTypes(desc);
                    // 方法名相同并且参数个数相同
                    if (!name.equals(method.getName()) || !sameType(args, method.getParameterTypes())) {
                        return super.visitMethod(access, name, desc, signature, exceptions);
                    }
                    MethodVisitor v = cv.visitMethod(access, name, desc, signature, exceptions);
                    return new MethodVisitor(Opcodes.ASM4, v) {
                        @Override
                        public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                            int i = index - 1;
                            // 如果是静态方法,则第一就是参数
                            // 如果不是静态方法,则第一个是"this",然后才是方法的参数
                            if (Modifier.isStatic(method.getModifiers())) {
                                i = index;
                            }
                            if (i >= 0 && i < paramNames.length) {
                                paramNames[i] = name;
                            }
                            super.visitLocalVariable(name, desc, signature, start, end, index);
                        }
                        
                    };
                }
            }, 0);
            return paramNames;
        } catch (Exception e) {
            throw e;
        }
    }
    
    /**
     * 比较参数类型是否一致
     * @param types asm的类型({@link Type})
     * @param clazzes java 类型({@link Class})
     * @return
     */
    private static boolean sameType(Type[] types, Class<?>[] clazzes) {
        // 个数不同
        if (types.length != clazzes.length) {
            return false;
        }

        for (int i = 0; i < types.length; i++) {
            if (!Type.getType(clazzes[i]).equals(types[i])) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取方法的参数名
     * @param Method
     * @return argsNames[]
     */
    public static String[] getMethodParamNames(final Method method) throws Exception {
        
        return getMethodParamNames(method.getDeclaringClass(), method);
    }

    public static void main(String[] args) throws Exception {
        Class<ParameterNameUtils> clazz = ParameterNameUtils.class;
        
        Method method = clazz.getDeclaredMethod("getMethodParamNames", Method.class);
        String[] parameterNames = ParameterNameUtils.getMethodParamNames(method);
        System.out.println(Arrays.toString(parameterNames));
        
        method = clazz.getDeclaredMethod("sameType", Type[].class, Class[].class);
        parameterNames = ParameterNameUtils.getMethodParamNames(method);
        System.out.println(Arrays.toString(parameterNames));
    }
}


加载配置文件:
package com.test.config;

import java.util.List;

import nz.net.ultraq.thymeleaf.LayoutDialect;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mobile.device.DeviceHandlerMethodArgumentResolver;
import org.springframework.mobile.device.DeviceResolverHandlerInterceptor;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver;

import com.test.Application;
import com.test.utils.json.CustomObjectMapper;

@Configuration
@ComponentScan(basePackageClasses = Application.class, includeFilters = @Filter(Controller.class), useDefaultFilters = false)
@ImportResource(value = "classpath:spring/applicationContext-mvc.xml")
class WebMvcConfig extends WebMvcConfigurationSupport {

    private static final String MESSAGE_SOURCE = "/WEB-INF/i18n/messages";
    private static final String VIEWS = "/WEB-INF/views/";

    private static final String RESOURCES_LOCATION = "/resources/";
    private static final String RESOURCES_HANDLER = RESOURCES_LOCATION + "**";

    @Override
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        RequestMappingHandlerMapping requestMappingHandlerMapping = super.requestMappingHandlerMapping();
        requestMappingHandlerMapping.setUseSuffixPatternMatch(false);
        requestMappingHandlerMapping.setUseTrailingSlashMatch(false);
        return requestMappingHandlerMapping;
    }

    @Bean(name = "messageSource")
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename(MESSAGE_SOURCE);
        messageSource.setCacheSeconds(5);
        return messageSource;
    }

    @Bean
    public TemplateResolver templateResolver() {
        TemplateResolver templateResolver = new ServletContextTemplateResolver();
        templateResolver.setPrefix(VIEWS);
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode("HTML5");
        templateResolver.setCacheable(false);
        templateResolver.setCharacterEncoding("utf-8");
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(templateResolver());
        templateEngine.addDialect(new LayoutDialect());
//        templateEngine.addDialect(new SpringSecurityDialect());
        return templateEngine;
    }

    @Bean
    public ThymeleafViewResolver viewResolver() {
        ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
        thymeleafViewResolver.setTemplateEngine(templateEngine());
        thymeleafViewResolver.setCharacterEncoding("UTF-8");
        return thymeleafViewResolver;
    }

    @Bean
    public DeviceResolverHandlerInterceptor
    deviceResolverHandlerInterceptor() {
        return new DeviceResolverHandlerInterceptor();
    }

    @Bean
    public DeviceHandlerMethodArgumentResolver
    deviceHandlerMethodArgumentResolver() {
        return new DeviceHandlerMethodArgumentResolver();
    }


    @Override
    public Validator getValidator() {
        LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource());
        return validator;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(RESOURCES_HANDLER).addResourceLocations(RESOURCES_LOCATION);
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }

    /**
     * Handles favicon.ico requests assuring no <code>404 Not Found</code> error is returned.
     */
    @Controller
    static class FaviconController {
        @RequestMapping("favicon.ico")
        String favicon() {
            return "forward:/resources/images/favicon.ico";
        }
    }

    @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new PortalStringHttpMessageConverter());
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
                new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setObjectMapper(new CustomObjectMapper());
        converters.add(mappingJackson2HttpMessageConverter);
    }

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(deviceResolverHandlerInterceptor());
    }

    @Override
    protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(deviceHandlerMethodArgumentResolver());
    }
}


package com.test.config;

import com.test.Application;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import redis.clients.jedis.JedisPoolConfig;

import static org.springframework.context.annotation.ComponentScan.Filter;

@Configuration
@ComponentScan(basePackageClasses = Application.class, excludeFilters = @Filter({Controller.class, Configuration.class}))
@ImportResource(value = "classpath:spring/applicationContext.xml")
class ApplicationConfig {

    @Bean
    public static PropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
        PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
        String dbConfigPath = System.getProperty("db.config.path");
        Resource dbResource = null;
        if(StringUtils.hasLength(dbConfigPath)){
            dbResource =  new FileSystemResource(dbConfigPath);
        }else {
            dbResource = new ClassPathResource("/persistence.properties");
        }
        ppc.setLocations(new Resource[]{
                dbResource,
                new ClassPathResource("/init.properties")
        });
        return ppc;
    }


    @Value(value = "${redis.pool.maxTotal}")
    private int redisPoolMaxTotal;
    @Value(value = "${redis.pool.maxIdle}")
    private int redisPoolMaxIdle;
    @Value(value = "${redis.pool.maxWait}")
    private int redisPoolMaxWait;
    @Value(value = "${redis.pool.testOnBorrow}")
    private boolean redisPoolTestOnBorrow;

    @Value(value = "${redis.host}")
    private String redisHost;
    @Value(value = "${redis.port}")
    private int redisPort;
    @Value(value = "${redis.password}")
    private String redisPassword;

    @Bean
    public JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        poolConfig.setMaxTotal(redisPoolMaxTotal);
        poolConfig.setMaxIdle(redisPoolMaxIdle);
        poolConfig.setMaxWaitMillis(redisPoolMaxWait);
        poolConfig.setTestOnBorrow(redisPoolTestOnBorrow);
        return poolConfig;
    }

    @Bean
    public JedisConnectionFactory jedisConnectionFactory(){
        JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
        connectionFactory.setHostName(redisHost);
        connectionFactory.setPort(redisPort);
        connectionFactory.setPassword(redisPassword);
        connectionFactory.setPoolConfig(jedisPoolConfig());
        return connectionFactory;
    }

    @Bean
    public RedisTemplate redisTemplate(){
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(jedisConnectionFactory());
        redisTemplate.setKeySerializer(redisTemplate.getStringSerializer());
//        redisTemplate.setDefaultSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        return redisTemplate;
    }

    @Bean
    public ValueOperations valueOperations(){
        return redisTemplate().opsForValue();
    }

    @Bean
    public ListOperations listOperations(){
        return redisTemplate().opsForList();
    }

    @Bean
    public HashOperations hashOperations(){
        return redisTemplate().opsForHash();
    }

    @Bean
    public SetOperations setOperations(){
        return redisTemplate().opsForSet();
    }

    @Bean
    public ZSetOperations zSetOperations(){
        return redisTemplate().opsForZSet();
    }
}



xml配置:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    <bean class="com.lvbb.base.utils.PropertiesManager" init-method="init">
        <property name="configFile" value="${config.file.path}"></property>
    </bean>

    <import resource="applicationContext-quartz.xml"></import>
   <import resource="applicationContext-aop.xml"></import>
    <!--  <import resource="applicationContext-mvc.xml"></import>   --> 
 </beans>



<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
						http://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/aop 
						http://www.springframework.org/schema/aop/spring-aop.xsd
						http://www.springframework.org/schema/context 
						http://www.springframework.org/schema/context/spring-context.xsd
						http://www.springframework.org/schema/tx 
						http://www.springframework.org/schema/tx/spring-tx.xsd
	">
    
    <bean id="externalApiMethodInterceptor" class="com.test.utils.web.interceptor.LogMethodInterceptor" />

    <aop:config proxy-target-class="true">
        <aop:pointcut id="externalApiMethodPointcut" expression="execution(* com.test.*.repository..*(..))" />
        <aop:advisor advice-ref="externalApiMethodInterceptor" pointcut-ref="externalApiMethodPointcut" />
    </aop:config>
   
</beans>




<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
		xmlns:aop="http://www.springframework.org/schema/aop" 
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc.xsd	
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context.xsd
	  http://www.springframework.org/schema/aop 
	 http://www.springframework.org/schema/aop/spring-aop.xsd">

 
   <context:annotation-config />
	
	<!--   访问拦截    -->
	  <mvc:interceptors >  
	  <mvc:interceptor>  
	        <mvc:mapping path="/**" />  
	        <mvc:exclude-mapping path="/pay/resources/**"/>
	        <mvc:exclude-mapping path="/resources/**"/>
	        <bean class="com.test.utils.web.interceptor.MVCRequestInterceptor"></bean>  
	    </mvc:interceptor>  
	</mvc:interceptors>   
	
   <aop:aspectj-autoproxy />  
   <bean id="logAspect" class="com.test.utils.web.interceptor.LogAspect"></bean> <!-- 将日志类注入到bean中。   -->
	<aop:config>  
	    <aop:aspect id="actionlog" ref="logAspect"><!-- 调用日志类   -->
	        <aop:pointcut id="actionLogPointcut" expression="execution(* com.test.payment.web.*.*(..))"/><!-- 配置在log包下所有的类在调用之前都会被拦截  --> 
	        <aop:before pointcut-ref="actionLogPointcut" method="doBefore"/><!-- 在log包下面所有的类的所有方法被调用之前都调用MyLog中的before方法   -->
	        <aop:after pointcut-ref="actionLogPointcut" method="doAfter"/><!-- 在log包下面所有的类的所有方法被调用之前都调用MyLog中的after方法   -->
	   		<aop:around pointcut-ref="actionLogPointcut"  method="doAround"/>
	   	  <!-- <aop:after-returning pointcut-ref="actionLogPointcut" method="afterReturning"  returning="returnValue"/> 后置通知,正常返回  
	        <aop:after-throwing  pointcut-ref="actionLogPointcut" method="afterThrowing"/>   异常通知   -->
	    </aop:aspect>  
	</aop:config>  
	
 
</beans>







相关文件:
/**
 * 
 */
package com.test.utils.web.interceptor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description: 这里用一句话描述这个类的作用
 * @see: ApplicationLogging 此处填写需要参考的类
 * @version 2016年12月13日 下午5:14:24
 * @author wangqj
 */
public abstract class ApplicationLogging {
	private Logger log = LoggerFactory.getLogger(ApplicationLogging.class);

	protected final void error(String msg, Object... objects) {
		log.error(msg, objects);
	}

	protected final void info(String msg, Object... objects) {
		log.info(msg, objects);
	}
}


如果有问题,请联系我,一起学习成长
分享到:
评论

相关推荐

    Spring MVC AOP通过注解方式拦截Controller等实现日志管理demo版本2

    Log4j提供了一个灵活的配置系统,允许我们定义不同的日志级别(如DEBUG、INFO、WARN),以及控制日志输出的目的地(如控制台、文件、网络等)。 通过这个示例,你可以学习如何在Spring MVC项目中使用AOP注解进行...

    springmvc+hibernate 日志管理工具

    功能日志:基于java aop思想设计,通过Spring advisorAutoProxy(自动代理)实现controller过滤代理拦截,并提供拦截filter过滤,支持spring EL表达式。 数据日志:设计中提供数据日志注入接口,管理数据日志注入,...

    spring hibernate 日志管理插件

    功能日志:基于java aop思想设计,通过Spring advisorAutoProxy(自动代理)实现controller过滤代理拦截,并提供拦截filter过滤,支持spring EL表达式。 数据日志:设计中提供数据日志注入接口,管理数据日志注入,...

    Spring aop.docx

    3. **编写Controller代码**:创建一个简单的RESTful API,例如一个返回"Hello, World!"的GET方法。 4. **编写@Aspect代码**:创建一个带有`@Aspect`注解的类,定义切入点表达式(例如匹配所有Controller方法),并...

    springboot 用aop打印web请求参数信息例子

    在实际项目中,你可能还需要考虑其他因素,比如日志的级别、格式,以及如何将日志输出到文件或日志服务等。这个例子只是一个基础的起点,你可以根据需要对其进行扩展和优化,以适应更复杂的需求。 综上所述,通过...

    spring + MyBatis Maven整合增删改查和导出excl表和分页

    7. **Controller层处理请求**: 创建Spring MVC的Controller类,处理HTTP请求,调用Service方法,并返回响应结果。 8. **导出Excel**: 使用Apache POI库来处理Excel文件,创建一个方法接收查询条件,生成Excel文件,...

    SpringMVC精品资源--Spring+Springmvc+Mybatis框架,后续集成日志插件log4j、lo.zip

    8. **日志配置**:log4j.properties或log4j.xml,用于设置日志输出的详细程度、目标位置等。 9. **示例代码**:可能包含演示如何使用这三个框架的简单应用或测试用例。 学习这个资源包,可以理解Spring、SpringMVC...

    springMVC_核心技术总结

    5. **Log4j**:Log4j是一个广泛使用的日志记录库,它允许开发者灵活地控制日志信息的输出级别、格式和目的地。在Spring MVC项目中,通过配置log4j.properties或log4j.xml,可以方便地进行日志记录,帮助调试和监控...

    Spring MVC 学习笔记 十二 PDF/Excel格式输出

    2. **ModelAndView**:Controller方法返回的对象,用于将模型数据和视图名称传递给视图层。你可以将数据放入ModelAndView的模型中,然后指定视图名称,如"viewName"。 3. **Model**:模型对象,包含业务数据。在...

    spring+springMVC+mybatis+log4j框架整合

    通过配置log4j.properties或log4j.xml文件,可以定制日志输出的位置、格式和级别,实现日志管理和分析。 在实际项目中,"spring+springMVC+mybatis+log4j框架整合"通常涉及以下步骤: 1. 引入相关jar包:添加Spring...

    springmvc 测试项目

    Controller处理完成后,将结果转发给View进行渲染并返回给客户端。在配置中,我们通常会定义一个servlet-mapping来指定DispatcherServlet的URL映射。 二、日志管理 在Spring MVC项目中,日志记录是非常重要的,它能...

    SpringMVC+Log4j

    4. **ModelAndView**:模型和视图对象,用于存放处理结果和返回的视图信息。 **Spring** Spring是Java企业级应用开发的全面解决方案,它提供了一个轻量级的容器,用于管理对象的生命周期和依赖关系。Spring的核心...

    ssm-拦截器.zip

    - 可能还包含日志输出或测试用例,用于验证拦截器功能。 通过这个示例项目,你可以学习到如何在SSM框架中使用拦截器,以及如何将其应用于实际项目中解决特定问题。这不仅有助于提高代码复用性和可维护性,还能让...

    Spring_MVC.rar_T7Y_springmvc

    关于“简单log4j的测试代码”,这可能涉及到在项目中配置log4j.properties文件,定义日志级别、输出格式和目的地,以及在代码中使用`Logger`来记录日志。 在压缩包中的"Spring_MVC"文件夹中,可能包含的是一个简单...

    springMVC spring mybatis完整jar包和增删改查

    8. 配置Logback进行日志记录,根据需要定制日志输出级别和格式。 这个项目对于初学者理解SSM框架的集成以及实际项目开发流程具有很好的学习价值。通过实践,开发者可以深入理解各组件间的协作,提升Web应用开发能力...

    SpringMVC原理共3页.pdf.zip

    3. **Controller**:Controller是SpringMVC中的业务逻辑处理组件,通常是一个实现了Controller接口或带有@Controller注解的类。它接收来自DispatcherServlet的请求,执行业务逻辑,并返回ModelAndView对象。 4. **...

    IntelliJ IDEA基于SSM框架整合开发模板带用户增删改查分页功能源代码

    9. **日志配置文件**:`logback.xml`用于配置logback的日志级别、输出目的地等。 这个项目是一个很好的学习资源,通过它你可以了解SSM框架如何协同工作,以及如何利用PageHelper实现分页功能。同时,通过后台日志的...

    spring+springmvc+mybatis的整合

    6. **日志整合**:选择合适的日志框架,如Log4j或Logback,配置日志输出级别、日志文件路径等。在代码中通过日志API记录操作信息。 7. **编写Service和Controller**:创建业务服务类和服务实现,使用Spring的@...

    SpringMVC配套资料.rar

    3. AOP(Aspect Oriented Programming):Spring的面向切面编程,用于处理横切关注点,如日志、事务管理等。 4. SpringMVC注解:如@Controller、@RequestMapping、@RequestParam、@PathVariable等,以及如何使用它们...

Global site tag (gtag.js) - Google Analytics