spring mvc源码学习笔记之六

  • pom.xml 内容如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.qsm</groupId>
        <artifactId>learn</artifactId>
        <version>1.0.0</version>
    </parent>

    <groupId>com.qs.demo</groupId>
    <artifactId>demo-077</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.28</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>
  • com.qs.demo.MyWebApplicationInitializer 内容如下
package com.qs.demo;

import com.qs.demo.root.AppConfig;
import com.qs.demo.sub.DispatcherConfig;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

/**
 * @author qs
 * @date 2024/09/24
 */
public class MyWebApplicationInitializer implements WebApplicationInitializer {

    // 这个例子来自于 WebApplicationInitializer 的文档

    @Override
    public void onStartup(ServletContext container) {
        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext =
                new AnnotationConfigWebApplicationContext();
        rootContext.register(AppConfig.class);

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        // Create the dispatcher servlet's Spring application context
        AnnotationConfigWebApplicationContext dispatcherContext =
                new AnnotationConfigWebApplicationContext();
        dispatcherContext.register(DispatcherConfig.class);

        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher =
                container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
        dispatcher.setLoadOnStartup(1);

        // 一个 DispatcherServlet 包圆了所有的请求
        // 可以搞多个 DispatcherServlet 分别处理不同的请求
        dispatcher.addMapping("/");
    }
}
  • com.qs.demo.root.AppConfig 内容如下
package com.qs.demo.root;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author qs
 * @date 2024/09/24
 */
@Configuration
@ComponentScan("com.qs.demo.root")
public class AppConfig {}
  • com.qs.demo.root.AppleService 内容如下
package com.qs.demo.root;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * @author qs
 * @date 2024/09/24
 */
@Service
public class AppleService implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public String a() {
        System.out.println(applicationContext);
        return UUID.randomUUID().toString();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
  • com.qs.demo.sub.DispatcherConfig 内容如下
package com.qs.demo.sub;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

/**
 * @author qs
 * @date 2024/09/24
 */
@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "com.qs.demo.sub")
public class DispatcherConfig {}
  • com.qs.demo.sub.BananaService 内容如下
package com.qs.demo.sub;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import java.util.UUID;

/**
 * @author qs
 * @date 2024/09/24
 */
@Service
public class BananaService implements ApplicationContextAware {

    public String a() {
        return UUID.randomUUID().toString();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println(applicationContext);
    }
}
  • com.qs.demo.sub.Demo01Controller 内容如下
package com.qs.demo.sub;

import com.qs.demo.root.AppleService;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author qs
 * @date 2024/09/24
 */
@RestController
public class Demo01Controller {

    @Resource private AppleService appleService;

    @Resource private BananaService bananaService;

    @GetMapping("/01")
    public String a() {
        return "01";
    }

    @GetMapping("/02")
    public String b() {
        return appleService.a();
    }

    @GetMapping("/03")
    public String c() {
        return bananaService.a();
    }
}

以上就是全部代码

写这个例子主要是为了介绍 WebApplicationInitializer 这个接口。简单点儿讲就是这个接口等价于 web.xml 这个配置文件。
写了这个接口就不用写 web.xml 配置文件了。
下面重点看下这个接口的 javadoc

