• [技术干货] Spring 核心技术解析【纯干货版】- V:Spring 基础模块 Spring-Context 模块精讲-转载
    1、Spring-Context 模块介绍1.1、Spring-Context 模块概述Spring-Context 模块,是 Spring 核心容器模块之一,它为应用程序上下文的管理提供了支持,同时也是许多其他 Spring 模块的依赖基础。应用程序上下文,也称为 Application Context,来源于设计模式中的一个术语。在许多设计模式中,上下文通常用于隐式表示执行某个行为时所需的环境或条件。在 Spring-Context 模块中,这一抽象概念被具体实现为各种 Context 对象。Spring-Context 模块中的 Context 是一个集中化的管理器,除了负责 Bean 的生命周期管理(如创建、初始化、销毁等),还提供了运行应用程序所需的各种服务。1.2、Spring-Context 模块依赖Spring-Context 模块的依赖有四个,分别是同为基础模块的 Spring-Beans 模块、Spring-Core 模块、Spring-Expression 模块和 AOP 模块中的 Spring-AOP 模块。其中 Spring Beans 模块是对 Spring Bean 进行定义,实现 IOC 基础功能的模块。Spring-Core 是 Spring 中的基础模块,它提供了框架运行所必需的核心功能。Spring-Expression 提供对 SpEL 的支持。而 Spring-AOP 提供对 AOP 的支持。1.3、Spring-Context 模块作用由于 Spring-Context 模块依赖了全部的 Spring 基本模块,并在他们的基础上进一步完善相关功能,包括但不限于:资源管理、环境与配置管理、生命周期管理、校验与格式化、AOP 与声明式事务支持等内容。本篇仅简单介绍一部分核心功能例如:应用上下文(ApplicationContext)、注解支持、事件驱动的内容。2、ApplicationContext 的介绍在 Spring 框架中,ApplicationContext 是最核心的接口之一,主要用于容纳和管理 Spring 容器中的所有 Bean 实例。它不仅拓展了 BeanFactory 接口,更是提供了更加丰富和灵活的功能。包括国际化支持、事件传播、AOP 支持等。2.1、ApplicationContext 的功能与特性下面是 ApplicationContext 的源码:public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {    @Nullable    String getId();    String getApplicationName();    String getDisplayName();    long getStartupDate();    @Nullable    ApplicationContext getParent();    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;}它继承了 BeanFactory、MessageSource、ApplicationEventPublisher 等 6 个接口。 下面是 ApplicationContext 继承的 6 个父接口的说明:MessageSource 接口:用于处理信息资源的国际化,能够支持多语言和地区化功能。ApplicationEventPublisher 接口:是事件发布的接口,允许在 Spring 应用中发布事件。事件可以用于解耦应用的不同组件,让它们以松耦合的方式进行交互。ResourcePatternResolver 接口:继承自 ResourceLoader,提供了扩展的功能来解析资源路径和资源模式。它支持通过模式(例如 classpath:)解析并加载资源,不仅能够加载文件,还可以加载类路径上的文件、网络资源等。EnvironmentCapable 接口:提供对应用程序环境的访问。ListableBeanFactory 接口:继承自 BeanFactory,增强了列举和查询 Bean 的能力。它允许你列出容器中所有 Bean 的名称、类型,甚至根据类型或名称进行过滤和查找。HierarchicalBeanFactory 接口:继承自 BeanFactory,引入了 Bean 工厂的分层概念。它允许 Spring 容器支持层次化的 Bean 工厂结构,使得上下文可以有父容器和子容器。从 ApplicationContext 的父接口,和下面的方法定义上,我们也可以大致总结出,ApplicationContext 有着:负责管理 Bean 的生命周期、提供事件发布、国际化支持、资源加载、环境配置及自动装配等功能。2.2、ApplicationContext 的实现上面我们介绍了 ApplicationContext 接口的功能,接着我们来看一下它的实现,Spring 提供了多个 ApplicationContext 实现类,每个实现类适用于不同的使用场景。 以下是 ApplicationContext 的主要实现的介绍及特性:ClassPathXmlApplicationContext:这是最常见的 ApplicationContext 实现之一,主要通过 XML 配置文件来加载和配置 Bean。它的实现基于 AbstractXmlApplicationContext 类,专门用于解析类路径下的 XML 配置文件,来初始化 Spring 容器。这种实现类适用于小型到中型项目,特别是在需要从类路径中加载配置文件的场景中。例如,假设我们有一个简单的 Spring 应用,配置文件位于 src/main/resources 目录下,可以使用 ClassPathXmlApplicationContext 来加载配置文件:ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");1FileSystemXmlApplicationContext:这个实现类可以从文件系统中加载 XML 配置文件。它适用于需要从文件系统中加载配置文件的场景,例如在开发环境中,配置文件可能位于项目的根目录或某个特定的文件夹中。使用 FileSystemXmlApplicationContext 可以方便地加载这些配置文件:ApplicationContext context = new FileSystemXmlApplicationContext("file:/path/to/applicationContext.xml");1AnnotationConfigApplicationContext:基于注解的配置而设计的实现类。它支持 Java 配置类的方式,允许通过注解(如 @Configuration, @ComponentScan, @Bean 等)来配置 Spring 容器中的 Bean。它是 Spring 4 引入的,以支持纯 Java 配置,特别适用于 Spring Boot 等需要更灵活和简洁配置的现代 Spring 应用。例如,假设我们有一个配置类 AppConfig,可以使用 AnnotationConfigApplicationContext 来加载配置类:ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);1GenericWebApplicationContext:Spring-Web 模块中提供的,是为 Web 应用设计的 ApplicationContext 实现类,继承自 GenericApplicationContext,专门用于 Spring Web 应用(例如 Spring MVC)。它结合了 Web 环境的特殊需求,提供了对 Web 组件的支持。GenericWebApplicationContext 通常通过 ContextLoaderListener 在应用启动时初始化:// web.xml 配置<context-param>    <param-name>contextConfigLocation</param-name>    <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value></context-param><listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>8选择合适的 ApplicationContext 实现类需要综合考虑项目规模、配置方式、应用类型和性能需求。对于小型到中型项目,ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 是不错的选择,前者适合 XML 配置,后者更适合注解和 Java 配置。而在大型或复杂项目中,AnnotationConfigApplicationContext 提供了更高的灵活性和扩展性,而 Web 应用推荐使用支持 Servlet 和 JSP 配置的 GenericWebApplicationContext。如果性能是关键考虑因素,注解驱动的 AnnotationConfigApplicationContext 通常比 XML 配置的实现类更高效。总之,根据具体需求选择最合适的实现类,能更好地平衡项目的开发效率与运行性能。3、核心注解:Bean、配置和自动扫描3.1、@Configuration模块:spring-context 模块。作用:标记一个类为配置类,类似于传统 XML 配置中的 <beans> 标签,表示该类中定义的 Bean 都会被 Spring 容器管理。使用方式:通常与 @Bean 注解一起使用,在配置类中定义 Bean。使用示例:@Configurationpublic class AppConfig {    @Bean    public MyService myService() {        return new MyService();    }}3.2、@Bean模块:spring-context 模块。作用:标记方法为 Bean 定义,用于将方法返回的对象注册到 Spring 容器中,通常配合 @Configuration 使用。使用方式:在 @Configuration 注解标注的类中,使用 @Bean 注解将方法返回值作为 Bean 注册到容器。3.3、@Component模块:spring-context 模块。作用:标记类为 Spring 的组件(Bean),Spring 会自动扫描并将其注册到容器中。@Component 是一个通用的注解,可以通过 @ComponentScan 来扫描指定包中的类。使用示例:package com.lizhengi.service@Componentpublic class MyService {    // Service logic}常见衍生注解:@Service:通常用于服务层的 Bean。@Repository:通常用于数据访问层的 Bean,包含数据访问相关的异常转换功能。@Controller:通常用于标注 Spring MVC 中的控制器。3.4、@ComponentScan模块:spring-context 模块。作用:用于自动扫描指定包中的 @Component 注解类,自动将它们注册到 Spring 容器中。通常配合 @Configuration 使用。使用方式:指定要扫描的包或包的路径,自动注册标记为 @Component、@Service、@Repository 和 @Controller 等注解的类。使用示例:@Configuration@ComponentScan(basePackages = "com.lizhengi")public class AppConfig {    // 自动扫描指定包中的 Bean}4、事件驱动Spring 的事件驱动模型,其实就是在 ApplicationContext 基础上加了个观察者模式。发布者负责发消息,监听者负责接收,Spring 负责中间传话。看似复杂,其实是个精简版的观察者模式,简单又高效。观察者模式 的核心是 发布者 和 订阅者 的解耦,通过一个中间层(如事件管理器)让二者不直接依赖。Spring 的事件驱动模型 则完全复用了这一思想,ApplicationContext 扮演了 “事件管理器” 的角色,负责维护发布者和监听者之间的关系。4.1、事件驱动核心概念及 Spring-Context 模块的实现4.1.1、事件事件(Event):事件是发生了某种操作或状态改变的信号。在 Spring 中,事件是 ApplicationEvent 的子类,也可以是任何自定义类。public class CustomEvent extends ApplicationEvent {    private String message;    public CustomEvent(Object source, String message) {        super(source);        this.message = message;    }    public String getMessage() {        return message;    }}4.1.2、事件发布器事件发布器(Event Publisher):Spring 提供了 ApplicationEventPublisher 接口,用于发布事件。通常,通过注入 ApplicationEventPublisher 来发布事件:@Componentpublic class EventPublisher {    private final ApplicationEventPublisher publisher;    public EventPublisher(ApplicationEventPublisher publisher) {        this.publisher = publisher;    }    public void publishCustomEvent(String message) {        CustomEvent event = new CustomEvent(this, message);        publisher.publishEvent(event);    }}4.1.3、事件监听器事件监听器(Event Listener):事件监听器用于处理特定类型的事件。可以通过 @EventListener 注解或者实现 ApplicationListener 接口来定义监听器:使用 @EventListener:@Componentpublic class EventListenerExample {    @EventListener    public void handleCustomEvent(CustomEvent event) {        System.out.println("Received event - " + event.getMessage());    }}实现 ApplicationListener 接口:@Componentpublic class CustomEventListener implements ApplicationListener<CustomEvent> {    @Override    public void onApplicationEvent(CustomEvent event) {        System.out.println("Handled event - " + event.getMessage());    }}4.1.4、上下文事件Spring 自带了一些标准事件,例如:ContextRefreshedEvent:容器初始化或刷新时发布。ContextStartedEvent:容器调用 start() 方法时发布。ContextStoppedEvent:容器调用 stop() 方法时发布。ContextClosedEvent:容器关闭时发布。4.2、使用示例发布事件:@SpringBootApplicationpublic class EventDemoApplication {    public static void main(String[] args) {        ConfigurableApplicationContext context = SpringApplication.run(EventDemoApplication.class, args);        EventPublisher publisher = context.getBean(EventPublisher.class);        publisher.publishCustomEvent("Hello, Spring Event!");    }}异步监听:通过 @Async 注解,可以让事件处理在单独的线程中执行:@Componentpublic class AsyncEventListener {    @Async    @EventListener    public void handleAsyncEvent(CustomEvent event) {        System.out.println("Processing event asynchronously - " + event.getMessage());    }}同时需要启用异步功能:@EnableAsync@SpringBootApplicationpublic class EventDemoApplication { }X、后记在快速发展的软件开发领域,Spring 框架凭借其灵活性和强大的功能始终处于领先地位,而 Spring-Context 模块作为其核心之一,为开发者提供了丰富的功能支持。掌握 Spring-Context 的使用,不仅可以帮助我们更高效地管理 Bean 生命周期和上下文环境,还能通过事件驱动、注解配置等特性构建出更加优雅和高效的应用架构。希望本文能够帮助您深入理解 Spring-Context 模块,并在实际开发中灵活运用。如果您对文中内容有疑问或建议,欢迎留言讨论。让我们携手前行,在技术的道路上不断探索,共同进步!————————————————                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                        原文链接:https://blog.csdn.net/weixin_45187434/article/details/144982638
  • [技术干货] Servlet中配置和使用过滤器-转载
    在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,以下是具体内容:创建过滤器类过滤器类需要实现javax.servlet.Filter接口,并重写其中的init、doFilter和destroy方法。init方法用于过滤器的初始化,在服务器启动时被调用,通常用于加载配置文件、初始化资源等操作。doFilter方法是过滤器的核心方法,用于实现具体的过滤逻辑,对每个进入过滤器链的请求和响应进行处理。destroy方法在服务器关闭时被调用,用于释放过滤器占用的资源。以下是一个简单的过滤器类示例,用于统一设置请求和响应的字符编码为UTF-8:import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;public class CharacterEncodingFilter implements Filter {    private String encoding;    @Override    public void init(FilterConfig filterConfig) throws ServletException {        // 从web.xml中获取配置的字符编码,如果没有配置则使用默认的UTF-8        encoding = filterConfig.getInitParameter("encoding");        if (encoding == null) {            encoding = "UTF-8";        }    }    @Override    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {        // 设置请求的字符编码        request.setCharacterEncoding(encoding);        // 设置响应的字符编码        response.setContentType("text/html;charset=" + encoding);        // 将请求传递给下一个过滤器或Servlet        filterChain.doFilter(request, response);    }    @Override    public void destroy() {        // 释放资源,这里没有需要释放的资源,所以为空方法    }}配置过滤器注解方式(Servlet 3.0及以上):在过滤器类上使用@WebFilter注解来配置过滤器。可以指定过滤的URL模式、过滤器名称等属性。import javax.servlet.Filter;import javax.servlet.annotation.WebFilter;@WebFilter(filterName = "CharacterEncodingFilter", urlPatterns = "/*")public class CharacterEncodingFilter implements Filter {    // 过滤器类的实现代码上述代码中,@WebFilter注解将CharacterEncodingFilter过滤器映射到所有的URL路径(/*)上,即对该Web应用中的所有请求都进行过滤。web.xml配置方式:在web.xml文件中使用<filter>和<filter-mapping>标签来配置过滤器。<web-app>    <!-- 过滤器定义 -->    <filter>        <filter-name>CharacterEncodingFilter</filter-name>        <filter-class>com.example.CharacterEncodingFilter</filter-class>        <!-- 过滤器初始化参数 -->        <init-param>            <param-name>encoding</param-name>            <param-value>UTF-8</param-value>        </init-param>    </filter>    <!-- 过滤器映射 -->    <filter-mapping>        <filter-name>CharacterEncodingFilter</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping></web-app>在上述配置中,<filter>标签定义了过滤器的名称、类名以及初始化参数。<filter-mapping>标签将过滤器名称与URL模式进行映射,这里同样是对所有路径进行过滤。使用过滤器当客户端发送请求到服务器时,请求会先进入过滤器链。如果请求的URL匹配过滤器的映射路径,那么对应的过滤器就会被执行。过滤器可以对请求进行预处理,如验证用户登录状态、检查请求参数等。如果请求通过了过滤器的验证,就会被传递给下一个过滤器或目标Servlet进行处理。在Servlet处理完请求生成响应后,响应会沿着过滤器链反向传递,过滤器可以对响应进行后处理,如修改响应头、压缩响应数据等。假设在一个Web应用中有多个Servlet,当配置了上述字符编码过滤器后,所有访问该Web应用的请求和响应的字符编码都会被设置为UTF-8,确保了数据在传输过程中的正确处理,避免了乱码问题。————————————————                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                        原文链接:https://blog.csdn.net/qq_25699299/article/details/144825390
  • [技术干货] Spring事务失效的方法或场景
    事务传播行为设置不当:错误地设置了事务的传播行为,如使用了不支持事务的传播行为,可能导致事务未能正确执行。解决方法:根据业务需求选择合适的事务传播行为。访问权限问题:如果事务方法的访问修饰符是private、protected或default,则事务将不会生效。Spring要求被代理方法必须是public的。解决方法:确保所有需要事务的方法都是public的。方法用final修饰:如果将事务方法定义成final,则无法被Spring的AOP代理重写,从而无法添加事务功能。解决方法:避免将事务方法定义为final。方法内部调用:在同一个类中,一个带有事务的方法直接调用另一个带事务的方法,Spring无法通过代理拦截这个调用,因此事务不会生效。解决方法:通过外部代理对象来调用事务方法,或者将需要事务的方法拆分到不同的类中,并通过Spring的依赖注入进行调用。异常处理不当:如果在事务中抛出异常,而异常处理逻辑未正确处理,可能导致事务回滚失败。解决方法:确保异常被正确捕获并处理,或者通过设置@Transactional注解的rollbackFor属性来指定哪些异常会触发回滚。事务超时:如果事务执行时间过长,超过设置的事务超时时间,可能导致事务自动回滚。解决方法:根据业务需求设置合理的事务超时时间。数据库锁定问题:数据库锁定机制可能导致事务在等待锁时超时或无法获取锁,从而失效。解决方法:优化数据库操作,减少锁竞争,或者调整数据库锁定策略。事务管理器的配置问题:错误地配置了事务管理器,可能导致事务无法正常工作。解决方法:检查并正确配置事务管理器。并发问题:在高并发环境下,多个事务同时操作同一数据,可能导致数据不一致。解决方法:使用乐观锁、悲观锁等并发控制机制来确保数据一致性。数据类型不匹配:在执行跨数据库操作时,数据类型的不匹配可能导致事务失效。解决方法:确保跨数据库操作的数据类型兼容。网络问题:网络中断或延迟可能导致事务通信失败,从而失效。解决方法:确保网络稳定可靠,或者使用事务补偿机制来处理网络故障。资源耗尽:系统资源耗尽(如内存溢出)也可能导致事务失效。解决方法:优化系统资源使用,确保系统有足够的资源来处理事务。
  • [技术干货] spring的三级缓存
    在Spring框架中,三级缓存机制是解决循环依赖问题的核心机制之一,它优化了单例bean的创建过程。以下是对Spring三级缓存机制的详细解释:三级缓存的构成一级缓存(singletonObjects):作用:存储已经完全初始化的bean对象。数据结构:Map<String, Object>,键是bean的名称,值是bean实例。说明:当bean完全创建并初始化完成后,它会被放入一级缓存中,表示该bean可供整个应用程序使用。二级缓存(earlySingletonObjects):作用:存储提前暴露的单例bean,即在bean实例化过程中,部分初始化好的对象。数据结构:Map<String, Object>,键是bean的名称,值是部分初始化的bean对象。说明:如果Spring容器发现bean在创建过程中,某些依赖已经创建好并且可以提供给其他bean使用,它会将这些尚未完全初始化的bean放入二级缓存中,以供后续使用。三级缓存(singletonFactories):作用:存储bean创建的工厂方法,即正在创建中的bean的工厂对象。数据结构:Map<String, ObjectFactory<?>>,键是bean的名称,值是一个ObjectFactory实例,用于获取正在创建中的bean。说明:当Spring遇到循环依赖问题,且目标bean尚未初始化时,它会将一个工厂方法放入三级缓存中,后续通过这个工厂方法来生成正在创建中的bean。三级缓存的工作流程当Spring需要实例化一个bean时,首先会检查该bean是否已经在一级缓存中。如果存在,则直接返回。如果bean不在一级缓存中,Spring会开始创建这个bean。此时,Spring会先在三级缓存中放入该bean的工厂方法(即ObjectFactory)。在bean的创建过程中,Spring会把已经部分初始化(例如构造函数已经调用完)的bean放入二级缓存中。这样,如果其他bean依赖于这个bean,能够获取到该bean的部分初始化实例(通常是一个代理对象)。如果存在循环依赖,即A依赖于B,而B又依赖于A,当Spring初始化A时,发现A依赖B,于是开始初始化B。在初始化B的过程中,发现B依赖A,此时A尚未完全初始化。为了避免死锁,Spring会通过三级缓存中的工厂方法获取到A的部分初始化实例(代理对象),然后继续初始化B。B初始化完成后,Spring会继续完成A的初始化。一旦A和B的循环依赖问题解决后,Spring会将它们完全初始化并放入一级缓存中。三级缓存的意义解决循环依赖:通过三级缓存中的工厂方法和提前暴露的部分初始化bean,Spring解决了循环依赖问题,保证了依赖关系能够正确解析和初始化。提高创建效率:三级缓存避免了多次创建相同的bean,提高了bean的创建效率。总之,三级缓存是Spring框架为了优化单例bean创建过程并解决循环依赖问题所引入的机制。通过三级缓存,Spring能够有效避免循环依赖带来的死锁问题,并提高bean的创建效率。
  • [技术干货] spring 参数校验Validation示例详解【转】
    前言在实际开发中,我们无法保证客户端传来的请求都是合法的。比如一些要求必传的参数没有传递,传来的参数长度不符合要求等,这种时候如果放任不管,继续执行后续业务逻辑,很有可能就会出现意想不到的bug。有人可能会说,这不是前端的问题吗,让前端校验去。话是这么说,但我们也不能前端校验百分百不会出现问题。并且有些请求可能也不是正规通过客户端发来的,可能是黑客恶意攻击,又或是通过Postman等发来的,这些请求就不一定会“合法”了。因此,对客户端传来的每个请求都进行必要的参数校验是十分重要的。而很多简单的校验如果都需要程序员自己去写的话,就会导致代码过于冗长、繁琐。为了让校验更加简洁明了,Spring为我们提供了Validation工具类来提供各种校验方法。一、Validation常见的校验注解空校验注解:@Null:被注释的元素必须为null。@NotNull:被注释的元素必须不为null。@NotBlank:被注释的字符串去掉前后空格后长度必须非零。@NotEmpty:被注释的字符串、集合或数组不能为空(字符串长度非零、集合大小非零)。布尔校验注解:@AssertTrue:被注释的元素必须为true。@AssertFalse:被注释的元素必须为false。日期校验注解:@Past:被注释的元素必须是一个过去的日期。@Future:被注释的元素必须是一个将来的日期。数字校验注解:@Min(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值。@Max(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值。@DecimalMin(value):被注释的元素必须是一个数字,其值必须大于等于指定的最小值。@DecimalMax(value):被注释的元素必须是一个数字,其值必须小于等于指定的最大值。长度校验注解:@Size(max, min):被注释的元素(如字符串、集合、数组)的大小必须在指定的范围内。模式匹配校验注解:@Pattern(regexp):被注释的元素必须符合指定的正则表达式。邮箱校验注解:@Email:被注释的元素必须是电子邮箱地址。范围校验注解:@Range(min, max):被注释的元素必须在合适的范围内。
  • [专题汇总] 快来看看吧,总有一篇帖子可以帮到你,11月干货合集。
     大家好一年马上结束了给大家带来11月份的干货合集,本次涉及springboot,springmvc,Python,MySQL,Redis,HarmonyOS等多类知识,希望可以帮助到大家。 1.使用SQL实现按每小时统计数据【转】 https://bbs.huaweicloud.com/forum/thread-0296168347647671062-1-1.html  2.MySQL获取数据库内所有表格数据总数的示例代码【转】 https://bbs.huaweicloud.com/forum/thread-02109168347516352050-1-1.html  3.Redis主从复制的实现示例【转】 https://bbs.huaweicloud.com/forum/thread-0296168346418210061-1-1.html  4.MySQL启动方式之systemctl与mysqld的对比详解【转】 https://bbs.huaweicloud.com/forum/thread-0296168346377082060-1-1.html  5.全面解析MySQL常见问题的排查与解决方法【转】 https://bbs.huaweicloud.com/forum/thread-0276168346339971051-1-1.html  6.Python代码调试Debug的实用技巧分享【转】 https://bbs.huaweicloud.com/forum/thread-0241168345445980044-1-1.html  7.Bash脚本实现实时监测登录【转】 https://bbs.huaweicloud.com/forum/thread-0241168345292684043-1-1.html  8.使用Python删除Word中表格的方法【转】 https://bbs.huaweicloud.com/forum/thread-02109168344979927049-1-1.html  9.基于Go语言实现压缩文件处理【转】 https://bbs.huaweicloud.com/forum/thread-0276168344745791050-1-1.html  10.Python实现批量图片去重【转】 https://bbs.huaweicloud.com/forum/thread-02112168344680315056-1-1.html  11.python实现二维列表的列表生成式【转】 https://bbs.huaweicloud.com/forum/thread-0296168340813812059-1-1.html  12.基于Python实现IP代理池【转】 https://bbs.huaweicloud.com/forum/thread-0276168340692413049-1-1.html  13.Gin框架中异步任务的实现【转】 https://bbs.huaweicloud.com/forum/thread-0296168340516828058-1-1.html  14.使用Go语言中的Context取消协程执行的操作代码【转】 https://bbs.huaweicloud.com/forum/thread-02109168340403402048-1-1.html  15.使用Python实现获取Apollo配置【转】 https://bbs.huaweicloud.com/forum/thread-02112168340011491055-1-1.html  16.【HarmonyOS】抖动动画方案 https://bbs.huaweicloud.com/forum/thread-02119168246419995040-1-1.html  17.【HarmonyOS】九宫格拼图游戏 https://bbs.huaweicloud.com/forum/thread-02112168246323162046-1-1.html  18.【HarmonyOS】Web组件同步与异步数据获取 https://bbs.huaweicloud.com/forum/thread-02109168246260516045-1-1.html  19.【HarmonyOS】图片下载加载方案 https://bbs.huaweicloud.com/forum/thread-02112168246161439045-1-1.html  20.【HarmonyOS】动画旋转方式比较 https://bbs.huaweicloud.com/forum/thread-0241168246072330040-1-1.html  21.Linux下的基本指令-转载 https://bbs.huaweicloud.com/forum/thread-02108167416586006015-1-1.html  22.Linux:认识文件系统-转载 https://bbs.huaweicloud.com/forum/thread-02115167416457957013-1-1.html  23.【JAVA】Spring MVC 详解-转载 https://bbs.huaweicloud.com/forum/thread-02108167416063721014-1-1.html  24.【Spring】MVC-转载 https://bbs.huaweicloud.com/forum/thread-0229167415942031022-1-1.html  25.【Spring篇】Spring中的Bean管理-转载 https://bbs.huaweicloud.com/forum/thread-02115167415823291012-1-1.html 
  • [技术干货] 重看Spring聚焦BeanDefinition分析和构造-转载
     干货分享,感谢您的阅读!  在这个迅速发展的技术时代,开源框架如春天般蓬勃生长,其中Spring框架则以其灵活性和强大功能赢得了开发者们的青睐。而在这个庞大的框架中,有一个小小的角色却承担着至关重要的任务,那就是BeanDefinition。它不仅是Spring容器的“元信息”守护者,更是实现高效、灵活应用的秘密武器。  想象一下,如果没有BeanDefinition,开发者们在创建和管理Bean时将面临怎样的混乱局面?是不是像失去了指南针的探险者,在茫茫大海中寻找方向?本文将带你深入探讨BeanDefinition的奥秘,从基本概念到实际应用,甚至是各种构造方式的对比分析,让你在一篇文章中全面理解这个看似不起眼但却不可或缺的组成部分。快来一起揭开BeanDefinition的面纱,看看它如何在背后默默地为你的应用程序提供支持和灵活性吧!  一、对BeanDefinition的理解 BeanDefinition 可以被认为是 Bean 的元信息。它不是 Bean 实例本身,而是描述了如何创建 Bean 实例以及 Bean 的配置信息。因此,BeanDefinition 提供了关于 Bean 的元数据,包括类名、作用域、构造函数参数、属性值等等。在 Spring 容器启动时,BeanDefinition 被解析并用于实例化和管理 Bean 实例。  (一)理解元信息 在计算机科学中,元信息是用于描述其他数据的数据。元信息提供关于数据的属性、结构、类型或其他相关信息,通常用于解释和管理数据,而不是直接操作数据本身。  在软件开发中,元信息的概念非常常见。比如,在数据库中,表的结构信息(如列名、数据类型、约束等)就是元信息;在编程语言中,注解(Annotation)提供了关于类、方法或字段的额外信息,也可以看作是元信息;在 Web 开发中,HTML 标签中的属性、HTTP 头部中的信息等都可以视为元信息。  (二)BeanDefinition理解分析 BeanDefinition 是关于 Bean 的元数据集合(包含了创建和管理 Bean 所需的所有信息),这些信息在 Spring 容器启动时被解析,并用于实例化和管理 Bean 实例。通过配置和操作 BeanDefinition可以控制和定制 Bean 的行为,实现更加灵活和高效的应用程序开发。具体的元信息可总结如下表进行查看:  元信息    描述 类信息 (Class Information)    Bean的类名,用于指定如何实例化Bean。 作用域信息 (Scope Information)    Bean的作用域,决定了Bean的生命周期范围,包括singleton、prototype、request、session等。 构造函数参数 (Constructor Arguments)    描述了Bean构造函数的参数信息,用于实例化Bean对象。 属性信息 (Property Information)    描述了Bean的属性值信息,包括属性名和属性值,用于在实例化后设置Bean的属性。 初始化和销毁方法 (Initialization and Destruction Methods)    指定了Bean的初始化方法和销毁方法,用于在Bean实例化后或销毁前执行额外的操作。 依赖信息 (Dependency Information)    描述了Bean之间的依赖关系,使得容器能够按正确的顺序实例化和管理Bean。 其他元信息 (Other Metadata)    包括Bean的描述、别名等其他元信息,用于进一步描述Bean的用途和特性。 二、BeanDefinition的结构设计分析 (一)整体结构体会  (二)重要接口和类分析 我们选取一些重要接口和类整理表格来快速回顾(源码暂时不进行分析了):  接口/类    描述 BeanDefinition 接口    定义了 Bean 的元信息,包括类名、作用域、构造函数参数、属性值等。 AbstractBeanDefinition 抽象类    BeanDefinition 接口的抽象实现类,提供了通用属性的默认实现,如 Bean 类型、作用域、懒加载等。 GenericBeanDefinition 类    AbstractBeanDefinition 的具体实现类,用于描述通用的 BeanDefinition 结构,适用于多种配置方式。 RootBeanDefinition 类    GenericBeanDefinition 的子类,增加了对 Bean 类型自动检测的支持,可以根据配置自动确定 Bean 的类型。 AnnotatedBeanDefinition 接口    表示使用注解配置的 BeanDefinition,继承自 BeanDefinition 接口,用于描述通过注解方式配置的 Bean。 BeanDefinitionHolder 类    BeanDefinition 的持有者,包含一个 BeanDefinition 对象以及与之关联的名称和别名。 BeanDefinitionRegistry 接口    定义了 BeanDefinition 注册的方法,允许向 Spring 容器注册新的 BeanDefinition,或者从容器中移除已有的 BeanDefinition。 DefaultListableBeanFactory 类    BeanDefinitionRegistry 接口的默认实现类,实现了 BeanDefinition 的注册和管理功能,是 Spring 容器的核心部分之一。 接下来我们重点看如何构造BeanDefinition。  三、构造 BeanDefinition:模式注解 + 组件扫描方式 基于约定优于配置的原则  使用注解(如 @Component、@Service、@Repository、@Controller 等)标记类,然后通过组件扫描(Component Scanning)方式,Spring 容器会自动扫描指定的包,并根据这些注解自动创建相应的 BeanDefinition。  这种方式在平时开发中最为常见,比如直接定义一个简单的组件类并用 @Component 注解进行标记如下:  package org.zyf.javabasic.spring.beandefinition;   import org.springframework.stereotype.Component;   /**  * @program: zyfboot-javabasic  * @description: 定义一个简单的组件类,并使用 @Component 注解进行标记  * @author: zhangyanfeng  * @create: 2024-05-02 11:03  **/ @Component public class ZyfComponent {     public void sayHello() {         System.out.println("Hello from ZyfComponent!");     } } 为符合其构造,我们在定义一个配置类并在其中启用组件扫描如下:  package org.zyf.javabasic.spring.beandefinition;   import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;   /**  * @program: zyfboot-javabasic  * @description: 定义一个配置类,并在其中启用组件扫描。  * @author: zhangyanfeng  * @create: 2024-05-02 11:08  **/ @Configuration @ComponentScan("org.zyf.javabasic.spring.beandefinition") public class ZyfAppConfig {     // 配置类的其他内容 } 直接验证如下:Spring 容器在启动时扫描指定包路径下的组件类,并将标记了 @Component 注解的类注册为 BeanDefinition,这样就可以方便地在应用程序中使用这些 Bean。  package org.zyf.javabasic.spring.beandefinition;   import org.springframework.context.annotation.AnnotationConfigApplicationContext;   /**  * @program: zyfboot-javabasic  * @description: ceshi  * @author: zhangyanfeng  * @create: 2024-05-02 11:09  **/ public class ZyfApplication {     public static void main(String[] args) {         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ZyfAppConfig.class);         ZyfComponent myComponent = context.getBean(ZyfComponent.class);         myComponent.sayHello();         context.close();     } }  四、构造 BeanDefinition:配置类 + @Bean 注解方式 显式配置每个 Bean 的创建过程  创建一个配置类,通常使用 @Configuration 注解标记,在这个类中,使用 @Bean 注解标记方法,方法返回的对象就是一个 Bean。  简单来说,可以先创建一个普通的 Java 类作为需要被 Spring 管理的 Bean:  package org.zyf.javabasic.spring.beandefinition;   /**  * @program: zyfboot-javabasic  * @description: 创建一个普通的 Java 类,作为需要被 Spring 管理的 Bean。  * @author: zhangyanfeng  * @create: 2024-05-02 11:18  **/ public class ZyfService {     public void performAction() {         System.out.println("Performing action in MyService!");     } } 在刚刚创建的配置类ZyfAppConfig中使用 @Bean 注解标记方法增加即可:  package org.zyf.javabasic.spring.beandefinition;   import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration;   /**  * @program: zyfboot-javabasic  * @description: 定义一个配置类,并在其中启用组件扫描。  * @author: zhangyanfeng  * @create: 2024-05-02 11:08  **/ @Configuration @ComponentScan("org.zyf.javabasic.spring.beandefinition") public class ZyfAppConfig {     // 配置类的其他内容     @Bean     public ZyfService zyfService() {         return new ZyfService();     } } 直接验证如下:  package org.zyf.javabasic.spring.beandefinition;   import org.springframework.context.annotation.AnnotationConfigApplicationContext;   /**  * @program: zyfboot-javabasic  * @description: ceshi  * @author: zhangyanfeng  * @create: 2024-05-02 11:09  **/ public class ZyfApplication {     public static void main(String[] args) {         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ZyfAppConfig.class);         ZyfComponent myComponent = context.getBean(ZyfComponent.class);         myComponent.sayHello();           ZyfService zyfService = context.getBean(ZyfService.class);         zyfService.performAction();         context.close();     } } 返回结果符合预期。   五、构造 BeanDefinition:通过XML配置文件 通过 XML 配置文件构造 BeanDefinition 是 Spring 框架最传统的方式之一。  传统的方式是通过 XML 配置文件来定义 Bean,XML 配置文件中的 <bean> 元素就是描述 BeanDefinition 的方式之一。  现在,我们将之前的ZyfService配置到XML 配置文件中如下:  <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">   <!--    <bean id="myTestMsgBean" class="org.zyf.javabasic.springextend.bfppext.MyTestMsgBean">--> <!--        <property name="message" value="Original Message"/>--> <!--    </bean>-->   <!--    <bean class="org.zyf.javabasic.springextend.bfppext.MyBeanFactoryPostProcessorForUpdateBean"/>--> <!--    <bean class="org.zyf.javabasic.springextend.bfppext.MyBeanFactoryPostProcessorForNewDefinRegi"/>--> <!--    <bean class="org.zyf.javabasic.springextend.bfppext.MyBeanFactoryPostProcessorForDefineMata"/>-->       <bean id="zyfService" class="org.zyf.javabasic.spring.beandefinition.ZyfService"/>   </beans> 使用 ClassPathXmlApplicationContext 类来加载配置文件,从而启动 Spring 容器如下:  package org.zyf.javabasic.spring.beandefinition;   import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;   /**  * @program: zyfboot-javabasic  * @description: ceshi  * @author: zhangyanfeng  * @create: 2024-05-02 11:09  **/ public class ZyfApplication {     public static void main(String[] args) {         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ZyfAppConfig.class);         ZyfComponent myComponent = context.getBean(ZyfComponent.class);         myComponent.sayHello();           ZyfService zyfService = context.getBean(ZyfService.class);         zyfService.performAction();           ClassPathXmlApplicationContext contextXml = new ClassPathXmlApplicationContext("zyf_application_context.xml");         ZyfService myServiceXml = context.getBean("zyfService", ZyfService.class);         myServiceXml.performAction();           context.close();     } }  六、构造 BeanDefinition:通过编程方式 通过编程方式构造 BeanDefinition允许开发人员完全控制 BeanDefinition 的创建过程。  我们可以使用 Spring 提供的类(如 GenericBeanDefinition、RootBeanDefinition 等)来创建 BeanDefinition 对象,并指定 Bean 的各种属性和配置信息。  也就是可以直接操作代码即可,在原始代码上直接修改如下:  package org.zyf.javabasic.spring.beandefinition;   import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.beans.factory.support.GenericBeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;   /**  * @program: zyfboot-javabasic  * @description: ceshi  * @author: zhangyanfeng  * @create: 2024-05-02 11:09  **/ public class ZyfApplication {     public static void main(String[] args) {         System.out.println("===================通过模式注解 + 组件扫描方式===================");         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ZyfAppConfig.class);         ZyfComponent myComponent = context.getBean(ZyfComponent.class);         myComponent.sayHello();           System.out.println("===================通过配置类 + @Bean 注解方式===================");         ZyfService zyfService = context.getBean(ZyfService.class);         zyfService.performAction();           System.out.println("===================通过XML配置文件方式===================");         ClassPathXmlApplicationContext contextXml = new ClassPathXmlApplicationContext("zyf_application_context.xml");         ZyfService myServiceXml = context.getBean("zyfService", ZyfService.class);         myServiceXml.performAction();           System.out.println("===================通过编程方式===================");         // 创建一个 BeanDefinition,并指定类名         GenericBeanDefinition beanDefinition = new GenericBeanDefinition();         beanDefinition.setBeanClass(ZyfService.class);           // 将 BeanDefinition 注册到 Spring 容器中         DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();         beanFactory.registerBeanDefinition("zyfService", beanDefinition);           // 获取 Bean,并调用方法         ZyfService myService = context.getBean("zyfService", ZyfService.class);         myService.performAction();           context.close();     } } 验证打印如下,符合预期。   七、对构造分析对比 方式    配置灵活性    可读性和维护性    适用场景 模式注解 + 组件扫描方式     配置简单,基于约定优于配置的原则  适用于大部分情况  配置简单,但可能导致扫描过多的类,降低可读性     简单的项目或小规模团队  快速开发原型或中小型项目  配置类 + @Bean 注解方式    灵活性更高,可以通过代码进行复杂的配置和逻辑处理    相对易读,也更易于维护,因为 Bean 的创建过程明确可见     需要更灵活配置的项目  对可维护性要求较高的大型项目  通过 XML 配置文件    传统方式,配置直观,但可读性较差    相对直观,但随项目规模增大,配置文件可能变得臃肿     传统项目  需要与其他框架整合的场景  通过编程方式    灵活性最高,可以完全控制 BeanDefinition 的创建过程    -代码量较多,可读性较差,维护成本相对较高     需要动态配置 BeanDefinition 的场景  需要在运行时动态注册 Bean 的场景 ————————————————                              版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                          原文链接:https://blog.csdn.net/xiaofeng10330111/article/details/138388372 
  • [技术干货] 【Spring篇】Spring中的Bean管理-转载
     Spring IOC容器 Spring框架的主要功能是通过Spring容器实现的,Spring容器可以管理人们开发的各种Bean。Spring提供了相应API来管理Bean,在Spring容器的API里,最常用的是BeanFactory和ApplicationContext这两个接口。  🚦BeanFactory接口 BeanFactory 是 Spring 框架中的一个核心接口,它定义了 Spring IoC 容器的基本功能。BeanFactory 提供了配置应用程序组件的方式,并且负责这些组件的生命周期和依赖关系的管理。它是 Spring 框架中最原始的 IoC 容器的表现形式。BeanFactory 通常由 ApplicationContext 接口实现。  BeanFactory接口的一些关键方法示例:  Object getBean(String name):根据给定的 Bean 名称获取一个 Bean 实例。  <T> T getBean(String name, Class<T> requiredType):根据给定的 Bean 名称和期望的类型获取一个 Bean 实例。  Object getBean(String name, Object... args):根据给定的 Bean 名称和构造函数参数获取一个 Bean 实例。  <T> T getBean(Class<T> requiredType):根据给定的类型获取一个 Bean 实例。  <T> T getBean(Class<T> requiredType, Object... args):根据给定的类型和构造函数参数获取一个 Bean 实例。  boolean containsBean(String name):检查是否包含一个具有给定名称的 Bean。  boolean isSingleton(String name):检查一个具有给定名称的 Bean 是否是单例作用域。  boolean isPrototype(String name):检查一个具有给定名称的 Bean 是否是原型作用域。  boolean isTypeMatch(String name, Class<?> targetType):检查一个具有给定名称的 Bean 是否是指定类型的一个匹配。  Class<?> getType(String name):获取一个具有给定名称的 Bean 的类型。  String[] getAliases(String name):获取一个具有给定名称的 Bean 的所有别名。  🚦ApplicationContext接口 ApplicationContext 接口是 Spring 框架中 BeanFactory 的一个扩展,它提供了更多的高级功能和特性,以支持企业级应用开发。ApplicationContext 包含了 BeanFactory 的所有功能。  ApplicationContext 接口的一些关键实现包括:  ClassPathXmlApplicationContext:从类路径下的 XML 配置文件中加载上下文定义。 FileSystemXmlApplicationContext:从文件系统下的 XML 配置文件中加载上下文定义。 AnnotationConfigApplicationContext:从注解配置类中加载上下文定义。 WebApplicationContext:用于 Web 应用程序,如 ServletContext 或 PortletContext。 🎯Bean的配置 在Spring框架中,Bean的配置是将类定义为Spring容器管理的对象的过程。Spring支持多种方式来配置Bean,包括XML配置、注解和Java配置类。  🚦Bean元素的多个属性 在Spring的XML配置中,<bean>元素具有多个属性,用于定义和管理Bean的创建和行为。以下是一些常用的<bean>元素属性:  id:Bean的唯一标识符。通常用于通过getBean方法按名称检索Bean。  class:Bean的全限定类名。Spring将使用这个类名来实例化Bean。  name:为Bean提供额外的名称。可以有多个名称,它们之间用逗号、空格或分号分隔。  scope:定义Bean的作用域。常见的作用域包括singleton(单例,默认值)、prototype(原型)、request(Web应用中的请求)、session(Web应用中的会话)等。  lazy-init:指定Bean是否应该延迟初始化,直到它被首次请求时才创建。  🚦Bean元素的多个子元素 在Spring的XML配置中,<bean>元素可以包含多个子元素,这些子元素用于定义Bean的属性、构造函数参数、元数据以及其他配置。以下是一些常用的<bean>子元素:  <property>:用于设置Bean的属性。它包含一个或多个<value>、<ref>或<bean>子元素,用于指定属性的值。  <constructor-arg>:用于提供构造函数参数。可以包含<value>、<ref>或<bean>子元素,或者通过index或type属性指定参数的位置或类型。  <property>的集合:可以定义多个<property>子元素来设置Bean的多个属性。  🎯Bean的实例化 在Spring框架中,Bean的实例化是指创建Bean实例的过程。Spring提供了多种方式来实例化Bean,这些方式可以通过配置来指定。以下是Spring中常见的Bean实例化方式:  🚦构造方法实例 在Spring中,构造方法实例化是通过调用类的构造方法来创建Bean实例的一种方式。这种方式适用于需要通过构造参数来初始化Bean的情况。以下是如何在Spring中使用构造方法实例化Bean的步骤:  ✨pom.xml文件  <dependencies>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-context</artifactId>             <version>5.2.8.RELEASE</version>         </dependency>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-core</artifactId>             <version>5.2.8.RELEASE</version>         </dependency>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-beans</artifactId>             <version>5.2.8.RELEASE</version>         </dependency>         <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-expression</artifactId>             <version>5.2.8.RELEASE</version>         </dependency>         <dependency>             <groupId>commons-logging</groupId>             <artifactId>commons-logging</artifactId>             <version>1.2</version>         </dependency>     </dependencies>  ✨创建Bean1类 public class Bean1 {     public Bean1(){         System.out.println("Bean1");     } } ✨编写applicationContext.xml文件  <bean id="bean1" class="com.han.Bean1"></bean> ✨编写测试类 public class Bean1Test {     public static void main(String[]args){         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");         Bean1 bean= (Bean1) applicationContext.getBean("bean1");         System.out.println(bean);     } } 🚦静态工厂实例化 静态工厂实例化是指使用类的静态方法来创建Bean实例的方式。在Spring中,可以通过配置XML文件来指定使用哪个类的静态方法来创建Bean。这种方式特别适用于那些没有构造函数参数或者需要通过特定工厂方法来创建实例的情况。  ✨创建Bean2类 public class Bean2 {     public Bean2(){         System.out.println("Bean2");     } } ✨创建MyBean2Factory类 public class Bean2Factory {     public static Bean2 createBean(){         return new Bean2();     } } ✨编写applicationContext.xml文件  <bean id="bean2" class="com.han.Bean2Factory" factory-method="createBean"></bean> ✨编写测试类 public class Bean2Test {     public static void main(String[]args){         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");         Bean2 bean2= (Bean2) applicationContext.getBean("bean2");         System.out.println(bean2);     } } 🚦实例工厂实例化 在Spring中,实例工厂实例化是一种创建Bean实例的方法,它允许你通过工厂方法来创建Bean,而不是通过构造函数或静态工厂方法。这种方式提供了更高的灵活性,因为你可以在工厂方法中执行复杂的逻辑来决定哪个Bean的实例应该被创建   ✨创建Bean3类 public class Bean3 {     public Bean3(){         System.out.println("Bean3");     } } ✨创建MyBean3Factory类 public class MyBean3Factory {     public MyBean3Factory(){         System.out.println("bean3工厂实例化中");     }     public Bean3 createBean(){         return new Bean3();     } } ✨编写applicationContext.xml文件     <bean id="mybean3" class="com.han.MyBean3Factory"/>     <bean id="bean3" factory-bean="mybean3" factory-method="createBean"/> ✨编写测试类 public class Bean3Test {     public static void main(String[]args){         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");         Bean3 bean3= (Bean3) applicationContext.getBean("bean3");         System.out.println(bean3);     } } 🎯Bean的作用域 在bean标签中可以通过scope属性指定对象的作用域  scope="singleton"表示当前bean是单例模式(默认饿汉模式,Spring容器初始化阶段就会完成此对象的创建,在bean标签中设置lazy-init="true"时变为懒汉模式)  scope="prototype"表示当前bean为非单例模式,每次通过Spring容器获取此bean的对象时都会创建一个新的对象。  单例  <bean id="book2Spring" class="com.haust.pojo.Book" scope="singleton" lazy-init="true"></bean> 非单例  <bean id="book1Spring" class="com.haust.pojo.Book" scope="prototype"></bean> bean的声明周期方法  在bean标签中通过init-method属性指定当前bean的初始化方法,初始化方法在构造器执行之后执行。  在bean标签中通过destory-method属性指定当前bean的销毁方法,销毁方法在对象销毁之前执行。  🎯Bean的装配方式 🚦基于Xml的装配 基于XML的装配是Spring框架中的一种配置方式,它允许开发者通过XML文件来定义和管理Bean的创建和依赖关系。这种方式在早期的Spring应用中非常常见,尽管现在注解和Java配置逐渐成为主流,但XML配置仍然是一种重要的配置手段,特别是在需要配置大量复杂Bean关系时。  在XML配置中,Bean的装配可以通过以下几种方式实现:  setter注入(Setter Injection):这是最常见的装配方式,通过在XML文件中使用<property>标签来注入依赖。这种方式要求Bean类必须提供一个无参构造方法,并且需要注入的属性必须有对应的setter方法。例如:  <bean id="student1" class="educoder.Student">     <property name="name" value="张三" />     <property name="age" value="25" /> </bean> 构造注入(Constructor Injection):通过构造器注入的方式装配Bean,需要在XML配置文件中使用<constructor-arg>标签来定义构造方法的参数。这种方式适用于需要通过构造器传递依赖的场景。例如:  <bean id="student2" class="educoder.Student">     <constructor-arg index="0" value="李四" />     <constructor-arg index="1" value="24" /> </bean> 🎯基于注解的装配  基于注解的装配是Spring框架中的一种依赖注入方式,它通过在代码中使用特定的注解来实现Bean的自动装配,从而减少了XML配置的复杂性。这种方式使得配置更加简洁,代码与配置的耦合度更低,提高了开发效率。以下是Spring中常用的几种注解装配方式:  @Component、@Service、@Repository、@Controller:这些注解用于声明一个类作为Spring容器管理的Bean。@Component是通用的,而其他注解提供了额外的语义信息。 @Value:用于注入外部配置的值,如properties文件中的值。 @Resource:这是Java标准的一部分,可以通过名称来自动装配Bean,如果Bean的名称与字段名或setter方法名相同,Spring容器会自动装配。 @Autowired:这是最常见的自动装配注解,Spring容器会通过类型来自动装配Bean。如果存在多个相同类型的Bean,可以通过@Qualifier注解来指定具体的Bean。 下面通过一个案例来演示用注解装配Bean,具体步骤及代码如下:  🚦导入依赖 <dependency>             <groupId>org.springframework</groupId>             <artifactId>spring-aop</artifactId>             <version>5.2.8.RELEASE</version>         </dependency> 🚦创建XML配置文件 在appicationContext.xml文件中添加如下代码:  <context:component-scan base-package="com.han"/> 代码中指定要扫描的包为com.han,这个包下的注解就会生效。   🚦定义实体类 实体类User是一个简单的Java类,使用@Component注解标记为Spring管理的Bean,并设置了作用域为单例。类中定义了三个属性:id、username和password,以及它们的getter和setter方法。@Value注解用于注入配置文件中的值。toString方法被覆盖以提供类的字符串表示。  @Component("user") @Scope("singleton") public class User {     @Value("1")     private int id;     @Value("haha")     private String username;     @Value("789")     private String password;       public int getId() {         return id;     }       public void setId(int id) {         this.id = id;     }       public String getUsername() {         return username;     }       public void setUsername(String username) {         this.username = username;     }       public String getPassword() {         return password;     }       public void setPassword(String password) {         this.password = password;     }       @Override     public String toString() {         return "User{" +                 "id=" + id +                 ", username='" + username + '\'' +                 ", password='" + password + '\'' +                 '}';     } } 🚦定义DAO层 DAO层定义了一个接口UserDao,其中包含一个save方法。这个接口代表了与数据库交互的数据访问对象,save方法用于表示保存数据的操作。  public interface UserDao {     public void save(); } 🚦实现DAO层 UserDaoImpl类实现了UserDao接口,并使用@Repository注解标记为Spring的Repository Bean。它的save方法中通过Spring的ApplicationContext获取了User Bean的实例,并打印了用户信息和保存操作的消息。  //使用Repository将UserDaoImpl类标识为Spring中的Bean @Repository("userDao") public class UserDaoImpl implements UserDao{     @Override     public void save() {         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");         User user= (User) applicationContext.getBean("user");         System.out.println(user);         System.out.println("执行UserDaoImpl.save()");     } } 🚦定义Service层 Service层定义了一个接口UserService,其中包含一个save方法。这个接口代表了业务逻辑层,save方法用于表示执行保存操作的业务逻辑。  public interface UserService {     public void save(); } 🚦实现Service层 UserServiceImpl类实现了UserService接口,并使用@Repository注解标记为Spring的Service Bean。它通过@Resource注解注入了UserDao,并在save方法中调用了UserDao的save方法,然后打印了业务逻辑层的保存操作消息。  @Repository("userService") public class UserServiceImpl implements UserService{     //使用Resource注解注入UserDao     @Resource(name="userDao")     private UserDao userDao;     @Override     public void save() {        this.userDao.save();        System.out.println("执行UserServiceImpl.save()");     } } 🚦定义Controller层 Controller层定义了一个UserController类,使用@Controller注解标记为Spring的Controller Bean。它通过@Resource注解注入了UserService,并在save方法中调用了UserService的save方法,然后打印了控制器层的保存操作消息。  //使用Controller注解将UserController类标识为Bean @Controller public class UserController {     @Resource(name="userService")     private UserService userService;     public void save(){         this.userService.save();         System.out.println("执行UserController.save()");     } } 🚦定义测试类 测试类AnnotationTest包含了一个main方法,用于初始化Spring的ApplicationContext并获取UserController的实例。然后调用UserController的save方法来执行保存操作,从而测试整个Spring应用的流程是否正确。  public class AnnotationTest {     public static void main(String[]args){         ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");         UserController userController= (UserController) applicationContext.getBean("userController");         userController.save();     } } 以上就是今天要讲的内容了,主要介绍了Bean的配置,实例化,作用域以及装配方式等相关内容,如果您感兴趣的话,可以订阅我的相关专栏。非常感谢您的阅读,如果这篇文章对您有帮助,那将是我的荣幸。我们下期再见啦🧸! ————————————————                              版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。                          原文链接:https://blog.csdn.net/m0_74202856/article/details/142881403 
  • [技术干货] Hystrix
     使用 Hystrix实现容错 Hystrix 是一个实现了超时机制和断路器模式的工具类库。先来了解什么是Hystrix。  Hystrix简介 Hystrix 是由 Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失败,从而提升系统的可用性与容错性。Hystrix主要通过以下几点实现延迟和容错。 ·包裹请求:使用HystrixCommand (或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用了设计模式中的“命令模式”。 ·跳闸机制:当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务一段时间。 ·资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。·监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时和被拒绝的请求等。 ·回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。  使用Hyur实 ·自我修复:断路器打开一段时间后,会自动进入“半开"状态。断路器打开,关 半开的逻辑转换,前面已经详细探讨过了,本小节不再赘述。 。Hystrix的GitHub: https://github.com/Netflix/Hystrix. ,命令模式:https://en.wikipedia.org/wiki/Command_pattern. 通用方式整合Hystrix 在Spring Cloud中,整合Hystrix非常方便。以项目microservice-consumer-movie-ribbon为例,我们来为它整合Hystrix。 1.复制项目microservice-consumer-movie-ribbon,将ArtifactId修改为microservice-con- sumer-movie-ribbon-hystrix。 2.为项目添加以下依赖。 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency> 3.在启动类上添加注解@EnableCircuitBreaker 或EnableHystrix ,从而为项目启用断路器支持。 4.修改MovieController,让其中的findByld方法具备容错能力。@RestController public class MovieController { private static final Logger LOGGER=LoggerFactory.getLogger(MovieController. class);@Autowired private RestTemplate restTemplate;@Autowired private LoadBalancerClient loadBalancerClient; @HystrixCommand(fallbackMethod =*findByIdFallback*)@GetMapping("/user/{id}") public User findById(@PathVariable Long id){ return this.restTemplate,getForObject("http://microservice-provider-user/" id,User.class);  end    Pgdn     enter ns    del      使用 Hystrix实现容错 } public User findByIdFallback(Long id){ User user = new User(); user.setId(-1L); user.setName("默认用户*); return user;} 由代码可知,为findById方法编写了一个回退方法findByldFallback,该方法与find- Byld 方法具有相同的参数与返回值类型,该方法返回了一个默认的User。 在findById方法上,使用注解@HystrixCommand的fallbackMethod属性,指定回退方法是findByIdFallback。注解@HystrixCommand由名为javanica(https://github.com/Netflix/ Hystrix/tree/master/hystrix-contrib/hystrix-javanica )的Hystrix contrib库提供。javanica是一个Hystrix 的子项目,用于简化Hystrix的使用。Spring Cloud 自动将Spring bean与该注解封装在一个连接到Hystrix断路器的代理中。 @HystrixCommand的配置非常灵活,可使用注解@HystrixProperty的commandProperties属性来配置@HystrixCommand。例如: @HystrixCommand(fallbackMethod ="findByIdFallback",commandProperties={ @HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds", value ="5000"), @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value =' 10000") },threadPoolProperties ={ @HystrixProperty(name = "coreSize", value = "1"),@HystrixProperty(name = "maxQueueSize",value ="10")}) @GetMapping("/user/{id}*) public User findById(@PathVariable Long id){//... 限于篇幅,笔者就不一一讲解Hystrix 的配置属性了。 https://github.com/Netflix/ Hystrix/tree/master/hystrix-contrib/hystrix-javanica#conf- iguration,详细了解注解@HystrixCommand如何使用。 
  • [用户故事] 【分享交流】你们觉得现在后端除了spring boot,其他语言是不是都被淘汰了
    你们觉得现在后端除了spring boot,其他语言是不是都被淘汰了
  • [专题汇总] 快来啊,8月份合集来了。
     大家好8月份给大家带来的主要是SpringWebFlux方面的知识。希望可以帮助大家。  1.SpringWebFlux响应式框架---HandlerMapping https://bbs.huaweicloud.com/forum/thread-02102160107395888002-1-1.html  2.SpringWebFlux响应式框架---HandlerAdapter https://bbs.huaweicloud.com/forum/thread-0205160107492076001-1-1.html  3.SpringWebFlux响应式框架---HandlerResultHandler https://bbs.huaweicloud.com/forum/thread-0205160107548247002-1-1.html  4.SpringWebFlux响应式框架---WebFilter https://bbs.huaweicloud.com/forum/thread-0249160107639633003-1-1.html  5.SpringWebFlux响应式框架---ServerWebExchange https://bbs.huaweicloud.com/forum/thread-0204160107694268002-1-1.html  6.SpringWebFlux响应式框架---ServerHttpRequest和ServerHttpResponse https://bbs.huaweicloud.com/forum/thread-0205160107731252003-1-1.html  7.SpringWebFlux响应式框架---WebSession https://bbs.huaweicloud.com/forum/thread-02108160108766229004-1-1.html  8.SpringWebFlux响应式框架---Reactive Streams https://bbs.huaweicloud.com/forum/thread-0205160108940083004-1-1.html  9.SpringWebFlux响应式框架---Reactor https://bbs.huaweicloud.com/forum/thread-02115160109128396001-1-1.html  10.SpringWebFlux响应式框架---WebClient https://bbs.huaweicloud.com/forum/thread-02102160109167400003-1-1.html  11.SpringWebFlux响应式框架---Spring Data Reactive https://bbs.huaweicloud.com/forum/thread-02115160109216453002-1-1.html  12.SpringWebFlux响应式框架---Spring Security Reactive https://bbs.huaweicloud.com/forum/thread-02115160109258160003-1-1.html  13. SpringWebFlux响应式框架---HttpHandler https://bbs.huaweicloud.com/forum/thread-0249160109341677005-1-1.html  14.SpringWebFlux响应式框架---ContextPathCompositeHandler https://bbs.huaweicloud.com/forum/thread-02108160109459892006-1-1.html  15.SpringWebFlux响应式框架---DispatcherHandler https://bbs.huaweicloud.com/forum/thread-0250160107329479004-1-1.html  16.深度长文解析SpringWebFlux响应式框架15个核心组件源码(一) https://bbs.huaweicloud.com/forum/thread-0250160107200239003-1-1.html 
  • [技术干货] keepalived+Nginx高可用案例
    Keepalived结合Nginx实现高可用性的案例涉及在两台或多台服务器上部署Nginx和Keepalived,以确保当主Nginx服务器出现故障时,备份Nginx服务器能够自动接管服务,从而保证服务的连续性和可用性。以下是一个详细的案例说明:一、方案概述目标:通过Keepalived和Nginx实现Web服务的高可用性。环境:两台服务器,分别配置为Master和Backup,均安装Nginx和Keepalived。二、环境准备安装Nginx:在两台服务器上分别安装Nginx。配置Nginx作为负载均衡器或Web服务器,具体取决于实际需求。安装Keepalived:在两台服务器上分别安装Keepalived。Keepalived的安装方式可以是使用包管理器(如yum、apt)或从源代码编译安装。三、配置Keepalived配置Master节点:编辑/etc/keepalived/keepalived.conf文件,设置状态为MASTER,并配置虚拟IP(VIP)。配置健康检查脚本,用于检查Nginx的状态。如果Nginx停止运行,则尝试重启;如果重启失败,则停止Keepalived服务,将VIP转移到Backup节点。示例配置(Master节点):! Configuration File for keepalived global_defs { router_id LVS_DEVEL_MASTER } vrrp_script chk_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 weight -5 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 101 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.200 } track_script { chk_nginx } }配置Backup节点:编辑/etc/keepalived/keepalived.conf文件,设置状态为BACKUP,并配置与Master节点相同的虚拟IP(VIP)。配置健康检查脚本,与Master节点相同。示例配置(Backup节点):! Configuration File for keepalived global_defs { router_id LVS_DEVEL_BACKUP } vrrp_script chk_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 weight -5 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.1.200 } track_script { chk_nginx } }编写Nginx健康检查脚本(check_nginx.sh):该脚本用于检查Nginx是否正在运行。如果未运行,则尝试启动;如果启动失败,则停止Keepalived服务。示例脚本:#!/bin/bash counter=$(ps -C nginx --no-heading | wc -l) if [ "${counter}" -eq 0 ]; then systemctl start nginx sleep 2 counter=$(ps -C nginx --no-heading | wc -l) if [ "${counter}" -eq 0 ]; then systemctl stop keepalived fi fi四、启动Keepalived服务在两台服务器上分别启动Keepalived服务。使用systemctl start keepalived命令启动服务,并确保服务设置为开机自启。五、测试高可用性通过VIP访问Nginx服务:确保通过VIP(在本例中为192.168.1.200)可以访问Nginx服务。模拟故障转移:停止Master节点的Nginx服务或Keepalived服务。观察VIP是否自动转移到Backup节点。通过VIP访问服务,验证服务是否仍然可用。六、注意事项确保两台服务器的网络互通,且时间同步。监控Keepalived和Nginx的日志文件,以便及时发现和解决问题。定期检查Keepalived和Nginx的配置,确保配置的正确性和安全性。通过以上步骤,你可以实现基于Keepalived和Nginx的高可用性Web服务。这种配置方式可以有效地防止单点故障,提高服务的可靠性和可用性。
  • [技术干货] spring security动态加载用户权限
    在Spring Security中动态加载用户权限通常意味着你需要实现一个用户详情服务(UserDetailsService),这个服务不仅需要根据用户名查找用户信息,还需要能够动态地加载该用户的权限信息。权限信息可能来自数据库、缓存或任何其他动态数据源。以下是一个基本步骤,指导你如何在Spring Security中动态加载用户权限:1. 创建用户实体首先,你需要一个用户实体(例如User),这个实体将包含用户名、密码(通常是加密的)、以及其他任何与权限相关的字段(如角色列表)。@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; @JsonIgnore private String password; @ManyToMany(fetch = FetchType.EAGER) @JoinTable( name = "user_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id") ) private Set<Role> roles = new HashSet<>(); // Getters and Setters }2. 创建角色实体接着,创建一个角色实体(例如Role),它将表示系统中的不同角色,每个角色都可以有零个或多个权限。@Entity public class Role { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // Getters and Setters }3. 实现UserDetailsService现在,你需要实现UserDetailsService接口,该接口定义了loadUserByUsername方法,该方法将根据用户名从数据库中加载用户及其权限。@Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; // 假设你有一个用户仓库 @Override @Transactional public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username)); return User.withUsername(user.getUsername()) .password(user.getPassword()) .roles(user.getRoles().stream() .map(role -> "ROLE_" + role.getName().toUpperCase()) .collect(Collectors.toList())) .build(); } }注意:这里的User.withUsername(...)、.password(...)、.roles(...) 和 .build() 是为了演示而简化的代码,你需要自己实现这些方法或类似功能来创建org.springframework.security.core.userdetails.UserDetails对象。4. 配置Spring Security在Spring Security配置中,你需要配置使用你的CustomUserDetailsService。@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomUserDetailsService customUserDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserDetailsService) .passwordEncoder(new BCryptPasswordEncoder()); } // 其他配置... }5. 处理权限更新由于权限是动态加载的,如果你在运行时更改了用户的权限,Spring Security的SecurityContext不会自动更新。你需要在更改权限后重新认证用户或手动更新SecurityContext。一个常见的做法是在修改用户权限后,重定向用户到登录页面或使用其他机制要求用户重新登录。结论以上就是如何在Spring Security中动态加载用户权限的基本步骤。记得根据你的具体需求调整和优化代码。特别是用户实体的结构、权限的管理和认证机制可能需要根据你的应用场景进行调整。
  • [技术干货] SpringSecurity基于JWT实现无状态认证
    Spring Security 结合 JWT(JSON Web Tokens)实现无状态认证是现代Web应用中的一种常见做法,特别适用于需要RESTful API的微服务架构。JWT提供了一种在客户端和服务器之间安全传输信息的方式,无需在服务器端存储用户的会话信息,从而实现了无状态认证。1. 理解JWTJWT是一种用于双方之间安全传输信息的简洁的、URL安全的令牌标准。一个JWT实际上是一个紧凑的、URL安全的JSON对象,它传递了信息的一种方式。JWT由三部分组成,它们通过点(.)分隔,分别是:Header(头部):声明了令牌的类型(通常是JWT)以及所使用的签名算法(如HMAC SHA256或RSA)。Payload(负载):包含了声明(claims)。声明是关于实体(通常是用户)和其他数据的声明。声明有三种类型:注册声明、公共声明和私有声明。Signature(签名):是对前两部分的签名,以防止数据被篡改。2. 引入依赖首先,在你的Spring Boot项目中引入Spring Security和JWT相关的依赖。如果你使用Maven,可以添加如下依赖:<!-- Spring Boot Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- JWT --> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency>3. 配置JWT过滤器你需要创建一个JWT过滤器,用于解析JWT,并基于JWT中的信息设置Spring Security的SecurityContext。@Component public class JwtRequestFilter extends OncePerRequestFilter { @Autowired private JwtUtil jwtUtil; @Autowired private UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String authorizationHeader = request.getHeader("Authorization"); String username = null; String jwt = null; if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { jwt = authorizationHeader.substring(7); username = jwtUtil.extractUsername(jwt); } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if (jwtUtil.validateToken(jwt, userDetails)) { UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); } } chain.doFilter(request, response); } }4. 配置Spring Security在你的Spring Security配置中,你需要配置HTTP安全,添加JWT过滤器,并配置无状态会话。@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private JwtRequestFilter jwtRequestFilter; @Override protected void configure(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/api/public/**").permitAll() .anyRequest().authenticated() .and() .exceptionHandling().and().sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); } // 其他配置... }5. 创建JWT工具类你需要一个JWT工具类来生成和验证JWT。@Component public class JwtUtil { // JWT密钥 private String secret = "your_secret_key"; // 生成JWT public String generateToken(String username) { // 逻辑... } // 验证JWT public boolean validateToken(String token, UserDetails userDetails) { // 逻辑... } // 提取JWT中的用户名 public String extractUsername(String token) { // 逻辑... } }6. 认证和授权在你的登录接口中,当用户成功认证后,生成一个JWT并返回给客户端。客户端在后续的请求中携带这个JWT,Spring Security通过JWT过滤器解析JWT,并进行相应的授权检查。以上是使用Spring Security和JWT实现无状态认证的基本步骤。根据你的具体需求,可能还需要进行一些调整和扩展。
  • [技术干货] 使用Nacos搭建配置中心
    使用Nacos搭建配置中心是一个涉及多个步骤的过程,主要适用于微服务架构中,以实现配置信息的集中管理和动态更新。以下是详细的步骤说明:一、Nacos安装与启动下载Nacos安装包从Nacos的GitHub或官方网站下载最新版本的Nacos安装包。解压并配置解压下载的安装包到指定目录。如果需要使用外部数据库(如MySQL)来存储配置信息,需要修改Nacos的配置文件(如application.properties),配置数据库连接信息。启动Nacos服务进入Nacos的bin目录,执行启动命令(如startup.cmd -m standalone在Windows上,或在Linux/Mac上使用sh startup.sh -m standalone)。启动后,可以通过浏览器访问Nacos的管理界面(默认地址为http://localhost:8848/nacos),进行进一步配置和管理。二、在Spring Cloud项目中集成Nacos配置中心引入依赖在项目的pom.xml文件中引入Nacos配置中心的依赖。例如,对于Spring Boot 2.x版本,可以添加如下依赖:<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>对应的版本号,如2.x.x.RELEASE</version> </dependency>注意版本号要与Spring Boot的版本相匹配。配置bootstrap.yml在src/main/resources目录下创建或修改bootstrap.yml文件,配置Nacos服务器的地址、应用的名称、配置文件的Data ID、Group等信息。例如:spring: application: name: your-application-name cloud: nacos: config: server-addr: localhost:8848 group: DEFAULT_GROUP file-extension: yaml prefix: your-prefix refresh-enabled: truebootstrap.yml文件用于加载外部配置中心的配置,它比application.yml更早加载,确保Nacos中的配置能够覆盖本地配置。在Nacos中添加配置登录Nacos管理界面,进入配置管理页面。点击“+”号新增配置,填写Data ID、Group、配置格式(YAML或Properties)等信息,并在配置内容区域填写具体的配置信息。Data ID的命名规则通常为${prefix}-${spring.profiles.active}.${file-extension},其中prefix默认为spring.application.name的值,spring.profiles.active为当前环境对应的profile(如dev、test、prod),file-extension为配置文件的格式(如yaml)。使用配置在Spring Boot应用中,通过@Value或@ConfigurationProperties注解来注入Nacos中的配置。如果需要实现配置的自动刷新,可以在配置类上添加@RefreshScope注解。三、测试与验证启动Spring Boot应用,检查应用是否能够正确加载Nacos中的配置。修改Nacos中的配置信息,并观察应用是否能够实时更新配置(如果使用了@RefreshScope注解)。通过以上步骤,你可以成功使用Nacos搭建配置中心,并在Spring Cloud项目中集成使用。Nacos配置中心提供了配置管理的集中化、动态化、版本化等功能,有助于提升微服务架构下应用的可维护性和可扩展性。