ITKeyword,专注技术干货聚合推荐

注册 | 登录

Spring Controller层记录日志配置二

ruishenh 分享于 2016-02-03

推荐:Spring AOP实现日志记录

使用Spring AOP实现日记记录 1.  加入Jar包 <span style="font-size:18px;">2. 目标方法packagecom.datatub.service;publicclass LoginService { privat

2019阿里云全部产品优惠券(新购或升级都可以使用,强烈推荐)
领取地址https://promotion.aliyun.com/ntms/yunparter/invite.html

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

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

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

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

 

配置xml:

 

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

 

推荐:Spring AOP拦截对Controller的请求时的配置失败

之前学了Spring AOP的内容,在普通的应用上使用是没有问题的,后来由于做web程序,所以想用来拦截http的请求,以便记录日志,但是在配置过程当中,出现了错误,

 

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






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<Param> params = new ThreadLocal<Param>() {
        @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<String, Object> 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<string,Object> from HttpServletRequest
     *
     * @param request
     * @return
     */
    public static Map<String, Object> getParmMap(HttpServletRequest request) {
        HashMap<String, Object> map = new HashMap<String, Object>();
        @SuppressWarnings("unchecked")
        Map<String, String[]> orimap = request.getParameterMap();
        Set<String> 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<HttpMessageConverter<?>> 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<HandlerMethodReturnValueHandler> returnValueHandlers = rma.getReturnValueHandlers();
            List<HandlerMethodReturnValueHandler> newList = new ArrayList<HandlerMethodReturnValueHandler>();
            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<HttpMessageConverter<?>> 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-Controller和@RequestMapping ModelAndView配置和用法-restful风格

Spring3系列13-Controller和@RequestMapping   Controller返回值,String或者ModelAndView @RequestMapping关联url @RequestMapping的属性   一、      Controll

接上文,我的小伙伴配置后不好使,原来当配置了mvc的配置 <mvc:annotation-driven/> <mvc:default-servlet-handler/> 配置这两行的时候上个配置就不起作用了 所以重新写了文件,记录controller

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。