美文网首页
springboot原理

springboot原理

作者: 幻如常 | 来源:发表于2021-03-29 21:59 被阅读0次

springboot原理

未使用springboot时,怎样构建web项目(ssm架构的)

  1. 导入web及其配置,spring,springmvc

  2. 在web.xml中配置dispatchServlet(前端控制器,作为分发器的作用)

  3. 配置包扫描路径,让我们的service层,controller层等里面的对象被spring容器进行管理

  4. 编写controller类

  5. 部署Tomcat

使用了springboot搭建web项目时

  1. 编写controller类
  2. 在项目根目录下新建一个类(如:App),作为配置类,在其上面贴上@SpringBootApplication注解
  3. 在App类里面启动方法
     public static void main(String[] args) { SpringApplication.run(App.class, args); 
     }
    
    SpringApplication.run(..)的作用:启动springBoot应用;加载自定义的配置类,完成自定义的功能;把当前项目部署到嵌入的Tomcat;启动Tomcat
  4. springboot方式不需要我们配置web,dispatchServlet,Tomcat,以及包扫描路径等

springboot对比传统方式简化的原理是什么?

  1. 因为在App类上面贴了@SpringBootApplication注解,该注解本身又被贴了以下三个核心注解
        @SpringBootConfiguration
        @EnableAutoConfiguration
        @ComponentScan
  1. 因为被贴了@SpringBootConfiguration这个注解,所以该App类就成为了配置类,一般springBoot项目只有一个启动类,启动类都是配置类
  2. 因为贴了@ComponentScan这个注解,所有具有了扫描包的功能,它的功能就是扫描当前类所在包及其子包所有贴了版型注解的类,并创建出对象交给spring管理,所以我们贴@controller,@service等注解的类并没有做额外配置,就可以直接从spring中拿,就是因为有该@ComponentScan注解,所以启动动类(贴了@SpringBootApplication注解的类)建议都是放在项目根包下
  3. @EnableAutoConfiguration:启用自动配置,这个注解的意思是根据你加载的依赖去猜测你需要怎样配置spring,(springBoot收集了很多第三方jar依赖,根据jar依赖的特点,springBoot对这些jar依赖作了进一步的分类,整合,再封装形成一个新的依赖工具集,每个工具集都是用来解决特定领域问题的,springBoot就把这些工具集称为启动器,所以spring-boot-starter-web这个也就是一个启动器(web项目的启动器),里面装了很多和web项目相关的依赖比如spring-webmvc,starter-tomcat等),因为我们配置了spring-boot-starter-web这个启动器,所以springBoot就知道我们是一个web项目,其底层就帮我们配置好了dispatchServlet,
  4. 那@EnableAutoConfiguration注解的具体实现原理是什么呢?
    1. 在该注解里面又有@Import(AutoConfigurationImportSelector.class)这么一个注解(自动配置导入选择器),该类(AutoConfigurationImportSelector)里面有一个方法List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes)这个方法是批量加载配置类的
    2. 点击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; 
              }
      
      SpringFactoriesLoader就是去加载maven:org.springframework.boot:spring-boot-autoconfigure下面的META- INF/spring.factories而Assert.notEmpty断言表示当configurations为空时就证明没有自动加载META- INF/spring.factories里的自动配置类,注意:不管是spring定制的启动器,还是第三方定制的启动器,都需要编写META�INF/spring.factories,里面指定启动器的自动配置类.
    3. META- INF/spring.factories里面写了很多自动加载类,难道每一个我们都会加载到spring容器中吗?只有满足条件的配置类才会被加载到spring容器中
    4. org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration举例,点击进入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 })
      
      
      1. @Configuration表示这也是一个配置类
      2. @ConditionalOnWebApplication(type = Type.SERVLET)这个注解表示在type为servlet这种条件下当前类的配置才生效(0n表示在什么条件下),因为我们一开始就配置了web启动器,所以我们是一个web项目,是满足当前这个条件的
      3. ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })表示必须有Servlet,DispatcherServlet,WebMvcConfigurer类当前配置才生效,这里就是判断你是否引入了SpringMVC相关的依赖
      4. @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)表示当我们没有主动配置WebMvcConfigurationSupport这个bean时,当前类的配置才会生效,意思就是说如果我们主动配置了WebMvcConfigurationSupport这个类型的bean,那么当前类的配置就会不生效,我们点击WebMvcConfigurationSupport进去看下,如果我们自己没有配置符合当前条件,springBoot会在WebMvcConfigurationSupport里面帮我们做什么事情呢?
            @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; 
            }
        
        主要是配置了视图解析器
      5. 方法 @AutoConfigureAfter这个注解表示在指定的类加载完了后,再加载本类(即先加载DispatcherServletAutoConfiguration类,再加载当前类WebMvcAutoConfiguration),而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;
      }
      
      所以我们便得到了前端控制器,此时只差一个Tomcat我们便能启动项目了
    5. Tomcat:springboot使用嵌入式tomcat,编程实现,默认端口是8080,后续可以通过 application.properties文件进行修改

