spring.cache 随笔0 集成设计

news2024/10/6 1:46:26

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
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            /**
             * 返回key
             * @param target 包名
             * @param method 方法名
             * @param params 参数
             * @return key 缓存密钥
             */
            @Override
            public 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
    @Override
    public 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
	@Nullable
	public Collection<CacheOperation> parseCacheAnnotations(Method method) {
		DefaultCacheConfig defaultConfig = new DefaultCacheConfig(method.getDeclaringClass());
		return parseCacheAnnotations(defaultConfig, method);
	}

	@Nullable
	private 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;
	}

	@Nullable
	private 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 -> CacheOperation
    private 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.expression

generateKey: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)
// CahceInterceptor

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$$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.coloradmin.cn/o/680310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java——文件操作

文件操作 1、File类概述2、File类的常用APIFile类的判断文件类型、获取文件信息功能创建文件、删除文件功能遍历文件夹文件搜索 3、字符集常见字符集字符集的编码、解码操作 4、IO流分类5、字节流的使用文件字节输入流文件字节输出流文件拷贝 6、字符类的使用文件字符输入流文件…

“前端已死”

一、一些迹象 逛社区&#xff0c;偶然看到了这张图片&#xff1a; 嗯……我眉头一皱&#xff0c;久久不语&#xff0c;心想&#xff0c;有这么夸张吗&#xff0c;假的吧&#xff1f; 突然想到&#xff0c;最近我在社区发了个前端招聘的信息&#xff0c;结果简历漫天纷飞&…

【C++】auto_ptr为何被唾弃?以及其他智能指针的学习

搭配异常可以让异常的代码更简洁 文章目录 智能指针 内存泄漏的危害 1.auto_ptr(非常不建议使用) 2.unique_ptr 3.shared_ptr 4.weak_ptr总结 智能指针 C中为什么会需要智能指针呢&#xff1f;下面我们看一下样例&#xff1a; int div() {int a, b;cin >&g…

图表制作办公首选--实用图表工具Echars

实用图表工具Echars 前言 由于工作的需要&#xff0c;在写材料的时候需要使用到柱状图、饼状图、折线图等等展示数据&#xff0c;可以使用PPT等办公软件构建出图表&#xff0c;在这里可以使用更加方便、更加美观的工具Echars。 Echars图表使用 Echars官网&#xff1a;Ecahr…

二叉平衡树之红黑树

目录 1.概念 2.性质 3.节点的定义 4.插入 1.按照二叉搜索树规则插入结点 2.调整颜色 1.uncle存在且为红色 2.uncle不存在或者为黑 cur为 3.根节点改为黑色 5.验证 6.比较 7.应用 1.概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存…

【计算机网络】计算机网络期末自测题(一)

目录 一、 填空题&#xff1a;(20 分&#xff0c;每空 1 分) 二、 选择题(20 分&#xff0c;每小题 1 分) 三、不定项选择题 (10 分&#xff0c;每小题 1 分) 四、名词解释 (15 分&#xff0c;每小题 3 分) 五、简答题 (25 分) 得分 一、 填空题&#xff1a;(20 分&#xff…

【C++】STL——string类详解

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f681; 个人主页&#xff1a;不 良 &#x1f525; 系列专栏&#xff1a;&#x1f6f8;C &#x1f6f9;Linux &#x1f4d5; 学习格言&#xff1a;博观而约取&#xff0…

混合策略改进的哈里斯鹰优化算法-附代码

混合策略改进的哈里斯鹰优化算法 文章目录 混合策略改进的哈里斯鹰优化算法1.哈里斯鹰优化算法2.改进哈里斯鹰优化算法2.1 初始化种群的改进2.1.1 初始种群多样化2.1.2 初始种群精英化 2.2 逃逸能量递减机制的改进2.4 拉普拉斯交叉算子策略 3.实验结果4.参考文献5.Matlab代码6.…

6.17 、Java初级:锁

1 同步锁 1.1 前言 经过前面多线程编程的学习,我们遇到了线程安全的相关问题,比如多线程售票情景下的超卖/重卖现象. 上节笔记点这里-进程与线程笔记 我们如何判断程序有没有可能出现线程安全问题,主要有以下三个条件: 在多线程程序中 有共享数据 多条语句操作共享数据 多…

