springboot原理

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);
            }
        }
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容