spring.cache 随笔0 集成设计

news/2025/2/20 0:37:43/

0. 最近感觉 “困意驱动睡眠” 也有他的意义

spring cache学习(一):spring cache注解简单了解

Java Caching JSR107介绍


同样,本章也会简单的集成redisson作为缓存服务

1. 从我们自己写的javaConfig开始吧

@Configuration
// 这块依赖只是为了先初始化 RedissonClient
@ConditionalOnClass(DemoRedissonConfiguration.class)
@DependsOn(value = "demoRedissonConfiguration")
@EnableCaching
// spring.cache 提供了 configurer 的方式暴露可配置的接入点
public class DemoCacheConfiguration extends CachingConfigurerSupport {private RedissonClient redissonClient;@Autowired(required = false)public void setRedissonClient(RedissonClient redissonClient) {this.redissonClient = redissonClient;}@Bean@Overridepublic KeyGenerator keyGenerator() {return new KeyGenerator() {/*** 返回key* @param target 包名* @param method 方法名* @param params 参数* @return key 缓存密钥*/@Overridepublic Object generate(Object target, Method method, Object... params) {StringBuilder sb = new StringBuilder();//拼接字符串sb.append(target.getClass().getName());sb.append(method.getName());sb.append("(");for (Object obj : params) {if (obj == null) {continue;}sb.append(obj.toString());sb.append(",");}sb.deleteCharAt(sb.length() - 1);sb.append(")");return sb.toString();}};}// Redisson 分布式缓存实现
//    @Primary
//    @Bean
//    @ConditionalOnClass({RedissonClient.class})
//    @Override
//    public CacheManager cacheManager() {
//        Map<String, CacheConfig> config = Maps.newHashMap();
//        Arrays.stream(CacheEnum.values()).filter(Objects::nonNull).forEach(var -> {
//            String cacheName = var.getName();
//            cn.angel.boot.demo.cache.CacheConfig  cacheConfig = var.getConfig();
//            CacheConfig redissonCacheConfig = new CacheConfig(cacheConfig.getExpireInSec(), cacheConfig.getExpireInSec());
//            config.put(cacheName, redissonCacheConfig);
//        });
//        return new RedissonSpringCacheManager(this.redissonClient, config);
//    }// Caffeine JVM缓存实现@Bean@Overridepublic CacheManager cacheManager() {SimpleCacheManager cacheManager = new SimpleCacheManager();List<CaffeineCache> caches = Arrays.stream(CacheEnum.values()).filter(Objects::nonNull).map(var -> {String cacheName = var.getName();CacheConfig cacheConfig = var.getConfig();return new CaffeineCache(cacheName,Caffeine.newBuilder().initialCapacity(cacheConfig.getInitialCapacity()).maximumSize(cacheConfig.getMaximumSize()).expireAfterWrite(cacheConfig.getExpireInSec(), TimeUnit.SECONDS).build());}).collect(Collectors.toList());cacheManager.setCaches(caches);return cacheManager;}
}

1.1 补充:spring.context.no-lazy.@Bean的初始化

  • 其实跟普通的bean初始化的位置是一样的

  • @Configuration.ProxyBeanMethod设为false,将不会走BeanMethodInterceptor

    • 此时调用其下的bean工厂方法将会产生一个实例,并不会优先从池中查找,这点需要注意
    • 这么做的好处即,少走一步,提升初始化的性能
// 我们自己的配置类
cacheManager:94, DemoCacheConfiguration (cn.angel.boot.demo.cache)
CGLIB$cacheManager$0:-1, DemoCacheConfiguration$$EnhancerBySpringCGLIB$$1feb92ca (cn.angel.boot.demo.cache)
invoke:-1, DemoCacheConfiguration$$EnhancerBySpringCGLIB$$1feb92ca$$FastClassBySpringCGLIB$$82302b20 (cn.angel.boot.demo.cache)
invokeSuper:244, MethodProxy (org.springframework.cglib.proxy)// @Configuration(proxyBeanMethods默认true)就会走这里
intercept:331, ConfigurationClassEnhancer$BeanMethodInterceptor (org.springframework.context.annotation)
cacheManager:-1, DemoCacheConfiguration$$EnhancerBySpringCGLIB$$1feb92ca (cn.angel.boot.demo.cache)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
instantiate:154, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
instantiate:650, ConstructorResolver (org.springframework.beans.factory.support)
// 在这里实例化工厂方法的返回值
instantiateUsingFactoryMethod:483, ConstructorResolver (org.springframework.beans.factory.support)
instantiateUsingFactoryMethod:1336, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)createBeanInstance:1176, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:556, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 1591916281 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$134)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)// 跟普通的spring.no-lazy-bean一同初始化
preInstantiateSingletons:897, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:879, AbstractApplicationContext (org.springframework.context.support)
refresh:551, AbstractApplicationContext (org.springframework.context.support)