移动web-渐变

渐变 使用场景&#xff1a;使用background-image属性实现渐变背景效果 代码&#xff1a;background-image: linear-gradient(参数1,参数2,参数3...); (默认的方位从上到下) 参数1 方位名词: to right, to left 角度deg: 直接写度数 参数2 颜色1 参数3 颜色2... 注意&#xff…

看完这篇 教你玩转渗透测试靶机vulnhub—Corrosion:1

Vulnhub靶机Corrosion:1渗透测试详解 Vulnhub靶机介绍&#xff1a;Vulnhub靶机下载&#xff1a;Vulnhub靶机安装&#xff1a;Vulnhub靶机漏洞详解&#xff1a;①&#xff1a;信息收集&#xff1a; Vulnhub靶机渗透总结&#xff1a; Vulnhub靶机介绍&#xff1a; vulnhub是个提…

canvas详解01-绘制基本图形

既然我们已经设置了 canvas 环境&#xff0c;我们可以深入了解如何在 canvas 上绘制。到本文的最后&#xff0c;你将学会如何绘制矩形&#xff0c;三角形&#xff0c;直线&#xff0c;圆弧和曲线&#xff0c;变得熟悉这些基本的形状。绘制物体到 Canvas 前&#xff0c;需掌握路…

软件工程——第5章总体设计知识点整理

本专栏是博主个人笔记&#xff0c;主要目的是利用碎片化的时间来记忆软工知识点&#xff0c;特此声明&#xff01; 文章目录 1.总体设计的基本目的&#xff1f; 2.总体设计的任务&#xff1f; 3.总体设计过程由哪两个阶段组成&#xff1f; 4.总体设计的步骤&#xff1f; 5…

【Linux从入门到精通】进程地址空间(虚拟地址 vs 物理地址)

本篇文章会围绕三个问题&#xff08;什么是地址空间&#xff1f;地址空间是如何设计的&#xff1f;为什么要有地址空间&#xff1f;&#xff09;进行展开讲述。其中主要是了解虚拟地址和物理地址的区别。希望本篇文章会对你有所帮助。 文章目录 一、什么是地址空间&#xff1f;…

《机器学习公式推导与代码实现》chapter6-k近邻算法

《机器学习公式推导与代码实现》学习笔记&#xff0c;记录一下自己的学习过程&#xff0c;详细的内容请大家购买作者的书籍查阅。 k近邻算法 k近邻(k-nearest neighbor, k-NN)算法是一种经典的分类算法。k近邻算法根据新的输入实例的k个最近邻实例的类别来决定其分类。所以k近…

rust abc(1): 最小环境搭建

文章目录 1. 目的2. 命令集合3. 安装或更新 rust3.1 命令3.2 运行结果 4. 包管理工具 Cargo5. 创建 Rust 的 Hello World 程序: 单个文件6. 创建 Rust 的 Hello World 工程&#xff1a; 基于 Cargo6.1 cargo new 创建工程6.2 cargo run6.3 完整输出6.4 解释 7. IDE/编辑器8. Re…

Jetson安装Anaconda(miniforge3)

1 miniforge3 miniforge集成了Anaconda的核心工具&#xff1a;conda。conda是一个包和环境管理工具。因此&#xff0c; miniforge里面的conda和Anaconda里面的conda完全一样&#xff1b;你能用Anaconda做的安装、升级、删除包等功能&#xff0c;miniforge都能做&#xff1b;你…

angular实现自定义模块路由懒加载;配置自定义模块路由及子路由

图片中绿色表示新建的文件;黄色表示被更改的文件; 1、创建一个新的项目 ng new angularlazyload2、创建一个用户模块,并配置路由 ng g module module/user --routing如图: 3 、在module/模块下创建user组件 ng g component module/user如图: 4、实现路由懒加载 依次…

java00——类和对象

在Java中一切皆对象 什么是对象&#xff1f; 一个人、一只猫、一条狗…这些就是一个对象&#xff1b; 每个对象都有属性和行为。 什么是类&#xff1f; 类即同类别&#xff0c;例如不论男人、女人、黑人、白人…&#xff0c;都是人类&#xff0c;即同一类事务的统称。 类的…