SpringBoot


springboot学习笔记

1、整合数据库

  • 数据库连接的配置

    spring:
      datasource:
        username: root
        password: root
        url: jdbc:mysql://localhost:3306/mybatis?useUnicode=ture&characterEncoding=utf-8&serverTimezone=UTC
        driver-class-name: com.mysql.jdbc.Driver
    
  • 整合druid

    • 导入依赖

      
      
          log4j
          log4j
          1.2.17
      
      
      
          com.alibaba
          druid
          1.1.22
      
      
    • 自定义数据源

      #自定义数据源
      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
      
    • 配置druid连接池后台管理

      @Configuration
      public class DruidConfig {
      
          @ConfigurationProperties(prefix = "spring.datasource")
          @Bean
          public DataSource druidDataSource(){
              return new DruidDataSource();
          }
      
          //配置后台监控
          @Bean
          public ServletRegistrationBean statViewServlet(){
      
              ServletRegistrationBean bean = new ServletRegistrationBean<>(new StatViewServlet(),"/druid/*");
      
              //存储后台设置参数的map集合
              Map initParams = new HashMap<>();
              initParams.put("loginUsername","admin");    //后台管理的账号
              initParams.put("loginPassword","123456");   //后台管理的密码
      
              //设置初始化参数
              bean.setInitParameters(initParams);
      
              return bean;
          }
      }
      
  • 整合mybatis

    • 导入springboot整合mybatis的启动类依赖

      
           org.mybatis.spring.boot
           mybatis-spring-boot-starter
           2.1.3
      
      
    • 整合mybatis的yml配置

      mybatis:
        mapper-locations: classpath:mapper/*.xml            #配置映射mapper文件路径
      #  config-location: classpath:mybatis-config.xml       #配置mybatis核心配置文件位置 不能和驼峰命名一起配置
        configuration:
          map-underscore-to-camel-case: true                #开启mybatis实体类属性驼峰命名
        type-aliases-package: com.wt.springbootdata.model   #指定实体类的包,起别名
      
    • mapper映射文件头配置信息

      <?xml version="1.0" encoding="UTF-8" ?>
      
      
          
      
      
    • dao层交给spring管理

      • 方案一:在mapper接口文件上加@mapper和@Component注解

      • 方案二:在mapper接口文件上加@mapper注解

        ? 在springboot启动类上加@MapperScan(basePackages = {"mapper接口所在的包"})


2、整合SpringSecurity

  • 简介 :Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。也是SpringBoot底层安全模块的默认技术选型。

  • 使用:

    • 导入Security坐标依赖

      
          org.springframework.boot
          spring-boot-starter-security  
      
      
    • 编写Security配置类,继承WebSecurityConfigurerAdapter类,并加上@EnableWebSecurity注解

      @EnableWebSecurity
      public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
          /**
           * 重写configure方法,进行权限授权
           * @param http
           * @throws Exception
           */
          @Override
          protected void configure(HttpSecurity http) throws Exception {
      
              //添加不同的权限
              http.authorizeRequests()
                      //首页所有人都能访问
                      .antMatchers("/").permitAll()
                      //等级1路径下,只有vip1用户才能访问
                      .antMatchers("/level1/**").hasRole("vip1")
                      //等级1路径下,只有vip2用户才能访问
                      .antMatchers("/level2/**").hasRole("vip2")
                      //等级1路径下,只有vip3用户才能访问
                      .antMatchers("/level3/**").hasRole("vip3");
      
              //没有权限默认会跳转登录页面
              http.formLogin();
      
              //关闭csrf功能,正常注销
              http.csrf().disable();
              //开启注销功能,注销成功跳转首页
              http.logout().logoutSuccessUrl("/");
      
          }
      
          /**
           * 权限认证
           * 密码要进行编译 new BCryptPasswordEncoder()
           * 用户信息默认应该从数据库中获取
           * @param auth
           * @throws Exception
           */
          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
              auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                      .withUser("test").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2")
                      .and()
                      .withUser("wt").password(new BCryptPasswordEncoder().encode("123")).roles("vip3");
          }
      }
      
    • 前端页面结合thymeleaf模板,实现授权和认证:

      1.导入thymeleaf模板依赖和thymeleaf和security整合的依赖

      
      
          org.thymeleaf.extras
          thymeleaf-extras-springsecurity4
          3.0.2.RELEASE
      
      
      
      
          org.springframework.boot
          spring-boot-starter-thymeleaf
      
      

      2.补全约束

      
      

      3.判断用户是否登录

      sec:authorize="isAuthenticated()":判断用户是否登录,如果登录,则显示div的内容

      sec:authentication="name":获取登录的用户名

      sec:authentication="principal.authorities":获取当前登录用户,所具有的角色信息

      
      
      
      
      
      
      

      4.根据当前用户所具有的角色,自动显示或隐藏内容

      sec:authorize="hasRole('vip1')":如果当前用户,具有vip1角色信息,就显示该内容

      
      

      5.自定义登录页面

      loginPage("/toLogin"):跳转登录页面路径

      loginProcessingUrl("/login"):登录表单的请求提交路径

      usernameParameter("username"):页面用户名的参数名称,默认为username

      passwordParameter("password"):页面密码的参数名称,默认为password

      http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login").usernameParameter("username").passwordParameter("password");
      

      6.记住登录角色功能

      rememberMeParameter("remember"):记住我按钮的参数名称

      记住密码
      
      //开启记住我功能 cookie默认保存两周
      http.rememberMe().rememberMeParameter("remember");
      