/**  
* <p>
* 下面这段话的关键点:
* 1、适用于 servlet 3.0+ 环境
* 2、该接口可以看做是传统的 web.xml 的替代品
* </p>
*
* Interface to be implemented in Servlet 3.0+ environments in order to configure the  
* {@link ServletContext} programmatically -- as opposed to (or possibly in conjunction  
* with) the traditional {@code web.xml}-based approach.  
*
* <p>
* 下面这段话的意思:
* 1、该接口的实现会自动被 SpringServletContainerInitializer 检测到
* 2、而 SpringServletContainerInitializer 又会被 servlet 3.0 容器自动带起来
* </p>
*
* <p>Implementations of this SPI will be detected automatically by {@link  
* SpringServletContainerInitializer}, which itself is bootstrapped automatically  
* by any Servlet 3.0 container. See {@linkplain SpringServletContainerInitializer its  
* Javadoc} for details on this bootstrapping mechanism.  
*
* <p>注意下面这个例子。看本接口是怎样替换 web.xml 配置的</p>
*
* <h2>Example</h2>  
* <h3>The traditional, XML-based approach</h3>  
* Most Spring users building a web application will need to register Spring's {@code  
* DispatcherServlet}. For reference, in WEB-INF/web.xml, this would typically be done as  
* follows:  
* <pre class="code">  
* {@code  
* <servlet>  
* <servlet-name>dispatcher</servlet-name>  
* <servlet-class>  
* org.springframework.web.servlet.DispatcherServlet  
* </servlet-class>  
* <init-param>  
* <param-name>contextConfigLocation</param-name>  
* <param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>  
* </init-param>  
* <load-on-startup>1</load-on-startup>  
* </servlet>  
*  
* <servlet-mapping>  
* <servlet-name>dispatcher</servlet-name>  
* <url-pattern>/</url-pattern>  
* </servlet-mapping>}</pre>  
*  
* <h3>The code-based approach with {@code WebApplicationInitializer}</h3>  
* Here is the equivalent {@code DispatcherServlet} registration logic,  
* {@code WebApplicationInitializer}-style:  
* <pre class="code">  
* public class MyWebAppInitializer implements WebApplicationInitializer {  
*  
* &#064;Override  
* public void onStartup(ServletContext container) {  
* XmlWebApplicationContext appContext = new XmlWebApplicationContext();  
* appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");  
*  
* ServletRegistration.Dynamic dispatcher =  
* container.addServlet("dispatcher", new DispatcherServlet(appContext));  
* dispatcher.setLoadOnStartup(1);  
* dispatcher.addMapping("/");  
* }  
*  
* }</pre>  
*
* <p>
* 上面的例子是实现 WebApplicationInitializer 接口。
* 也可以继承 AbstractDispatcherServletInitializer 类。
* </p>
*
* As an alternative to the above, you can also extend from {@link  
* org.springframework.web.servlet.support.AbstractDispatcherServletInitializer}.  
*  
* As you can see, thanks to Servlet 3.0's new {@link ServletContext#addServlet} method  
* we're actually registering an <em>instance</em> of the {@code DispatcherServlet}, and  
* this means that the {@code DispatcherServlet} can now be treated like any other object  
* -- receiving constructor injection of its application context in this case.  
*  
* <p>This style is both simpler and more concise. There is no concern for dealing with  
* init-params, etc, just normal JavaBean-style properties and constructor arguments. You  
* are free to create and work with your Spring application contexts as necessary before  
* injecting them into the {@code DispatcherServlet}.  
*  
* <p>Most major Spring Web components have been updated to support this style of  
* registration. You'll find that {@code DispatcherServlet}, {@code FrameworkServlet},  
* {@code ContextLoaderListener} and {@code DelegatingFilterProxy} all now support  
* constructor arguments. Even if a component (e.g. non-Spring, other third party) has not  
* been specifically updated for use within {@code WebApplicationInitializers}, they still  
* may be used in any case. The Servlet 3.0 {@code ServletContext} API allows for setting  
* init-params, context-params, etc programmatically.  
*
* <p>
* 在上面的例子中,web.xml 被替换了,但是 dispatcher-config.xml 依然存在。
* 下面的例子就彻底摆脱 xml 配置了。
* </p>
*
* <h2>A 100% code-based approach to configuration</h2>  
* In the example above, {@code WEB-INF/web.xml} was successfully replaced with code in  
* the form of a {@code WebApplicationInitializer}, but the actual  
* {@code dispatcher-config.xml} Spring configuration remained XML-based.  
* {@code WebApplicationInitializer} is a perfect fit for use with Spring's code-based  
* {@code @Configuration} classes. See @{@link  
* org.springframework.context.annotation.Configuration Configuration} Javadoc for  
* complete details, but the following example demonstrates refactoring to use Spring's  
* {@link org.springframework.web.context.support.AnnotationConfigWebApplicationContext  
* AnnotationConfigWebApplicationContext} in lieu of {@code XmlWebApplicationContext}, and  
* user-defined {@code @Configuration} classes {@code AppConfig} and  
* {@code DispatcherConfig} instead of Spring XML files. This example also goes a bit  
* beyond those above to demonstrate typical configuration of the 'root' application  
* context and registration of the {@code ContextLoaderListener}:  
* <pre class="code">  
* public class MyWebAppInitializer implements WebApplicationInitializer {  
*  
* &#064;Override  
* public void onStartup(ServletContext container) {  
* // Create the 'root' Spring application context  
* AnnotationConfigWebApplicationContext rootContext =  
* new AnnotationConfigWebApplicationContext();  
* rootContext.register(AppConfig.class);  
*  
* // Manage the lifecycle of the root application context  
* container.addListener(new ContextLoaderListener(rootContext));  
*  
* // Create the dispatcher servlet's Spring application context  
* AnnotationConfigWebApplicationContext dispatcherContext =  
* new AnnotationConfigWebApplicationContext();  
* dispatcherContext.register(DispatcherConfig.class);  
*  
* // Register and map the dispatcher servlet  
* ServletRegistration.Dynamic dispatcher =  
* container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));  
* dispatcher.setLoadOnStartup(1);  
* dispatcher.addMapping("/");  
* }  
*  
* }</pre>  
*  
* As an alternative to the above, you can also extend from {@link  
* org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer}.  
*  
* Remember that {@code WebApplicationInitializer} implementations are <em>detected  
* automatically</em> -- so you are free to package them within your application as you  
* see fit.  
*
* <p>
* 多个 WebApplicationInitializer 之间可以指定顺序。但是这种一般不常用。一个 WebApplicationInitializer 就够了。
* </p>
*
* <h2>Ordering {@code WebApplicationInitializer} execution</h2>  
* {@code WebApplicationInitializer} implementations may optionally be annotated at the  
* class level with Spring's @{@link org.springframework.core.annotation.Order Order}  
* annotation or may implement Spring's {@link org.springframework.core.Ordered Ordered}  
* interface. If so, the initializers will be ordered prior to invocation. This provides  
* a mechanism for users to ensure the order in which servlet container initialization  
* occurs. Use of this feature is expected to be rare, as typical applications will likely  
* centralize all container initialization within a single {@code WebApplicationInitializer}.  
*  
* <h2>Caveats</h2>  
*
* <p>
* 注意 web.xml 和 WebApplicationInitializer 不是相互排斥的。
* 二者可以同时存在。
* </p>
*
* <h3>web.xml versioning</h3>  
* <p>{@code WEB-INF/web.xml} and {@code WebApplicationInitializer} use are not mutually  
* exclusive; for example, web.xml can register one servlet, and a {@code  
* WebApplicationInitializer} can register another. An initializer can even  
* <em>modify</em> registrations performed in {@code web.xml} through methods such as  
* {@link ServletContext#getServletRegistration(String)}. <strong>However, if  
* {@code WEB-INF/web.xml} is present in the application, its {@code version} attribute  
* must be set to "3.0" or greater, otherwise {@code ServletContainerInitializer}  
* bootstrapping will be ignored by the servlet container.</strong>  
*  
* <h3>Mapping to '/' under Tomcat</h3>  
* <p>Apache Tomcat maps its internal {@code DefaultServlet} to "/", and on Tomcat versions  
* &lt;= 7.0.14, this servlet mapping <em>cannot be overridden programmatically</em>.  
* 7.0.15 fixes this issue. Overriding the "/" servlet mapping has also been tested  
* successfully under GlassFish 3.1.<p>  
*  
* @author Chris Beams  
* @since 3.1  
* @see SpringServletContainerInitializer  
* @see org.springframework.web.context.AbstractContextLoaderInitializer  
* @see org.springframework.web.servlet.support.AbstractDispatcherServletInitializer  
* @see org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer  
*/ 

