Spring Controller层记录日志配置二

接上文,我的小伙伴配置后不好使,原来当配置了mvc的配置

<mvc:annotation-driven/>
<mvc:default-servlet-handler/>

配置这两行的时候上个配置就不起作用了

所以重新写了文件,记录controller的日志,比上个文章配置更简单。代码可能比较长但是,copy配置下就ok,方便操作

 

配置xml:

 

<beanclass="com.ruishenh.spring.test.MyModelAndViewResolver"id="myModelAndViewResolver"/>

 

 

把下面的类写到自己的代码里






package com.ruishenh.spring.test;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.*;

/**
 * Created by Administrator on 2016/1/30.
 */
public class MyModelAndViewResolver extends ViewNameMethodReturnValueHandler implements ModelAndViewResolver, BeanPostProcessor, ApplicationContextAware {

    private static Logger log = LoggerFactory.getLogger(MyModelAndViewResolver.class);
    /**
     * 支持处理多种参数逻辑
     */
    public static final ThreadLocal params = new ThreadLocal() {
        @Override
        protected Param initialValue() {
            return new Param();
        }
    };

    public ModelAndView resolveModelAndView(Method handlerMethod, Class handlerType, Object returnValue, ExtendedModelMap implicitModel, NativeWebRequest webRequest) {
        handlerMonitor(handlerMethod, returnValue, (ServletWebRequest) webRequest);
        return ModelAndViewResolver.UNRESOLVED;
    }

    private void handlerMonitor(Method handlerMethod, Object returnValue, ServletWebRequest webRequest) {
        Class declaringClass = handlerMethod.getDeclaringClass();
        String clsAndMethod = declaringClass.getSimpleName() + "." + handlerMethod.getName();
        HttpServletRequest request = webRequest.getRequest();
        //获取请求ip
        Map parmMap = getParmMap(request);
        params.get().setP1(parmMap);
        String ip = request.getRemoteAddr();
        Object retStr = returnValue;
        if (returnValue != null && !isPrimitive(returnValue.getClass()))
            retStr = JSON.toJSONString(returnValue);

        //此处改写到自己的日志输出器里或者其他地方
        log.error(clsAndMethod + " prm:" + params.get() + " ret:" + retStr + " ip:" + ip);
        params.get().clear();
    }

    /**
     * 检查是否是基本类型
     *
     * @param cls
     * @return 是 基本 返回true,否则反之
     */
    private static boolean isPrimitive(Class cls) {
        return cls.isPrimitive() || cls == Boolean.class || cls == Byte.class || cls == Character.class || cls == Short.class || cls == Integer.class || cls == Long.class || cls == Float.class
                || cls == Double.class || cls == String.class || cls == Date.class || cls == Class.class;
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        handlerMonitor(returnType.getMethod(), returnValue, (ServletWebRequest) webRequest);
        super.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }

    /**
     * extract a Map from HttpServletRequest
     *
     * @param request
     * @return
     */
    public static Map getParmMap(HttpServletRequest request) {
        HashMap map = new HashMap();
        @SuppressWarnings("unchecked")
        Map orimap = request.getParameterMap();
        Set keys = orimap.keySet();
        for (String key1 : keys) {
            String key = key1;
            String[] value = orimap.get(key);
            if (value.length > 1) {
                map.put(key, value);
            } else {
                map.put(key, value[0]);
            }
        }
        return map;
    }

    private ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String s) throws BeansException {
        if (bean instanceof RequestMappingHandlerAdapter) {
            RequestMappingHandlerAdapter rma = (RequestMappingHandlerAdapter) bean;
            //处理自定义messageConverters
            List> messageConverters = rma.getMessageConverters();
            for (HttpMessageConverter httpMessageConverter : messageConverters) {
                if (MappingJackson2HttpMessageConverter.class.isAssignableFrom(httpMessageConverter.getClass())) {
                    messageConverters.remove(httpMessageConverter);
                    MappingJackson2HttpMessageConverter bean2 = new MappingJackson2HttpMessageConverter() {
                        @Override
                        public Object read(Type type, Class contextClass, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
                            Object o = super.read(type, contextClass, inputMessage);
                            MyModelAndViewResolver.params.get().setP2(o);//set到 自定义的Params中去
                            return o;
                        }
                    };
                    messageConverters.add(bean2);
                    break;
                }
            }
            rma.setMessageConverters(messageConverters);
            //处理自定义的handler
            List returnValueHandlers = rma.getReturnValueHandlers();
            List newList = new ArrayList();
            for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
                if (ViewNameMethodReturnValueHandler.class.isAssignableFrom(returnValueHandler.getClass())) {
                    MyModelAndViewResolver bean2 = applicationContext.getBean(MyModelAndViewResolver.class);
                    newList.add(bean2);
                }
                if (RequestResponseBodyMethodProcessor.class.isAssignableFrom(returnValueHandler.getClass())) {
                    MyRequestResponseBodyMethodProcessor bean2 = new MyRequestResponseBodyMethodProcessor(rma.getMessageConverters());
                    newList.add(bean2);
                }
                newList.add(returnValueHandler);
            }
            rma.setReturnValueHandlers(newList);
        }
        return bean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 封装一下参数对象,因为当json的时候是获取不到get,post的一些servlet参数的
     */
    public static class Param {
        Object p1;
        Object p2;

        public Param() {
        }

        public void clear() {
            p1 = null;
            p2 = null;
        }

        public Object getP1() {
            return p1;
        }

        public void setP1(Object p1) {
            this.p1 = p1;
        }

        public Object getP2() {
            return p2;
        }

        public void setP2(Object p2) {
            this.p2 = p2;
        }

        @Override
        public String toString() {
            return "Param{" +
                    "p1=" + p1 +
                    ", p2=" + p2 +
                    '}';
        }
    }

    public class MyRequestResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor {

        public MyRequestResponseBodyMethodProcessor(List> messageConverters) {
            super(messageConverters);
        }

        @Override
        public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws IOException, HttpMediaTypeNotAcceptableException {
            handlerMonitor(returnType.getMethod(), returnValue, (ServletWebRequest) webRequest);
            super.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
        }
    }
}


运行效果:

02-03 15:26:40.803 | ERROR| MyModelAndViewResolver.java:67| LogTestController.b prm:Param{p1={name=sdfds}, p2=null} ret:path ip:0:0:0:0:0:0:0:1
02-03 15:26:45.848 | ERROR| MyModelAndViewResolver.java:67| LogTestController.a prm:Param{p1={name=sdfds}, p2=null} ret:{"age":20,"name":"sdfds2"} ip:0:0:0:0:0:0:0:1
02-03 15:26:53.379 | ERROR| MyModelAndViewResolver.java:67| LogTestController.c prm:Param{p1={}, p2=Adata{name='sdfds2', age=20}} ret:{"age":20,"name":"sdfds2"} ip:0:0:0:0:0:0:0:1



你可能感兴趣的:(spring,MVC-视图层)