转载请注明出处哈:http://carlosfu.iteye.com/blog/2240426
一、spring-mvc添加拦截器配置: 对所有/下的访问都做拦截
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.sohu.tv.mobil.web.interceptor.VisitCounterStatInterceptor"/> </mvc:interceptor> </mvc:interceptors>
二、 定义VisitCounterStatInterceptor
1. 这里我们使用了guava的中的AtomicLongMap, 它的底层是ConcurrentHashMap<String,Long>,可以用来记录每个key的counter, 可以作为一种很高效的计数器。
2. 这里我们用定义了两个AtomicLongMap, 分别记录每个controller-uri对应的访问次数以及慢查询次数(例如超过100秒)。
3. 耗时是通过ThreadLocal来记录,在preHandle记录开始时间,在afterCompletion计算整个controller的耗时,但是这里强调一下finally中一定要调用costThreadLocal.remove();
package com.sohu.tv.mobil.web.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.google.common.util.concurrent.AtomicLongMap; /** * 访问相关统计拦截器 * * @author leifu * @Date 2015年10月30日 * @Time 上午9:36:16 */ public class VisitCounterStatInterceptor extends HandlerInterceptorAdapter { private Logger logger = LoggerFactory.getLogger(VisitCounterStatInterceptor.class); /** * 记录接口访问 */ public static final AtomicLongMap<String> VISIT_COUNT_MAP = AtomicLongMap.create(); /** * 记录接口慢查询 */ public static final AtomicLongMap<String> VISIT_SLOW_COST_MAP = AtomicLongMap.create(); /** * 耗时 */ private ThreadLocal<Long> costThreadLocal = new ThreadLocal<Long>(); /** * 最大接受的耗时 */ private final static long MAX_ACCEPT_TIME = 100; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String uri = request.getRequestURI(); if (StringUtils.isNotBlank(uri)) { VISIT_COUNT_MAP.incrementAndGet(uri); // 记录startTime costThreadLocal.set(System.currentTimeMillis()); } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { try { String uri = request.getRequestURI(); if (StringUtils.isNotBlank(uri)) { long startTime = costThreadLocal.get(); long costTime = System.currentTimeMillis() - startTime; if (costTime > MAX_ACCEPT_TIME) { VISIT_SLOW_COST_MAP.incrementAndGet(uri); } } } catch (Exception e) { logger.error(e.getMessage(), e); } finally { costThreadLocal.remove(); } } }
三、利用jmx记录controller-uri的调用统计
1. 定义MBean:
package com.sohu.tv.mobil.common.jmx; import java.util.Map; public interface CounterMapMBean { void clear(); Map<String,Long> getCounterMap(); }
2.定义MBean的实现:
package com.sohu.tv.mobil.common.jmx.impl; import com.google.common.util.concurrent.AtomicLongMap; import com.sohu.tv.mobil.common.jmx.CounterMapMBean; import java.util.*; public class CounterMapImpl implements CounterMapMBean { public final AtomicLongMap<String> counterMap; public CounterMapImpl(AtomicLongMap<String> counterMap) { this.counterMap = counterMap; } @Override public void clear() { counterMap.clear(); } @Override public Map<String, Long> getCounterMap() { List<Map.Entry<String, Long>> entryList = new ArrayList<>(counterMap.asMap().entrySet()); Collections.sort(entryList, new Comparator<Map.Entry<String, Long>>() { @Override public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) { Long v1 = o1.getValue(); Long v2 = o2.getValue(); if (v1 > v2) { return -1; } else if (v1 < v2) { return 1; } else { return o1.getKey().compareTo(o2.getKey()); } } }); Map<String, Long> resultMap = new LinkedHashMap<String, Long>(); for (Map.Entry<String, Long> entry : entryList) { resultMap.put(entry.getKey(), entry.getValue()); } return resultMap; } }
3. 在spring中定义jmx:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd" default-autowire="byName"> <bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"> <property name="locateExistingServerIfPossible" value="true"/> </bean> <bean id="visitCounterMap" class="com.sohu.tv.mobil.common.jmx.impl.CounterMapImpl"> <constructor-arg index="0"> <util:constant static-field="com.sohu.tv.mobil.web.interceptor.VisitCounterStatInterceptor.VISIT_COUNT_MAP"/> </constructor-arg> </bean> <bean id="visitSlowCostMap" class="com.sohu.tv.mobil.common.jmx.impl.CounterMapImpl"> <constructor-arg index="0"> <util:constant static-field="com.sohu.tv.mobil.web.interceptor.VisitCounterStatInterceptor.VISIT_SLOW_COST_MAP"/> </constructor-arg> </bean> <bean id="mBeanServer" class="org.springframework.jmx.export.MBeanExporter"> <property name="beans"> <map> <entry key="mobilJMX:myjavaobj=visitCounterMap" value-ref="visitCounterMap"/> <entry key="mobilJMX:myjavaobj=visitSlowCostMap" value-ref="visitSlowCostMap"/> </map> </property> <property name="server" ref="mbeanServer"/> <property name="assembler" ref="assembler"/> </bean> <bean id="assembler" class="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler"> <property name="managedInterfaces"> <list> <value>com.sohu.tv.mobil.common.jmx.CounterMapMBean</value> </list> </property> </bean> </beans>
4. 上线后,就可以在jvisualvm或者jconsole中看到MBean的调用统计:
5. 我们在后台,调用jmx,并做成界面:
四、 存在的几个问题
1. request.getRequestURI()可能会存在问题,比如如果使用了如下配置,可能会撑爆AtomicLongMap, 造成内存溢出,解决方法还要进一步观察(但是暂时我们的系统没有使用这种调用方式)
@RequestMapping(value = "/drama/{pid}", produces = "text/javascript; charset=UTF-8")
2. 使用了<mvc:mapping path="/**"/>后,出现了很多奇怪的uri, 比如下图中的情况,具体原因还要查询。
3. jmx是非持久化的,只能查询实时数据,如果需要的话可以定期统计jmx到mysql或者其他存储,方便查询历史数据,帮助有效定位问题
4. jmx的数据可以结合nagios或者ganglia来使用,不需要单独开发后台界面。
附图一张:
相关推荐
3. `org.springframework.web.servlet-3.0.2.RELEASE.jar`:这是 Spring MVC 的核心模块,提供了控制器(Controller)、模型视图(ModelAndView)以及调度器Servlet(DispatcherServlet)等关键组件。...
MVC(Model-View-Controller)设计模式是构建动态网站的标准模式之一。`spring-webmvc.jar`实现了这一模式,提供了控制器、视图解析器、表单标签库等功能。它使得构建Web应用变得更加简单、直观。 #### spring-...
6. **JMX(Java Management Extensions)集成**:Spring 3.0 提供了对 JMX 的全面支持,使应用程序的管理更加便捷,可以监控和管理应用的运行状态。 7. **Spring Expression Language (SpEL)**:Spring 3.0 引入的 ...
2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6 .3. 任务规划 2.6.4. 对Java 5(Tiger)的支持 2.7. 移植到Spring 2.0 ...
此外,Spring 0.9还包括对JMS(Java Message Service)、JMX(Java Management Extensions)以及邮件服务的支持,为企业级应用开发提供了全面的解决方案。 总结,Spring框架0.9版本虽然相比现在的高级版本在功能上...
4. **MVC(Model-View-Controller)**:Spring MVC是Spring框架的一部分,用于构建Web应用程序。它提供了一个灵活的架构,将模型、视图和控制器分离,使得代码结构清晰,易于维护。在3.2.5版本中,Spring MVC引入了...
8. **JMX支持**:Spring 3.2.4提供了对Java Management Extensions(JMX)的增强支持,允许应用管理和监控。 9. **WebSocket支持**:在3.2版本中,Spring引入了对WebSocket协议的支持,以实现双向通信,提高了Web...
7. **WebMvc**:这部分是Spring MVC,Spring的Model-View-Controller实现,是构建Web应用的主要组件。它提供了控制器、视图解析、数据绑定等功能,使开发者能够快速构建高性能的Web应用。 在Spring 4.2.0版本中,有...
3. **MVC(Model-View-Controller)**:Spring MVC是Spring框架的一部分,用于构建Web应用程序。它提供了一种模型驱动的方式,将业务逻辑、数据展示和用户交互分离。 **Spring 4的新特性和改进** 1. **Java 8支持*...
4. **Spring MVC增强**:Spring 3.0的MVC模块有了显著增强,如支持RESTful风格的Web服务,改进的模型-视图-控制器(Model-View-Controller)架构,以及强大的视图解析能力。 5. **JMX支持**:增加了对Java ...
这两个框架在Java企业级应用开发中占据着重要地位,Struts提供了MVC(Model-View-Controller)架构,而Spring则为依赖注入(Dependency Injection)和面向切面编程(Aspect-Oriented Programming)提供了强大支持。...
这个压缩包中的 jar 文件包含了 Spring MVC、Spring 和 iBATIS 的所有依赖,方便开发者快速搭建开发环境。使用这些 jar 包时,要注意版本兼容性,确保各个组件之间的协调工作。同时,随着技术的发展,现代项目更多地...
Struts2是一个强大的Java web应用程序框架,用于构建和管理MVC(Model-View-Controller)架构的Web应用程序。Struts2.1.8是该框架的一个特定版本,它包含了若干改进和更新,以提高开发效率和应用性能。在这个"struts...
再者,Struts是一个基于MVC(Model-View-Controller)设计模式的Web应用框架。它专注于控制层,处理HTTP请求,调用业务逻辑,然后将结果传递给视图层。Struts通过Action和ActionForm对象来处理用户请求,Action...
标题 "spring4+springMVC+mybaits3" 提示我们关注的是Spring框架的第四版(Spring 4)与Spring MVC以及MyBatis 3的整合应用。这是一个常见的Java Web开发技术栈,用于构建高效、灵活且可扩展的企业级应用程序。 ...
3. **MVC框架**:Spring MVC是Spring提供的Web开发框架,提供了Model-View-Controller模式的实现,支持RESTful、模板引擎等多种特性。 4. **测试**:Spring Test模块提供了对单元测试和集成测试的支持,与JUnit和...
2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态...
Spring还支持其他功能,如远程服务调用(RMI、Hessian、 Burlap)、邮件服务、任务调度、缓存(如 Ehcache 和 Hazelcast 集成)、JMX支持以及测试工具等。这些都为开发者提供了丰富的选择,以满足不同场景下的开发...
2.5.1. Spring MVC合理的默认值 2.5.2. Portlet 框架 2.5.3. 基于Annotation的控制器 2.5.4. Spring MVC的表单标签库 2.5.5. 对Tiles 2 支持 2.5.6. 对JSF 1.2支持 2.5.7. JAX-WS支持 2.6. 其他 2.6.1. 动态...