如何搭建SpringBoot项目

简介: 如何搭建SpringBoot项目

 如何搭建一个SpringBoot项目

步骤

1、创建一个普通maven项目:SpringBootDemo

2、在pom.xml文件设置项目打包方式

<packaging>jar</packaging>

image.gif

3、在pom.xml文件导入SpringBoot父项目

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
    <relativePath/>
</parent>

image.gif

4、在pom.xml文件导入Web项目依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

image.gif

5、编写普通Controller类

/**
 * 控制层
 */
@Controller
public class HelloController {
    @RequestMapping("hello")
    public Object hellp(){
        return "Hello SpringBoot!";
    }
}

image.gif

6、编写启动类,启动SpringBoot项目

/**
 * SpringBoot项目启动类
 */
@SpringBootApplication
public class SpringBootDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class,args);
    }
}

image.gif

7、浏览器访问测试: http://localhost:8080/hello

问题

    1. Web打包不应该是war,为什么是jar?
    2. pom.xml文件中继承的spring-boot-starter-parent有什么用?
    3. pom.xml文件中导入的依赖spring-boot-starter-web又有什么用?
    4. 启动类SpringBootDemoApplication头顶上的@SpringBootApplication注解做了什么?
    5. 没有配置tomcat,没有设置端口服务器怎么来,又怎么启动的?
    6. main方法中SpringApplication.run(..)又是什么情况?

    分析

    问题1:Web打包不应该是war,为什么是jar

    SpringBoot默认的打包方式就是jar,传统的外接tomcat或插件式tomcat与web项目是相互独立,相互对接时必须满足一定规则,war包结构项目就是规则约定之一。而SpringBoot项目采用的是内嵌式(简单理解为编码方式)tomcat,项目与tomcat融为一体,部署,启动,运行一体化,就没有各种条条框框的约束了。

    问题2:pom.xml文件中继承的spring-boot-starter-parent有啥用

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
        <relativePath/>
    </parent>

    image.gif

    spring-boot-starter-parent其实是SpringBoot提供了工具工程,工程收集了市面上常用各种第三方jar依赖,并对这些jar依赖进行了版本管理。当我们的项目继承这个项目工程,就自动成为SpringBoot项目,并无偿继承了这些第三方jar依赖。后续项目中需要某个第三方依赖,只需要引入依赖坐标即可, 不需要关系依赖版本。比如:

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    image.gif

    一个拓展:

    继承是 Maven 中很强大的一种功能,继承可以使得子POM可以获得 parent 中的部分配置(groupId,version,dependencies,build,dependencyManagement等),可以对子pom进行统一的配置和依赖管理。

      • parent项目中的dependencyManagement里的声明的依赖 , 只具有声明的作用,并不实现引入,因此子项目需要显式的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,可以不指定具体版本,会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本
      • parent项目中的dependencies里声明的依赖会被所有的子项目继承

      问题3:pom.xml文件中导入的依赖spring-boot-starter-web又有啥用

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

      image.gif

      问题2中说了,SpringBoot收集了很多常用的第三方jar依赖,为了进一步提高用户体验感,SpringBoot根据jar依赖特点,对这些依赖进一步分类,整合,再封装,形成一个新的依赖工具集, 每个工具集都解决特定领域的依赖问题。SpringBoot将这些依赖工具称为:启动器(组件),命名规则: spring-boot-starter-xxx。 如果是非SpringBoot定制的启动器, 一般命名规则:xxx-spring-boot-starter

      入门案例中导入的spring-boot-starter-web 就是用于解决web项目依赖的工具集(启动器)

      image.gif编辑

      常用的启动器(starter)还有很多:

      spring-boot-starter: 核心启动器 , 提供了自动配置,日志和YAML配置支持

      spring-boot-starter-aop: 支持使用 Spring AOPAspectJ 进行切面编程。

      spring-boot-starter-freemarker: 支持使用 FreeMarker 视图构建Web 应用

      spring-boot-starter-test: 支持使用 JUnit, 测试 Spring Boot 应用

      spring-boot-starter-web: 支持使用 Spring MVC 构建 Web 应用,包括 RESTful 应用,使用 Tomcat 作为默认的嵌入式容器。

      spring-boot-starter-actuator: 支持使用 Spring Boot Actuator 提供生产级别的应用程序监控和管理功能。

      spring-boot-starter-logging: 提供了对日志的支持 , 默认使用Logback

      问题4:启动类App头顶上的@SpringBootApplication注解做了什么

      要回答这个问题, 就必须讲清楚springboot的自动配置原理(也称自动装配)

      springboot的精髓就在这个注解里。

      @SpringBootApplication
      public class App {
          public static void main(String[] args) {
              SpringApplication.run(App.class, args);
          }
      }

      image.gif

      先回顾一下以前使用SpringMVC搭建web项目时, 我们是怎么做的

      1>导入Web, Spring, SpringMVC依赖

      2>在web.xml文件配置前端控制器:DispatcherServlet

      3>编写controller类

      4>配置controller扫描包路径

      5>部署到tomcat并启动

      从上面步骤上看,刚刚入门案例不需要我们去做的有几步?

      1:不需要配置前端控制器

      2:不需要配置包扫描路径

      3:不需要部署tomcat这步

      这些步骤我们都没做,项目却跑起来,那肯定有人帮我们做了,那会是谁?所有问题关键就是这个:@SpringBootApplication注解。

      @SpringBootApplication源码解析

      点击进入,查看源码:

      @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 {
          ......
      }

      image.gif

      注解上面又有一堆注解,核心的有3个:

        • @SpringBootConfiguration
        • @EnableAutoConfiguration
        • @ComponentScan

        这里注意:注解头顶又贴有注解(非元注解),表示当前注解为复合注解,当前注解也拥有所贴注解功能。

        @ComponentScan

        功能:spring组件扫描注解,扫描所贴的类所在包及其子包所有贴有版型注解的类,并创建对象交给spring容器管理。

        入门案例中, 我们将@SpringBootApplication 注解贴在App类里面,那么它会扫描App类所有包及其子包里面所有贴有版型注解的类,并创建实例, 那么controller包下的HelloController类就可以被扫描到。

        一个注意点: 一般贴有@SpringBootApplication注解的类称之为启动类,建议放置在根包下。

        @SpringBootConfiguration

        @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        @Documented
        @Configuration
        public @interface SpringBootConfiguration {
            ....
        }

        image.gif

        该注解头顶贴了@Configuration注解, 前面Javaconfig讲过贴有@Configuration类为配置类

        @SpringBootApplication   头顶贴有  @SpringBootConfiguration  

        @SpringBootConfiguration 头顶贴有  @Configuration        

        根据上面注解关系推导下:入门案例中贴有@SpringBootApplication注解的App类就是一个项目配置类。

        一个注意点:一般springboot项目只有唯一一个启动类,启动类都是配置类。

        @EnableAutoConfiguration

        @EnableAutoConfiguration的作用,告诉SpringBoot基于你所添加的依赖,去“猜测”你想要如何配置Spring。比如当我们引入了spring-boot-starter-web这个启动器,spring会解析这个启动器,推测当前项目为web项目,根据启动器默认配置要求自动配置web及SpringMVC相关对象创建与管理。比如:前端控制的创建,比如前端控制的路径映射等。

        SpringBoot对自带启动器与第三方启动器进行了大量的默认配置,这些配置是否生效,是否加载到spring容器中使用,取决于我们项目是否引入了对启动器依赖,如果有那么默认配置就会生效。

        那么

          • 这些默认配置是在哪里定义的呢?
          • 为何依赖引入就会触发配置生效呢?

          看源码:

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

          image.gif

          @EnableAutoConfiguration注解import导入了一个AutoConfigurationImportSelector自动配置类选择器,该类可以实现配置类批量载入 spring容器。其核心方法是getCandidateConfigurations

          protected List<String> getCandidateConfigurations(
              AnnotationMetadata metadata, AnnotationAttributes attributes) {
              List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
                  getSpringFactoriesLoaderFactoryClass(),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;
          }

          image.gif

          getCandidateConfigurations方法作用是委托SpringFactoriesLoader去读取jar包中的META-INF/spring.factories文件, 并加载里面配置的自动配置对象,其中包括: AOP / PropertyPlaceholder / FreeMarker / HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager / DispatcherServlet / WebMvc 等等。

          image.gif编辑

          一个注意点:不管是spring定制的启动器,还是第三方定制的启动器,都需要编写META-INF/spring.factories,里面指定启动器的自动配置类

          接上面分析, spring.factories文件中配置很多自动配置类,哪些会生效(加载到Spring容器并跑起来)呢, 此时需要满足这些启动类生效条件才会自动装配。

          以我们熟悉SpringMVC为例子:

          在spring.factories找WebMvcAutoConfiguration自动配置类

          org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

          点进去看源码

          @Configuration(proxyBeanMethods = false)
          @ConditionalOnWebApplication(type = Type.SERVLET)
          @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
          @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
          @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
          @AutoConfigureAfter({ 
                  DispatcherServletAutoConfiguration.class, 
                  TaskExecutionAutoConfiguration.class,
                  ValidationAutoConfiguration.class })
          public class WebMvcAutoConfiguration {
              ...
          }

          image.gif

          我们看到这个类上的4个注解:

            • @Configuration:声明这个类是一个配置类
              • @ConditionalOnWebApplication(type = Type.SERVLET)
                ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是是Type.SERVLET类型,我们现在的项目就满足了, 就是一个web服务(web项目)
              • @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
                这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer。这里就是判断你是否引入了SpringMVC相关依赖,引入依赖后该条件成立,当前类的配置才会生效!
              • @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
                这个条件与上面不同,OnMissingBean,是说环境中没有指定的Bean这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个WebMVCConfigurationSupport的bean, 代表容器里已经存在该bean了,那么这个默认配置就会失效!这里允许我们定制自己的bean替换spring默认的。

              接着,我们查看WebMvcAutoConfiguration该类中定义了什么:(如果它生效了,会创建什么对象并载入容器进行管理)

              视图解析器:

              @Bean
              @ConditionalOnMissingBean
              public InternalResourceViewResolver defaultViewResolver() {
                 InternalResourceViewResolver resolver = new InternalResourceViewResolver();
                 resolver.setPrefix(this.mvcProperties.getView().getPrefix());
                 resolver.setSuffix(this.mvcProperties.getView().getSuffix());
                 return resolver;
              }
              @Bean
              @ConditionalOnBean(View.class)
              @ConditionalOnMissingBean
              public BeanNameViewResolver beanNameViewResolver() {
                 BeanNameViewResolver resolver = new BeanNameViewResolver();
                 resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
                 return resolver;
              }

              image.gif

              WebMvcAutoConfiguration中使用了@AutoConfigureAfter注解, 意为指定的类加载完了后,再加载本类

              @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })

              而DispatcherServletAutoConfiguration中又做了很多事情, 比如配置了前端控制器

              @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
              public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
                  DispatcherServlet dispatcherServlet = new DispatcherServlet();
                  dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
                  dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
                  dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.
                                                                      isThrowExceptionIfNoHandlerFound());
                  dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
                  dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
                  return dispatcherServlet;
              }

              image.gif

              总结:

              @SpringBootApplication注解内部是3大注解功能的集成

                • @ComponentScan: 开启组件扫描
                • @SpringBootConfiguration: 作用等同于@Configuration注解,也是用于标记配置类
                • @EnableAutoConfiguration: 内部导入AutoConfigurationImportSelector,该类中有个getCandidateConfigurations方法, 读取jar包中META-INF/spring.factories文件中配置类, , 再根据条件进行加载和配置, 比如: AOP / PropertyPlaceholder / FreeMarker / HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager / DispatcherServlet / WebMvc 等等

                问题5:没有配置tomcat,没有设置端口服务器怎么来,又怎么启动的

                SpringBoot使用嵌入式tomcat,编程实现,默认端口是8080,后续可以通过application.properties文件进行修改

                image.gif编辑

                问题6:main方法中SpringApplication.run(..)又是什么情况

                SpringApplication.run(..)的作用:

                  • 启动SpringBoot应用
                  • 加载自定义的配置类,完成自动配置功能
                  • 把当前项目部署到嵌入的Tomcat服务器
                  • 启动Tomcat服务器跑项目

                  总结

                  SpringBoot项目完整结构

                  image.gif编辑

                  SpringBoot优缺点

                  优点:

                    1. 创建独立运行的Spring应用程序 ;
                    2. 嵌入的Tomcat,无需部署war文件;
                    3. 简化Maven配置 ;
                    4. 自动配置Spring ;
                    5. 提供生产就绪型功能,如:日志,健康检查和外部配置等;
                    6. 不要求配置 XML;
                    7. 非常容易和第三方框架集成起来。

                    缺点:

                      1. 版本更新较快,可能出现较大变化;
                      2. 因为约定大于配置,所以经常会出现一些很难解决的问题。


                      目录
                      相关文章
                      |
                      NoSQL Java 数据库连接
                      Idea创建SpringBoot多模块项目
                      我们可以定义一个维度,以此来划分模块,例如上述商城、可以划分成商品、库存和订单模块。也可以目录结构分层,`Controller`层,只不过没人这样做。这样就引申出了下一个问题`拆分策略`。
                      922 0
                      Idea创建SpringBoot多模块项目
                      |
                      Java 应用服务中间件 Maven
                      传统maven项目和现在spring boot项目的区别
                      Spring Boot:传统 Web 项目与采用 Spring Boot 项目区别
                      492 0
                      传统maven项目和现在spring boot项目的区别
                      |
                      XML Java 数据库连接
                      创建springboot项目的基本流程——以宠物类别为例
                      创建springboot项目的基本流程——以宠物类别为例
                      153 0
                      创建springboot项目的基本流程——以宠物类别为例
                      |
                      存储 机器学习/深度学习 IDE
                      SpringBoot 项目与被开发快速迁移|学习笔记
                      快速学习 SpringBoot 项目与被开发快速迁移
                      SpringBoot 项目与被开发快速迁移|学习笔记
                      |
                      Java Spring
                      自定义SpringBoot项目的启动Banner
                      ``Banner``是``SpringBoot``框架一个特色的部分,其设计的目的无非就是一个框架的标识,其中包含了版本号、框架名称等内容,既然``SpringBoot``为我们提供了这个模块,它肯定也是可以更换的这也是``Spring``开源框架的设计理念。
                      |
                      前端开发 Java 应用服务中间件
                      基于springboot+mybatisplus+vue-科技项目评审及专家库管理系统
                      基于springboot+mybatisplus+vue-科技项目评审及专家库管理系统
                      261 0
                      基于springboot+mybatisplus+vue-科技项目评审及专家库管理系统
                      |
                      Java Spring
                      【Java】【Spring Boot】CP01:创建一个SpringBoot项目(Spring Initializr)
                      【Java】【Spring Boot】CP01:创建一个SpringBoot项目(Spring Initializr)
                      278 0
                      【Java】【Spring Boot】CP01:创建一个SpringBoot项目(Spring Initializr)
                      |
                      消息中间件 NoSQL Java
                      47K Star 的SpringBoot+MyBatis+docker电商项目,附超详细的文档
                      该项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现,采用Docker容器化部署。 前台商城系统:首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。 后台管理系统:商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。 该项目使用现阶段主流技术实现。涵盖了SpringBoot 2.3.0、MyBatis 3.4.6、Elasticsearch 7.6.2、RabbitMQ 3.7.15、Redis 5.0、MongoDB 4.2.5、
                      |
                      安全 Java 关系型数据库
                      Mall电商实战项目全面升级!支持最新版SpringBoot,干掉循环依赖
                      技术栈升级 mall项目采用现阶主流技术实现,这些主流技术基本都升级了目前最新稳定版,具体升级内容大家可以参考下表。 技术版本说明
                      |
                      Java 应用服务中间件 Linux
                      springboot上传下载文件(1)(项目和文件资源放在同一个服务器上)
                      springboot上传下载文件(1)(项目和文件资源放在同一个服务器上)
                      325 0
                      springboot上传下载文件(1)(项目和文件资源放在同一个服务器上)
                      下一篇
                      无影云桌面