1.统计接口调用耗时
一般我们在不借助第三方工具的情况下,打印接口耗时通常会在接口处理逻辑的开始和结束位置分别记录当前时间戳,然后计算时间差来获取耗时,如下示例:
@GetMapping("/time") public Object time() throws Exception { startTime = Instant.now(); //TODO, 业务操作 System.err.printf("接口耗时: %d 毫秒%n", (Duration.between(startTime, Instant.now()).toMillis())); return "take time"; }
上面统计了耗时情况,但是不够准确,为了更准确地反应处整个请求处理过程的耗时,包括Spring框架根据请求查找对应的Controller、拦截器执行等操作,SpringMVC在这些过程执行完成后是发布了一个事件,我们可以通过监听该事件来获取整个请求生命周期的耗时,如下示例:
@Component public class TakeTimeCountListener implements ApplicationListener<ServletRequestHandledEvent> { @Override public void onApplicationEvent(ServletRequestHandledEvent event) { Throwable failureCause = event.getFailureCause() ; if (failureCause != null) { System.err.printf("错误原因: %s%n", failureCause.getMessage()) ; } System.err.printf("请求客户端地址:%s, 请求URL: %s, 请求Method: %s, 请求耗时: %d%n", event.getClientAddress(), event.getRequestUrl(), event.getMethod(), event.getProcessingTimeMillis()) ; } }
通过监听ServletRequestHandledEvent事件,可以有效的获取客户端地址,请求的URL等完整的信息,其中ProcessingTimeMillis属性反应的就是这个请求耗时情况。
是不是非常的方便及准确!
2. 动态注册静态资源
通常情况下,一般都是在配置文件中或者自定义WebMvcConfigurer进行静态资源的配置及注册,如下示例:
spring:
web:
resources:
static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
以上是默认的路径,我们可以在这自定义自己的今天资源路径。如下添加文件系统目录
spring:
web:
resources:
static-locations: ..., file:///d:/images/
也可以通过编程的方式注册静态资源
public class WebConfig implements WebMvcConfigurer { public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/images/**").addResourceLocations("file:///d:\\images\\") ; } }
以上方式都是实现配置或代码中定义好,这都需要重启服务,无法做到实时生效。要想实时生效可以通过如下方式动态注册
@RestController public class RegController { @Resource private SimpleUrlHandlerMapping resourceHandlerMapping ; @Resource private ApplicationContext context ; // 如:requestURI=/s/**, path=d:/images/ @GetMapping("") public Object reg(String requestURI, String path) throws Throwable { ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler(); handler.setLocations(List.of(new FileSystemResource(path))) ; handler.setApplicationContext(context) ; handler.afterPropertiesSet() ; resourceHandlerMapping.registerHandler(requestURI, handler); return "register success"; } }
通过如上方式动态注册静态资源,你也可以对相应的静态资源进行删除。
3. 容器启动完成操作
当你希望Spring容器正确初始化加载完成以后,执行一些操作,那么你可以监听ContextRefreshedEvent事件。该实际的触发是在refresh方法执行的最后阶段。
@Component public class ContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> { @Override public void onApplicationEvent(ContextRefreshedEvent event) { System.out.println("上下文刷新完成...") ; // TODO } }
通过监听该事件,你可以在这里实现你自己的逻辑。