狂神 SpringBoot笔记

引用转载https://blog.csdn.net/fanjianhai?spm=1011.2124.3001.5348

1. 微服务阶段

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2. 什么是SpringBoot

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3. 微服务

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4. 第一个springboot项目搭建 springboot-01-helloworld

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5. SpringBoot自动装配原理

在这里插入图片描述

在这里插入图片描述

 

在这里插入图片描述

在这里插入图片描述

5.1. 自动装配原理分析

  • @SpringBootApplication

    • @SpringBootConfiguration

      • @Configuration

        • @Component

    • @EnableAutoConfiguration 自动导入包

      • @AutoConfigurationPackage 将 添加该注解的类所在的package 作为 自动配置package 进行管理

        • @Import({Registrar.class})

      • @Import({AutoConfigurationImportSelector.class}) 自动导入包的核心

        • getAutoConfigurationEntry(annotationMetadata); 获取自动装配的实体

  • getCandidateConfigurations(annotationMetadata, attributes); 获取候选的配置

    • protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; } 标注了EnableAutoConfiguration注解的类

      • public static List loadFactoryNames(): 获取所有的加载配置

  • loadFactories() loadSpringFactories() - 项目资源: classLoader.getResources(FACTORIES_RESOURCE_LOCATION) "META-INF/spring.factories"; 从这里获取配置 spring-boot-autoconfigure-2.2.0.RELEASE.jar META-INF spring.factories;所有的自动配置类都在这里了!(自动配置生效,需要导入对应的start核心注解:@ConditionalOnXXX, 如果这里的条件都满足,才生效!)

    • 系统资源:classLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION) - 从这些资源中遍历了所有的nextElement(自动配置),遍历完成之后,封装成Properties供我们使用

    • @ComponentScan 扫描当前主启动类同级的包

5.2. SpringApplication 启动 run

在这里插入图片描述

5.3. 自动配置原理再理解

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

6. yaml讲解

# k = v
# 对空格要求十分严格
# 普通的 key-value

# 注入到我们的配置类中!

name: xiaofan

# 对象
student:
name: xiaofan
age: 3

# 行内写法
teacher: {name: xiaofan, age: 3}

# 数组
pets:
- cat
- dog
- pig

# 行内写法
animals: [cat, dog, pig]
  • yaml

package com.xiaofan.pojo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
   private String name;
   private int age;
   private boolean happy;
   private Date birth;
   private Map<String, Object> maps;
   private List<Object> lists;
   private Dog dog;

   public Person() {
  }

   public Person(String name, int age, boolean happy, Date birth, Map<String, Object> maps, List<Object> lists, Dog dog) {
       this.name = name;
       this.age = age;
       this.happy = happy;
       this.birth = birth;
       this.maps = maps;
       this.lists = lists;
       this.dog = dog;
  }

   public String getName() {
       return name;
  }

   public void setName(String name) {
       this.name = name;
  }

   public int getAge() {
       return age;
  }

   public void setAge(int age) {
       this.age = age;
  }

   public boolean isHappy() {
       return happy;
  }

   public void setHappy(boolean happy) {
       this.happy = happy;
  }

   public Date getBirth() {
       return birth;
  }

   public void setBirth(Date birth) {
       this.birth = birth;
  }

   public Map<String, Object> getMaps() {
       return maps;
  }

   public void setMaps(Map<String, Object> maps) {
       this.maps = maps;
  }

   public List<Object> getLists() {
       return lists;
  }

   public void setLists(List<Object> lists) {
       this.lists = lists;
  }

   public Dog getDog() {
       return dog;
  }

   public void setDog(Dog dog) {
       this.dog = dog;
  }

   @Override
   public String toString() {
       return "Person{" +
               "name='" + name + '\'' +
               ", age=" + age +
               ", happy=" + happy +
               ", birth=" + birth +
               ", maps=" + maps +
               ", lists=" + lists +
               ", dog=" + dog +
               '}';
  }
}
<!-- 解决有红色提示问题 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-configuration-processor</artifactId>
   <optional>true</optional>
</dependency>
person:
name: xiaofan${random.int}
age: ${random.int}
happy: true
birth: 2021/11/07
hello: 小小的一个
maps: {k1: v1, k2: v2}
lists:
  - code
  - music
  - girl
dog:
  name: ${person.hello1:hello}_旺财
  age: 3
  • properties