3、shiro

3.1 Shiro快速入门

  • 简介:Shiro是Apache旗下的一个Java安全权限管理框架。既可以作用在JavaSE环境,也可以在JavaEE环境中使用。Shiro可以完成认证,授权,加密,会话管理,Web集成,缓存等。

  • 官网:http://shiro.apache.org/

  • 快速入门

    • 导入Maven依赖

      
          
              org.apache.shiro
              shiro-core
              1.4.1
          
      
          
          
              org.slf4j
              jcl-over-slf4j
              1.7.21
          
          
              org.slf4j
              slf4j-log4j12
              1.7.21
          
          
              log4j
              log4j
              1.2.17
          
      
      
    • 创建log4j.properties

      log4j.rootLogger=INFO, stdout
      
      log4j.appender.stdout=org.apache.log4j.ConsoleAppender
      log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
      log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
      
      # General Apache libraries
      log4j.logger.org.apache=WARN
      
      # Spring
      log4j.logger.org.springframework=WARN
      
      # Default Shiro logging
      log4j.logger.org.apache.shiro=INFO
      
      # Disable verbose logging
      log4j.logger.org.apache.shiro.util.ThreadContext=WARN
      log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
      
    • 创建shiro.ini

      [users]
      # user 'root' with password 'secret' and the 'admin' role
      root = secret, admin
      # user 'guest' with the password 'guest' and the 'guest' role
      guest = guest, guest
      # user 'presidentskroob' with password '12345' ("That's the same combination on
      # my luggage!!!" ;)), and role 'president'
      presidentskroob = 12345, president
      # user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
      darkhelmet = ludicrousspeed, darklord, schwartz
      # user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
      lonestarr = vespa, goodguy, schwartz
      
      # -----------------------------------------------------------------------------
      # Roles with assigned permissions
      #
      # Each line conforms to the format defined in the
      # org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
      # -----------------------------------------------------------------------------
      [roles]
      # 'admin' role has all permissions, indicated by the wildcard '*'
      admin = *
      # The 'schwartz' role can do anything (*) with any lightsaber:
      schwartz = lightsaber:*
      # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
      # license plate 'eagle5' (instance specific id)
      goodguy = winnebago:drive:eagle5
      
    • 新建Quickstart文件

      import org.apache.shiro.SecurityUtils;
      import org.apache.shiro.authc.*;
      import org.apache.shiro.config.IniSecurityManagerFactory;
      import org.apache.shiro.mgt.SecurityManager;
      import org.apache.shiro.session.Session;
      import org.apache.shiro.subject.Subject;
      import org.apache.shiro.util.Factory;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      
      public class Quickstart {
      
          private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
      
          public static void main(String[] args) {
      
              Factory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
              SecurityManager securityManager = factory.getInstance();
              SecurityUtils.setSecurityManager(securityManager);
      
              // 获取当前的用户对象Subject
              Subject currentUser = SecurityUtils.getSubject();
      
              // 获取当前用户的Session对象 存值取值
              Session session = currentUser.getSession();
              session.setAttribute("someKey", "aValue");
              String value = (String) session.getAttribute("someKey");
              if (value.equals("aValue")) {
                  log.info("Retrieved the correct value! [" + value + "]");
              }
      
              // 判断当前用户是否被认证
              if (!currentUser.isAuthenticated()) {
                  //通过用户名和密码生成token 令牌。
                  UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
                  //设置记住我
                  token.setRememberMe(true);
                  try {
                      //执行登录操作
                      currentUser.login(token);
                  } catch (UnknownAccountException uae) {
                      //用户名错误异常
                      log.info("There is no user with username of " + token.getPrincipal());
                  } catch (IncorrectCredentialsException ice) {
                      //密码错误异常
                      log.info("Password for account " + token.getPrincipal() + " was incorrect!");
                  } catch (LockedAccountException lae) {
                      //账户被锁定异常
                      log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                              "Please contact your administrator to unlock it.");
                  }
                  // ... catch more exceptions here (maybe custom ones specific to your application?
                  catch (AuthenticationException ae) {
                      //认证异常
                      //unexpected condition?  error?
                  }
              }
      
              //say who they are:
              //print their identifying principal (in this case, a username):
              log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");
      
              //test a role:
              //判断角色信息
              if (currentUser.hasRole("schwartz")) {
                  log.info("May the Schwartz be with you!");
              } else {
                  log.info("Hello, mere mortal.");
              }
      
              //test a typed permission (not instance-level)
              //判断权限信息
              if (currentUser.isPermitted("lightsaber:wield")) {
                  log.info("You may use a lightsaber ring.  Use it wisely.");
              } else {
                  log.info("Sorry, lightsaber rings are for schwartz masters only.");
              }
      
              //a (very powerful) Instance Level permission:
              if (currentUser.isPermitted("winnebago:drive:eagle5")) {
                  log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                          "Here are the keys - have fun!");
              } else {
                  log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
              }
      
              //注销
              currentUser.logout();
              //关闭系统
              System.exit(0);
          }
      }
      

