技术控

    今日:61| 主题:49101
收藏本版 (1)
最新软件应用技术尽在掌握

[其他] Spring框架下的 “接口调用、MVC请求” 调用参数、返回值、耗时信息输出 ...

[复制链接]
火包友 发表于 4 天前
98 2

立即注册CoLaBug.com会员,免费获得投稿人的专业资料,享用更多功能,玩转个人品牌!

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
主要拦截前端或后天的请求,打印请求方法参数、返回值、耗时、异常的日志。方便开发调试,能很快定位到问题出现在哪个方法中。
   
Spring框架下的 “接口调用、MVC请求” 调用参数、返回值、耗时信息输出 ...-1 (function,package,spring,import,拦截器)


Spring框架下的 “接口调用、MVC请求” 调用参数、返回值、耗时信息输出 ...-2 (function,package,spring,import,拦截器)

  前端请求拦截,mvc的拦截器
  [code]

  1 import java.util.Date;
  2 import java.util.Iterator;
  3 import java.util.Map;
  4 import java.util.Set;
  5
  6 import javax.servlet.http.HttpServletRequest;
  7 import javax.servlet.http.HttpServletResponse;
  8
  9 import org.codehaus.jackson.map.ObjectMapper;
10 import org.springframework.core.NamedThreadLocal;
11 import org.springframework.web.servlet.HandlerInterceptor;
12 import org.springframework.web.servlet.ModelAndView;
13
14 import com.xxx.eduyun.sdk.log.ApplicationLogging;
15 import com.xxx.flipclass.sdk.client.utils.TimeUtil;
16
17 /**
18  * function: spring mvc 请求拦截器
19  * @author hoojo
20  * @createDate 2016-11-24 下午3:19:27
21  * @file MVCRequestInterceptor.java
22  * @package com.xxx.eduyun.app.mvc.interceptor
23  * @project eduyun-app-web
24  * @blog http://blog.csdn.net/IBM_hoojo
25  * @email [email protected]
26  * @version 1.0
27  */
28 public class MVCRequestInterceptor extends ApplicationLogging implements HandlerInterceptor {
29
30     private static final ObjectMapper mapper = new ObjectMapper();
31     private NamedThreadLocal  startTimeThreadLocal = new NamedThreadLocal("StopWatch-startTimed");  
32     
33     @Override
34     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
35         
36         
37         info("##############################【一个MVC完整请求开始】##############################");
38         
39         info("*******************MVC业务处理开始**********************");
40         try {
41             long timed = System.currentTimeMillis();
42             startTimeThreadLocal.set(timed);
43            
44             String requestURL = request.getRequestURI();
45             info("当前请求的URL:【{}】", requestURL);
46             info("执行目标方法: {}", handler);
47            
48             Map params = request.getParameterMap();
49             if (!params.isEmpty()) {
50                 info("当前请求参数打印:");
51                 print(request.getParameterMap(), "参数");
52             }
53         } catch (Exception e) {
54             error("MVC业务处理-拦截器异常:", e);
55         }
56         info("*******************MVC业务处理结束**********************");
57         
58         return true;
59     }
60
61     @Override
62     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
63         
64         info("*******************一个MVC 视图渲染开始**********************");
65         
66         try {
67             info("执行业务逻辑代码耗时:【{}】", TimeUtil.formatTime(new Date().getTime() - startTimeThreadLocal.get()));
68             String requestURL = request.getRequestURI();
69             info("当前请求的URL:【{}】", requestURL);
70            
71             if (modelAndView != null) {
72                 info("即将返回到MVC视图:{}", modelAndView.getViewName());
73                 
74                 if (modelAndView.getView() != null) {
75                     info("返回到MVC视图内容类型ContentType:{}", modelAndView.getView().getContentType());
76                 }
77                 
78                 if (!modelAndView.getModel().isEmpty()) {
79                     
80                     info("返回到MVC视图{}数据打印如下:", modelAndView.getViewName());
81                     print(modelAndView.getModel(), "返回数据");
82                 }
83             }
84         } catch (Exception e) {
85             error("MVC 视图渲染-拦截器异常:", e);
86         }
87         
88         info("*******************一个MVC 视图渲染结束**********************");
89     }
90
91     @Override
92     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
93         
94         try {
95             String requestURL = request.getRequestURI();
96             info("MVC返回请求完成URL:【{}】", requestURL);
97             info("MVC返回请求完成耗时:【{}】", TimeUtil.formatTime(new Date().getTime() - startTimeThreadLocal.get()));
98             if (ex != null) {
99                 info("MVC返回请求发生异常:", ex.getMessage());
100                 error("异常信息如下:", ex);
101             }
102         } catch (Exception e) {
103             error("MVC完成返回-拦截器异常:", e);
104         }
105         
106         info("##############################【一个MVC完整请求完成】##############################");
107     }
108     
109     private void print(Map map, String prefix) {
110         if (map != null) {
111             Set keys = map.keySet();
112             Iterator iter = keys.iterator();
113             while (iter.hasNext()) {
114                 
115                 String name = iter.next();
116                 if (name.contains("org.springframework.validation.BindingResult")) {
117                     continue;
118                 }
119                 
120                 String value = "";
121                 try {
122                     value = mapper.writeValueAsString(map.get(name));
123                 } catch (Exception e) {
124                     error("转换参数【{}】发生异常:", name, e);
125                 }
126                 info("{} \"{}\": {}", prefix, name, value);
127             }
128         }
129     }
130 }

