- 浏览: 67764 次
- 性别:
- 来自: 绍兴
最新评论
埋点的作用是把客户端每次访问服务端的操作记录下来,包括请求连接 请求者ip 请求参数 请求结果等等,以便于在出现异常的情况下排查,在用户量庞大的情况下还可以对这些记录做数据分析.这个功能我还是坚持一直以来的原则,一次封装终身受用,使用拦截器的方式全局做埋点记录.
首先创建一个注解类,这个注解类的作用是在action方法上标注当前方法的中文信息,记录到日志以后有便于查阅
这个方法的缺点是需要在每个action上进行配置,对我这种比较爱偷懒的猿来说还是有点不怎么好忍受的,还好我有权限系统(上一篇),记录每个权限对应的链接,也就是我知道客户端访问的链接后就能通过权限数据获取到对应的权限(就是菜单),菜单的名称其实就是我需要的备注,这样我就不需要在每个action方法做备注了,当然有些没进行权限配置的action方法还是需要注解的,先来看下注解的代码
很简单的注解,然后在来看下核心代码,action拦截器
简单的一个拦截器记录操作信息到单独的日志文件,你也可以记录到数据库,我是感觉如果记录到数据库的话多多少少会影响一点效率,而且这个数据量也是挺大的.这边还值得一提的是结果值是被调用的action的toString方法,还记不记得上一篇讲的action基类,所有的action类都从它派生,在这里他又发挥作用了,看一下基类里面的toString代码
因为我所有的返回值都是基于entity和searchList实现的,所以可以很方便的把返回值获取到,其实程序中有很多模块的实现不是随便想想的,大多数情况下这些设计都是可以复用的,这也体现出了设计模式的重要性.
最后只要在struts文件中配置拦截器就可以了
首先创建一个注解类,这个注解类的作用是在action方法上标注当前方法的中文信息,记录到日志以后有便于查阅
package cn.sdh.common.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface WebOperateAnno { String memo() default "无定义"; }
这个方法的缺点是需要在每个action上进行配置,对我这种比较爱偷懒的猿来说还是有点不怎么好忍受的,还好我有权限系统(上一篇),记录每个权限对应的链接,也就是我知道客户端访问的链接后就能通过权限数据获取到对应的权限(就是菜单),菜单的名称其实就是我需要的备注,这样我就不需要在每个action方法做备注了,当然有些没进行权限配置的action方法还是需要注解的,先来看下注解的代码
/** * 跳转到主页 * * @throws JSONException */ @WebOperateAnno(memo="主页") public String index() throws JSONException { entity = SpringSecurityUtils.getCurrentUser(); List<Permission> perList = entity.getSignPer(); HttpServletRequest request = ServletActionContext.getRequest(); request.setAttribute("perList", perList); request.setAttribute("perListJson", JSONUtil.serialize(perList)); return "index"; }
很简单的注解,然后在来看下核心代码,action拦截器
package cn.sdh.common.intercepter; import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; import org.apache.struts2.ServletActionContext; import cn.sdh.common.annotation.WebOperateAnno; import cn.sdh.entity.Account; import cn.sdh.utils.MyCacheUtil; import cn.sdh.utils.MyJsonUtil; import cn.sdh.utils.SpringSecurityUtils; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; @SuppressWarnings("serial") public class WebOperateIntercepter extends MethodFilterInterceptor { private static final Logger logger = Logger.getLogger("oplog"); private static final Logger sysLogger = Logger.getLogger(WebOperateIntercepter.class); @Override protected String doIntercept(ActionInvocation invocation) throws Exception { String result = null; try { //先执行action方法 result = invocation.invoke(); String enterMethod = invocation.getProxy().getMethod(); //获取action方法上的WebOperateAnno 注解 WebOperateAnno webOperateAnno = invocation.getAction().getClass().getMethod(enterMethod, new Class[0]).getAnnotation(WebOperateAnno.class); Object returnData = invocation.getAction(); writeLog(webOperateAnno,returnData); } catch (Exception e) { sysLogger.error("操作日志记录失败",e); } return result; } private void writeLog(WebOperateAnno ano, Object returnData){ //当前登录用户 Account account = SpringSecurityUtils.getCurrentUser(); String operate = ""; if(account != null){ operate = account.getUsername(); } //从注解中获取备注 String memo = ""; if(ano != null){ memo = ano.memo(); } HttpServletRequest request = ServletActionContext.getRequest(); //请求者ip String ip = request.getRemoteAddr(); //请求类型 post or get String method = request.getMethod(); //请求的链接 String url = request.getRequestURI(); //通过请求的链接从权限系统获取到当前模块 String module = MyCacheUtil.getPerNameByUrl(url); //对请求的参数进行json格式化 String entityString = MyJsonUtil.getJsonByObject(request.getParameterMap()); //做日志记录 logger.info(module+"|"+operate+"|"+ip+"|"+memo+"|"+method+"|"+url+"|"+entityString+"|"+returnData.toString()); } }
简单的一个拦截器记录操作信息到单独的日志文件,你也可以记录到数据库,我是感觉如果记录到数据库的话多多少少会影响一点效率,而且这个数据量也是挺大的.这边还值得一提的是结果值是被调用的action的toString方法,还记不记得上一篇讲的action基类,所有的action类都从它派生,在这里他又发挥作用了,看一下基类里面的toString代码
public String toString(){ StringBuilder builder = new StringBuilder(); builder.append(",success:"); builder.append(this.success); if(this.entity != null){ builder.append("entity:"); builder.append(this.entity.toString()); }if(this.searchList != null){ builder.append("searchList:"); builder.append(this.searchList.toString()); } return builder.toString(); }
因为我所有的返回值都是基于entity和searchList实现的,所以可以很方便的把返回值获取到,其实程序中有很多模块的实现不是随便想想的,大多数情况下这些设计都是可以复用的,这也体现出了设计模式的重要性.
最后只要在struts文件中配置拦截器就可以了
<interceptors> <interceptor name="webOperate" class="cn.sdh.common.intercepter.WebOperateIntercepter" /> <interceptor-stack name="crudStack"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="webOperate" /> </interceptor-stack> </interceptors> <default-interceptor-ref name="crudStack" />
发表评论
-
Web开发学习13聊聊java反射
2016-07-12 18:41 717很喜欢一本叫《走出软件作坊》的书,其中有一句话让我较为深刻,“ ... -
Web开发学习12 浅谈设计模式
2016-07-01 13:33 1282在我刚接触 ... -
Web开发学习11 全局缓存控制
2015-10-12 14:27 705缓存用的好可以减少数据库的压力,在大并发的情况下极大的提升服务 ... -
Web开发学习10 hadoop实战
2015-10-09 14:02 696前一篇说到项目记录了很多埋点日志,当有一天项目需求需要对这些日 ... -
Web开发学习8Struts2基类封装
2015-07-24 12:03 666一个好的基类可以帮助开发者减少很多开发工作,像我这种爱偷懒的人 ... -
Web开发学习7按钮级别权限控制
2015-07-23 16:21 13244这个功能的思路是自己原创的,没看过其他例子,其实是在做之前网上 ... -
Web开发学习6添加liqiubase
2015-07-22 14:29 1400开发过程中经常碰到数据库更改的情况,在日常环境下如果每位开发人 ... -
浅列JavaEnum
2014-01-05 16:42 748enum Province{ ZHEJIANG,SHANGHA ... -
maven常用命令
2013-07-08 10:20 7491、创建普通Java项目: ... -
canvas绘制科赫雪花
2012-12-20 17:24 2107<html> <head> ... -
html5 audio与video方法属性事件概括
2012-12-20 14:46 1059play() 继续播放 pause() ... -
spring 整合mina
2012-12-20 11:48 1071首先定义自定义过滤器 <bean id=" ... -
Web开发学习(5)添加springsecurity应用
2011-12-14 15:00 918我学习公司这个架构多半就是为了把springsecurity搞 ... -
Web开发学习(4)添加spring应用
2011-12-14 14:45 760印象中似乎没做过不用spring的项目,因为它在web开发中的 ... -
Web开发学习(3)配置struts-tiles插件(附带json插件)
2011-12-05 15:22 2514struts的tiles插件是非常实用的,从某些方面可以很好的 ... -
使用线程删除导出临时文件
2011-12-01 16:33 2218项目支持大数据量导出e ... -
jQuery实现表格行点击选中复选框
2011-11-23 12:36 5941这个需求是在项目完成后客户提出的要求,看似简单但是还需要一点小 ... -
Web开发学习(2)配置convention插件
2011-11-04 10:28 1347注解的方式某些程度上能减少xml的配置量,个人感觉使程序更加清 ... -
Web开发学习(1)使用eclipse搭建maven项目
2011-10-20 10:04 5695首先用eclipse创建工程 ne ... -
数据库连接泛型基类创建
2011-06-30 11:49 950记录 以便以后参考---- 基类代码 public cl ...
相关推荐
asp.net core webapi项目配置全局路由 asp.net core webapi项目配置全局路由 asp.net core webapi项目配置全局路由 博文:https://blog.csdn.net/hefeng_aspnet/article/details/135891877
WEB开发规范 目 录 1. 编程规范... 4 1.1. HTML页面... 4 1.1.1. 页面规范... 4 1.1.2. 元素id命名规范(蓝色表示常用) 4 1.1.3. 元素name命名规范... 6 1.2. ASP页面... 6 1.2.1. 文件命名规范... 6 1.2.2....
第3章 Vue开发基础(下) 全局API 全局配置 实例属性 组件进阶 学习目标 目录 ☞点击查看本节相关知识点 ☞点击查看本节相关知识点 实例属性 ☞点击查看本节相关知识点 ☞点击查看本节相关知识点 组件进阶 知识架构 ...
以基于矩的图像归一化技术及分形相关知识为基础,提出一种可有效抵抗几何攻击的数字水印新方案。方案利用归一化技术将原始图像映射到几何不变空间内,结合不变质心理论提取出归一化图像的重要区域;...
matlab遗传算法学习和全局化算法参考.pdf
1.2.12. 局部变量与全局变量 9 1.2.13. 显示标准错误信息 9 1.3. VBScript 9 1.3.1. 命名规范 9 1.3.2. 常量命名规范 9 1.3.3. 变量命名规范 9 1.3.4. 变量作用范围 9 1.3.5. 变量与函数命名 10 1.3.6. 对象...
主要介绍了asp.net core webapi项目配置全局路由的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
03_JPA详解_搭建JPA开发环境和全局事务介绍.zip
matlab开发-获取全局和全局级别。获取1992年至今全球平均海平面的时间序列。
目前与本文档相对应的产品版本为:ZStack 2.1 ZStack 2.1 开发手册 系统全局相关
matlab开发-确定全局信号回归的必要性。一种确定静息状态fmri研究中全局信号回归必要性的方法
matlab遗传算法学习和全局化算法.docxmatlab遗传算法学习和全局化算法.docxmatlab遗传算法学习和全局化算法.docxmatlab遗传算法学习和全局化算法.docxmatlab遗传算法学习和全局化算法.docxmatlab遗传算法学习和全局...
论文研究-矿产资源开发全局优化决策的多目标集成技术.pdf, 从系统论的观点出发,提出了矿产资源开发复杂大系统的概念,探讨了矿产资源开发全局优化决策的多目标集成方法...
03_传智播客JPA详解_搭建JPA开发环境和全局事务介绍
尽管强化学习(RL)最初是为解决马尔可夫决策问题而开发的,但可以与某些改进一起使用以优化数学函数。 在MORELA的核心处,围绕在可行解决方案空间中找到的最佳解决方案生成一个子环境,并将其与原始环境进行比较。...
matlab开发-全局优化。globalmin查找给定间隔内实变量x的函数f(x)的全局最小值。
Axure9 教程:利用全局变量实现跨页面传值.docx
uni开发微信小程序解决全局分享分销问题 1. 需求 1.小程序内每个页面都要打开胶囊分享按钮并实现分销 2.分享功能应该是在用户登录之后才予以打开 3.不想做在每个页面都写分享钩子的傻逼操作 2.实现 1.技术点: vueX ...
XWEB框架是一款基于Python语言的Web开发框架 ##Why Python? 我曾经使用过Java、PHP、Ruby和Python来开发Web应用,至于为什么使用Python作为XWEB的语言,其实最主要的原因: 1. Ruby不再需要新的WEB开发框架,...
周期监听 pageListener 能监听所有页面的 onLoad、onShow 等周期事件,方便埋点、统计等行为。 全局事件 methods,一处声明,所有 wxml 直接可用的函数。 适合原生小程序,即使后期引入,也只需增加几行代码。 更新...