1.2 补充:configurer范式

  • 相比于 Customizer 的扩展方法,我还是更喜欢 configurer的方式

  • spring.function.SingletonSupplier 是个函数式接口,impls j.u.Function

    • 这也是configurer 扩展模式的"奥秘",即借助函数式接口延迟执行,随取随用

看下我们对configurer中CacheManager的实现方法,在哪里被访问

cacheManager:72, DemoCacheConfiguration (cn.angel.boot.demo.cache)
get:-1, 497333241 (org.springframework.cache.annotation.AbstractCachingConfiguration$$Lambda$361)
resolve:40, SupplierUtils (org.springframework.util.function)// 简单来说就是 CacheResolver 委托了 CacheManager
// CacheResolver 帮助 CacheManager 利用cache的cacheName
lambda$configure$0:119, CacheAspectSupport (org.springframework.cache.interceptor)
get:-1, 5987161 (org.springframework.cache.interceptor.CacheAspectSupport$$Lambda$372)
get:100, SingletonSupplier (org.springframework.util.function)
resolve:40, SupplierUtils (org.springframework.util.function)getCacheResolver:185, CacheAspectSupport (org.springframework.cache.interceptor)
afterSingletonsInstantiated:217, CacheAspectSupport (org.springframework.cache.interceptor)// 可以看到在程序启动过程中就已经访问了
preInstantiateSingletons:914, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:879, AbstractApplicationContext (org.springframework.context.support)
refresh:551, AbstractApplicationContext (org.springframework.context.support)

2. spring.cache 相关注解的元信息解析

这个也是发生在程序启动过程中的,准确的来说,是在AbstractAutoProxyCreator.postProcessAfterInitialization这个阶段

  • CacheOperation 即我们使用的spring.cache 或 javax.caching(spring中称之为JCache) 注解被解析后的元信息
  • CacheOperationSource 用于引导 CacheOperation 初始化的
// 这玩意用来解析 cache 相关的注解的
parseCacheAnnotations:98, SpringCacheAnnotationParser (org.springframework.cache.annotation)
parseCacheAnnotations:83, SpringCacheAnnotationParser (org.springframework.cache.annotation)
parseCacheAnnotations:78, SpringCacheAnnotationParser (org.springframework.cache.annotation)
// AnnotationCacheOperationSource is-a CacheOperationSource
lambda$findCacheOperations$1:125, AnnotationCacheOperationSource (org.springframework.cache.annotation)
getCacheOperations:-1, 265330243 (org.springframework.cache.annotation.AnnotationCacheOperationSource$$Lambda$376)
determineCacheOperations:141, AnnotationCacheOperationSource (org.springframework.cache.annotation)
findCacheOperations:125, AnnotationCacheOperationSource (org.springframework.cache.annotation)
computeCacheOperations:137, AbstractFallbackCacheOperationSource (org.springframework.cache.interceptor)
getCacheOperations:99, AbstractFallbackCacheOperationSource (org.springframework.cache.interceptor)
matches:48, CacheOperationSourcePointcut (org.springframework.cache.interceptor)
canApply:252, AopUtils (org.springframework.aop.support)
canApply:289, AopUtils (org.springframework.aop.support)
findAdvisorsThatCanApply:321, AopUtils (org.springframework.aop.support)
findAdvisorsThatCanApply:128, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
findEligibleAdvisors:97, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:78, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
wrapIfNecessary:347, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
// 这里找上了代理
postProcessAfterInitialization:299, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:430, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
// bean实例化的后置处理initializeBean:1798, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:594, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:516, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:324, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 1123236701 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$130)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:322, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)preInstantiateSingletons:897, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:879, AbstractApplicationContext (org.springframework.context.support)
refresh:551, AbstractApplicationContext (org.springframework.context.support)