View Code[/code]  spring-mvc.xml增加配置内容
  [code]

1
2     
3         
4         
5         
6         
7         
8         
9         
10         
11     

12


View Code[/code]  过滤静态资源,一些静态资源不需要拦截,在这里配置黑名单不让它进入拦截器。
  下面是sdk接口拦截器,用到spirng的aop的MethodIntercept
  [code]

  1 package com.xxx.flipclass.sdk.framework.aop;
  2
  3 import java.lang.reflect.Method;
  4 import java.util.Date;
  5
  6 import org.aopalliance.intercept.MethodInterceptor;
  7 import org.aopalliance.intercept.MethodInvocation;
  8 import org.apache.logging.log4j.LogManager;
  9 import org.apache.logging.log4j.Logger;
10 import org.codehaus.jackson.map.ObjectMapper;
11
12 import com.xxx.flipclass.sdk.client.utils.ParameterNameUtils;
13 import com.xxx.flipclass.sdk.client.utils.TimeUtil;
14
15 /**
16  * function: Spring 接口调用拦截器,主要拦截com.xxx.*.sdk.client对外接口
17  * @author hoojo
18  * @createDate 2016-11-24 下午5:39:57
19  * @file ExecutionApiLogMethodInterceptor.java
20  * @package com.xxx.eduyun.sdk.framework
21  * @project eduyun-sdk-service
22  * @blog http://blog.csdn.net/IBM_hoojo
23  * @email [email protected]
24  * @version 1.0
25  */
26 public class ExecutionApiLogMethodInterceptor implements MethodInterceptor {
27
28     private Logger log = LogManager.getLogger(ExecutionApiLogMethodInterceptor.class);
29     private static final ObjectMapper mapper = new ObjectMapper();
30     
31     @Override
32     public Object invoke(MethodInvocation invocation) throws Throwable {
33
34         info("************************************【接口调用拦截开始】*************************************");
35         String targetName = invocation.getThis().getClass().getSimpleName();
36         Method method = invocation.getMethod();
37         String methodName = method.getName();
38         
39         info("系统开始执行方法:{}.{}", targetName, methodName);
40         
41         info("【{}.{}】方法参数打印如下:", targetName, methodName);
42         Object[] args = invocation.getArguments();
43         
44         //printArgs(args, method, invocation.getThis().getClass());
45         printArgs(args, method);
46         
47         try {
48             long timed = System.currentTimeMillis();
49            
50             Object result = invocation.proceed();
51
52             info("【{}.{}】方法执行完成,耗时:【{}】", targetName, methodName, TimeUtil.formatTime(new Date().getTime() - timed));
53             info("【{}.{}】方法执行返回结果:{}", targetName, methodName, result);
54            
55             info("【{}.{}】方法返回数据打印如下:", targetName, methodName);
56             printResult(result);
57             info("************************************【接口调用拦截结束*】************************************");
58            
59             return result;
60         } catch (Throwable throwable) {
61             error("外部接口调用方法【{}.{}】异常:", targetName, methodName, throwable);
62            
63             info("************************************【接口异常拦截结束】*************************************");
64             throw throwable;
65         }
66     }
67     
68     private void printArgs(Object[] args, Method method) {
69         try {
70            
71             String[] argNames = null;
72             try {
73                 argNames = ParameterNameUtils.getMethodParamNames(method);
74             } catch (Exception e) {
75                 error("获取参数名称异常:", e);
76             }
77            
78             if (args != null) {
79                 for (int i = 0; i < args.length; i++) {
80                     String argName = "";
81                     if (argNames != null && argNames.length >= i) {
82                         argName = argNames;
83                     }
84                     
85                     if (args != null) {
86                         String value = "";
87                         try {
88                             value = mapper.writeValueAsString(args);
89                         } catch (Exception e) {
90                             error("转换参数 \"{}\" 发生异常:", argName, e);
91                         }
92                         info("【参数 \"{}\" 】:({})", argName, value);
93                     } else {
94                         info("参数 \"{}\":NULL", argName);
95                     }
96                 }
97             }
98         } catch (Exception e) {
99             error("【接口调用拦截器】打印方法执行参数异常:", e);
100         }
101     }
102     
103     private void printResult(Object result) {
104         if (result != null) {
105             try {
106                 info("【返回数据】:({})", mapper.writeValueAsString(result));
107             } catch (Exception e) {
108                 error("返回数据打印异常:", e);
109             }
110         } else {
111             info("【返回数据】:NULL");
112         }
113     }
114     
115     protected final void error(String msg, Object... objects) {
116         log.error(msg, objects);
117     }
118
119     protected final void info(String msg, Object... objects) {
120         log.info(msg, objects);
121     }
122 }

