SpringMVC源码:HandlerMapping加载1

news/2024/4/25 12:40:41/文章来源:https://blog.csdn.net/wzngzaixiaomantou/article/details/129223720

参考资料:

《SpringMVC源码解析系列》

《SpringMVC源码分析》

《Spring MVC源码》

        写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。

前文:

《SpringMVC源码:DispatcherServlet初始化流程》

        在前文中我们介绍了DispatcherServlet的初始化,其中有两个重要的过程分别是initHandlerMappings和initHandlerAdapters,本文我们介绍下这两个组件。

目录

一、HandlerMapping

        1、HandlerMapping接口

        2、AbstractHandlerMapping类

        2.1、类属性

        2.2、类方法

二、AbstractUrlHandlerMapping类

        简介

        类方法

        registerHandler

         getHandlerInternal

        lookupHandler

         buildPathExposingHandler

        实现类

        SimpleUrlHandlerMapping类

        initApplicationContext

        registerHandler

        AbstractDetectingUrlHandlerMapping类

        detectHandlers

         BeanNameUrlHandlerMapping#determineUrlsForHandler


一、HandlerMapping

        1、HandlerMapping接口

        HandlerMapping接口定义主要用来提供request 请求对象和Handler对象 映射关系的接口。所谓request对象比如我们web应用中的http 请求,Handler对象则指的是对应rquest请求的相关处理逻辑(可以理解为我们对应改请求的业务处理逻辑)。

        该接口只有一个方法getHandler(),入参是Http对应的请求对象,返回会值是HandlerExecutionChain对象,该对象包含一个处理器对象Handler和匹配该处理器的若干interceptors 拦截器列表。