注解的解析逻辑

// org.springframework.cache.annotation.SpringCacheAnnotationParser.java// 被注解的Method -> CacheConfig@Override@Nullablepublic Collection<CacheOperation> parseCacheAnnotations(Method method) {DefaultCacheConfig defaultConfig = new DefaultCacheConfig(method.getDeclaringClass());return parseCacheAnnotations(defaultConfig, method);}@Nullableprivate Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae) {Collection<CacheOperation> ops = parseCacheAnnotations(cachingConfig, ae, false);if (ops != null && ops.size() > 1) {// More than one operation found -> local declarations override interface-declared ones...Collection<CacheOperation> localOps = parseCacheAnnotations(cachingConfig, ae, true);if (localOps != null) {return localOps;}}return ops;}@Nullableprivate Collection<CacheOperation> parseCacheAnnotations(DefaultCacheConfig cachingConfig, AnnotatedElement ae, boolean localOnly) {Collection<? extends Annotation> anns = (localOnly ?AnnotatedElementUtils.getAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS) :AnnotatedElementUtils.findAllMergedAnnotations(ae, CACHE_OPERATION_ANNOTATIONS));if (anns.isEmpty()) {return null;}// 就这几个cache注解final Collection<CacheOperation> ops = new ArrayList<>(1);anns.stream().filter(ann -> ann instanceof Cacheable).forEach(ann -> ops.add(parseCacheableAnnotation(ae, cachingConfig, (Cacheable) ann)));anns.stream().filter(ann -> ann instanceof CacheEvict).forEach(ann -> ops.add(parseEvictAnnotation(ae, cachingConfig, (CacheEvict) ann)));anns.stream().filter(ann -> ann instanceof CachePut).forEach(ann -> ops.add(parsePutAnnotation(ae, cachingConfig, (CachePut) ann)));anns.stream().filter(ann -> ann instanceof Caching).forEach(ann -> parseCachingAnnotation(ae, cachingConfig, (Caching) ann, ops));return ops;}// cacheConfig -> CacheOperationprivate CacheableOperation parseCacheableAnnotation(AnnotatedElement ae, DefaultCacheConfig defaultConfig, Cacheable cacheable) {CacheableOperation.Builder builder = new CacheableOperation.Builder();builder.setName(ae.toString());builder.setCacheNames(cacheable.cacheNames());builder.setCondition(cacheable.condition());builder.setUnless(cacheable.unless());builder.setKey(cacheable.key());builder.setKeyGenerator(cacheable.keyGenerator());builder.setCacheManager(cacheable.cacheManager());builder.setCacheResolver(cacheable.cacheResolver());builder.setSync(cacheable.sync());defaultConfig.applyDefault(builder);CacheableOperation op = builder.build();validateCacheOperation(ae, op);return op;}

AnnotationCacheOperationSource 内部维护了 SpringCacheAnnotationParser
请添加图片描述

CacheOperationSource 引导了 CacheOperation 的初始化
请添加图片描述

3. 接入 spring.expression

这块解析 spel表达式肯定是发生在运行过程中的

parseExpression:43, TemplateAwareExpressionParser (org.springframework.expression.common)
getExpression:89, CachedExpressionEvaluator (org.springframework.context.expression)
key:104, CacheOperationExpressionEvaluator (org.springframework.cache.interceptor)
// 接入 spring.expressiongenerateKey:795, CacheAspectSupport$CacheOperationContext (org.springframework.cache.interceptor)
generateKey:592, CacheAspectSupport (org.springframework.ciiiiiache.interceptor)
findCachedItem:535, CacheAspectSupport (org.springframework.cache.interceptor)
execute:402, CacheAspectSupport (org.springframework.cache.interceptor)
execute:346, CacheAspectSupport (org.springframework.cache.interceptor)
invoke:61, CacheInterceptor (org.springframework.cache.interceptor)
// CahceInterceptorproceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:749, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:691, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
cache:-1, DemoCacheController$$EnhancerBySpringCGLIB$$5086a077 (cn.angel.boot.demo.cache)
// 我们的代理方法invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:190, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:105, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:878, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:792, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1040, DispatcherServlet (org.springframework.web.servlet)
doService:943, DispatcherServlet (org.springframework.web.servlet)
processRequest:1006, FrameworkServlet (org.springframework.web.servlet)
doGet:898, FrameworkServlet (org.springframework.web.servlet)
service:626, HttpServlet (javax.servlet.http)
service:883, FrameworkServlet (org.springframework.web.servlet)
service:733, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:100, RequestContextFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, FormContentFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, WebMvcMetricsFilter (org.springframework.boot.actuate.metrics.web.servlet)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:201, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:202, StandardWrapperValve (org.apache.catalina.core)
invoke:97, StandardContextValve (org.apache.catalina.core)
invoke:541, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:143, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:374, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:868, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1590, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)