springBoot优缺点

  • 优点:
    1. 创建独立运行的spring应用程序
    2. 内嵌的猫,不用再打war包(如果不是用的springBoot那么用到Tomcat要打war包,不然Tomcat用不了)
    3. 不用搞一堆的spring配置,自动进行spring配置(如视图解析器,aop等等)
    4. 不用xml配置
    5. 很方便集成第三方jar依赖
    6. 简化maven(springBoot都重新整合了一个个的工具集,例如web项目直接导入一个web启动器,相应的依赖就都帮我们导入了)
    7. 提供了日志,健康检查,外部配置等生产就绪功能
  • 缺点:
    1. 版本更新快,可能会出现较大变化
    2. 因为约定大于配置,所以可能出现一些不好解决的问题

application.properties优先级

  • 一个项目中可以有多个application.properties文件存放在不同目录中,此时他们会遵循固定的优先级来处理有冲突的属性配置, 优先级由高到底,高优先级的配置会覆盖低优先级的配置

    1. 项目/config/application.properties
    2. 项目/application.properties
    3. classpath:config/application.properties1
    4. classpath:application.properties2(calsspath就是指Resources)

    一般都在classpath:application.properties做配置,其他方式不使用

WEB集成相关

  1. Resources下面的static就相当于以前web-app的根目录用于存放静态资源( 默认情况下,Springboot会从classpath下的 /static , /public , /resources , /META-INF/resources下加载静态资源)
  2. templates用于存放模板文件,如ftl或jsp
  3. 可以在application.properties中配置spring.resources.staticLocations属性来修改静态资源加载地址,但一般不建议修改
  4. 因为应用是打成jar包,所以之前的src/main/webapp就作废了,如果有文件上传,那么就的必须去配置图片所在的路径
  5. 因为springBoot通过WebMvcAutoConfiguration自动配置类配置了dispatchServlet,其默认路径为/(<
    url-pattern >是 /),所以如果我们还想使用localhost/list.do这种.do的形式,那么就需要在application.properties中配置spring.mvc.pathmatch.use-suffix-pattern=true(这个是表示在匹配模式时是否使用后缀模式匹配)
  6. 配置freemarker时,除了导入依赖外,以下三个配置我们要配上
        #暴露session对象的属性 
        spring.freemarker.expose-session-attributes=true 
        #配置为传统模式,空值自动处理 spring.freemarker.settings.classic_compatible=true 
        #重新指定模板文件后缀 springboot 2.2.x 后 默认后缀为 .ftlh 
        spring.freemarker.suffix=.ftl
  1. springBoot自带了异常处理,SpringBoot默认情况下,会把所有错误都交给BasicErrorController类完成处理,错误的视图导向到classpath:/static/error/ 和 classpath:/templates/error/ 路径上,http状态码就是默认视图的名称,注意这里一定要是在error文件夹下,且必须是404.html(必须是html才有用),出现5xx类错误 ->
    classpath:/static/error/5xx.html(名字必须是5xx.html)
  2. 针对不同的需要我们还可以自定义异常
        //控制器增强器
    @ControllerAdvice
    public class ExceptionControllerAdvice {
    @ExceptionHandler(RuntimeException.class)//处理什么类型的异常
    
    public String handleException(Exception e, Model model, HandlerMethod method){
        /*这里就是和普通的 @RequestMapping("/list")注解下的方法一样用,即可以返回json类型的数据
        还可以直接返回到指定的ftl页面,通过method可以拿到检测的控制器方法上面是否贴了json类型的注解@ResponseBody
        从而进行json返回数据和返回页面的不同处理
        */
        return "errorView";
        }
    }  
    
  3. 我们可以自定义拦截器,实现下HandlerInterceptor接口即可,如下:
        @Component public class LoginInterceptor implements HandlerInterceptor { 
            @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String uri = request.getRequestURI();
            if (uri.contains("list")) {
            response.sendRedirect("/login.html");
            return false;
            }
        return true;
            }
        }
    
    以前我们自定义拦截器后还需要在< mvc:interceptors >标签中去注册我们的拦截器,用了springBoot后,则只需让启动类实现WebMvcConfigurer接口,并调用addInterceptors方法即可;
        @SpringBootApplication
        @MapperScan("cn.sushen.mapper")
        //实现WebMvcConfigurer接口,调用addInterceptors方法配置拦截器
        public class App implements WebMvcConfigurer {
    
        @Autowired
        private LoginInterceptor loginInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
        /*
        1.第一个参数表示注册哪一个拦截器
        2.addPathPatterns表示要拦截的路径是哪些
        3.excludePathPatterns不用拦截的是哪些
         */ 
        registry.addInterceptor(loginInterceptor).
                addPathPatterns("/**").
                excludePathPatterns("/static/**","/*/list");
        }
    
        public static void main(String[] args) {
                SpringApplication.run(App.class,args);
            }
        }
    

相关文章

网友评论

      本文标题:springboot原理

      本文链接:https://www.haomeiwen.com/subject/jfyihltx.html