多说一嘴,这个例子中用到了 DispatcherServlet 的有参构造(DispatcherServlet只有2个构造方法,一个无参一个有参,无参构造在其他文章中介绍了)。
这里就顺便详细看下这个有参构造的 javadoc

/**
 * 使用给定的 web 应用上下文来创建一个 DispatcherServlet。
 * 无参的构造是在 DispatcherServlet 内部自己创建维护 web 应用上下文。
 * 这个有参的构造是用外部传过来的 web 应用上下文。
 * 这个构造方法主要是用在 servlet 3.0+ 的环境中。
 * 用了这个构造方法以后,setContextClass setContextConfigLocation setContextAttribute setNamespace 这4个方法就无效了。
 * 对应的 contextClass contextConfigLocation contextAttribute namespace 等四个 servlet init-param 也无效了。
 * 传进来的 web 应用上下文可能已经 refresh() 了,也可能没有 refresh()。
 * 建议是不要 refresh()。
 * 如果不刷新的话,将会发生这些事情:
 * 1、如果传进来的web应用上下文还没有设置父应用上下文,则将 root web 应用上下文设置为它的父应用上下文。
 * 2、如果传进来的web应用上下文还没有设置id,将会给它设置一个id。
 * 3、将ServletContext和ServletConfig存到web应用上下文中。
 * 4、postProcessWebApplicationContext 方法会被调用。
 * 5、ApplicationContextInitializer 会被调用。可以用这个东西对web应用上下文进行自定义配置,其他文章也有提过。
 * 6、如果传进来的web应用上下文实现了ConfigurableApplicationContext的话,refresh()方法将会被调用。
 * 如果传进来的web应用上下文已经 refresh() 过了,上面提到的几点都不会发生。
 * 
 * 另外,这个有参构造怎么用,可以参考 WebApplicationInitializer 接口。这不就跟本文写的代码对应上了么。
 *
 * Create a new {@code DispatcherServlet} with the given web application context. This
 * constructor is useful in Servlet 3.0+ environments where instance-based registration
 * of servlets is possible through the {@link ServletContext#addServlet} API.
 * <p>Using this constructor indicates that the following properties / init-params
 * will be ignored:
 * <ul>
 * <li>{@link #setContextClass(Class)} / 'contextClass'</li>
 * <li>{@link #setContextConfigLocation(String)} / 'contextConfigLocation'</li>
 * <li>{@link #setContextAttribute(String)} / 'contextAttribute'</li>
 * <li>{@link #setNamespace(String)} / 'namespace'</li>
 * </ul>
 * <p>The given web application context may or may not yet be {@linkplain
 * ConfigurableApplicationContext#refresh() refreshed}. If it has <strong>not</strong>
 * already been refreshed (the recommended approach), then the following will occur:
 * <ul>
 * <li>If the given context does not already have a {@linkplain
 * ConfigurableApplicationContext#setParent parent}, the root application context
 * will be set as the parent.</li>
 * <li>If the given context has not already been assigned an {@linkplain
 * ConfigurableApplicationContext#setId id}, one will be assigned to it</li>
 * <li>{@code ServletContext} and {@code ServletConfig} objects will be delegated to
 * the application context</li>
 * <li>{@link #postProcessWebApplicationContext} will be called</li>
 * <li>Any {@code ApplicationContextInitializer}s specified through the
 * "contextInitializerClasses" init-param or through the {@link
 * #setContextInitializers} property will be applied.</li>
 * <li>{@link ConfigurableApplicationContext#refresh refresh()} will be called if the
 * context implements {@link ConfigurableApplicationContext}</li>
 * </ul>
 * If the context has already been refreshed, none of the above will occur, under the
 * assumption that the user has performed these actions (or not) per their specific
 * needs.
 * <p>See {@link org.springframework.web.WebApplicationInitializer} for usage examples.
 * @param webApplicationContext the context to use
 * @see #initWebApplicationContext
 * @see #configureAndRefreshWebApplicationContext
 * @see org.springframework.web.WebApplicationInitializer
 */