4. 接入 aop

请添加图片描述

  • spring.cache 整合了 javax.caching(JCache)、spring 两种风格

  • javax.caching 是一套规范,而非实现,redisson支持了其实现

  • javax.caching 支持 进程层面的缓存、分布式缓存,通过声明(注解)使用

cache:22, DemoCacheController (cn.angel.boot.demo.cache)
invoke:-1, DemoCacheController$$FastClassBySpringCGLIB$$4381acd0 (cn.angel.boot.demo.cache)
invoke:218, MethodProxy (org.springframework.cglib.proxy)
invokeJoinpoint:771, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
proceed:163, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:749, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
// 往上就是cglib代理类反射调用方法lambda$invoke$0:53, CacheInterceptor (org.springframework.cache.interceptor)
invoke:-1, 209189072 (org.springframework.cache.interceptor.CacheInterceptor$$Lambda$938)// 该切面为@Cacheable处理逻辑// 缓存命中,直接返回// 没有命中,调用原始方法// Cache.put()// 如果有的话,执行缓存的延迟失效(该失效方法支持 延迟/即可 失效)// Cache.evict()// 及其相关的clear方法清理资源
invokeOperation:366, CacheAspectSupport (org.springframework.cache.interceptor)
execute:421, CacheAspectSupport (org.springframework.cache.interceptor)
// 使用的命令行,可支持批量的操作,CacheOperation
execute:346, CacheAspectSupport (org.springframework.cache.interceptor)
// MethodInterceptor 来的(同时也 exts CacheAspectSupport)
invoke:61, CacheInterceptor (org.springframework.cache.interceptor)// 进入切面
proceed:186, ReflectiveMethodInvocation (org.springframework.aop.framework)
proceed:749, CglibAopProxy$CglibMethodInvocation (org.springframework.aop.framework)
intercept:691, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
cache:-1, DemoCacheController$$EnhancerBySpringCGLIB$$e4584159 (cn.angel.boot.demo.cache)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:190, InvocableHandlerMethod (org.springframework.web.method.support)
invokeForRequest:138, InvocableHandlerMethod (org.springframework.web.method.support)
invokeAndHandle:105, ServletInvocableHandlerMethod (org.springframework.web.servlet.mvc.method.annotation)
invokeHandlerMethod:878, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handleInternal:792, RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
handle:87, AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
doDispatch:1040, DispatcherServlet (org.springframework.web.servlet)
doService:943, DispatcherServlet (org.springframework.web.servlet)
processRequest:1006, FrameworkServlet (org.springframework.web.servlet)
doGet:898, FrameworkServlet (org.springframework.web.servlet)
service:626, HttpServlet (javax.servlet.http)
service:883, FrameworkServlet (org.springframework.web.servlet)
service:733, HttpServlet (javax.servlet.http)
internalDoFilter:231, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilter:53, WsFilter (org.apache.tomcat.websocket.server)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:100, RequestContextFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, FormContentFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:93, WebMvcMetricsFilter (org.springframework.boot.actuate.metrics.web.servlet)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
doFilterInternal:201, CharacterEncodingFilter (org.springframework.web.filter)
doFilter:119, OncePerRequestFilter (org.springframework.web.filter)
internalDoFilter:193, ApplicationFilterChain (org.apache.catalina.core)
doFilter:166, ApplicationFilterChain (org.apache.catalina.core)
invoke:202, StandardWrapperValve (org.apache.catalina.core)
invoke:97, StandardContextValve (org.apache.catalina.core)
invoke:541, AuthenticatorBase (org.apache.catalina.authenticator)
invoke:143, StandardHostValve (org.apache.catalina.core)
invoke:92, ErrorReportValve (org.apache.catalina.valves)
invoke:78, StandardEngineValve (org.apache.catalina.core)
service:343, CoyoteAdapter (org.apache.catalina.connector)
service:374, Http11Processor (org.apache.coyote.http11)
process:65, AbstractProcessorLight (org.apache.coyote)
process:868, AbstractProtocol$ConnectionHandler (org.apache.coyote)
doRun:1590, NioEndpoint$SocketProcessor (org.apache.tomcat.util.net)
run:49, SocketProcessorBase (org.apache.tomcat.util.net)
runWorker:1149, ThreadPoolExecutor (java.util.concurrent)
run:624, ThreadPoolExecutor$Worker (java.util.concurrent)
run:61, TaskThread$WrappingRunnable (org.apache.tomcat.util.threads)
run:748, Thread (java.lang)

