SpringMvc-面试用
一、SpringMvc常用注解
1、修饰在类的
@RestController
@RequestMapping("/test")
@RestController是什么?其实是一个复合注解
@Controller //其实就是@Component
@ResponseBody //独立的注解
public @interface RestController {}
@RequestMapping 也可以认为是一个独立的注解
2、修饰在方法上
@ResponseBody
@GetMapping("/add")
@PostMapping("/add")
@GetMapping 也是复合注解,@PostMapping也是一样,其实就是@RequestMapping
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {}@RequestMapping(method = RequestMethod.POST)
public @interface PostMapping {}
比较独立的注解一共就这三种,针对这三种注解都有对应的处理类
1、@RequestMapping
RequestMappingHandlerMapping类处理,如果带有@RequestMapping就会将其转成Mapping2、@Controller
RequestMappingHandlerMapping类处理,会将其转成Mapping3、@ResponseBody
RequestResponseBodyMethodProcessor类里面的,在返回结果时会解析方法是否有这个注解
一、启动流程
SpringMvc是spring的一个独立模块,就像AOP一样。在springmvc中把web框架和springioc融合在一起,是通过ContextLoaderListener监听servlet上下文的创建后来加载父容器完成的,然后通过配置一个servlet对象DispatcherServlet,在初始化DispatcherServlet时来加载具体子容器
启动的时候,我们重点关注下3面三个类,因为在处理请求的时候,重点也是这3个类。
1、DispatcherServlet
2、RequestMappingHandlerMapping
3、RequestMappingHandlerAdapter
RequestMappingHandlerMapping是什么?
RequestMappingHandlerMapping是HandlerMapping接口实现类,在IOC容器里面。他主要用到处理被@RequestMapping和@Controller修饰的类,解析这些类里面的每个方法,将这些方法封装成RequestMappingInfo对象,并且把把每个方法的url和RequestMappingInfo,存到mappingRegistry集合中去。mappingRegistry后面我们经常提到。
RequestMappingHandlerMapping是在DispatcherServlet初始化时候,从容器拿到所有实现HandlerMapping接口的bean,并保存到DispatcherServlet的属性里面,后续处理请求需要用到。
RequestMappingInfo又是什么?
RequestMappingInfo是对带有@RequestMapping注解的类或者方法的一个描述。在匹配url时候有很重要的作用。
@RequestMapping注解一共有六项配置,可以看出这些配置项是用于限定被注解的方法对象可以处理哪些类型的request请求。当spring启动过程中创建HandlerMapping对象时,会寻找所有被@Controller注解的类中被@RequestMapping注解的方法对象,然后解析方法对象的@RequestMapping注解,把解析结果封装成RequestMappingInfo对象,也就是说RequestMappingInfo对象是用来装载请求处理方法的配置信息的,每个请求处理方法对象都会对应一个RequestMappingInfo对象。
@RequestMapping注解一共有6个配置项,这6个配置项其实就是6种过滤器,限定了请求处理方法对象可处理的请求,通过这6种过滤条器把方法不能处理的请求都pass掉,RequestMappingInfo对象持有这6种过滤器
所以我们需要看下这三个类,怎么被加载导IOC容器里面去的,并且在初始化的时候,会给这三个类所对应的对象,做什么初始化的操作。
1、加载DispatcherServlet
DispatcherServlet是通过加载DispatcherServletConfiguration创建的,而至于DispatcherServletConfiguration是怎么被加载到IOC里面,可以理解成是通过Spring.factories,自定义的启动器都是通过这种方式。
@Configuration(proxyBeanMethods = false)
@Conditional(DefaultDispatcherServletCondition.class)
@ConditionalOnClass(ServletRegistration.class)
@EnableConfigurationProperties(WebMvcProperties.class)
protected static class DispatcherServletConfiguration {@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {DispatcherServlet dispatcherServlet = new DispatcherServlet();return dispatcherServlet;}
}
2、加载RequestMappingHandlerAdapter和RequestMappingHandlerMapping
RequestMappingHandlerAdapter和RequestMappingHandlerMapping的加载,是通过WebMvcAutoConfiguration这个配置类来完成的。而EnableWebMvcConfiguration是通过WebMvcAutoConfigurationAdapter导进来的,最开始还是通过Spring.factories这种方式。
@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {........
}//通过@Import导入EnableWebMvcConfiguration@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {//RequestMappingHandlerAdapter作用,通过url请求对应的Controller中的方法,返回执行结果值@Beanpublic RequestMappingHandlerAdapter requestMappingHandlerAdapter(RequestMappingHandlerAdapter = new RequestMappingHandlerAdapter();......return }//通过解析HadlerMapping注解,创建Mapping和Handler的controller的关系,关注是注册到了mappingRegistry里面去。@Bean public RequestMappingHandlerMapping requestMappingHandlerMapping(){RequestMappingHandlerMapping requestMappingHandlerMapping = createRequestMappingHandlerMapping();......return requestMappingHandlerMapping;}
}
3、实例化DispatcherServlet
4、实例化RequestMappingHandlerAdapter
5、实例化RequestMappingHandlerMapping
RequestMappingHandlerMapping间接实现了InitializingBean,而InitializingBean就只有afterPropertiesSet方法,处理逻辑大部分都是afterPropertiesSet里面,看下afterPropertiesSet的逻辑,拿到所有的Bean类型,判断是否是Handler
@Override
public void afterPropertiesSet() {//1、拿到所有的BeanName,判断是否是Handlerfor (String beanName : getCandidateBeanNames()) { processCandidateBean(beanName);}handlerMethodsInitialized(getHandlerMethods());
}protected void processCandidateBean(String beanName) {//获取Bean的类型,判断这个Bean是不是一个Handler,判断Handler的标准也很简单是否包含Controller和RequestMapping注解,如果符合就把里面的Method转成RequestMappingInfo对象,并保存到mappingRegistry里面去Class<?> beanType = obtainApplicationContext().getType(beanName);if (beanType != null && isHandler(beanType)) {detectHandlerMethods(beanName);}
}
detectHandlerMethods的处理逻辑
protected void detectHandlerMethods(Object handler) {Class<?> handlerType = (handler instanceof String ? obtainApplicationContext().getType((String) handler) : handler.getClass());if (handlerType != null) {//把带有@Controller和@RequestMapping注解的类,转成Map,key=类中的某个Method,value是这个方法所封装的RequestMappingInfo对象Map<Method, RequestMappingInfo> methods = MethodIntrospector.selectMethods(userType,(MethodIntrospector.MetadataLookup<T>) method -> {return getMappingForMethod(method, userType);});methods.forEach((method, mapping) -> {.....注册到mappingRegistry里面去,后面处理请求的时候,会通过url从里面找到对应的MethodregisterHandlerMethod(handler, invocableMethod, mapping);});}
}//注册到mappingRegistry里面去
protected void registerHandlerMethod(Object handler, Method method, T mapping) {this.mappingRegistry.register(mapping, handler, method);
}
二、调用
先说下调用过程中的流程
1. 用户通过浏览器发起 HttpRequest 请求到前端控制器 (DispatcherServlet)。
2. DispatcherServlet 将用户请求发送给处理器映射器 (HandlerMapping)。
3. 处理器映射器 (HandlerMapping)会根据请求,找到负责处理该请求的处理器,并将其封装为处理器执行链 返回 (HandlerExecutionChain) 给 DispatcherServlet
4. DispatcherServlet会根据处理器执行链中的处理器,找到能够执行该处理器的处理器适配器(HandlerAdaptor) --注,处理器适配器有多个
5. 处理器适配器 (HandlerAdaptoer) 会调用对应的具体的 Controller
6. Controller 将处理结果及要跳转的视图封装到一个对象 ModelAndView 中并将其返回给处理器适配器 (HandlerAdaptor)
7. HandlerAdaptor直接将ModelAndView交给DispatcherServlet ,至此,业务处理完毕
8. 业务处理完毕后,我们需要将处理结果展示给用户。于是DisptcherServlet调用ViewResolver,将ModelAndView中的视图名称封装为视图对象
9. ViewResolver将封装好的视图 (View) 对象返回给 DIspatcherServlet
10. DispatcherServlet 调用视图对象,让其自己 (View) 进行渲染(将模型数据填充至视图中),形成响应对象 (HttpResponse)
11. 前端控制器 (DispatcherServlet) 响应 (HttpResponse) 给浏览器,展示在页面上。
1、initStrategies方法
第一次调用时会初始化DispatcherServlet类的9个属性,或者说是9个组件,这些属性其实可以把他理解成处理器,属性的赋值主要是通过调用initStrategies方法完成,为什么要提前给这些属性赋值,因为在处理请求的时候,要用到这些处理器,而且每个请求的用到的处理都是这些。
public class DispatcherServlet extends FrameworkServlet {//比较重要的2个组件private List<HandlerMapping> handlerMappings;private List<HandlerAdapter> handlerAdapters;//次要的7个组件private MultipartResolver multipartResolver;private LocaleResolver localeResolver;private ThemeResolver themeResolver;private List<HandlerExceptionResolver> handlerExceptionResolvers;private RequestToViewNameTranslator viewNameTranslator;private FlashMapManager flashMapManager;@Overrideprotected void onRefresh(ApplicationContext context) {initStrategies(context);}protected void initStrategies(ApplicationContext context) {//从IOC容器中拿到所有HandlerMapping实现类,存到DispatcherServlet的属性handlerMappings里面去initHandlerMappings(context);//拿到IOC容器中拿到所有HandlerAdapter实现类,存到DispatcherServlet的属性handlerAdapters里面去initHandlerAdapters(context);//下面也是一样,通过IOC获取不同类型Bean存到DispatcherServlet对应的属性里面去initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);}
}
Spring MVC 九大内置处理器
1、HandlerMapping
根据request找到相应的处理器,这里说的处理器是指HandlerMethod。因为HandlerMethod有两中形式,一种是基于类的Handler,另一种是基于Method的Handler。2、HandlerAdapter
HandlerAdapter负责调用Handler的适配器。如果把HandlerMethod当做工具的话,那么HandlerAdapter就相当于干活的工人,人通过工具完成一系列的事情。3、HanderExceptionResolver
对异常的处理4、ViewResolver
用来将String类型的视图名和Locale解析为View类型的视图5、RequestToViewNameTranslator
有的Handler(Controller)处理完后没有设置返回类型,比如是Void方法,这是需要从request中获取的viewName6、LocaleResolver
从request中解析出Locale。Locale表示一个区域,比如zh-cn,对于不同的区域的用户,显示不同的结果,这就是i18你(SpringMVC中有具体的拦截器LocaleChangelnterceptor)7、ThemeResolver
主题解析,这种类似于我们手机的主题8、MultipartResolver
处理上传请求,将普通的request封装成MultipartHttpServletRequest9、FlashMapManager
用于管理FlashMap,FlashMap用于在redirect重定向中传递参数
2、doDispatch方法
在调用完initStrategies方法后,接着调用DispatcherServlet的doDispatch方法,这里才是开始处理request请求。处理时主要会通过HandlerMapping拿到符合request的HandlerMethod和HandlerInterceptor,HandlerMethod和HandlerInterceptor会被包装成HandlerExecutionChain。
接着在拿到HandlerAdapter,在通过HandlerAdapter调用HandlerMethod方法,也就是我们Controller里面的方法,HandlerAdapter再把方法返回的内容封装成ModelAndView对象返回出去
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {//通过request判断是否是multipart类型,multipart就是上传的类型//通过multipartResolver将其封装成MultipartHttpServletRequest对象processedRequest = checkMultipart(request);//通过request的请求url,通过RequestMappingHandlerMapping,找到对应的HandlerMethod和HandlerInterceptor拦截器//并将HandlerMethod和HandlerInterceptor封装成HandlerExecutionChain//后面在调用HandlerExecutionChain的时候,会先调用拦截器的PreHandle方法,在调用具体的Controller方法,在调用拦截器的PostHandle方法mappedHandler = getHandler(processedRequest);if (mappedHandler == null) {//如果获取不到,则根据配置抛出异常或返回404错误noHandlerFound(processedRequest, response);return;}//获得当前handler对应的HandlerAdapter对象,Adapter就是请求对应handler方法,并返回视图HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());//调用HandlerExecutionChain里面的拦截器PreHandle方法if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}//通过Adapter调用handler方法,并返回视图ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());//如果需要异步处理,直接返回if (asyncManager.isConcurrentHandlingStarted()) {return;}//当view为空时,根据request设置默认的viewapplyDefaultViewName(processedRequest, mv);//调用HandlerExecutionChain里面的拦截器PreHandle方法mappedHandler.applyPostHandle(processedRequest, response, mv);//处理返回结果,包括处理异常、渲染页面、触发Interceptor的afterCompletionprocessDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
}
doDispatch() 主要执行流程
1、获得请求对应的HandlerExecutionChain对象(HandlerMethod和HandlerInterceptor拦截器集合)
2、获得当前handler对应的HandlerAdapter对象3、执行Interceptor拦截器的preHandler
4、执行Controller里面的Method方法
5、执行响应的interceptor的postHandler方法6、处理返回结果,包括处理异常、渲染页面、触发Interceptor的afterCompletion
挑几个上面重要的方法看下:getHandler、getHandlerAdapter、ha.handle
2.1 getHandler(processedRequest)
先看getHandler,该方法时拿到DispatcherServlet在initStrategies时,从IOC容器里面获取到的所有HandlerMapping的实现类,有多个,这里主要看RequestMappingHandlerMapping,在调用RequestMappingHandlerMapping的getHandler方法,该方法主要是,通过url和RequestMappingInfo匹配,返回RequestMappingInfo里面的HandlerMethod。
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;
}
//通过request匹配正确的HandlerMethod
@Override
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {//从request拿到UrlString lookupPath = getUrlPathHelper().getLookupPathForRequest(request);this.mappingRegistry.acquireReadLock();//获取锁try {//通过Url匹配对应的HandlerMethodHandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);}finally {this.mappingRegistry.releaseReadLock();//释放锁}
}@Nullable
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {List<Match> matches = new ArrayList<>();//前面我们说了在初始化RequestMappingHandlerMapping对象的时候,会解析所有带有@RequestMapping注解的类,存到这个mappingRegistry里面去,key是url,value=RequestMappingInfo//URL进行精准匹配RequestMappingInfoList<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);if (directPathMatches != null) {addMatchingMappings(directPathMatches, matches, request);//如果匹配上了,就封装成Match存到matches里面去。Match是什么?}if (matches.isEmpty()) {//没有精确匹配上,则执行模糊匹配,模糊匹配是处理@RequestMapping的url中配了"xxx/{name}"addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);}if (!matches.isEmpty()) {Match bestMatch = matches.get(0);//默认拿第一个....//返回匹配好的方法,也就是HandlerMethodreturn bestMatch.handlerMethod;} else {return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request);}
}
2.2 getHandlerAdapter(mappedHandler.getHandler())
获得当前handler对应的HandlerAdapter对象
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
DispatcherServlet在initStrategies时,从IOC容器里面获取到的所有HandlerAdapter的实现类,也是会拿到很多实现类,这里也包含我们要用到RequestMappingHandlerAdapter
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {//拿到多个handlerAdapters,返回其中一个,过滤也没什么逻辑,都是返回第一个Adaptersif (this.handlerAdapters != null) {for (HandlerAdapter adapter : this.handlerAdapters) {if (adapter.supports(handler)) {return adapter;}}}
}
2.3 ha.handle(processedRequest, response, mappedHandler.getHandler())
通过Adapter调用handler方法,并返回视图
ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {ServletWebRequest webRequest = new ServletWebRequest(request, response);WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);if (this.argumentResolvers != null) {invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);}if (this.returnValueHandlers != null) {invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);}invocableMethod.setDataBinderFactory(binderFactory);invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);//封装model和view的容器ModelAndViewContainer mavContainer = new ModelAndViewContainer();mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));modelFactory.initModel(webRequest, mavContainer, invocableMethod);mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);//异步请求相关AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);asyncWebRequest.setTimeout(this.asyncRequestTimeout);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.setTaskExecutor(this.taskExecutor);asyncManager.setAsyncWebRequest(asyncWebRequest);asyncManager.registerCallableInterceptors(this.callableInterceptors);asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);if (asyncManager.hasConcurrentResult()) {Object result = asyncManager.getConcurrentResult();mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];asyncManager.clearConcurrentResult();invocableMethod = invocableMethod.wrapConcurrentResult(result);}//调用Controller中的具体方法并处理返回值invocableMethod.invokeAndHandle(webRequest, mavContainer);if (asyncManager.isConcurrentHandlingStarted()) {return null;}return getModelAndView(mavContainer, modelFactory, webRequest);
}
相关文章:
SpringMvc-面试用
一、SpringMvc常用注解 1、修饰在类的 RestController RequestMapping("/test")RestController是什么?其实是一个复合注解 Controller //其实就是Component ResponseBody //独立的注解 public interface RestController {}RequestMapping 也可以认…...
并发编程 # 3
文章目录 一、进程和线程的比较二、GIL全局解释器锁1.引入2.Python解释器的种类结论:在CPython解释其中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势。得出结论:GIL锁就是保证在同一时刻只…...
ESP32C3 LuatOS TM1650①驱动测试
合宙TM1650驱动资料 TM1650.lua源码 引脚连接 TM1650ESP32C3SCLGPIO5SDAGPIO4 下载TM1650.lua源码,并以文件形式保存在项目文件夹中 驱动测试源码 --注意:因使用了sys.wait()所有api需要在协程中使用 -- 用法实例 PROJECT "ESP32C3_TM1650" VERSION …...
TCP为什么需要三次握手和四次挥手?
一、三次握手 三次握手(Three-way Handshake)其实就是指建立一个TCP连接时,需要客户端和服务器总共发送3个包 主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备 过程如下ÿ…...
【C++】一些C++11特性
C特性 1. 列表初始化1.1 {}初始化1.2 initializer_list 2. 声明2.1 auto2.2 typeid2.3 decltype2.4 nullptr 3. STL3.1 新容器3.2 新接口 4. 右值引用5. 移动构造与移动赋值6. lambda表达式7. 可变参数模板8. 包装器9. bind 1. 列表初始化 1.1 {}初始化 C11支持所有内置类型和…...
leetcode 647. 回文子串、516. 最长回文子序列
647. 回文子串 给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。 回文字符串 是正着读和倒过来读一样的字符串。 子字符串 是字符串中的由连续字符组成的一个序列。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成&#…...
Vue Router 刷新当前页面
Vue项目, 在实际工作中, 有些时候需要在 加载完某些数据之后对当前页面进行刷新, 以期 onMounted 等生命周期函数, 或者 数据重新加载. 总之是期望页面可以重新加载一次. 目前总结有三种途径可实现以上需求: 一, reload 直接刷新页面 window.location.reload(); $router.go(…...
lstm 回归实战、 分类demo
预备知识 lstm 参数 输入、输出格式 nn.LSTM(input_dim,hidden_dim,num_layers); imput_dim 特征数 input:(样本数、seq, features_num) h0,c0 (num_layers,seq, hidden_num) output: (样本数、seq, hidden_dim) 再加一个全连接层,将 outpu…...
实践DDD模拟电商系统总结
目录 一、事件风暴 二、系统用例 三、领域上下文 四、架构设计 (一)六边形架构 (二)系统分层 五、系统实现 (一)项目结构 (二)提交订单功能实现 (三࿰…...
`SQL`编写判断是否为工作日函数编写
SQL编写判断是否为工作日函数编写 最近的自己在写一些功能,遇到了对于工作日的判断,我就看了看sql,来吧!~(最近就是好疲惫) 我们一起看看(针对ORACLE) 1.声明: CREATE OR REPLACE PACKAGE GZYW_2109_1214.PKG_FUN_GETDAY_HDAY AS /** * 通过节假日代码获取指定的日期[查找基…...
零信任身份管理平台,构建下一代网络安全体系
随着数字化时代的到来,网络安全已成为企业和组织面临的一项重要挑战。传统的网络安全方法已经无法满足不断演变的威胁和技术环境。近期,中国信息通信研究院(简称“中国信通院”)发布了《零信任发展研究报告( 2023 年&a…...
《数据结构、算法与应用C++语言描述》使用C++语言实现链表队列
《数据结构、算法与应用C语言描述》使用C语言实现链表队列 定义 队列的定义 队列(queue)是一个线性表,其插入和删除操作分别在表的不同端进行。插入元素的那一端称为队尾(back或rear),删除元素的那一端称…...
RT-Thread学习笔记(四):RT-Thread Studio工具使用
RT-Thread Studio工具使用 官网详细资料实用操作1. 查看 RT-Thread RTOS API 文档2.打开已创建的工程3.添加头文件路径4. 如何设置生成hex文件5.新建工程 官网详细资料 RT-Thread Studio 用户手册 实用操作 1. 查看 RT-Thread RTOS API 文档 2.打开已创建的工程 如果打开项目…...
【计算机网络笔记】OSI参考模型中端-端层(传输层、会话层、表示层、应用层)功能介绍
系列文章目录 什么是计算机网络? 什么是网络协议? 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能(1)——速率、带宽、延迟 计算机网络性能(2)…...
RabbitMQ高级知识点
以下是一些 RabbitMQ 的高级知识点: 1. Exchange: RabbitMQ 中的 Exchange 是消息路由器,用来接收消息并且转发到对应的 Queue 中。Exchange 有四种类型:Direct Exchange、Fanout Exchange、Topic Exchange 和 Headers Exchange。…...
Node直接执行ts文件
Node直接执行ts文件 1、常规流程 node 执行 【ts 文件】 流程: 1、编写ts代码 2、编译成js代码 [命令如 :tsc xx.ts] 3、执行js代码 [node xx.js]2、直接执行 想要直接执行 ts 文件,需要安装如下依赖工具。 执行如下命令: # 安装…...
log4j的级别的说明
一 log4j的级别 1.1 级别类型 TRACE 》DEBUG 》 INFO 》 WARN 》 ERROR 》 FATAL 级别高低顺序为: trace级别最低 ,Fatal级别最高。由左到右,从低到高 1.2 包含范围 原则: 本级别包含本级别以及大于本级别的内容,…...
头脑风暴之约瑟夫环问题
一 问题的引入 约瑟夫问题的源头完全可以命名为“自杀游戏”。本着和谐友爱和追求本质的目的,可以把问题描述如下: 现有n个人围成一桌坐下,编号从1到n,从编号为1的人开始报数。报数也从1开始,报到m人离席,…...
【四:Spring整合Junit】
目录 相同点不同点1、导入依赖增加2、编写的位置不同。。路径一定要与实现类一致 相同点 前面都一样和Spring整合mybatis(基于注解形式)一样Spring整合Mybatis 不同点 1、导入依赖增加 <!-- 单元测试 --><dependency><groupId>junit&…...
openHarmony UI开发
常用组件和布局方式 组件 ArkUI有丰富的内置组件,包括文本、按钮、图片、进度条、输入框、单选框、多选框等。和布局一样,我们也可以将基础组件组合起来,形成自定义组件。 按钮: Button(Ok, { type: ButtonType.Normal, stateEf…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
