精华内容
下载资源
问答
  • 这篇文章主要是告诉我们怎么创建自己的SpringBoot autoconfiguration Auto-configuration classes能被绑定一个外部jar包并且能被Spring Boot加载。每一个Auto-configuration能够被关联到一个starter,创建步骤(1...

    以前对于SpringBoot的starter机制一直很好奇,为什么我们引入一个开源框架的starter,就可以直接使用了,如何做到的。于是就看了几个starter的源码,探究一下。

    (1)其实对于每个starter里面并没有源码,只是依赖了一个对应的autoconfiguration,这个autoconfiguration的jar包下有一个XxxxxxAutoConfiguration.class,里面配置了框架启动需要自动注入的一些bean(默认优于配置)。所以会自动启动这个XxxxxxAutoConfiguration.class

    (2)在META-INF/spring.factories加上自动装配配置;META-INF/spring-configuration-metadata.json下配置application.properties的key-value的提示项。

    创建步骤

    (1)实现XxxxxxAutoConfiguration.class类,并加上@Conditional限制条件

    这需要实现需要自动装载的bean

    (2)在META-INF/spring.factories里面加上如下:

    # 如果有多个XxxxxAutoConfiguration,用逗号分隔
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxx.xxx.xxx.xxx.XxxxxAutoConfiguration

    (3)限制Auto-Configuration的顺序

    使用 @AutoConfigureAfter or @AutoConfigureBefore可以限制XxxxxxAutoConfiguration.class的加载顺序

    (4)创建metadata

    (META-INF/spring-configuration-metadata.json) to make sure your keys are properly documented.
    这里的配置是作用XxxxxxAutoConfiguration需要用到的一些properties的,这些properties我们可以写在application.properties里面,然后通过这个文件的规约给出提示。

    此外我们可以写一个XxxxProperties.java, 然后通过 @ConfigurationProperties 注解,自动装载application.properties的值到XxxxProperties.java中。

    (5)编写startermodule,引入Auto-Configuration这个module

    展开全文
  • 前几天我们学会了如何创建springboot项目今天我们说一下他是怎么运行的为什么不需要我们再去编写繁重的配置文件的 @SpringBootApplication 首先我们看一下这个注解,他是用来标注主程序的,表明他是一个...

    前几天我们学会了如何创建springboot项目今天我们说一下他是怎么运行的为什么不需要我们再去编写繁重的配置文件的

    @SpringBootApplication

    首先我们看一下这个注解,他是用来标注在主程序的,表明他是一个springboot项目

    @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @SpringBootConfiguration
      @EnableAutoConfiguration
      @ComponentScan(
          excludeFilters = {
            @Filter(type = FilterType.CUSTOM,classes = {TypeExcludeFilter.class}),    
            @Filter( type = FilterType.CUSTOM,classes = {AutoConfigurationExcludeFilter.class})
          }
      )
      public @interface SpringBootApplication {
    }

     

    点进@SpringBootApplication注解后我们重点关注最后三个注解

    @ComponentScan(包扫描)
    • component是组件,scan是扫描,所以这个注解的含义就是用来扫描组件的,

    • componentScan就是扫描所标注的类所在包下的所有需要注入的组件,将其注入,这里他是在@SpringBootApplication 中体现的,所以这个注解会自动注入所有在主程序所在包下的组件

    • 以前在ssm项目中我们需要去配置我们的包扫描

      
    <context:component-scan base-package="com.xxx"></context:component-scan>

     

    @EnableAutoConfiguration(开启自动装配)
    @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @AutoConfigurationPackage
      @Import({AutoConfigurationImportSelector.class})
      public @interface EnableAutoConfiguration {
          String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
      ​
          Class<?>[] exclude() default {};
      ​
          String[] excludeName() default {};
      }

    这里我们关注两个注解

    一、@AutoConfigurationPackage

      
     @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Inherited
      @Import({Registrar.class})
      public @interface AutoConfigurationPackage {
      }

     

    在这个注解中,主要是获取我们注解所在包下的组件去进行注册

      
     static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
              Registrar() {
              }
      ​
        //metadata是我们注解所在的元信息
              public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
                //看这里 将我们注解所在包下所有的组件去进行注册
                  AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
              }
      ​
              public Set<Object> determineImports(AnnotationMetadata metadata) {
                  return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
              }
          }

     

    register方法:通过AutoConfigurationPackages去对包下的组件进行注册

      
     private static final String BEAN = AutoConfigurationPackages.class.getName();
      ​
      public static void register(BeanDefinitionRegistry registry, String... packageNames) {
         //先判断整个BEAN有没有被注册
              if (registry.containsBeanDefinition(BEAN)) {
                //获取bean的定义
                  BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
                //通过bean获取构造函数的参数值
                  ConstructorArgumentValues constructorArguments = beanDefinition.getConstructorArgumentValues();
                //添加参数值,
                  constructorArguments.addIndexedArgumentValue(0, addBasePackages(constructorArguments, packageNames));
              } else {
                //创建一个新的bean的定义
                  GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
                //设置bean的类型为AutoConfigurationPackages类型
                  beanDefinition.setBeanClass(AutoConfigurationPackages.BasePackages.class);
                  beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, packageNames);
                  beanDefinition.setRole(2);
                //进行bean的注册
                  registry.registerBeanDefinition(BEAN, beanDefinition);
              }
          }

     

    二、@Import({AutoConfigurationImportSelector.class})

    装配我们的 自动配置导入选择器

    我们点进去这个类,下面有一个方法getAutoConfigurationEntry 获取自动装配的入口、

      
    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
              if (!this.isEnabled(annotationMetadata)) {
                  return EMPTY_ENTRY;
              } else {
                  AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                  List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                  configurations = this.removeDuplicates(configurations);
                  Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                  this.checkExcludedClasses(configurations, exclusions);
                  configurations.removeAll(exclusions);
                  configurations = this.filter(configurations, autoConfigurationMetadata);
                  this.fireAutoConfigurationImportEvents(configurations, exclusions);
                  return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
              }
          }

     

    这个方法他主要是获取了configurations的一个集合在这我们点进去getCandidateConfigurations方法

      
    protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
              List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
              Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
              return configurations;
          }

     

    我们首先看他这个红色报错信息:在META-INF/spring.factories中没有找到自动配置类。根据他的错误信息我们可以得出他是从META-INF/spring.factories获取我们的自动配置信息的

    我们也可以在点进这个loadFactoryNames这个方法

       public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
              String factoryClassName = factoryClass.getName();
         //调用了下面的方法loadSpringFactories
              return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
          }
      ​
          private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
              MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
              if (result != null) {
                  return result;
              } else {
                  try {
                    //根据类加载器去获取配置文件里的信息
                      Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                      LinkedMultiValueMap result = new LinkedMultiValueMap();
      ​
                      while(urls.hasMoreElements()) {
                          URL url = (URL)urls.nextElement();
                          UrlResource resource = new UrlResource(url);
                        //配置信息经过多次转换最终成为properties形式
                          Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                          Iterator var6 = properties.entrySet().iterator();
                      //循环获取所有的配置信息
                          while(var6.hasNext()) {
                              Entry<?, ?> entry = (Entry)var6.next();
                              String factoryClassName = ((String)entry.getKey()).trim();
                              String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
                              int var10 = var9.length;
      ​
                              for(int var11 = 0; var11 < var10; ++var11) {
                                  String factoryName = var9[var11];
                                  result.add(factoryClassName, factoryName.trim());
                              }
                          }
                      }
      ​
                      cache.put(classLoader, result);
                      return result;
                  } catch (IOException var13) {
                      throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
                  }
              }
          }

     

    而这个配置文件在哪里呢

    在我们项目的External Libraries中找到我们的spring-boot-autoconfigure中

    这样就完成我们默认的一些自动装配了

    @SpringBootConfiguration

    这个方法就比较简单了,表明了这是一个配置类

      @Target({ElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      @Documented
      @Configuration
      public @interface SpringBootConfiguration {
      }
     
    到这我们三个注解就讲完了,有什么问题请大佬们指明谢谢。

    有过挣扎,有过失败,但仍然会爬起来继续战斗

     

    转载于:https://www.cnblogs.com/guomie/p/11241306.html

    展开全文
  • 平常的开发中经常要同时执行一些业务,比如发送邮件,处理数据等。为了不阻塞线程,就能采用多线程的方式进行处理。 同步情况下首先新建一个Service: ...为了不等待,直接响应请求该怎么做呢? Ser...

    在平常的开发中经常要同时执行一些业务,比如发送邮件,处理数据等。为了不阻塞线程,就能采用多线程的方式进行处理。

    同步情况下首先新建一个Service类:

    之后新建一个Controller类来调用此方法:

    之后启动服务, 

    由于service会等待三秒,所以调用hello方法时会等待三秒才能返回success.

    重点来了:

    为了不等待,直接响应请求该怎么做呢?

    在Service里面的hello方法上加上 @Async 注解告诉Spring这是一个异步任务。spring就会自己创建一个线程池来调用这个方法。

     有了@Async注解还不够,想要它生效还要在启动类上加上@EnableAsync 启动异步注解功能

     之后再次启动启动类,访问hello方法,不用等待就能直接访问。

     处理数据也会被调用。

    展开全文
  • 使用过springboot的都知道,我们创建一个主启动,然后创建一个main函数,然后SpringApplication.run(Application.class); 我们的程序就启动起来了,至于怎么启动起来的,当前是什么样的环境,我们的tomcat容器...

    源码地址:springboot2.x源码解读仓库,源码中包含有注释

    使用过springboot的都知道,我们创建一个主启动类,然后创建一个main函数,然后SpringApplication.run(Application.class); 我们的程序就启动起来了,至于怎么启动起来的,当前是什么样的环境,我们的tomcat容器在哪里启动的等,对于使用者,无需关心。但是对于好奇心比较人来说(比如我),就像一探究竟,他是通过什么样的方式来判断我们的应用程序是什么环境的,他又是如何加载我们的bean的,tomcat容器,他又是怎么嵌入进去的。

    话不多说:先看如下代码:

    package com.osy;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class);
        }
    }
    

    这段代码,简单粗暴,run完我们的程序就启动完成了。
    那么我们就看看他是怎么走的吧。
    1、调用静态方法run函数

    // 调用静态方法run函数
    public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    	// 调用另一个重载run方法,
    	return run(new Class<?>[] { primarySource }, args);
    }
    

    2、调用另一个重载run方法

    	/**
    	 * 静态方法启动类入口
    	 * @param primarySources 要加载的主要源,传入主程序的Class对象
    	 * @param args 应用程序参数(通常从java main方法传递)一般是一些jvm调优的参数设置
    	 * @return the running {@link ApplicationContext}
    	 */
    	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    		// 首先构造一个SpringApplication实例,然后再调用run方法。看看构造实例的时候他做了什么?
    		return new SpringApplication(primarySources).run(args);
    	}
    

    1和2的这两个run方法重载,参数一个是直接传入一个Class对象,一个数传入Class对象数组,
    从这里就可以看出,springboot最终需要的是一个数组,但是考虑到我们使用者,所以他写了一个重载方法,传入我们的主启动类,然后对其进行封装一遍成为数组,而且从调用来看,它的第一个run方法是专门的为我们使用者准备的,由此可以看出,spring在用户体验方面,是其他框架无法比拟的。
    3、创建SpringApplication实例

    	public SpringApplication(Class<?>... primarySources) {
    		// 调用另一个构造函数
    		this(null, primarySources);
    	}
    

    构造函数重载,真正做事的是他。

    	/**
    	 * 创建一个SpringApplication实例,应用程序将会通过基本的资源(主函数下面的所有包下面进行扫描)加载bean,
    	 * 在调用run方法之前,我们可以定制实例,比如添加初始化器,比如添加监听器等...
    	 */
    	@SuppressWarnings({ "unchecked", "rawtypes" })
    	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    		// 这里的resourceLoader在这里是为null的
    		this.resourceLoader = resourceLoader;
    		// 断言,判断传入的主程序入口程序的Class是否为null,如果为null,则抛出异常,校验参数是否合法
    		Assert.notNull(primarySources, "PrimarySources must not be null");
    		// 这里将初级的资源赋值,并且将主程序的Class存入。primarySources的值,就是我们的主启动类的Class对象
    		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    		// 赋值web应用类型,根据classLoader去加载对应的全限定类名来进行判断当前是什么环境
    		this.webApplicationType = WebApplicationType.deduceFromClasspath();
    		// 通过SpringFactories去加载配置的spring.factories设置初始化器
    		// 原理:通过类加载器去加载属于ApplicationContextInitializer类型的类,然后放入initializers中,
    		// 也就是我们在项目中的classpath下面创建META-INF/spring.factories,指定我们实现了ApplicationContextInitializer的类,
    		// springboot就会加载到,当然,如果需要了解细节,我有文章写到添加初始化器。关注我,不迷路
    		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    		// 设置监听器,其中的原理和加载初始化器是一样的,方法调用的都是同一个,
    		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    		// 推断主应用程序类
    		// 通过调用栈获取所有的方法,然后找到有main函数的那个类,那么springboot就认为他就是主启动类
    		this.mainApplicationClass = deduceMainApplicationClass();
    	}
    

    从这个构造方法来看,构造SpringApplication实例的时候,他做了这些初始化工作。
    根据上面的注释看下来,这里想说明两点:

    1. 在调用run方法之前,我们可以定制实例
    2. 通过调用栈推断主入口函数

    SpringApplication实例如何定制?
    SpringApplication的构造函数做的事无非就是:设置基础资源、推断应用程序的环境、通过SpringFactories加载我们自定义的初始化器和监听器、推断主入口类。然后调用run方法。

    然后我们就可以对他创建实例这里进行定制:
    以下是伪代码,只谈思路,不谈具体实现:

    @SpringBootApplication
    public class Application {
        public static void main(String[] args) {
            SpringApplication springApplication = new SpringApplication(Application.class);
            // 硬编码添加初始化器
            springApplication.addInitializers(new ZyInitializers());
            // 硬编码添加监听器
            springApplication.addListeners(new ZyListeners());
            // 从新设置应用环境
            springApplication.setWebApplicationType(WebApplicationType.SERVLET);
            // 设置是否延迟加载bean
            springApplication.setLazyInitialization(true);
            ...
            // 开始启动
            springApplication.run();
            
        }
    }
    

    当然了,大部分情况下使用他默认的即可。如无特殊情况,建议不用定制化。

    他是如何推断我们的主入口程序的,我们传入的Application.class的作用又是什么?

    private Class<?> deduceMainApplicationClass() {
    		try {
    			// 通过RuntimeException实例能够获取到运行到这里的调用栈,
    			StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
    			// 循环调用栈,获取方法名进行对比,如果有调用了main函数的,那么就把他当做主入口程序
    			for (StackTraceElement stackTraceElement : stackTrace) {
    				if ("main".equals(stackTraceElement.getMethodName())) {
    					// 通过反射获取主入口函数的Class对象
    					return Class.forName(stackTraceElement.getClassName());
    				}
    			}
    		}
    		catch (ClassNotFoundException ex) {
    			// Swallow and continue
    		}
    		// 如果没有调用main函数,那么就返回null
    		return null;
    	}
    

    从上面的注释中可以看出,他是通过RuntimeException的实例获取调用栈,然后判断方法名为main的类为主入口函数,那么我们传入的Application.class他放入了Set集合primarySources中,而他是要加载的主要源,也就是他会扫描他下面所以的包下面的所有的bean,然后加入spring容器中。

    一个相信努力就会有结果的程序员,以兴趣驱动技术!         ------ CoderOu

    展开全文
  • 1.SpringBoot加载顺序怎么能知道? Bean的默认构造函数里面使用System.out.println就能知道创建顺序。 2.一个问题:SpringBoot的main函数中能够使用IOC容器中的Bean吗? 可以,但是是run程序之后,通过...
  • 当项目中引入了web依赖后,会在META-INF目录的spring.factories文件中保存DispatcherServletAutoConfiguration的全限定名,在SpringBoot启动时自动加载该文件,初始化文件中的 查看...
  • 当自己写的Controller所在的包和启动同一个包下时,需要怎么做呢, 启动上加上一个注解,@ComponentScan(basePackages = {“包名”}), 没加的话,可能会出现如下问题 IDEA中启动成功,但是访问自己写的...
  • 根据实体自动创建数据库表格 配置文件中添加这个 启动项目创建完之后你会发现数据库字段和实体不一样 是乱序的 是因为hibernate源码中用的是TreeMap存储实体字段属性是无序的 后来我就把本中所有的...
  • 作为java程序开发,离不开spring,那么spring中怎么创建多线程并将注册到spring的类在多线程中使用呢?我自己总结了一下,可以有两种方式,使用线程池和spring自带多线程注解使用。 使用线程池 我一般使用固定...
  • SpringBoot中Spring如何自动创建Bean对象

    千次阅读 2019-12-28 19:45:11
    Bean对象:Spring中交给Spring自动创建,不需要我们手动去new,所创建的对象,都叫Bean对象。 Spring怎么知道什么对象应该交给他创建呢?的字节码对象上有注解注释时,他所需要创建的对象,都交给spring创建。 ...
  • 你可能已经知道怎么为你的应用的一个写单元测试了,所以,该篇博客会专注于使用spring的测试和springboot的功能来测试你的代码和spring之间的关系,你会应用上下文加载成功后开启测试,并继续使用MockMvc来测试web层...
  • springboot开发时,由controller、service接口、service实现组成,一个service接口有多种实现,需要实现根据不同的请求,例如不同地区的请求,调用不同的实现,这种实现和地区的对应有一个配置,我们计划...
  • 那我我们先来看下是怎么创建 SpringApplication对象的吧。 刚才这个静态方法下面又封装了一层,传入了一个null的resourceLoader,这个参数一定程度上可以理解为加载器,传入为null时实际上最后用到加载器的是...
  • 情况描述:当application启动直接创建在资源根目录(即标记为source root的文件夹)下是会报出启动类在默认包的错误。遂自作聪明给建了一个application的包装着启动。结果代码写好了,怎么调试也是404。 解决...
  • springboot全局异常处理

    2019-11-14 10:35:57
    springboot项目怎么搭建 这里就忽略了,既然你都怎么处理springboot项目的全局异常,那说明你肯定有一个springboot项目 首先亮一下我的springboot项目结构, 你的结构可以不跟我一样包含以下几个步骤就可以了 ...
  • 默认的application启动,在创建项目时自动生成application启动,直接run执行即可。 方式二:使用外置的tomcat启动 默认的启动要继承SpringBootServletInitiailzer,并复写configure()方法。 ...
  • 该篇博客会让你创建一个简单的spring应用并且使用Junit来测试它,怎么创建spring应用参考我创建一个简答你的springboot应用并且运行,您可能已经知道如何应用程序中编写和运行单个的单元测试,因此,对于本博客,...
  • 基于springboot的junit单元测试

    千次阅读 2020-02-17 12:21:30
    首先就是要有一个springboot项目,具体怎么创建就不过多赘述,不懂的小伙伴自行查找资料。 创建好springboot项目后,添加单元测试需要的依赖,这是我项目的依赖 导入jar包后就可以对要测试的进行快速测试,右击想...
  • springboot打war包

    2019-06-26 11:44:26
    记录一次springboot的war包的记录。 新建项目的时候传采用的是jar包,后来准备上限部署,pom.xml里面添加 <packaging>war</packaging>...//启动同级目录下创建这个,继承Spr...
  • 文章目录前言一、添加依赖二、创建两个工具2.1、新建一个基于面向切面的2.2、新建分页的工具三、业务逻辑层(Service)调用分页工具3.1、业务逻辑层3.2、业务逻辑层实现四、Junit测试总结 前言 最近有...
  • 程序员的懒方法,springboot的starter包 Spring提供了强大的bean管理能力,我们很简单地从IOC容器中把bean拿...很简单,写入配置文件或者配置中,例如,xml文件或者是java的配置,我们这个里面创建一个个的bean,
  • 上篇文章我们讲到了怎么对数据的查询操作,每次查询数据都会返回中构建一个匿名去封装返回结果,这样的话导致我们有大量的冗余代码,这并不是我们想要的结果,这篇文章主要讲解一下对数据结果的封装,也就是自定义...
  • 我们创建过大大小小很多个springboot框架的项目,我们创建完一个Maven工程之后,需要完成关键的三步,就可以启动项目了 1、引入依赖 我们知道springboot框架的优点主要有两点: 解决复杂的配置问题; 解决混乱的...
  • maven导入jar包,项目根目录创建libs文件夹,然后pom.xml添加如下: <dependency> <groupId>com.github.whvcse</groupId> <artifactId>easy-captcha</artifactId> <version&...
  • SpringBoot 与 Web开发(1)

    2020-12-06 10:02:05
    如果忘了相关模块的配置怎么写,可以去autuoconfigure jar 包下直接找对应的,然后找到@EnableConfigurationProperties 这个注释,点进去就能看见相关配置怎么写了。 3)自己编写业务代码:..
  • SpringBoot的第一个web项目完整小案例

    万次阅读 2018-01-06 19:55:26
    本文旨在展示第一次使用SpringBoot怎么运行起来一个项目,首先你的idea安装好了, 我们安装好idea之后,就可以创建SpringBoot项目了 1.右击File 2.选择是生成 3.注意选择java版本和包的不同 4.选择需要使用到...
  • 关于异常的概念什么的这里就不多说了(详见:https://www.cnblogs.com/williamjie/p/9103658.html),我们来直接看在SpringBoot怎么统一处理异常吧。 1.创建统一处理异常的 @ControllerAdvice public class ...
  • 怎么通过SpringBoot创建WebSocket服务的文章很多, 类似于单点登录,一个账号只能一个地方登录,我们的长连接也经常会需要限制一个用户只能保持一个长连接 这里就讲一下实现单点连接的一种思路 /** * ...
  • 首先创建一个SpringBoot项目 导入实体 我们再resources文件夹下创建静态资源文件 并导入几个页面。 我们可以看到public文件夹下和templates文件夹下都有index.html 我们启动服务: 可以看到访问的是public...
  • 前言: 平时做项目时,Controller层只会返回一个JSON串来表示信息是否成功~还真的没有考虑到异常是怎么处理的,不过肯定是统一管理异常。一、全局错误页面: Spring Boot提供了一个默认的映射:/error(当然该...

空空如也

空空如也

1 2 3 4 5
收藏数 88
精华内容 35
关键字:

在springboot怎么创建类

spring 订阅