Spring Boot 框架基础

Spring Boot 框架基础

基础案例

pom.xml

<parent>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-parentartifactId>
    <version>2.6.4version>
    <relativePath/> 
parent>

web环境依赖

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>

controller

@RestController
@RequestMapping("/demo")
public class DemoController {
    @RequestMapping("/handle01")
    public String handle01() {
        return "你好 springboot";
    }
}

测试

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-testartifactId>
    <scope>testscope>
dependency>
@Autowired
private DemoController demoController;

@Test
void contextLoads() {
    System.out.println(demoController.handle01());
}

热部署

pom.xml


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-devtoolsartifactId>
dependency>

使用IDEA工具热部署支持:

  1. File => Settings => Build, Execution, Deployment => Compiler => 勾选 Build project automatically
  2. “Ctrl+Shift+Alt+/” 组合键打开 Registry 面板 => 勾选 compiler.automake.allow.when.app.running

热部署原理:

​ 在编译器上启动项目,改动代码,编译器会自动触发编译,替换掉原来的 class 文件,项目检测到有文件变更后会重启项目。

​ 当引入插件后,插件会监控 classpath 下文件的变化,当 classpath 有变化后,会触发重启。

​ 快速重启的原因:对类采用了两种加载机制,对于第三方的 jar 包采用 base-classloader 来加载,对于开发人员自己开发的代码使用 restart-classLoader 来加载,这里比停掉服务重启快得多,因为使用插件只重启开发人员编写的代码部分。

@Component
public class Devtools implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
        // 在添加了 devtools 插件
        // 第三方 jar 包 使用 base-classloader 来加载
        // 自己开发的代码 使用 restart-classLoader 来加载

        // org.springframework.boot.devtools.restart.classloader.RestartClassLoader@472075a1
        System.out.println(Devtools.class.getClassLoader());

        // jdk.internal.loader.ClassLoaders$AppClassLoader@e73f9ac
        System.out.println(DispatcherServlet.class.getClassLoader());
    }
}

配置文件中属性注入

@Value

@Component
@Data
public class JdbcConfiguration {
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.driverClassName}")
    private String driverClassName;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;
}

配置文件

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/bank
jdbc.username=root
jdbc.password=123

测试

@Autowired
private JdbcConfiguration jdbcConfiguration;

@Test
void JdbcValueConfigTest() {
    System.out.println(jdbcConfiguration);
}

结果

JdbcConfiguration(url=jdbc:mysql://127.0.0.1:3306/bank, driverClassName=com.mysql.jdbc.Driver, username=root, password=123)

@ConfigurationProperties

pom.xml


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-configuration-processorartifactId>
    <optional>trueoptional>
dependency>

定义需要被注入属性的实体类

@Component
@ConfigurationProperties(prefix = "person")
@Data
public class Person {
    private int id;
    private String name;
    private List<String> hobbies1;
    private List<String> hobbies2;
    private String[] family;
    private Map<String, Object> map1;
    private Map<String, Object> map2;
    private Pet pet;
}

@Component
@Data
public class Pet {
    private String name;
    private String type;
}

配置文件

application.properties

# 自定义属性注入到对应的实体中
person.id=1
person.name=应巅
person.hobbies1=吃饭,睡觉,打豆豆
person.hobbies2=睡觉,睡觉,睡觉
person.family=爸爸,妈妈,爷爷,奶奶
person.map1.extra1=1额外的信息1
person.map1.extra2=1额外的信息2
person.map2.extra1=2额外的信息1
person.map2.extra2=2额外的信息2
person.pet.type=猫
person.pet.name=旺财

application.yml

person:
  id: 2
  family: [爸爸,妈妈,爷爷,奶奶]
  name: 应巅
  hobbies1:
    睡觉,
    睡觉,
    睡觉
  hobbies2:
    - 吃饭
    - 睡觉
    - 打豆豆
  map1:
    extra1: 1额外的信息1
    extra2: 1额外的信息2
  map2: {extra1: 2额外的信息2, extra2: 2额外的信息2}
  pet:
    type:name: 旺财

测试

@Autowired
private Person person;

@Test
void personConfigTest() {
    System.out.println(person);
}

结果

Person(id=1, name=应巅, hobbies1=[吃饭, 睡觉, 打豆豆], hobbies2=[睡觉, 睡觉, 睡觉], family=[爸爸, 妈妈, 爷爷, 奶奶], map1={extra1=1额外的信息1, extra2=1额外的信息2}, map2={extra1=2额外的信息1, extra2=2额外的信息2}, pet=Pet(name=旺财, type=猫))

日志框架

日志抽象层 日志实现层
JCL、SLF4J、jboos-logging jul、log4j、log4j2、logback

springboot 默认使用 SLF4J 为日志抽象层,logback 为日志实现层。

日志使用

private Logger logger = LoggerFactory.getLogger(SpringBootDemoApplicationTests.class);

@Test
void logTest() {
    // 日志级别:trace < debug < info < warn < error
    // 日志默认使用:SLF4j + LogBack
    // spring boot 默认日志级别 为Info
    logger.trace("Trace 日志...");
    logger.debug("Debug 日志...");
    logger.info("Info 日志...");
    logger.warn("Warn 日志...");
    logger.error("Error 日志...");
}

配置文件

# 调整某个包下面的日志级别
logging.level.com.demo=trace
# 日志的输出格式
# 控制台
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
# 文件
logging.pattern.file=%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
# 文件路径 默认的日志文件名 spring.log
#logging.file.path=springLog
# 写入具体的文件
logging.file.name=log/log.log

缓存

pom.xml

<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <scope>runtimescope>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-jpaartifactId>
dependency>

application.properties

spring.datasource.url=jdbc:mysql:///bank?
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.show-sql=true
@Data
@Entity
@Table(name = "employee")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    @Column(name = "last_name")
    private String lastName;
    @Column(name = "email")
    private String email;
    @Column(name = "gender")
    private Integer gender; //性别 1男 0女
    @Column(name = "d_id")
    private Integer dId;
}

