美文网首页
Spring Boot 3 遇到的一些变化、知识点

Spring Boot 3 遇到的一些变化、知识点

作者: 狄仁杰666 | 来源:发表于2023-05-16 23:19 被阅读0次

    前言

    来啦老铁!

    前一阵子公司举办了编程比赛,我与几位同事也参加了,项目与结果且不说,重在参与!重在学习到了什么!!!

    我记录一下在这过程当中学习(踩坑)到的一些技术知识吧~

    今天先来记录后端部分~

    学习路径

    1. Spring Boot 3 配置 Mybatis + Mysql;
    2. 跨域配置:allowedOriginPatterns;
    3. domain 与 entity 、dao 概念的理解;
    4. 多环境配置与使用;
    5. mysql 插入数据后,返回插入数据的值;
    6. 10 位数 timestamp;

    1. Spring Boot 3 配置 Mybatis + Mysql;

    我们在三年前曾经涉足 Mybatis + Mysql 的使用,当时是 Spring Boot 2,使用起来也是相当简单,详情请见:

    而随着时间的流逝,Spring Boot 已经来到了 Spring Boot 3,我们在本次编程使用了 Spring Boot 3,没想到在这方面遇到困难,正确的做法是:

    1. 安装 druid datasource maven 依赖,如:
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.9</version>
    </dependency>
    
    2. 使用 druid datasource;

    在项目配置文件 application.yml 中增加如下配置

    com.alibaba.druid.pool.DruidDataSource
    
    druid datasource
    3. 添加 Mybatis 配置类,以取代默认的 Mybatis 配置,代码如下:
    package com.XXXX.cosmos.configuration;
    
    import com.alibaba.druid.pool.DruidDataSource;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class MyBatisConfig {
        @Autowired
        private DataSourceProperties dataSourceProperties;
    
    
        @Bean()
        @ConfigurationProperties(prefix = "spring.datasource")
        public DruidDataSource dataSource() {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setUrl(dataSourceProperties.getUrl());
            dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
            dataSource.setUsername(dataSourceProperties.getUsername());
            dataSource.setPassword(dataSourceProperties.getPassword());
    
            return dataSource;
    
        }
    
        @Bean
        public SqlSessionFactory sqlSessionFactory() throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource());
            return sqlSessionFactoryBean.getObject();
        }
    }
    
    4. 在程序入口类上添加注解,如:
    package com.XXXX.cosmos;
    
    import org.mybatis.spring.annotation.MapperScan;
    import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.ComponentScan;
    
    @SpringBootApplication(exclude = MybatisAutoConfiguration.class)
    @ComponentScan(basePackages = {"com.XXX"})
    @MapperScan(basePackages = {"com.XXXX.cosmos.dao"})
    public class CosmosBackendApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(CosmosBackendApplication.class, args);
        }
    }
    

    核心是:@SpringBootApplication(exclude = MybatisAutoConfiguration.class),意思是取消 Mybatis 默认配置;

    这几个动作非常关键,因为 Mybatis 目前还不支持 Spring Boot 3,因此需要使用自定义的配置取代默认的 Mybatis。

    Spring Boot 连接数据库的其他文章还有:

    需要请自取~

    2. 跨域配置:allowedOriginPatterns;

    在允许跨域方面,Spring Boot 3 也与之前稍有不同;

    package com.XXXX.cosmos.configuration;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.*;
    
    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowCredentials(true)
                    .allowedHeaders("*")
                    .allowedMethods("*")
                    .allowedOriginPatterns("*")
                    .maxAge(3600);
        }
    }
    

    以前,在 addCorsMappings 方法是这样的:

    @Override
    public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowCredentials(true)
                    .allowedHeaders("*")
                    .allowedMethods("*")
                    .allowedOrigins("*")
                    .maxAge(3600);
        }
    

    眼尖的同学应该会发现,allowedOrigins("") 改为 allowedOriginPatterns("") 了,这也是 Spring Boot 2 到 Spring Boot 3 的一个变化;

    3. domain 与 entity 、dao 概念的理解;

    (按我个人理解与习惯来说)

    • domain 是存放实体类的包,通常存放与数据库无关的实体类,例如我们可以放:汽车类、动物类之类的。

    • entity 也是存放实体类的包,但通常存放的是与数据库相关的实体类,例如 rule 表,对应 Rule 类,在 Rule 类中存放的是与数据库字段相同的字段、类型,例如:

    package com.XXXX.cosmos.entity;
    
    import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
    import lombok.Data;
    
    import java.io.Serial;
    import java.io.Serializable;
    import java.util.Date;
    
    @Data
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class Rule implements Serializable {
        @Serial
        private static final long serialVersionUID = 1L;
    
        private int rule_id;
        private String name;
        private String description;
        private String expression;
        private Integer active;
        private String created_by;
        private String updated_by;
        private Date created_when;
        private Date updated_when;
    }
    
    • dao 是指数据持久层,例如存放 sql,我喜欢这么做:
    package com.XXXX.cosmos.dao;
    
    import com.XXXX.cosmos.entity.Rule;
    import org.apache.ibatis.annotations.*;
    
    import java.util.List;
    
    @Mapper
    public interface RuleDao {
        @Select("select * from rule where active=1 order by rule_id desc")
        @Results(value = {
                @Result(property = "rule_id", column = "RULE_ID"),
                @Result(property = "name", column = "NAME"),
                @Result(property = "description", column = "DESCRIPTION"),
                @Result(property = "expression", column = "EXPRESSION"),
                @Result(property = "active", column = "ACTIVE"),
                @Result(property = "created_by", column = "CREATED_BY"),
                @Result(property = "updated_by", column = "UPDATED_BY"),
                @Result(property = "created_when", column = "CREATED_WHEN"),
                @Result(property = "updated_when", column = "UPDATED_WHEN")
        })
        List<Rule> getActiveRules();
    
        @Select("select * from rule where rule_id = #{rule_id}")
        @Results(value = {
                @Result(property = "rule_id", column = "RULE_ID"),
                @Result(property = "name", column = "NAME"),
                @Result(property = "description", column = "DESCRIPTION"),
                @Result(property = "expression", column = "EXPRESSION"),
                @Result(property = "active", column = "ACTIVE"),
                @Result(property = "created_by", column = "CREATED_BY"),
                @Result(property = "updated_by", column = "UPDATED_BY"),
                @Result(property = "created_when", column = "CREATED_WHEN"),
                @Result(property = "updated_when", column = "UPDATED_WHEN")
        })
        Rule getRuleById(@Param("rule_id") int rule_id);
    
        @Options(useGeneratedKeys = true, keyProperty = "rule.rule_id")
        @Insert("insert into rule (name,description,expression,created_by) values (#{rule.name},#{rule.description},#{rule.expression},#{rule.created_by});")
        void addNewRule(@Param("rule") Rule rule);
    
        @Insert("update rule set active=0,updated_by=#{updated_by},updated_when=CURRENT_TIMESTAMP where rule_id = #{rule_id};")
        void deleteRule(@Param("rule_id") int rule_id, @Param("updated_by") String updated_by);
    
        @Insert("update rule set name=#{rule.name},description=#{rule.description},expression=#{rule.expression},updated_by=#{rule.updated_by},updated_when=CURRENT_TIMESTAMP where rule_id = #{rule.rule_id};")
        void updateRule(@Param("rule") Rule rule);
    }
    

    4. 多环境配置与使用;

    通常,我们会有不同的环境,如开发环境、集成环境、生产环境等,其资源通常是互相隔离的,那么我们又如何在不同环境下使用不同的资源呢?

    这时候就要用到多环境配置了~

    例如(注意文件后缀是 .yml 不是 .yaml):

    多环境配置
    • 生产环境 mysql 配置(application.yml):
    生产环境 mysql 配置
    • dev 环境 mysql 配置(application-dev.yml)
    dev 环境 mysql 配置
    • 如何启动不同环境(使用不同资源);

    例如启动 dev 环境,那么我知道的有几种方式:

    a. 直接启动项目:

    mvn spring-boot:run -Dspring-boot.run.profiles=dev
    

    这种方式一般是本地调试用吧~

    b. 将项目达成 jar 包,启动:

    // 打包
    mvn package
    
    // 启动
    java -jar -Dspring.profiles.active=dev cosmos-backend-0.0.1-SNAPSHOT.jar
    

    这种方式让我能清晰感受到,以前为什么开发老说要打包,为什么说要将包传到服务器,又为什么说又要重启服务;

    注意:-Dspring.profiles.active=dev 要放在 jar 包前~

    5. mysql 插入数据后,返回插入数据的值;

    我们知道,insert 语句是没有返回值的,因此 insert 语句在 dao 层的接口,其返回类型为 void,那么,在某些场景下,我们需要知道插入的数据是什么,以便返回给前端,又该如何做呢?

    Mybatis 提供了一个我认为很棒的方式,如:

    @Options(useGeneratedKeys = true, keyProperty = "rule.rule_id")
        @Insert("insert into rule (name,description,expression,created_by) values (#{rule.name},#{rule.description},#{rule.expression},#{rule.created_by});")
        void addNewRule(@Param("rule") Rule rule);
    

    这样,在数据插入完成后,我们就可以很方便地拿到新插入数据的 id 了:

    返回插入数据的值

    6. 10 位数 timestamp;

    new Date().getTime() / 1000
    

    有时候会遇到 10 位数时间戳,就这么简单~

    目前想到的值得记录有这些,希望对大家有所帮助~

    (我想,下一篇我们可以来记录一下前端部分,因为也挺久没有用前端了,前端框架也在不断进化)。

    如果本文对您有帮助,麻烦点赞、关注!

    谢谢!

    相关文章

      网友评论

          本文标题:Spring Boot 3 遇到的一些变化、知识点

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