http://www.ppmy.cn/news/552659.html

相关文章

C语言学习(二十六)---指针练习题(二)

在上节的内容中&#xff0c;我们进一步学习了有关指针的内容&#xff0c;并做了一些关于指针的题目&#xff0c;今天我们将继续练习一些指针的题目&#xff0c;以便大家更好的理解和掌握指针的知识&#xff0c;好了&#xff0c;话不多说&#xff0c;开整&#xff01;&#xff0…

LOL(英雄联盟)提示不支持虚拟机登录,解决方法

LOL&#xff08;英雄联盟&#xff09;提示不支持虚拟机登录&#xff0c;解决方法 参考文章&#xff1a; &#xff08;1&#xff09;LOL&#xff08;英雄联盟&#xff09;提示不支持虚拟机登录&#xff0c;解决方法 &#xff08;2&#xff09;https://www.cnblogs.com/luoruiy…

LoL_Skip使用说明(英雄联盟换肤工具)

一、使用前注意&#xff1a; 记得将安装路径下的Game文件夹里的ClientZips.txt备份下&#xff0c;防止出现不可预料的事件的后续修复 二、使用方法&#xff1a; 1、将LoL_Skip解压到电脑上 2、双击LoL_Skip.bat运行 3、点击Game按钮选择LoL安装路径下的Game文件夹 4、点击进入…

不用装Windows!在MacOS中也可以玩英雄联盟LOL国服!

游戏体验一直都是 Mac 的短板&#xff0c;一方面是游戏生态匮乏导致的无游戏可玩&#xff0c;另一方面是性能和配置的偏向让 Mac 天生对游戏不太感冒。比如风靡全球的英雄联盟&#xff0c;Mac上目前只有美服版。今天小编就带来了在Mac上玩国服英雄联盟的好办法&#xff01; 腾…

Python进阶知识(四)

文章目录 1.Python并发编程之Futures2.Python 垃圾回收机制3.Python上下文管理器4.Python数组的存储和处理Numpy模块4.1. NumPy数组&#xff08;ndarray&#xff09;&#xff1a;4.2. 创建数组&#xff1a;4.3. 数组属性&#xff1a;4.4 数组索引和切片&#xff1a;4.5. 数组运…

远心镜头案例锦集

远心镜头&#xff08;Telecentric lens&#xff09; 定义&#xff1a;远心镜头是一类将其入瞳或出瞳放置于无穷远的光学系统。是为纠正传统镜头视差而设计&#xff0c;它可以在一定的物距范围内&#xff0c;使得到的图像放大倍率不会变化&#xff0c;即这种镜头拍出来的图像没…

算法--PageRank

概念 PageRank是Google提出的算法&#xff0c;用于衡量特定网页相对于搜索引擎索引中的其他网页而言的重要程度。是Google创始人拉里佩奇和谢尔盖布林于1997年创造的PageRank实现了将链接价值概念作为排名因素。 GOOGLE PageRank并不是唯一的链接相关的排名算法&#xff0c;而…

Mixly制作的MP3播放和七彩灯、台灯控制例子

Mixly制作的MP3播放和七彩灯、台灯控制例子 这是七彩灯的控制部分&#xff1b; MP3播放的竟然没保存&#xff0c;不过更简单。