接上文,我的小伙伴配置后不好使,原来当配置了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<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