// JPA实现简单CRUD
public interface EmployeeDao extends JpaRepository<Employee, Integer> {}
@SpringBootApplication
@EnableCaching //开启基于注解的缓存
public class SpringBootDemoApplication {

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

添加缓存

@GetMapping("/emp/{id}")
// 添加缓存 cacheNames:缓存的名字 = value;
// key:默认参数的值 次数为id的值1;可以使用 SpEL 表达式
@Cacheable(cacheNames = {"emp"})
public Employee getEmp(@PathVariable("id") Integer id) {
    return employeeDao.findById(id).get();
}

更新缓存

 @GetMapping("/emp/update")
// 更新缓存
@CachePut(value = "emp", key = "#employee.id")
public Employee updateEmp(Employee employee) {
    employeeDao.save(employee);
    return employee;
}

删除缓存

@DeleteMapping("/emp/{id}")
// 删除缓存
// beforeInvocation:默认为 false,译为在方法调用之后删除缓存;设置为 true,译为在方法调用之前删除缓存
// 若方法出现异常,在方法调用之后清除缓存将不起作用。
@CacheEvict(value = "emp", key = "#id", beforeInvocation = true)
public void delEmp(@PathVariable("id") Integer id) {
    employeeDao.deleteById(id);
}

SpEL 表达式

@GetMapping("/SpELDemo/{id}")
@Cacheable(cacheNames = {"emp"}, key = "#root.method")
public Employee SpELDemo(@PathVariable("id") Integer id) {
    return employeeDao.findById(id).get();
}
SpEL 表达式 描述
#root.methodName 方法的名称 SpELDemo
#root.method 方法 public com.demo.pojo.Employee com.demo.controller.DemoController.SpELDemo(java.lang.Integer)
#root.args[0] 当前被调用的方法的参数列表 {id}的值
#iban、#a0、#p0 方法参数的名字,可以直接 #参数名,也可以使用 #p0 或 #a0 的形式,0 代表参数的索引 {id}的值
#result 方法执行后的返回值

基于redis 实现缓存

pom.xml

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>
spring.redis.database=1
spring.redis.host=127.0.0.1

需要实现 Serializable 接口

public class Employee implements Serializable {}

SpringBoot默认采用的是JDK的对象序列化方式。

自定义RedisCacheManager

使用 JSON 格式进行对象的序列化操作。

@Configuration
public class RedisConfig {

    // 自定义一个RedisTemplate
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        //设置redisTemplate模板API的序列化方式为json
        template.setDefaultSerializer(getJackson2JsonRedisSerializer());
        return template;
    }

    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        // 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
        RedisSerializer<String> strSerializer = new StringRedisSerializer();
        // 定制缓存数据序列化方式及时效
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofDays(1))
                .serializeKeysWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(strSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair
                        .fromSerializer(getJackson2JsonRedisSerializer()))
                .disableCachingNullValues();
        return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
    }

    private Jackson2JsonRedisSerializer<Object> getJackson2JsonRedisSerializer() {
        // 创建JSON格式序列化对象,对缓存数据的key和value进行转换
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        // 解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        return jackson2JsonRedisSerializer;
    }
}

打包部署

pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-maven-pluginartifactId>
        plugin>
    plugins>
build>

运行:

java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar

多环境部署

两种方式:

1、@Profile 注解:可以使用在 @Component 或 @Configuration 注解的类上,指定一个字符串值用于约定生效的环境。

@Configuration
// 字符串需要和 激活的参数一致
@Profile("dev")
public class DataSourceConfig {
    private String name="devName";
    private String config="devConfig";
}

2、创建 application-dev.properties 配置文件。-dev 需要和 激活的参数一致

@Component
@Data
public class Sound {
    @Value("${sound.name}")
    String name;

    @Value("${sound.location}")
    String location;
}
# application-dev.properties
sound.name=devName
sound.location=devLocation

application.properties 中配置文件激活:spring.profiles.active=dev

如果不添加在打包的时候使用命令:

java -jar spring-boot-demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev

测试:此时使用的配置文件是 application-dev.properties。注入的类是 @Profile(“dev”) 修饰过的。

@Autowired
private Sound sound;

@Test
void devConfig() {
    System.out.println(sound);
}

@Autowired
private DataSourceConfig dataSourceConfig;

@Test
void devDataSourceConfig() {
    System.out.println(dataSourceConfig);
}

参考git:https://gitee.com/zhangyizhou/learning-spring-boot-demo.git

你可能感兴趣的:(java,后端,spring,boot)