public interface HandlerMapping {String BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;}

         下图是HandlerMapping接口以及其目前所有子类的UML类图:

        从类图中可以看到HandlerMapping有一个初始的抽象类AbstractHandlerMapping,在该抽象类,分成两个体系一个是以AbstractUrlHandlerMapping(url和类级别的Handler处理器映射 url ->Controller),另一个是AbstractHandlerMethodMapping(url和method方法级别的Handler处理器)。

        2、AbstractHandlerMapping类

        AbstractHandlerMapping是HandlerMapping的抽象实现,同时实现了Order接口继承了WebApplicationObjectSupport类,order接口主要是为了如果spring容器中有多个HandlerMapping,则按照order 排序去一次使用HandlerMapping获取handler对象,order小的优先被使用。

 由于该处理器抽象类继承WebApplicationObjectSupport对象,通过查看WebApplicationObjectSupport的继承关系,其也间接实现了ApplicationContextAware和ServlerContextAware,意味着该类在spring容器中被初始化完成后自动拥有ApplicationContext对象和ServletContext对象。

    //WebApplicationObjectSupport.java@Overridepublic final void setServletContext(ServletContext servletContext) {if (servletContext != this.servletContext) {this.servletContext = servletContext;if (servletContext != null) {initServletContext(servletContext);}}}@Overrideprotected void initApplicationContext(ApplicationContext context) {super.initApplicationContext(context);if (this.servletContext == null && context instanceof WebApplicationContext) {this.servletContext = ((WebApplicationContext) context).getServletContext();if (this.servletContext != null) {initServletContext(this.servletContext);}}}

        2.1、类属性

        AbstractHandlerMapping包含以下类属性:        

	//如果处理器映射器没有获取到对应的Handlerm,则使用的默认Handler, 可以通过xml/注解的形式配置。private Object defaultHandler;//Url路径匹配的帮助类,包含ur编码方式设置获取,或者根据请求请求路径等方法private UrlPathHelper urlPathHelper = new UrlPathHelper();//Spring提供的路径匹配策略接口的路径匹配器private PathMatcher pathMatcher = new AntPathMatcher();//通过该属性来设置相关的拦截器,设置的方式可以通过xml配置private final List<Object> interceptors = new ArrayList<Object>();//该集合下的拦截器不需要匹配会通过getHandler()方法全部添加到HandlerExecutionChain中private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<HandlerInterceptor>();//排序属性 默认最大值,如果不设置意味着其对应的处理器对象优先级最小private int order = Ordered.LOWEST_PRECEDENCE;  

        2.2、类方法

                 initApplicationContext()方法:对拦截器集合做处理

	@Overrideprotected void initApplicationContext() throws BeansException {//spring提供钩子函数,子类可以实现该方法来为集合设置拦截器extendInterceptors(this.interceptors);//从spring容器中获取所有MappedInterceptordetectMappedInterceptors(this.adaptedInterceptors);//将所有设置在interceptors中的拦截器添加到adaptedInterceptors中initInterceptors();}//从spring容器中获取所有MappedInterceptor并添加到adaptedInterceptors中protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(getApplicationContext(), MappedInterceptor.class, true, false).values());}//将所有设置在interceptors中的拦截器添加到adaptedInterceptors中protected void initInterceptors() {if (!this.interceptors.isEmpty()) {for (int i = 0; i < this.interceptors.size(); i++) {Object interceptor = this.interceptors.get(i);if (interceptor == null) {throw new IllegalArgumentException("Entry number " + i + " in interceptors array is null");}this.adaptedInterceptors.add(adaptInterceptor(interceptor));}}}protected HandlerInterceptor adaptInterceptor(Object interceptor) {if (interceptor instanceof HandlerInterceptor) {return (HandlerInterceptor) interceptor;}else if (interceptor instanceof WebRequestInterceptor) {return new WebRequestHandlerInterceptorAdapter((WebRequestInterceptor) interceptor);}else {throw new IllegalArgumentException("Interceptor type not supported: " + interceptor.getClass().getName());}}

         getHandler()方法:核心方法,主要作用是根据请求获取包装了Handler对象和拦截器的HandlerExecutionChain对象。该方法采用模板方法获取拦截器处理器链。

	@Overridepublic final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {//交由子类实现的根据请求获取处理器的具体逻辑 不同的子类获取Handler的逻辑不同Object handler = getHandlerInternal(request);//如果没有获取到Handler 则获取默认的Handler//默认的处理器可以通过配置映射器实例的时候通过属性设置if (handler == null) {handler = getDefaultHandler();}//如果默认的Handler还是没有则返回空if (handler == null) {return null;}//Handler处理器是字符串类型 说明获取的Handler是beanName//则从spring 容器中获取bean实例对象if (handler instanceof String) {String handlerName = (String) handler;handler = getApplicationContext().getBean(handlerName);}//为Handler添加拦截器,并最终返回HandlerExecutionChain对象HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);if (CorsUtils.isCorsRequest(request)) {CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);executionChain = getCorsHandlerExecutionChain(request, executionChain, config);}return executionChain;}

        getHandlerExecutionChain():将getHandlerInternal()方法返回的Handler对象包装成HandlerExecutionChain对象。

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {//判断如果当前的Handler本身是HandlerExecutionChain对象 则强转//否则创建HandlerExecutionChain对象HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));//根据request找寻对应的逻辑处理路径 lookupPathString lookupPath = this.urlPathHelper.getLookupPathForRequest(request);//遍历所有拦截器for (HandlerInterceptor interceptor : this.adaptedInterceptors) {//判断是否为MappedInterceptor类型if (interceptor instanceof MappedInterceptor) {MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;//判断该拦截器是否与当前请求地址适配if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {//将拦截器加入到当前请求的执行链中chain.addInterceptor(mappedInterceptor.getInterceptor());}}else {chain.addInterceptor(interceptor);}}return chain;}

二、AbstractUrlHandlerMapping类

        简介

        AbstractUrlHandlerMapping继承自AbstractHandlerMapping类,从名字可以看出该类是一个urlPath和Handler对象对一一对应的HandlerMapping。

        换句话说一个rquest可以解析出一个对应的路径urlPath 则一个路径可能会匹配最符合的一个与之对应的Handler对象,所以其有一个存储url和Handler对象对应关系的Map集合属性handlerMap。其还有两个属性一个是与url “/”对应的特定Handler对象,以及是否Handler 懒加载 lazyInitHandlers。

        AbstractUrlHandlerMapping类有如下属性:

	// /与"/" 匹配的特定RootHandler 用户可以在配置AbstractUrlHandlerMapping实例进行设置private Object rootHandler;// 是否懒加载Handler 如果是true 则map中可以存储string,在使用的时候才从spring容器中进行加载private boolean lazyInitHandlers = false;// 用于存储url和handler匹配的map集合private final Map<String, Object> handlerMap = new LinkedHashMap<String, Object>();

        类方法

        registerHandler

        对urlpath 和Handler进行处理存放。

	protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException {Assert.notNull(urlPaths, "URL path array must not be null");for (String urlPath : urlPaths) {registerHandler(urlPath, beanName);}}protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {Assert.notNull(urlPath, "URL path must not be null");Assert.notNull(handler, "Handler object must not be null");Object resolvedHandler = handler;//lazyInitHandlers 为false 则不允许懒加载 对于Handler是string类型 需要从容器中获取到Handler实例存放到Map中//如果允许懒加载则 不需要进行实力获取 直接存储在使用的时候再从spring容器中获取if (!this.lazyInitHandlers && handler instanceof String) {String handlerName = (String) handler;if (getApplicationContext().isSingleton(handlerName)) {resolvedHandler = getApplicationContext().getBean(handlerName);}}//判断集合中对应的urlPath已存在且对应的Handler和要存储的Handler不一样抛出异常Object mappedHandler = this.handlerMap.get(urlPath);if (mappedHandler != null) {if (mappedHandler != resolvedHandler) {throw new IllegalStateException("Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath +"]: There is already " + getHandlerDescription(mappedHandler) + " mapped.");}}else {//集合中对应的urlPath不存在//对于 / 和/*进行特殊处理 / 讲Handler 存储在rootHandler中 /* 设置为defaultHandlerif (urlPath.equals("/")) {                if (logger.isInfoEnabled()) {logger.info("Root mapping to " + getHandlerDescription(handler));}setRootHandler(resolvedHandler);}else if (urlPath.equals("/*")) {if (logger.isInfoEnabled()) {logger.info("Default mapping to " + getHandlerDescription(handler));}setDefaultHandler(resolvedHandler);}else {//非特殊情况则存放进map中this.handlerMap.put(urlPath, resolvedHandler);if (logger.isInfoEnabled()) {logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));}}}}

         getHandlerInternal

        整个请求分为两部分,首先根据请求路径获取到对应的Handler,然后对于获取到的Handler进行包装构造。在该方法中核心的两个方式是lookupHandler方法和buildPathExposingHandler方法

	@Overrideprotected Object getHandlerInternal(HttpServletRequest request) throws Exception {//通过UrlPathHelper对象从request解析出urlPathString lookupPath = getUrlPathHelper().getLookupPathForRequest(request);//使用lookupPath 从HandlerMap中获取handler (精确匹配和Pattern匹配)Object handler = lookupHandler(lookupPath, request);//如果没有获取到 则可能是特殊路径或者该路径没有可以匹配的Handlerif (handler == null) {//如果没有获取到 则可能是特殊路径 需要特殊处理 比如 /路径匹配RootHandlerObject rawHandler = null;if ("/".equals(lookupPath)) {rawHandler = getRootHandler();}//没有匹配的Handler 则使用默认的handlerif (rawHandler == null) {rawHandler = getDefaultHandler();}//因为有可能有懒加载,需要对string类型的handler获取其实例if (rawHandler != null) {if (rawHandler instanceof String) {String handlerName = (String) rawHandler;rawHandler = getApplicationContext().getBean(handlerName);}//子类扩展 用于校验获取到的Handler是否匹配业务逻辑validateHandler(rawHandler, request);//返回添加了拦截器的HandlerExecutionChainhandler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);}}if (handler != null && logger.isDebugEnabled()) {logger.debug("Mapping [" + lookupPath + "] to " + handler);}else if (handler == null && logger.isTraceEnabled()) {logger.trace("No handler mapping found for [" + lookupPath + "]");}return handler;}

        lookupHandler

        该方法实现根据urlPath获取Handler。此时有两种情况 ,一是精确匹配,二是Pattern模式匹配,该方法中对这两种方式进行相关处理,其中Pattern模式匹配比较复杂,首先该方式可能会匹配到多个Handler,这里需要进行排序获取最优,同时针对最优有多个的情况进行处理,该方法中多次使用PathMatcher对象。

	protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {//先尝试从已有的映射关系中获取Object handler = this.handlerMap.get(urlPath);if (handler != null) {//获取Handler实例并构造HandlerExecuteChain对象返回if (handler instanceof String) {String handlerName = (String) handler;handler = getApplicationContext().getBean(handlerName);}validateHandler(handler, request);return buildPathExposingHandler(handler, urlPath, urlPath, null);}//handler 支持Pattern匹配 比如 /manager/student/* 类似的Pattern//该方式下无法直接获取而且 需要使用一种匹配方法 一个pathern可能匹配多个url  则需要获取其最优的HandlerList<String> matchingPatterns = new ArrayList<String>();//遍历handlerMap 获取所有PathMatcher匹配成功的Handler存放集合中for (String registeredPattern : this.handlerMap.keySet()) {if (getPathMatcher().match(registeredPattern, urlPath)) {matchingPatterns.add(registeredPattern);}else if (useTrailingSlashMatch()) {if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) {matchingPatterns.add(registeredPattern + "/");}}}//根据PathMatcher获取到的排序器 对matchingPatterns 进行匹配 获取最优的Handler对象String bestMatch = null;Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);if (!matchingPatterns.isEmpty()) {Collections.sort(matchingPatterns, patternComparator);if (logger.isDebugEnabled()) {logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);}bestMatch = matchingPatterns.get(0);}//如果有最优Handler 则获取Handler实例对象if (bestMatch != null) {handler = this.handlerMap.get(bestMatch);if (handler == null) {if (bestMatch.endsWith("/")) {handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1));}if (handler == null) {throw new IllegalStateException("Could not find handler for best pattern match [" + bestMatch + "]");}}if (handler instanceof String) {String handlerName = (String) handler;handler = getApplicationContext().getBean(handlerName);}validateHandler(handler, request);String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath);//对于可能会有多个最优解的情况此处将所有的最优 即多个最优排序一样只是集合添加使其有先后Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();for (String matchingPattern : matchingPatterns) {if (patternComparator.compare(bestMatch, matchingPattern) == 0) {Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);uriTemplateVariables.putAll(decodedVars);}}if (logger.isDebugEnabled()) {logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);}return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables);}// No handler found...return null;}

         buildPathExposingHandler

        为执行链增加两个拦截器PathExposingHandlerInterceptor与UriTemplateVariablesHandlerInterceptor。

	protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,String pathWithinMapping, Map<String, String> uriTemplateVariables) {HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));if (!CollectionUtils.isEmpty(uriTemplateVariables)) {chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));}return chain;}

        实现类

        从UML类图中可以大概清楚,在其抽象类下有两个分支,SimpleUrlHandlerMapping、AbstractDetectingUrlHandlerMappin,同时该类下还有一个子类BeanNameUrlHandlerMapping。在前文中我们介绍了AbstractUrlHandlerMapping类通过模板的方式实现了从请求request到Handler对象的主要逻辑,那么可想而知其后面的子类主要的功能点是初始化url和Handler的映射关系。

        SimpleUrlHandlerMapping类

        该类只有一个核心属性urlMap,用于存储url和handler的映射关系

private final Map<String, Object> urlMap = new LinkedHashMap<String, Object>();

        initApplicationContext

        因为该类间接实现了WebApplicationObjectSupport,所以该类重写了该方法。方法内容主要是初始化url和handler的映射关系,用于后续使用过程中的request请求映射。

	@Overridepublic void initApplicationContext() throws BeansException {//调用父类的initApplicationContext()方法,设置相关的拦截器super.initApplicationContext();//核心方法注册相关urlMapregisterHandlers(this.urlMap);}

        registerHandler

        SimpleUrlHandlerMapping类重写了父类的registerHandler方法

	protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {if (urlMap.isEmpty()) {logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");}else {//遍历urlMap 对url进行处理for (Map.Entry<String, Object> entry : urlMap.entrySet()) {String url = entry.getKey();Object handler = entry.getValue();// 如果没有‘/’前缀,则添加前缀‘/’if (!url.startsWith("/")) {url = "/" + url;}// Remove whitespace from handler bean name.if (handler instanceof String) {handler = ((String) handler).trim();}//调用父类注册的核心方法最终将其存储在handlerMap集合registerHandler(url, handler);}}}

        SimpleUrlHandlerMapping很简单,几乎所有的核心方法都在父类中,SimpleHandlerMapping只是用于做url映射的初始化,这种映射是直接匹配的形式,即通过request解析出其中的urlPath,根据urlPath路径直接从handlerMap中获取urlPath匹配的Handler对象。

        AbstractDetectingUrlHandlerMapping类

        AbstractDetectingUrlHandlerMapping类和上面SimpleUrlHandlerMapping的结构相关,都是重写了其中的initApplicationContext()方法,只是其注册逻辑不是需要显示的设置相关的url而是从spring容器中获取所有的bean实例,通过其BeanName(Handler对象)获取其匹配的url列表。

        detectHandlers

        该方法获取所有的beanName并获取其url列表后进行注册。

	@Overridepublic void initApplicationContext() throws ApplicationContextException {super.initApplicationContext();detectHandlers();}protected void detectHandlers() throws BeansException {if (logger.isDebugEnabled()) {logger.debug("Looking for URL mappings in application context: " + getApplicationContext());}//detectHandlersInAncestorContexts true 则获取其容器和父容器中所有的bean实例对象//为false 则只从当前容器对象中获取bean实例String[] beanNames = (this.detectHandlersInAncestorContexts ?BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :getApplicationContext().getBeanNamesForType(Object.class));//遍历所有的beanName 根据beanName获取其逻辑匹配的urls 然后调用父类的registerHandler()方法注册相关的映射关系for (String beanName : beanNames) {//交由子类实现根据beanName获取url列表String[] urls = determineUrlsForHandler(beanName);if (!ObjectUtils.isEmpty(urls)) {registerHandler(urls, beanName);}else {if (logger.isDebugEnabled()) {logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");}}}}

         BeanNameUrlHandlerMapping#determineUrlsForHandler

	@Overrideprotected String[] determineUrlsForHandler(String beanName) {List<String> urls = new ArrayList<String>();//使用beanName 作为urlif (beanName.startsWith("/")) {urls.add(beanName);}String[] aliases = getApplicationContext().getAliases(beanName);//bean实例的所有别名作为urlfor (String alias : aliases) {if (alias.startsWith("/")) {urls.add(alias);}}return StringUtils.toStringArray(urls);}

        本文我们整理了HandlerMapping接口、AbstractHandlerMapping类、AbstractUrlHandlerMapping类,介绍了URL与类对应关系的映射注册,下文我们将介绍AbstractHandlerMethodMapping类与我们最常用的实现类RequestMappingHandlerMapping

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_75146.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

跨设备文件传输工具横评

文章目录对比QQ微信SnapDropLocalSendIntelUnisonLANDropTailscaleAirDroidSendAnywhere参考文献对比 传输速度测试条件大致相同&#xff0c;文件大小约为 100 MB 工具优点缺点传输速度备注QQ支持断点续传不要求同一局域网需要安装1.81 MB/s微信方便需要安装不支持大文件传完还…

ROS1学习笔记:ROS中的坐标管理系统(ubuntu20.04)

参考B站古月居ROS入门21讲&#xff1a;ROS中的坐标系管理系统 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录一、机器人中的坐标变换二、TF功能包三、小海龟跟随实验3.1 启动实验3.2 查看当前的TF树3.3 坐标相对位置可视化3.3.1 tf_echo3.3.2 rviz一、机器人中的坐标变换…

15个Spring扩展点,一般人知道的不超过5个!

Spring的核心思想就是容器&#xff0c;当容器refresh的时候&#xff0c;外部看上去风平浪静&#xff0c;其实内部则是一片惊涛骇浪&#xff0c;汪洋一片。Spring Boot更是封装了Spring&#xff0c;遵循约定大于配置&#xff0c;加上自动装配的机制。很多时候我们只要引用了一个…

Maven高级操作,别说你不知道

如果文章对你有帮助欢迎【关注❤️❤️❤️点赞&#x1f44d;&#x1f44d;&#x1f44d;收藏⭐⭐⭐】一键三连&#xff01;一起努力&#xff01; &#x1f916; 一、聚合 &#x1f47b; 1、作用&#xff1a; 用于快速构建maven工程&#xff0c;一次性构建多个模块/项目 &am…

【人脸识别】DDL:数据分布知识蒸馏思想,提升困难样本(遮挡、低分辨率等)识别效果

论文题目&#xff1a;《Improving Face Recognition from Hard Samples via Distribution Distillation Loss》 论文地址&#xff1a;https://arxiv.org/pdf/2002.03662v3.pdf 代码地址&#xff1a;https://github.com/HuangYG123/DDL 1.前言及相关工作 Large facial variatio…

阿里前端二面常考react面试题(必备)

说说 React组件开发中关于作用域的常见问题。 在 EMAScript5语法规范中&#xff0c;关于作用域的常见问题如下。 &#xff08;1&#xff09;在map等方法的回调函数中&#xff0c;要绑定作用域this&#xff08;通过bind方法&#xff09;。 &#xff08;2&#xff09;父组件传递…

华为OD机试模拟题 用 C++ 实现 - 最左侧冗余覆盖子串(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明最左侧冗余覆盖子串题目输入输出示例一输入输出说明示例二输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写…

HCIP-5距离矢量路由协议RIP学习笔记

前言 路由信息协议RIP&#xff08;Routing Information Protocol&#xff09;的简称&#xff0c;它是一种基于距离矢量&#xff08;Distance-Vector&#xff09;算法的协议&#xff0c;使用跳数作为度量来衡量到达目的网络的距离。RIP主要应用于规模较小的网络中。Rip是第一个动…

RK3568平台开发系列讲解(驱动基础篇)SMP(Symmetrical Multi-Processing)

🚀返回专栏总目录 文章目录 一、linux SMP 和 AMP二、linux SMP的启动流程三、CPU的描述:cpumask四、CPU之间的关系沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将介绍 SMP(Symmetrical Multi-Processing)。 一、linux SMP 和 AMP 目前支持多核处理器的实时操…

QT学习14:QtXlsx操作Excel表

一、前言操作excel方式有&#xff1a;QAxObject 和QtXlsx区别&#xff1a;Qt自带的QAxObject库操作excel的前提是电脑已经安装微软的Office&#xff08;包含EXCEL&#xff09;&#xff0c;而QtXlsx可以直接使用免装Office且操作更简单。二、QtXlsx操作示例参考&#xff1a;http…

【Solved】java.lang.IllegalStateException: Could not delete shutdown key file

详细错误&#xff1a; Exception in thread “main” java.lang.IllegalStateException: Could not delete shutdown key file at edu.stanford.nlp.pipeline.StanfordCoreNLPServer.(StanfordCoreNLPServer.java:219) at edu.stanford.nlp.pipeline.StanfordCoreNLPServer.lau…

IDOR漏洞

IDOR漏洞 一、概述 IDOR&#xff0c;Insecure Direct Object reference&#xff0c;即"不安全的直接对象引用"&#xff0c;场景为基于用户提供的输入对象进行访问时&#xff0c;未进行权限验证&#xff0c;是一类访问控制漏洞。在OWASP API安全前10名的API漏洞中排名…

回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(多指标评价)

回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(多指标评价) 文章目录 回归预测 | MATLAB实现GRU(门控循环单元)多输入单输出(多指标评价)预测效果基本介绍程序设计参考资料预测效果 基本介绍 GRU神经网络是LST

Android SlidingPaneLayout实践

Android SlidingPaneLayout实践 可折叠设备在这里这一事实是无法回避的。在应用程序开发方面&#xff0c;它们带来了一些新的挑战。其中之一是可折叠设备的外形尺寸会根据折叠状态而变化。Android在设计上支持不同的外形尺寸&#xff0c;因此这很容易处理。但是&#xff0c;有…

软件测试面试题 —— 整理与解析(2)

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;&#x1f30e;【Austin_zhai】&#x1f30f; &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xf…

零基础入门网络安全,看这一篇就够了!

前景 很多零基础朋友开始将网络安全作为发展的大方向&#xff0c;的确&#xff0c;现如今网络安全已经成为了一个新的就业风口&#xff0c;不仅大学里开设相关学科&#xff0c;连市场上也开始大量招人。 那么网络安全到底前景如何&#xff1f;大致从市场规模、政策扶持、就业…

高精度真空度程序控制在真空解冻过程中的应用

摘要&#xff1a;为了解决目前各种真空冷冻过程中存在的真空压力还是人工手动调节&#xff0c;无法进行可编程准确自动控制的问题&#xff0c;本文提出了具体解决方案。解决方案的基本原理是根据动态平衡法&#xff0c;具体实现是依据不同的真空压力设定值分别采用电动针阀调节…

华为OD机试题,用 Java 解【斗地主】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

第13天-仓储服务(仓库管理,采购管理 ,SPU规格维护)

1.仓储服务开发配置 1.1.加入到Nacos注册中心 spring:application:name: gmall-warecloud:nacos:discovery:server-addr: 192.168.139.10:8848namespace: 36854647-e68c-409b-9233-708a2d41702c1.2.配置网关路由 spring:cloud:gateway:routes:- id: ware_routeuri: lb://gmal…

TOSCA自动化测试工具

TOSCA由德国公司Tricentis研发&#xff0c;提供英文和德语两种版本。 目前他们的网上培训课程大约是2000一套&#xff0c;从初级到高级&#xff0c;从工程师到BA&#xff0c;有技术&#xff0c;也有测试管理。 TOSCA的思想是&#xff0c;不用会编程的测试人员可以直接上手自动…