Spring Boot学习(六):任务(异步,定时,邮件)、安全

十二、Spring Boot与任务

1、异步任务

在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应
迟缓的情况,之前大部分都是使用多线程来完成此类任务,springboot中可以用异步任务解决。

两个注解

  • @Async在需要异步执行的方法上标注注解
  • @EnableAsync在主类上标注开启异步任务支持

开启异步任务之后,当controller层调用该方法会直接返回结果,该任务异步执行

@Service
public class AsyncService {
    //告诉Spring这是一个异步方法
    @Async
    public void hello(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("处理数据中...");
    }
}

2、定时任务

项目开发中经常需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息。Spring为我们提供了异步执行
任务调度的方式,提供TaskExecutor、TaskScheduler接口。

两个注解

  • @EnableScheduling标注在主类,开启对定时任务支持
  • @Scheduled标注在执行的方法上,并执行cron属性
@Service
public class ScheduledService {
    /*
    * second(秒),minute(分),hour(时),day of month(日),month(月),day of week(周几)
    * 0 * * * * MON-FRI
    * 【0 0/5 14,18 * * ?】 每天14点整,和18点整,每隔5分钟执行一次
    * 【0 15 10 ? * 1-6】 每个月的周一至周六10:15分执行一次
    * 【0 0 2 ? * 6L】每个月的最后一个周六凌晨2点执行一次
    * 【0 0 2 LW * ?】每个月的最后一个工作日凌晨2点执行一次
    * 【0 0 2-4 ? * 1#1】每个月的第一个周一凌晨2点到4点期间,每个整点都执行一次;
    * */
    //@Scheduled(cron = "0 * * * * MON-MON")    任意
    //@Scheduled(cron = "0,1,2,3,4,5 * * * * MON-MON")  枚举
    //@Scheduled(cron = "0-10 * * * * MON-MON")    区间
    //@Scheduled(cron = "0/5 * * * * MON-MON")    步长
    public void hello(){
        System.out.println("hello...");
    }
}
字段允许值允许的特殊字符
0-59,- * /
0-59,- * /
小时0-23,- * /
日期1-31,- * ? / L W C
月份1-12,- * /
星期0-7或者SUN-SAT,0,7是SUN,- * ? / L C #
特殊字符代表含义
枚举
-区间
*任意
/步长
日/星期冲突匹配
L最后
W工作日
C和calendar联系后计算过的值
#星期,4#2,第二个星期四

3、邮件任务

Springboot自动配置包中MailSenderAutoConfiguration通过@Import注解向容器中导入了MailSenderJndiConfiguration,而MailSenderJndiConfiguration向容器中导入了JavaMailSenderImpl类,我们可以使用该类发送邮件。

配制文件

spring.mail.username=2770371800@qq.com		//邮箱用户名
spring.mail.password=sfeyabakupzrddbb		//邮箱密码或者授权码
spring.mail.host=smtp.qq.com				
spring.mail.properties.mail.smtp.ssl.enable=true

自动注入

@Autowired
JavaMailSenderImpl mailSender;

简单邮件发送

@Test
//发送简单邮件
public void contextLoads() {
    SimpleMailMessage message = new SimpleMailMessage();
    //设置主题和内容
    message.setSubject("通知");
    message.setText("你在干啥");
	//设置发送方和接收方
    message.setTo("15891724250@163.com");
    message.setFrom("2770371800@qq.com");
    mailSender.send(message);
}

复杂邮件发送

new MimeMessageHelper(message,true),设置multipart=true,开启对内联元素和附件的支持,helper.setText(“xxxx”,true),html=ture,设置content type=text/html,默认为text/plain

@Test
//发送复杂邮件
public void test02() throws Exception {
    //1、创建一个复杂的消息邮件
    MimeMessage mimeMessage = mailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
    //邮件设置
    helper.setSubject("通知:下周计划");
    helper.setText("<font style='color:red'>下周一回陕西</font>",true);
    helper.setTo("15891724250@163.com");
    helper.setFrom("2770371800@qq.com");
    //上传文件
    helper.addAttachment("2018601.jpg",new File("C:\\Users\\ASUS\\Pictures\\Camera Roll\\2018601.jpg"));
    helper.addAttachment("2025167.jpg",new File("C:\\Users\\ASUS\\Pictures\\Camera Roll\\2025167.jpg"));
    mailSender.send(mimeMessage);
}

十三、Spring Boot与安全

1、安全

应用程序的两个主要区域是“认证”和“授权”(或者访问控制),这两个主要区域是安全的两个目标。身份验证意味着确认您自己的身份,而授权意味着授予对系统的访问权限。

  • 认证