public DispatcherServlet(WebApplicationContext webApplicationContext) {
    super(webApplicationContext);
    setDispatchOptionsRequest(true);
}

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

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

相关文章

Python:交互式物质三态知识讲解小工具

学着物理写着Python 以下是一个使用Python的Tkinter库实现的简单示例程序&#xff0c;通过图形界面展示并讲解固态、液态、气态的一些特点&#xff0c;代码中有详细的注释来帮助你理解各部分功能&#xff1a; 完整代码 import tkinter as tk from tkinter import ttk import …

ESP32-S3遇见OpenAI:OpenAI官方发布ESP32嵌入式实时RTC SDK

目录 OpenAI RTC SDK简介应用场景详解智能家居控制系统个人健康助手教育玩具 技术亮点解析低功耗设计快速响应高精度RTC安全性保障开发者指南 最近&#xff0c;OpenAI官方发布了一款针对ESP32-S3的嵌入式实时RTC&#xff08;实时时钟&#xff09;SDK&#xff0c;这标志着ESP32-…

Windows 11 关闭 VBS(基于虚拟化的安全性)

注&#xff1a;本文为 “Windows 11 关闭 VBS” 相关方法文章合辑。 重传部分 csdn 转储异常图片&#xff0c;未整理去重。 Win11 关闭 VBS 的几种方法 适用机型&#xff1a;台式 / ThinkCentre / 笔记本 / ThinkPad 分析 Virtualization-based Security (VBS) 基于虚拟化的…