View Code[/code]  上面使用到了方法参数获取的工具类,代码如下:
  [code]

  1 package com.xxx.flipclass.sdk.client.utils;
  2
  3 import java.io.InputStream;
  4 import java.lang.reflect.Method;
  5 import java.lang.reflect.Modifier;
  6 import java.util.Arrays;
  7
  8 import org.springframework.asm.ClassReader;
  9 import org.springframework.asm.ClassVisitor;
10 import org.springframework.asm.ClassWriter;
11 import org.springframework.asm.Label;
12 import org.springframework.asm.MethodVisitor;
13 import org.springframework.asm.Opcodes;
14 import org.springframework.asm.Type;
15
16 /**
17  * function: 获取方法参加名称
18  * @createDate 2016-11-25 下午3:40:33
19  * @file ParameterNameUtils.java
20  * @package com.xxx.flipclass.sdk.client.utils
21  * @project flipclass-sdk-client
22  * @version 1.0
23  */
24 public abstract class ParameterNameUtils {
25
26     /**
27      * 获取指定类指定方法的参数名
28      *
29      * @param clazz 要获取参数名的方法所属的类
30      * @param method 要获取参数名的方法
31      * @return 按参数顺序排列的参数名列表,如果没有参数,则返回null
32      */
33     public static String[] getMethodParamNames(Class clazz, final Method method) throws Exception {
34         
35         try {
36            
37             final String[] paramNames = new String[method.getParameterTypes().length];
38             String className = clazz.getName();
39            
40             int lastDotIndex = className.lastIndexOf(".");
41             className = className.substring(lastDotIndex + 1) + ".class";
42             InputStream is = clazz.getResourceAsStream(className);
43            
44             final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
45             ClassReader cr = new ClassReader(is);
46            
47             cr.accept(new ClassVisitor(Opcodes.ASM4, cw) {
48                 @Override
49                 public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
50                     final Type[] args = Type.getArgumentTypes(desc);
51                     // 方法名相同并且参数个数相同
52                     if (!name.equals(method.getName()) || !sameType(args, method.getParameterTypes())) {
53                         return super.visitMethod(access, name, desc, signature, exceptions);
54                     }
55                     MethodVisitor v = cv.visitMethod(access, name, desc, signature, exceptions);
56                     return new MethodVisitor(Opcodes.ASM4, v) {
57                         @Override
58                         public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
59                             int i = index - 1;
60                             // 如果是静态方法,则第一就是参数
61                             // 如果不是静态方法,则第一个是"this",然后才是方法的参数
62                             if (Modifier.isStatic(method.getModifiers())) {
63                                 i = index;
64                             }
65                             if (i >= 0 && i < paramNames.length) {
66                                 paramNames = name;
67                             }
68                             super.visitLocalVariable(name, desc, signature, start, end, index);
69                         }
70                        
71                     };
72                 }
73             }, 0);
74             return paramNames;
75         } catch (Exception e) {
76             throw e;
77         }
78     }
79     
80     /**
81      * 比较参数类型是否一致
82      * @param types asm的类型([email protected] Type})
83      * @param clazzes java 类型([email protected] Class})
84      * @return
85      */
86     private static boolean sameType(Type[] types, Class[] clazzes) {
87         // 个数不同
88         if (types.length != clazzes.length) {
89             return false;
90         }
91
92         for (int i = 0; i < types.length; i++) {
93             if (!Type.getType(clazzes).equals(types)) {
94                 return false;
95             }
96         }
97         return true;
98     }
99
100     /**
101      * 获取方法的参数名
102      * @param Method
103      * @return argsNames[]
104      */
105     public static String[] getMethodParamNames(final Method method) throws Exception {
106         
107         return getMethodParamNames(method.getDeclaringClass(), method);
108     }
109
110     public static void main(String[] args) throws Exception {
111         Class clazz = ParameterNameUtils.class;
112         
113         Method method = clazz.getDeclaredMethod("getMethodParamNames", Method.class);
114         String[] parameterNames = ParameterNameUtils.getMethodParamNames(method);
115         System.out.println(Arrays.toString(parameterNames));
116         
117         method = clazz.getDeclaredMethod("sameType", Type[].class, Class[].class);
118         parameterNames = ParameterNameUtils.getMethodParamNames(method);
119         System.out.println(Arrays.toString(parameterNames));
120     }
121 }