身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。系统确定您是否就是您所说的使用凭据。在公共和
专用网络中,系统通过登录密码验证用户身份。身份验证通常通过用户名和密码完成,
  • 授权
另一方面,授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)
的完全权限。简单来说,授权决定了您访问系统的能力以及达到的程度。验证成功后,系统验证您的身份后,即可授权您访问
系统资源。

2、Spring Security

Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型。他可以实现强大的web安全控制。对于安全控制,我们仅需引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。

WebSecurityConfigurerAdapter:自定义Security策略

通过在配置类中继承该类重写configure(HttpSecurity http)方法来实现自定义策略

@EnableWebSecurity:开启WebSecurity模式

在配置类上标注@EnableWebSecurity开启WebSecurity模式

3、Springboot整合security

1、导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

导入spring security的包之后,默认情况所有应用访问认证授权,默认用户名user,密码为随机生成的uuid,启动时打印在控制台

2、登录/注销

@EnableWebSecurity
public class MySecurityConfig 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?error表示登陆失败
        http.formLogin();
        
        //开启自动配置的注销功能
        //向/logout发送post请求表示注销
        http.logout();
    }
}

此时除了主页,点击其他的页面都会自动跳转到security自动生成的登录页面,/login来到登陆页,重定向到/login?error表示登陆失败;

http.logout()开启自动配置的注销功能,向/logout发送post请求表示注销,需要在欢迎页加上注销表单,默认注销后自动跳转到登录页面,若想改变转发路径,可以通过logoutSuccessUrl(url)设置路径

<form th:action="@{/logout}" method="post">
   <input type="submit" value="注销">
</form>

3. 定义认证规则

为了保证密码能安全存储,springboot内置PasswordEncoder对密码进行转码,默认密码编码器为DelegatingPasswordEncoder。在定义认证规则时,我们需要使用PasswordEncoder将密码转码,由于withDefaultPasswordEncoder()并非安全已被弃用,因此仅在测试中使用。

@Bean
public UserDetailsService users() {
    //使用默认的PasswordEncoder
    User.UserBuilder builder = User.withDefaultPasswordEncoder();
    //定义账户用户名、密码、权限
    UserDetails user1 = builder.username("zhangsan")
            .password("123456")
            .roles("VIP1", "VIP2")
            .build();
    UserDetails user2 = builder.username("lisi")
            .password("123456")
            .roles("VIP3", "VIP2")
            .build();
    UserDetails user3 = builder.username("wangwu")
            .password("123456")
            .roles("VIP1", "VIP3")
            .build();
    //使用内存保存用户信息
    return new InMemoryUserDetailsManager(user1,user2,user3);
}

4.自定义欢迎页

导入依赖

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>

引入命名空间

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
     xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

根据是否登录显示游客或用户信息

<!-- 未登录显示此div -->
<div sec:authorize="!isAuthenticated()">
   <h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/userlogin}">请登录</a></h2>
</div>
<!-- 登录显示此div -->
<div sec:authorize="isAuthenticated()">
    <!-- 显示用户名 -->
   <h2>尊敬的<span th:text="${#authentication.name}"></span>,您好!您的角色有:
       <!-- 显示用户角色 -->
      <span th:text="${#authentication.authorities}"></span></h2>
   <form th:action="@{/logout}" method="post">
      <input type="submit" value="注销">
   </form>
</div>

根据角色类型显示信息

<!-- 具有VIP1的角色显示以下div -->
<div sec:authorize="hasRole('VIP1')">
   <h3>普通武功秘籍</h3>
   <ul>
      <li><a th:href="@{/level1/1}">罗汉拳</a></li>
      <li><a th:href="@{/level1/2}">武当长拳</a></li>
      <li><a th:href="@{/level1/3}">全真剑法</a></li>
   </ul>
</div>

5. 自定义登录页/记住我

@Override
protected void configure(HttpSecurity http) throws Exception {
    ...
    //定制登录页
    http.formLogin()
            .usernameParameter("user")  //表单用户名name
            .passwordParameter("pwd")   //表单密码name
            .loginPage("/userlogin");   //定制登陆页路径
    ...

    //开启记住我
    http.rememberMe().
        rememberMeParameter("rem");		//设置表单记住我name值

}

通过loginPage(url)设置登录页路径后,在定制的登录页发送post url即为登录请求,并设置表单的name属性都为对应值;

通过勾选记住我,session退出后依然能通过cookie保存用户信息,下次免登陆

<form th:action="@{/userlogin}" method="post">
   用户名:<input name="user"/><br>
   密码:<input name="pwd"><br/>
   <input type="checkbox" name="rem">记住我<br>
   <input type="submit" value="登陆">
</form>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值