小程序租赁系统的优势与应用探索

内容概要 小程序租赁系统&#xff0c;听起来很高大上&#xff0c;但实际上它比你想象的要实用得多&#xff01;设想一下&#xff0c;几乎所有的租赁需求都能通过手机轻松解决。这种系统的便捷性体现在让用户随时随地都能发起租赁请求&#xff0c;而不再受制于传统繁琐的手续。…

简历_专业技能_熟悉Redis常用数据结构及其操作命令

系列博客目录 文章目录 系列博客目录1.Redis通用命令2.String类型3.Hash类型4.List类型5.Set类型6.Sorted类型7.StringRedisTemplate 1.Redis通用命令 通用指令是部分数据类型的&#xff0c;都可以使用的指令&#xff0c;常见的有&#xff1a; KEYS&#xff1a;查看符合模板的…

USB 驱动开发 --- Gadget 设备连接 Windows 免驱

环境信息 测试使用 DuoS(Arm CA53&#xff0c; Linux 5.10) 搭建方案验证环境&#xff0c;使用 USB sniff Wirekshark 抓包分析&#xff0c;合照如下&#xff1a; 注&#xff1a;左侧图中设备&#xff1a;1. 蓝色&#xff0c;USB sniff 非侵入工 USB 抓包工具&#xff1b;2. …

2025年1月4日蜻蜓q旗舰版st完整开源·包含前后端所有源文件·开源可商用可二开·优雅草科技·优雅草kir|优雅草星星|优雅草银满|优雅草undefined

2025年1月4日蜻蜓q旗舰版st完整开源包含前后端所有源文件开源可商用可二开优雅草科技优雅草kir|优雅草星星|优雅草银满|优雅草undefined 产品介绍&#xff1a; 本产品主要贡献者优雅草科技优雅草kir|优雅草星星|优雅草银满|优雅草undefined-青史留名&#xff0c;时光如川浪淘…

【文献精读笔记】Explainability for Large Language Models: A Survey (大语言模型的可解释性综述)(三)

****非斜体正文为原文献内容&#xff08;也包含笔者的补充&#xff09;&#xff0c;灰色块中是对文章细节的进一步详细解释&#xff01; 3.2 全局解释&#xff08;Global Explanation&#xff09; 与旨在解释模型个体预测的局部解释不同&#xff0c;全局解释提供了对语言模型…

体验谷歌最新Gemini 2.0 Flash原生多模态音视频对话桌面分享功能

Gemini 2.0是谷歌最新推出的原生多模态输入输出的AI模型。Gemini 2.0 Flash是2.0家族第一个模型&#xff0c;以多模态输入输出和Agent技术为核心&#xff0c;速度比 1.5 Pro快两倍&#xff0c;关键性能指标超过 1.5 Pro。模型支持原生工具调用和实时音视频流输入&#xff0c;提…

Leecode刷题C语言之我的日程安排表③

执行结果:通过 执行用时和内存消耗如下&#xff1a; typedef struct {int size;int maxIntersection;int** books;// #ifdef DEBUG// int runCount;// #endif } MyCalendarThree;void insert(MyCalendarThree*, int, int, int, int); int* binarySearch(int*, int, int);MyCal…

C++ 函数名字后面带const

C++中,在函数名后面加上const关键字表示该函数是一个常量成员函数。 常量成员函数,可以在const对象上被调用,并且不会修改对象的状态。 VC6新建一个单文档工程;添加一个一般类; 把类的代码做好; // MyClass.h: interface for the MyClass class. // //#if !defined(AFX_…

SMTP发送邮件的过程

&#xff08;1&#xff09;SMTP客户端首先请求与服务器端的25号端口建立TCP连接(1分)。&#xff08;2&#xff09;连接建立成功后&#xff0c;客户端和服务器通过握手阶段验证双方身份(1分)。&#xff08;3&#xff09;验证成功后&#xff0c;客户端首先向服务器端通告邮件发送…

qml Rectangle详解

1、概述 Rectangle是Qt Quick中的一个基础图形元素&#xff0c;用于在QML界面上绘制一个可带边框和可填充的矩形区域。它继承自Item类&#xff0c;因此具有Item的所有属性和功能&#xff0c;如位置、尺寸、变换等。通过Rectangle&#xff0c;可以创建各种矩形形状&#xff0c;…

软件工程实验-实验2 结构化分析与设计-总体设计和数据库设计

一、实验内容 1. 绘制工资支付系统的功能结构图和数据库 在系统设计阶段&#xff0c;要设计软件体系结构&#xff0c;即是确定软件系统中每个程序是由哪些模块组成的&#xff0c;以及这些模块相互间的关系。同时把模块组织成良好的层次系统&#xff1a;顶层模块通过调用它的下层…

Innodisk iSMART V6使用说明_SSD还能用多久?已经读写了多少次数?……

Innodisk iSMART是一款SSD健康数据读取软件。它能轻松获取大部分SSD内部寄存器中的健康数据&#xff0c;并以简洁的图形界面展示给用户。在程序界面的顶部&#xff0c;是页面标签&#xff0c;点击页面标签就能切换到相应的页面。页面标签的下面是磁盘选择栏。点击磁盘编号&…

windows11(或centos7)安装nvidia显卡驱动、CUDA、cuDNN

本文是我瞎搞时写的问题汇总及参考文献&#xff0c;记录了一些问题解决的进度及对问题的思考。 最近一次更新时间&#xff1a;2025年1月4日 一、安装或更新nvidia显卡驱动 首先&#xff0c;需要确保你的设备安装了最新的显卡驱动。 &#xff08;1&#xff09;centos7安装显…

2、蓝牙打印机点灯-GPIO输出控制

1、硬件 1.1、看原理图 初始状态位高电平. 需要驱动PA1输出高低电平控制PA1. 1.2、看手册 a、系统架构图 GPIOA在APB2总线上。 b、RCC使能 GPIOA在第2位。 c、GPIO寄存器配置 端口&#xff1a;PA1 模式&#xff1a;通用推挽输出模式 -- 输出0、1即可 速度&#xff1a;5…

WPS表格技巧01-项目管理中的基本功能-计划和每日记录的对应

前言&#xff1a; 在项目管理中&#xff0c;一般就是用些项目管理工具来管理这个任务和 task&#xff0c;但是就是要学这些工具很麻烦&#xff0c;比较好的方法&#xff0c;通用的方法就是用 Excel 表格去做&#xff08;这非常适合松散的团队组织&#xff09;&#xff0c;然后…

Vue 项目中实现打印功能:基于目标 ID 的便捷打印方案

一、引言 在 Vue 项目开发中&#xff0c;实现打印功能是一个常见的需求。本文将介绍如何封装一个打印方法&#xff0c;使得用户只需传入需要打印的目标 ID 名称&#xff0c;即可轻松实现预览并打印的功能。这种方法不仅简单易用&#xff0c;还具有一定的通用性&#xff0c;适合…

ARM 汇编基础总结

GNU 汇编语法 编写汇编的过程中&#xff0c;其指令、寄存器名等可以全部使用大写&#xff0c;也可以全部使用小写&#xff0c;但是不能大小写混用。 1. 汇编语句的格式 label: instruction comment label即标号&#xff0c;表示地址位置&#xff0c;有些指令前面可能会有标…