# 加载指定的配置文件
@PropertySource(value="classpath:xiaofan.properties")

 

6.1. yaml 和properties的对比

在这里插入图片描述

  • 松散绑定

    @Component
    @ConfigurationProperties(prefix = "person")
    public class Person {
     private String lastName;
person:
last-name: xiaofan${random.int}
  • JSR303 数据校验

在这里插入图片描述

在这里插入图片描述

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

7. 多环境配置及配置文件的位置

  • 配置文件的位置

在这里插入图片描述

在这里插入图片描述

  • 多环境

spring:
profiles:
  active: test

---
server:
port: 8088
spring:
config:
  activate:
    on-profile: dev
---
server:
port: 8089
spring:
config:
  activate:
    on-profile: test

9 Web开发探索

在这里插入图片描述

9.1. 静态资源导入

  • WebMvcAutoConfiguration

    内部类:EnableWebMvcConfiguration (WebProperties)

public void addResourceHandlers(ResourceHandlerRegistry registry) {
   // 是否自定义静态资源路径,自定义之后,默认的将会失效
   if (!this.resourceProperties.isAddMappings()) {
       logger.debug("Default resource handling disabled");
  } else {
       Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
       CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
       // 如果配置了webjars: https://www.webjars.org/ (一般不用)
       if (!registry.hasMappingForPattern("/webjars/**")) {
           this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl).setUseLastModified(this.resourceProperties.getCache().isUseLastModified()));
      }

       // 没有自定义路径,new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
       private String[] staticLocations;
       String staticPathPattern = this.mvcProperties.getStaticPathPattern();
       if (!registry.hasMappingForPattern(staticPathPattern)) {
           this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl).setUseLastModified(this.resourceProperties.getCache().isUseLastModified()));
      }

  }
}

在这里插入图片描述

9.2. 首页

直接把首页放入到static目录即可!

9.3. Thymeleaf模板引擎

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
<!--所有html元素都可以被thymeleaf替换接管: th:元素名-->
<div th:text="${msg}"></div>
<div th:utext="${msg}"></div>
<br>

<h3 th:each="user:${users}" th:text="${user}"></h3>
</body>
</html>
package com.xiaofan.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.Arrays;

@Controller
public class HelloController {

   @GetMapping("/test")
   public String hello(Model model) {
       model.addAttribute("msg", "<h1>hello springboot!</h1>");
       model.addAttribute("users", Arrays.asList("中国", "美国", "日本"));
       return "test";
  }
}

9.4. MVC配置原理

package com.xiaofan.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Locale;

// 扩展springmvc
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {

  @Bean
  public ViewResolver myViewResolver() {
      return new myViewResolver();
  }

  public static class myViewResolver implements ViewResolver {

      @Override
      public View resolveViewName(String s, Locale locale) throws Exception {
          return null;
      }
  }
}

在这里插入图片描述

10. 员工管理系统springboot-04-system

在这里插入图片描述

在这里插入图片描述

11. 如何写一个网站

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

12. Spring Data

  • JDBC

在这里插入图片描述

  • Druid

在这里插入图片描述

spring:
datasource:
  username: root
  password: 123456
   # 如果时区报错了需要添加时区字段 serverTimezone
  url: jdbc:mysql://192.168.1.30:3306/mybatis?useUnicode=true&characterEncoding=utf-8
  driver-class-name: com.mysql.cj.jdbc.Driver
   # 默认是用的是 com.zaxxer.hikari.HikariDataSource
  type: com.alibaba.druid.pool.DruidDataSource

   #Spring Boot 默认是不注入这些属性值的,需要自己绑定
   #druid 数据源专有配置
  initialSize: 5
  minIdle: 5
  maxActive: 20
  maxWait: 60000
  timeBetweenEvictionRunsMillis: 60000
  minEvictableIdleTimeMillis: 300000
  validationQuery: SELECT 1 FROM DUAL
  testWhileIdle: true
  testOnBorrow: false
  testOnReturn: false
  poolPreparedStatements: true

   #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
   #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
   #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j
  filters: stat,wall,log4j
  maxPoolPreparedStatementPerConnectionSize: 20
  useGlobalDataSourceStat: true
  connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
