JAVA小工具-05-利用springmvc拦截器实现接口调用监控
程序员文章站
2022-07-09 19:08:20
...
言于头:在项目中服务中通常我们需要监控服务接口的调用情况,在springboot项目中,我们可以使用 spring-boot-starter-actuator模块进行实现,然而在spring体系中,我们也可以利用mvc拦截器进行简单实现。
下面就是一个利用HandlerInterceptor和WebMvcConfigurer 实现的服务接口调用监控小例子,完整代码整理如下。
/**
* 拦截器策略配置类
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry interceptorRegistry) {
InterceptorRegistration registration=interceptorRegistry.addInterceptor(new ControllerInterceptor());
// 此处添加拦截策略 /**表示全部拦截
registration.addPathPatterns("/**");
}
@Override
public void configurePathMatch(PathMatchConfigurer pathMatchConfigurer) {}
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer contentNegotiationConfigurer) {}
@Override
public void configureAsyncSupport(AsyncSupportConfigurer asyncSupportConfigurer) { }
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer defaultServletHandlerConfigurer) {}
@Override
public void addFormatters(FormatterRegistry formatterRegistry) {}
@Override
public void addResourceHandlers(ResourceHandlerRegistry resourceHandlerRegistry) {}
@Override
public void addCorsMappings(CorsRegistry corsRegistry) {}
@Override
public void addViewControllers(ViewControllerRegistry viewControllerRegistry) {}
@Override
public void configureViewResolvers(ViewResolverRegistry viewResolverRegistry) {}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) {}
@Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) {}
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> list) {}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> list) {}
@Override
public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {}
@Override
public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> list) {}
@Override
public Validator getValidator() {return null;}
@Override
public MessageCodesResolver getMessageCodesResolver() {return null;}
}
/**
* 拦截后的处理类
*/
public class ControllerInterceptor implements HandlerInterceptor {
private static final Logger LOGGER = LoggerFactory.getLogger(ControllerInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String method = request.getMethod();
String url = request.getRequestURL().toString();
String requestIp = getRequestIp(request);
StringBuilder sb = new StringBuilder();
sb .append("【开始请求】:\n-------------------------------------------------------------\n");
HandlerMethod h = (HandlerMethod) handler;
sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n");
sb.append("Method : ").append(method).append("\n");
sb.append("URL : ").append(url).append("\n");
sb.append("IP : ").append(requestIp).append("\n");
sb .append("-------------------------------------------------------------\n");
LOGGER.info(sb.toString());
// 填入当前接口的调用开始时间
request.setAttribute("startTime",System.currentTimeMillis());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView mav) {}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception) {
String method = request.getMethod();
String url = request.getRequestURL().toString();
Long startTime=(Long)request.getAttribute("startTime");
Long expireTime=System.currentTimeMillis()-startTime;
String requestIp = getRequestIp(request);
StringBuilder sb = new StringBuilder();
sb .append("【结束请求】:\n-------------------------------------------------------------\n");
HandlerMethod h = (HandlerMethod) handler;
sb.append("Controller: ").append(h.getBean().getClass().getName()).append("\n");
sb.append("Method : ").append(method).append("\n");
sb.append("URL : ").append(url).append("\n");
sb.append("IP : ").append(requestIp).append("\n");
sb.append("EXPIRETIME: ").append(expireTime).append("(ms)\n");
sb .append("-------------------------------------------------------------\n");
LOGGER.info(sb.toString());
}
/* *
* @description: 获取客户端真实IP
**/
private String getRequestIp(HttpServletRequest request)
{
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if(ip.equals("127.0.0.1")){
//根据网卡取本机配置的IP
InetAddress inet=null;
try {
inet = InetAddress.getLocalHost();
} catch (Exception e) {
LOGGER.error("获取ip异常",e);
}
if (inet!=null){
ip= inet.getHostAddress();
}else{
ip="";
}
}
}
// 多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if(ip != null && ip.length() > 15 && ip.indexOf(",")>=1){
ip = ip.substring(0,ip.indexOf(","));
}
return ip;
}
}
项目中加入以上配置后,在接口调用时会输出接口调用类、方法类型、请求的url、客户端IP以及调用完成后本次请求的耗时信息等。调用结果如下: