`
wj196
  • 浏览: 298314 次
  • 性别: 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方法),并...

    JAVA实现通用日志记录方法

    传统的日志记录方法往往是在系统的关键位置直接加入日志输出语句,如使用System.out.println()或者日志框架提供的API。但这种方法存在诸多不便之处,例如无法统一管理日志级别、格式不统一、修改困难等。因此,...

    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的@...

Global site tag (gtag.js) - Google Analytics