package com.xiaofan.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DruidConfig {

   @ConfigurationProperties(prefix = "spring.datasource")
   @Bean
   public DataSource druidDataSource() {
       return new DruidDataSource();
  }

   @Bean
   public ServletRegistrationBean statViewServlet() {
       ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
       Map<String, String> initParams = new HashMap<>();
       initParams.put("loginUsername", "admin"); //后台管理界面的登录账号
       initParams.put("loginPassword", "123456"); //后台管理界面的登录密码

       //后台允许谁可以访问
       //initParams.put("allow", "localhost"):表示只有本机可以访问
       //initParams.put("allow", ""):为空或者为null时,表示允许所有访问
       initParams.put("allow", "");
       //deny:Druid 后台拒绝谁访问
       //initParams.put("kuangshen", "192.168.1.20");表示禁止此ip访问

       //设置初始化参数
       bean.setInitParameters(initParams);
       return bean;
  }
}

13. 整合mybaits框架

  • pom.xml

<!--mybatis 自研-->
<dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>2.1.4</version>
</dependency>
  • UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
       PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
       "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaofan.mapper.UserMapper">

   <select id="queryUserList" resultType="User">
      select * from user
   </select>

   <select id="queryUserById" resultType="User">
      select * from user where id = #{id}
   </select>

   <insert id="addUser" parameterType="User">
      insert into user (id, name, pwd) values (#{id}, #{name}, #{pwd})
   </insert>

   <update id="updateUser" parameterType="User">
      update user set name = #{name}, pwd = #{pwd} where id = #{id}
   </update>

   <delete id="deleteUser" parameterType="int">
      delete from user where id = #{id}
   </delete>
</mapper>
  • Springboot整合mybatis

# 整合mybatis
mybatis:
type-aliases-package: com.xiaofan.pojo
mapper-locations: classpath:mybatis/mapper/*.xml
  • 编写controller进行测试

package com.xiaofan.controller;

import com.xiaofan.mapper.UserMapper;
import com.xiaofan.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class UserController {

   @Autowired
   UserMapper userMapper;

   @GetMapping("/queryUserList")
   public List<User> queryUserList() {
       List<User> users = userMapper.queryUserList();
       for (User user : users) {
           System.out.println(user);
      }
       return users;
    }
}

14. SpringSecurity

在这里插入图片描述

在这里插入图片描述

14.1. 核心点

  • pom.xml

<!-- 整合 springsecurity thymeleaf -->
<dependency>
   <groupId>org.thymeleaf.extras</groupId>
   <artifactId>thymeleaf-extras-springsecurity5</artifactId>
   <version>3.0.4.RELEASE</version>
</dependency>
  • SecurityConfig.java

package com.xiaofan.config;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

// AOP: 拦截器!
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

   // 授权
   @Override
   protected void configure(HttpSecurity http) throws Exception {
       // 首页所有人可以访问, 功能页只有对应权限的人才能访问
       // 请求授权规则
       http.authorizeRequests()
              .antMatchers("/").permitAll()
              .antMatchers("/level1/**").hasRole("vip1")
              .antMatchers("/level2/**").hasRole("vip2")
              .antMatchers("/level3/**").hasRole("vip3");

       // 没有权限,默认会到登录页面, 定制login页面 注意这里的链接和login.html表单中的做成一直就可以
       http.formLogin().loginPage("/toLogin");
       // 开启了注销功能

       http.csrf().disable();  // 防止跨域攻击csrf springsecurity5不加也没报错
       http.logout().logoutSuccessUrl("/");

       // 开启记住我功能, 默认两周时间, 自定义接收前端的参数
       http.rememberMe().rememberMeParameter("remember");
  }

   // 认证, springboot 2.1.x 可以直接使用
   // 密码编码: PasswordEncoder
   // 在Spring Security 5.0 + 增加了很多加密的方法
   @Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
              .withUser("xiaofan").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2")
              .and()
              .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2", "vip3")
              .and()
              .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
  }
}
  • index.html页面重点

<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<div sec:authorize="!isAuthenticated()">
                   <!--未登录-->
                   <a class="item" th:href="@{/toLogin}">
                       <i class="address card icon"></i> 登录
                   </a>
               </div>

               <div sec:authorize="isAuthenticated()">
                   <a class="item">
                      用户名:<span sec:authentication="name"></span>
                      角 色:<span sec:authentication="principal.authorities"></span>
                   </a>
               </div>

               <div sec:authorize="isAuthenticated()">
                   <!--如果登录,用户名,注销-->
                   <a class="item" th:href="@{/logout}">
                       <i class="sign-out icon"></i> 注销
                   </a>
               </div>
package com.xiaofan.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Controller
public class RouteController {

  @GetMapping({"/", "/index"})
  public String index() {
      return "index";
  }

  @GetMapping("/toLogin")
  public String toLogin() {
      return "views/login";
  }

  @GetMapping("/level{suffix}/{id}")
  public String level(@PathVariable("suffix") Integer suffix, @PathVariable("id") Integer id) {
      return "views/level" + suffix + "/" + id;
  }

}

15. Shiro

在这里插入图片描述

在这里插入图片描述

  • 三大对象在这里插入图片描述

    • Subject: 用户

    • SecurityManager: 管理所有用户

    • Realm: 连接数据

springboot-08-shiro下面包含了多个module

16. Swagger

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

16.1. springboot集成swagger

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

16.2. 配置Swagger

16.3. 配置Swagger接口扫描及开关

16.4. 配置多个分组

  • application.yaml

spring:
profiles:
  active: dev

---
server:
port: 8080
spring:
config:
  activate:
    on-profile: dev
---
server:
port: 8080
spring:
config:
  activate:
    on-profile: test
---
server:
port: 8080
spring:
config:
  activate:
    on-profile: prod
  • SwaggerConfig.java

package com.xiaofan.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;

@Configuration
@EnableSwagger2
public class SwaggerConfig {

   @Bean
   public Docket docket1() {
       return new Docket(DocumentationType.SWAGGER_2).groupName("A");
  }

   @Bean
   public Docket docket2() {
       return new Docket(DocumentationType.SWAGGER_2).groupName("B");
  }

   @Bean
   public Docket docket3() {
       return new Docket(DocumentationType.SWAGGER_2).groupName("C");
  }


   @Bean
   public Docket docket(Environment environment) {
       // 设置要显示swagger环境
       Profiles profiles = Profiles.of("dev", "test");
       // 判断是否处在在自己设定的环境当中
       boolean flag = environment.acceptsProfiles(profiles);


       return new Docket(DocumentationType.SWAGGER_2)
              .apiInfo(apiInfo())
              .enable(flag)      // 是否启动swagger
              .groupName("雪山飞狐")
              .select()
               /**
                * 配置要扫描的接口的方式 RequestHandlerSelectors
                * basePackage:指定要扫描的包
                * any(): 扫描全部
                * none():不扫描
                * withClassAnnotation(RestController.class): 扫描类上有RestController.class的注解
                * withMethodAnnotation(GetMapping.class):   扫描方法上的注解
                */
              .apis(RequestHandlerSelectors.basePackage("com.xiaofan.controller"))
               // 过滤请求路径
              .paths(PathSelectors.ant("/xiaofan/**"))
              .build();
  }

   private ApiInfo apiInfo() {
       // 作者信息
       Contact contact = new Contact("雪山飞狐", "https://blog.csdn.net/fanjianhai", "594042358@qq.com");

       return new ApiInfo(
               "小范的SwaggerAPI文档",
               "即使再小的帆也能远航",
               "v1.0",
               "https://github.com/fanjianhai/kuangshen",
               contact,
               "Apache 2.0",
               "http://www.apache.org/licenses/LICENSE-2.0",
               new ArrayList<>()
      );
  }

}
  • HelloController.java