3.2 SpringBoot整合Shiro

  • shiro三大对象

    • Subject:当前操作用户。
    • SecurityManager:Shiro框架的核心,并通过它进行安全管理。
    • Realm:Shiro与应用安全数据间的“桥梁”或者“连接器”。
  • 环境搭建

    • 导入shiro相关的依赖

      
              
                  com.github.theborakompanioni
                  thymeleaf-extras-shiro
                  2.0.0
              
      
              
              
                  org.mybatis.spring.boot
                  mybatis-spring-boot-starter
                  2.1.3
              
            
              
                mysql
                  mysql-connector-java
                  runtime
              
              
                  org.springframework.boot
                  spring-boot-starter-jdbc
              
              
              
                  com.alibaba
                  druid
                  1.1.22
              
              
              
                  org.apache.shiro
                  shiro-spring
                  1.6.0
              
              
              
                  org.springframework.boot
                  spring-boot-starter-thymeleaf
              
      
    • 编写自定义的认证授权配置类:UserRealm

      package com.wt.shirospringboot.config;
      
      import com.wt.shirospringboot.model.User;
      import com.wt.shirospringboot.service.serviceImpl.UserServiceImpl;
      import org.apache.shiro.SecurityUtils;
      import org.apache.shiro.authc.*;
      import org.apache.shiro.authz.AuthorizationInfo;
      import org.apache.shiro.authz.SimpleAuthorizationInfo;
      import org.apache.shiro.realm.AuthorizingRealm;
      import org.apache.shiro.session.Session;
      

    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.subject.Subject;

    import javax.annotation.Resource;

    /**

    • 自定义UserRealm
      */
      public class UserRealm extends AuthorizingRealm {

      @Resource
      private UserServiceImpl userService;

      /**

      • 授权

      • @param principalCollection

      • @return
        */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //获取当前用户对象
        Subject subject = SecurityUtils.getSubject();
        User currentUser = (User) subject.getPrincipal();

        //授权,将数据库中存储的用户权限,并进行授权
        info.addStringPermission(currentUser.getPerms());
        return info;
        }

      /**

      • 认证

      • @param authenticationToken

      • @return

      • @throws AuthenticationException
        */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //连接数据库,获取用户信息
        User user = userService.queryUserByName(token.getUsername());

        if (user == null){
        //返回null之后,自动抛出UnknownAccountException异常
        return null;
        }

        //将用户信息存储到Session中
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        session.setAttribute("user",user);

        //密码。shiro自动认证,密码做了加密
        return new SimpleAuthenticationInfo(user,user.getPassword(),"");
        }
        }

    
    - 编写Shiro配置文件ShiroConfig
    
    ```Java
    package com.wt.shirospringboot.config;
    
    import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
    import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
    import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    @Configuration
    public class ShiroConfig {
    
    
        @Bean
        public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
            //设置安全管理器
            factoryBean.setSecurityManager(securityManager);
    
            //添加shiro的内置过滤器
            /*
                anon:无需认证就可以访问
                authc:必须认证了才可以访问资源
                user:必须选择了记住我功能才能访问
                perms:必须对某个资源有权限才能访问
                role:拥有某个角色的权限才能访问
             */
    
            Map filterMap = new LinkedHashMap<>();
            //授权    /user/add路径下必须有user:add权限才能访问,写在authc权限设置后,不生效
            filterMap.put("/user/add","perms[user:add]");
            filterMap.put("/user/update","perms[user:update]");
            //设置user/下的所有路径,都必须认证了才能访问
            filterMap.put("/user/*","authc");
            factoryBean.setFilterChainDefinitionMap(filterMap);
    
            //设置登录页面
            factoryBean.setLoginUrl("/toLogin");
            //设置没有权限跳转的页面
            factoryBean.setUnauthorizedUrl("/unauthorized");
    
            return factoryBean;
        }
    
    
        /**
         * 创建shiro安全管理类
         * @param userRealm
         * @return
         */
        @Bean(name = "securityManager")
        public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
    
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            //关联UserRealm
            securityManager.setRealm(userRealm);
            return securityManager;
        }
    
        /**
         * 创建realm对象
         * @return
         */
        @Bean
        public UserRealm userRealm(){
            return new UserRealm();
        }
    
        /**
         * 用来整合Shiro和thymeleaf
         * @return
         */
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
    }
    
    
    • 登录之后,进行权限判断

      @RequestMapping("/login")
      public String login(String username,String password,Model model){
          //获取当前用户
          Subject subject = SecurityUtils.getSubject();
          //封装登录数据
          UsernamePasswordToken token = new UsernamePasswordToken(username, password);
      
          try {
              //执行登录方法,不报异常就是通过认证
              subject.login(token);
              return "index";
          }catch (UnknownAccountException e){
              model.addAttribute("msg","用户名错误");
              return "login";
          }catch (IncorrectCredentialsException e){
              model.addAttribute("msg","密码错误");
              return "login";
          }
      }
      
    • 前端页面shiro与thymeleaf整合

      
      
      
      
          
          Title
      
      
      

      首页


      add

4、集成Swagger

4.1 简介

  • 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。
  • 总体目标是使客户端和文件系统作为服务器以同样的速度来更新。

4.2 SpringBoot集成swagger

  • 导入swagger依赖 swagger2+swagger-ui

    
    
        io.springfox
        springfox-swagger2
        2.9.2
    
    
    
    
        io.springfox
        springfox-swagger-ui
        2.9.2
    
    
  • 编写swagger配置类

    package com.wt.swagger.config;
    
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig {
        
    }
    
  • swagger接口测试页面地址:http://localhost:8080/swagger-ui.html

4.3 配置swagger

  • 通过注册Docket实例,对swagger进行配置。 通过配置多个Docket进行多个分组设置

  • 方法:

    • .apiInfo()	//swagger页面信息配置
      
    • //组合使用
      .select()
      .apis(RequestHandlerSelectors.basePackage("com.wt.swagger.controller"))	//指定swagger要扫描的接口
      .paths(PathSelectors.ant("/wt/**"))		//指定swagger不扫描的接口
      .build()
      

      扫描可传入的参数:

      • basePackage():指定要扫描的包路径
      • any():扫描全部
      • none():全部都不扫描
      • withClassAnnotation():扫描类上有指定注解的接口方法 参数:类的注解class对象 RestController.class
      • withMethodAnnotation():扫描方法上有指定注解的接口方法 参数:方法的注解的class对象 RequestMapping.class
    • enable(false)	//是否在项目中禁用swagger,默认为true
      
    • groupName("wt的分组")	//配置默认分组信息
      
  • 获取当前的项目环境

    配置文件:

    • application.properties:主配置文件
    • application-dev.properties :生产环境配置文件
    • application-test.properties :测试环境配置文件

    在主配置文件中进行指定当前环境

    • spring.profiles.active=dev	//指定为生产环境
      

    获取当前环境

    //设置要显示swagger环境
    Profiles profiles = Profiles.of("dev", "test");
    //判断当前环境是否是在设置的环境中
    boolean flag = environment.acceptsProfiles(profiles);
    
  • SwaggerConfig配置类

    package com.wt.swagger.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 org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    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 {
    
        /**
         * 配置Swagger的Docket的bean实例
         * @return
         */
        @Bean
        public Docket docket(Environment environment){
    
            ApiInfo apiInfo = apiInfo();
    
            //设置要显示swagger环境
            Profiles profiles = Profiles.of("dev", "test");
            //判断当前环境是否是在设置的环境中
            boolean flag = environment.acceptsProfiles(profiles);
    
    
            return new Docket(DocumentationType.SWAGGER_2)
                    .apiInfo(apiInfo)
                	.groupName("wt的分组")
                    .enable(flag)
                    .select()
                    .apis(RequestHandlerSelectors.basePackage("com.wt.swagger.controller"))
                    .paths(PathSelectors.ant("/wt/**"))
                    .build();
        }
    
        /**
         * 配置swagger页面信息
         * @return
         */
        private ApiInfo apiInfo(){
            //作者信息
            Contact contact = new Contact("吴涛", "", "2456512878@qq.com");
            return new ApiInfo(
                    "吴涛的swagger接口文档",
                    "springboot集成swagger项目的demo接口测试文档",
                    "v1.0",
                    "urn:tos",
                     contact,
                    "Apache 2.0",
                    "http://www.apache.org/licenses/LICENSE-2.0",
                    new ArrayList<>());
        }
    }
    

4.2 swagger常用注解

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

5、任务

5.1 异步任务

  • @Async 标明该方法为异步方法,在运行时,使用异步处理

  • @EnableAsync 写在springboot启动类上,开启异步注解功能

  • 例:用户访问/hello接口时,会执行 asyncService.hello();方法时,会同时异步响应消息

    @Async
    public void hello(){
    
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
        System.out.println("程序正在执行");
    }
    
    @RequestMapping("/hello")
    public String hello(){
        asyncService.hello();
        return "响应消息来了";
    }
    

5.2 邮件任务

  • 导入邮件依赖

    
    
        org.springframework.boot
        spring-boot-starter-mail
    
    
  • 邮件信息配置

    # 邮箱地址
    spring.mail.username=2456512878@qq.com
    # 邮箱生成的验证码
    spring.mail.password=nqeocllkxzibeaje
    # qq邮箱主机地址
    spring.mail.host=smtp.qq.com
    # 开启加密验证
    spring.mail.properties.mail.stml.ssl.enable=true
    
  • 编写代码

    @Resource
    JavaMailSenderImpl mailSender;
    
    @Test
    void contextLoads() {
    
        //发送一封简单的邮件
        SimpleMailMessage message = new SimpleMailMessage();
    
        message.setSubject("邮件发送测试");
        message.setText("这是一封通过Java发送的邮件");
    
        message.setTo("2456512878@qq.com");
        message.setFrom("2456512878@qq.com");
    
        mailSender.send(message);
    }
    
    @Test
    void contextLoads2() throws MessagingException {
    
        //发送一封复杂的邮件
        MimeMessage message = mailSender.createMimeMessage();
        //组装    参数:message-邮件对象,true-开启多文件上传
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        //正文
        helper.setSubject("发送复杂邮件测试");
        //参数true:开启html解析
        helper.setText("

    您的验证码是:33355

    ",true); //附件 helper.addAttachment("壁纸.jpg",new File("C:\\Users\\Administrator\\Pictures\\t01a22ce414beb453d4.jpg")); //设置发送双方 helper.setTo("2456512878@qq.com"); helper.setFrom("2456512878@qq.com"); mailSender.send(message); }

5.3 定时任务

  • 在springboot启动类上添加@EnableScheduling注解,开启定时任务注解。

  • @Scheduled:标注需要定时的任务方法(定时任务方法所在的类,需要加上@Component注解,该类也需要在启动类的子包下)

    /**
     * 定时执行的任务
     * cron:表达式,指定该任务什么时候执行 在约定的时间执行已经计划好的工作
     */
    @Scheduled(cron = "30 56 8 * * ?")
    public void hello(){
        System.out.println(new Date() + "定时任务运行了!!!!");
    }