zoukankan      html  css  js  c++  java
  • springboot学习

    1.0 spring boot是做到如何简化配置的

      我们来看下启动类,发现特别的地方有两个

        - 注解:@SpringBootApplication
        - run方法:SpringApplication.run()

      1.1 @SpringBootApplication分析

        点进去查看源码,发现注解上还有三个注解@SpringBootConfiguration@EnableAutoConfiguration、@ComponentScan

        1.1.1 @SpringBootConfiguration分析

          点进去查看源码,在这个注解上面,又有一个@Configuration注解,这个注解的作用就是声明当前类是一个配置类,然后Spring会自动扫描到添加了`@Configuration`的类,并且读取其中的配置信息。而`@SpringBootConfiguration`是来声明当前类是SpringBoot应用的配置类,项目中只能有一个

        1.1.2 @EnableAutoConfiguration分析

          点进去查看源码,注释上面写道此注解可以开启spring boot自动配置,简单来讲作用就是根据引用的jar包猜测你想要做什么,然后自动帮你配置

        1.1.3 @ComponentScan分析

          点进去查看源码,注释上面写道,此注解可以开启包扫描

      1.2 SpringApplication.run()分析

        return new SpringApplication(primarySources).run(args);   
          this(null, primarySources); 
            deduceFromClasspath()判断当前应用类型
              如果是 WEBFLUX_INDICATOR_CLASS,则为spring5里面的新的react响应式编程
              如果不包含任何一个"javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext"
              否则项目是web工程     
            getSpringFactoriesInstances()加载初始化工厂类
              loadFactoryNames,从 FACTORIES_RESOURCE_LOCATION,即META-INF/spring.factories中读取需要初始化的类,他在spring boot
    autoconfigure jar包中,通过这个加载了自动配置包中的大部分自动配置类,配置类是否生效呢,在类名称上面有条件判断注解,以WebMvcAutoConfiguration类为例
          - `@ConditionalOnWebApplication(type = Type.SERVLET)`
              ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是是Type.SERVLET类型,也就是一个普通web工程,显然我们就是
          - `@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })`
              这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了tomcat依赖自然会有,后两个需要引入SpringMVC才会有。这里就是判断你是否引入了相关依赖,引入依赖后该条件成立,当前类的配置才会生效!
          - `@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)`
              这个条件与上面不同,OnMissingBean,是说环境中没有指定的Bean这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个WebMVCConfigurationSupport的类,那么这个默认配置就会失效!

     

    2.0 spring boot 如何修改默认配置

      2.1 简单默认配置

        如果我们要覆盖这些默认属性,只需要在application.properties中定义与其前缀prefix和字段名一致的属性即可

        例如修改静态资源加载位置

        spring.resources.static-locations = classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${file.uploadPath}

      2.2 其它复杂配置

        例如配置拦截器

        拦截器不是一个普通属性,而是一个类,所以就要用到java配置方式了。在SpringBoot官方文档中有这么一段说明:

          > If you want to keep Spring Boot MVC features and you want to add additional [MVC configuration](https://docs.spring.io/spring/docs/5.0.5.RELEASE/spring-framework-reference/web.html#mvc) (interceptors, formatters, view controllers, and other features), you can add your own `@Configuration` class of type `WebMvcConfigurer` but **without** `@EnableWebMvc`. If you wish to provide custom instances of `RequestMappingHandlerMapping`, `RequestMappingHandlerAdapter`, or `ExceptionHandlerExceptionResolver`, you can declare a `WebMvcRegistrationsAdapter` instance to provide such components.
          > If you want to take complete control of Spring MVC, you can add your own `@Configuration` annotated with `@EnableWebMvc`. 

        翻译:
        > 如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器,格式化器, 视图控制器、消息转换器 等等),你应该让一个类实现`WebMvcConfigurer`,并且添加`@Configuration`注解,但是**千万不要**加`@EnableWebMvc`注解。如果你想要自定义`HandlerMapping`、`HandlerAdapter`、`ExceptionResolver`等组件,你可以创建一个`WebMvcRegistrationsAdapter`实例 来提供以上组件。

        > 如果你想要完全自定义SpringMVC,不保留SpringBoot提供的一切特征,你可以自己定义类并且添加`@Configuration`注解和`@EnableWebMvc`注解

     

    public class LoginInterceptor implements HandlerInterceptor {
    
        private Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
            logger.debug("preHandle method is now running!");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
            logger.debug("postHandle method is now running!");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
            logger.debug("afterCompletion method is now running!");
        }
    }
    

      

    @Configuration
    public class MvcConfig implements WebMvcConfigurer{
        /**
         * 通过@Bean注解,将我们定义的拦截器注册到Spring容器
         * @return
         */
        @Bean
        public LoginInterceptor loginInterceptor(){
            return new LoginInterceptor();
        }
    
        /**
         * 重写接口中的addInterceptors方法,添加自定义拦截器
         * @param registry
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 通过registry来注册拦截器,通过addPathPatterns来添加拦截路径
            registry.addInterceptor(this.loginInterceptor()).addPathPatterns("/**");
        }
    }
    

      数据库连接池配置

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

        <dependency>
              <groupId>mysql</groupId>
              <artifactId>mysql-connector-java</artifactId>
        </dependency>

      引入jdbc启动器的时候SpringBoot已经自动帮我们引入了一个连接池HikariCP应该是目前速度最快的连接池了

      # 连接四大参数
        spring.datasource.url=jdbc:mysql://localhost:3306/springboot
        spring.datasource.username=root
        spring.datasource.password=123
        # 可省略,SpringBoot自动推断
        spring.datasource.driverClassName=com.mysql.jdbc.Driver    com.mysql.cj.jdbc.Driver
        spring.datasource.hikari.idle-timeout=60000
        spring.datasource.hikari.maximum-pool-size=30
        spring.datasource.hikari.minimum-idle=10
      如果你更喜欢Druid连接池,也可以使用Druid官方提供的启动器

      <!-- Druid连接池 -->
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid-spring-boot-starter</artifactId>
          <version>1.1.6</version>
      </dependency>
     

      连接信息的配置与上面是类似的,只不过在连接池特有属性上,方式略有不同
     spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
      #初始化连接数
      spring.datasource.druid.initial-size=1
      #最小空闲连接
      spring.datasource.druid.min-idle=1
      #最大活动连接
      spring.datasource.druid.max-active=20
      #获取连接时测试是否可用
      spring.datasource.druid.test-on-borrow=true
      #监控页面启动
      spring.datasource.druid.stat-view-servlet.allow=true

      spring 2.0之前数据库连接池的默认初始化方式

      检查tomcat的数据库连接池实现是否可用,如可用,则启用。使用spring.datasource.tomcat.*可以控制连接池的行为。
      检查hikari是否可用,如可用,则启用。使用spring.datasource.hikari.*可以控制连接池的行为。
      检查dbcp是否可用,如可用,则启用;该连接池被Spring Boot标记为deprecated,不建议在生产环境使用该连接池的实现。
      检查dbcp2是否可用,如可用,则启用。使用spring.datasource.dbcp2.*可以控制连接池的行为。

      spring 2.0之后数据库连接池的默认初始化方式

      检查hikari是否可用,如可用,则启用。使用spring.datasource.hikari.*可以控制连接池的行为。
      检查tomcat的数据库连接池实现是否可用,如可用,则启用。使用spring.datasource.tomcat.*可以控制连接池的行为。
      检查dbcp2是否可用,如可用,则启用。使用spring.datasource.dbcp2.*可以控制连接池的行为。

      使用时最好指定数据源格式,防止默认数据源的变动带来的不确定

      整合mybatis

        SpringBoot官方并没有提供Mybatis的启动器,不过Mybatis[官网](https://github.com/mybatis/spring-boot-starter)自己实现了

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        # mybatis 别名扫描
        mybatis.type-aliases-package=com.study.pojo
        # mapper.xml文件位置,如果没有映射文件,请注释掉
        mybatis.mapper-locations=classpath:mappers/*.xml

      需要注意,这里没有配置mapper接口扫描包,因此我们需要给每一个Mapper接口添加`@Mapper`注解,才能被识别。

      整合通用mapper

        通用Mapper的作者也为自己的插件编写了启动器,我们直接引入即可,里面包含了mybatis依赖,jdbc依赖

        <!-- 通用mapper -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.0.2</version>
        </dependency>

      @Mapper
      public interface UserMapper extends tk.mybatis.mapper.common.Mapper<User>{
      }

      如果你使用的是包扫描而不是@Mapper注解,那你的包扫描应该是这个@tk.mybatis.spring.annotation.MapperScan(basePackages = "扫描包")

      注意:

      1、表名默认使用类名,驼峰转下划线(只对大写字母进行处理),如UserInfo默认对应的表名为user_info。

      2、表名可以使用@Table(name = "tableName")进行指定,对不符合第一条默认规则的可以通过这种方式指定表名.

      3、字段默认和@Column一样,都会作为表字段,表字段默认为Java对象的Field名字驼峰转下划线形式.

      4、可以使用@Column(name = "fieldName")指定不符合第3条规则的字段名

      5、使用@Transient注解可以忽略字段,添加该注解的字段不会作为表字段使用.

      6、建议一定是有一个@Id注解作为主键的字段,可以有多个@Id注解的字段作为联合主键

      详解:

        https://www.cnblogs.com/lichangyun/p/8530975.html

        https://www.cnblogs.com/kitor/p/11009434.html

        http://www.mybatis.tk/

        https://github.com/abel533

      整合thymeleaf

      模板默认放在classpath下的templates文件夹,我们新建一个html文件放入其中:
     
      编写html模板,渲染模型中的数据:
      注意,把html 的名称空间,改成:`xmlns:th="http://www.thymeleaf.org"` 会有语法提示
      ```html
      <!DOCTYPE html>
      <html xmlns:th="http://www.thymeleaf.org">
       <head>
          <meta charset="UTF-8">
          <title>首页</title>
          <style type="text/css">
              table {border-collapse: collapse; font-size: 14px; 80%; margin: auto}
              table, th, td {border: 1px solid darkslategray;padding: 10px}
          </style>
      </head>
      <body>
      <div style="text-align: center">
          <span style="color: darkslategray; font-size: 30px">欢迎光临!</span>
          <hr/>
        <table class="list">
            <tr>
                <th>id</th>
                <th>姓名</th>
                <th>用户名</th>
                <th>年龄</th>
                <th>性别</th>
                <th>生日</th>
                <th>备注</th>
            </tr>
            <tr th:each="user : ${users}">
                <td th:text="${user.id}">1</td>
                <td th:text="${user.name}">张三</td>
                <td th:text="${user.userName}">zhangsan</td>
                <td th:text="${user.age}">20</td>
                <td th:text="${user.sex} == 1 ? '男': '女'">男</td>
                <td th:text="${#dates.format(user.birthday, 'yyyy-MM-dd')}">1980-02-30</td>
                <td th:text="${user.note}">1</td>
            </tr>
        </table>
    </div>
    </body>
    </html>
    ```
    我们看到这里使用了以下语法:
    - `${}` :这个类似与el表达式,但其实是ognl的语法,比el表达式更加强大
    - `th-`指令:`th-`是利用了Html5中的自定义属性来实现的。如果不支持H5,可以用`data-th-`来代替
      - `th:each`:类似于`c:foreach`  遍历集合,但是语法更加简洁
      - `th:text`:声明标签中的文本
        - 例如`<td th-text='${user.id}'>1</td>`,如果user.id有值,会覆盖默认的1
        - 如果没有值,则会显示td中默认的1。这正是thymeleaf能够动静结合的原因,模板解析失败不影响页面的显示效果,因为会显示默认值!
     
     
  • 相关阅读:
    【Life】 今天的思考
    【openpyxl】 关于 单元格背景色 的疑惑
    【xlwings】 wps 和 office 的excel creat_sheet区别
    [git] git error: unable to unlink old
    【python tkinter】对于窗口存在的认识
    【求教 探讨】python tkinter的messagebox
    [python]近日 用3种库 实现简单的窗口 的回顾~
    AE(After Effects)的简单使用——记一次模板套用的过程
    python3爬虫应用--爬取网易云音乐(两种办法)
    【KataDaily 191015】Sort the Gift Code
  • 原文地址:https://www.cnblogs.com/helloworldmybokeyuan/p/11625205.html
Copyright © 2011-2022 走看看