package com.xiaofan.controller;

import com.xiaofan.pojo.User;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.web.bind.annotation.*;

@RestController
public class HelloController {

   @ApiOperation("hello测试")
   @GetMapping("/xiaofan/hello")
   public String hello() {
       return "hello swagger!";
  }


   /**
    * 只要我们的接口中,返回值中存在实体类,它就会被扫描的swagger中
    */
   @PostMapping("/xiaofan/user")
   public User user() {
       return new User("东邪", "黄药师");
  }


   @ApiOperation("登录接口")
   @PostMapping("/xiaofan/login")
   public String login(@ApiParam("用户名") String username, @ApiParam("用户密码") String password) {
       return "login succeed!";
  }

   @ApiOperation("测试前端传递json接口")
   @PostMapping(value="/xiaofan/jsontest")
   public String jsonTest(@ApiParam("json传参") @RequestBody String json){
       System.out.println(json);
       return json;

  }
}

16.5. swagger2常用注解说明

常用注解: - @Api()用于类; 表示标识这个类是swagger的资源 - @ApiOperation()用于方法; 表示一个http请求的操作 - @ApiParam()用于方法,参数,字段说明; 表示对参数的添加元数据(说明或是否必填等) - @ApiModel()用于类 表示对类进行说明,用于参数用实体类接收 - @ApiModelProperty()用于方法,字段 表示对model属性的说明或者数据操作更改 - @ApiIgnore()用于类,方法,方法参数 表示这个方法或者类被忽略 - @ApiImplicitParam() 用于方法 表示单独的请求参数 - @ApiImplicitParams() 用于方法,包含多个 @ApiImplicitParam