View Code[/code]  最后需要添加配置,拦截哪些接口或是实现类,具体看个人业务
  [code]

1
2 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4     xmlns:aop="http://www.springframework.org/schema/aop"
5     xsi:schemaLocation="http://www.springframework.org/schema/beans
6                         http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
7                         http://www.springframework.org/schema/aop
8                          http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
9                        
10
11     
12
13     
14         
15         
16     

17


View Code[/code]
友荐云推荐




上一篇:[工具资源] koth/kcws: Deep Learning Chinese Word Segment
下一篇:iOS开发进阶 - 富文本正则替换表情
酷辣虫提示酷辣虫禁止发表任何与中华人民共和国法律有抵触的内容!所有内容由用户发布,并不代表酷辣虫的观点,酷辣虫无法对用户发布内容真实性提供任何的保证,请自行验证并承担风险与后果。如您有版权、违规等问题,请通过"联系我们"或"违规举报"告知我们处理。

523694 发表于 4 天前
楼主,约么?
回复 支持 反对

使用道具 举报

董小磊 发表于 4 天前
太高深了,理解力不够用了!
回复 支持 反对

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

我要投稿

推荐阅读

扫码访问 @iTTTTT瑞翔 的微博
回页顶回复上一篇下一篇回列表手机版
手机版/CoLaBug.com ( 粤ICP备05003221号 | 文网文[2010]257号 )|网站地图 酷辣虫

© 2001-2016 Comsenz Inc. Design: Dean. DiscuzFans.

返回顶部 返回列表