https://blog.csdn.net/u014231523/article/details/76522486?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

 

16.6. 总结

在这里插入图片描述

17. 任务

17.1. 异步任务

  • @EnableAsync
    @SpringBootApplication
    public class Springboot10TaskApplication {
    @Async // 告诉spring这是一个异步方法
    public String hello() {
       try {
           Thread.sleep(3000);
      } catch (InterruptedException e) {
           e.printStackTrace();
      }
       System.out.println("执行完毕...");
       return "hello async";
    }

     

17.2. 邮件任务以qq邮箱为例

  • maven坐标

<!--底层导入的本质还是javax.mail 配置-->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
  • yaml配置

spring:
mail:
  username: 594042358@qq.com
  password: qrfrhtepnixxbeje
  host: smtp.qq.com
   # qq 邮箱需要开启这个
  properties: {"mail.smtp.ssl.enable": "true"}
  • 测试类

package com.xiaofan;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMailMessage;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;

@SpringBootTest
class Springboot10TaskApplicationTests {
   
   @Autowired
   JavaMailSenderImpl mailSender;

   @Test
   void contextLoads() {
       SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
       simpleMailMessage.setSubject("文飞扬你好呀~");
       simpleMailMessage.setText("你这家伙又在玩游戏了??");
       simpleMailMessage.setTo("594042358@qq.com");
       simpleMailMessage.setFrom("594042358@qq.com");
       mailSender.send(simpleMailMessage);
  }

   @Test
   void contextLoads2() throws MessagingException {
       // 一个复杂的邮件~
       MimeMessage mimeMessage = mailSender.createMimeMessage();
       // 组装
       MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);

       // 正文
       helper.setSubject("雪山飞狐你好呀~plus");
       helper.setText("<p style='color:red'>你这家伙又在玩游戏了??</p>", true);

       // 添加附件
       helper.addAttachment("abc.jpg", new File("C:\\Users\\59404\\Pictures\\images\\jar\\abc.jpg"));

       helper.setTo("594042358@qq.com");
       helper.setFrom("594042358@qq.com");


       mailSender.send(mimeMessage);
  }

}

 

17.3. 定时执行任务

  • 任务调度者:TaskScheduler

  • 任务执行者:TaskExecutor

  • 开启定时注解的功能:@EnableScheduling

package com.xiaofan.service;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class ScheduledService {

   // 每隔3秒钟执行一次
   @Scheduled(cron = "0/3 * * * * ?")
   public void hello() {
       System.out.println("hello, 你被执行了~");
  }
}

18.SpringBoot整合redis

https://github.com/fanjianhai/kuangshen/tree/master/7.redis%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0

19. 分布式 Dubbo + Zookeeper

19.1. 分布式

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

19.2. RPC

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

RPC两个核心模块:通讯,序列化

 

19.3. Dubbo

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

 

  • 安装zookeeper(3.4.3)

  • 安装Dubbo

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

19.4. 服务发现

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Dubbo + Zookeeper 还得深入研究,这里只是简单的测试!

19.5. Dubbo+Zookeeper vs Spring Cloud 之间的比较

总的来说这两个搭建分布式系统的框架各有各的好处,在选择时要根据自己的需求等情况综合做选择; 但是Eureka作为单纯的服务注册中心来说感觉要比Zookeeper更加“专业”,因为注册服务更重要的是高可用性,可以接受短期内,达不到一致性的状况

20.回顾

在这里插入图片描述

 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210118191309671.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ZhbmppYW5oYWk=,size_16,color_FFFFFF,t_70)

在这里插入图片描述

在这里插入图片描述

 

posted @   codeSpiderMan  阅读(667)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示