sprintboot

Easter79
• 阅读 686

一、邮件发送

使用springboot自带的邮件系统就能实现邮件的发送,首先导入依赖:

1、新建springboot项目,添加依赖

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

2、以qq邮箱为例,在application文件中配置邮箱信息

spring.mail.host=smtp.qq.com
spring.mail.username=用户名
spring.mail.password=密码 #为客户端登录授权码,并不是邮箱登录密码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true

授权码获取:

sprintboot

选择开启,点击后会让你用绑定的手机号发送一条信息,发送后点击已发送就会看到自己的登录授权码,一定记得要保存修改。不然会出问题

3、编写一个简单的测试用例

@Autowired
private      mailSender;//注入邮件发送对象。会自动加载配置文件中的邮件设置

@Test
public void contextLoads() {

    MimeMessage mimeMessage = mailSender.createMimeMessage();
    MimeMessageHelper helper;
    String[] strings = new String[3];
    strings[2]="email1";
    strings[1]="email2";
    strings[0]="email3";
    try {
        helper = new MimeMessageHelper(mimeMessage, true);
        helper.setFrom("email");//发送人
        helper.setTo("emailTo");//邮件接收人
        helper.setCc(strings);//抄送邮件接收人,可以抄送多个
        helper.setSubject("群发邮件");//邮件标题
FileSystemResource file = new FileSystemResource(new File("detail.jpg"));
helper.addAttachment("附件-1.jpg", file);//发送附件
helper.addInline("jpg", file);

        helper.setText("<html><body> <div>群发邮件</div></body></html>", true);//可以使用html
        mailSender.send(mimeMessage);
    } catch (MessagingException e) {

        e.printStackTrace();
    }

4、上述工作完成后启动测试类,即可成功发送指定内容至指定邮箱。

在这个过程中遇到了几个问题,这里记录一下:

问题1:Caused by: javax.mail.AuthenticationFailedException: 535 Error: ÇëʹÓÃÊÚȨÂëµÇ¼¡£ÏêÇéÇë¿´

这是在application.properties中设置的密码不是授权码或者属性值后面带有空格等导致的

问题2:Caused by: com.sun.mail.smtp.SMTPAddressFailedException: 550 Mailbox not found or access denied

这是由于邮箱地址填写错误导致的。还有就是使用企业邮箱时,在发送的邮箱中由于有人离职导致该地址不存在而导致发送异常。

至此一个简单的邮件发送就完成了,然而在实际开发中仅仅这样是不能满足我们的开发需求的,所以我们要对其进行加工,让变得更加丰满。

二、进阶——定时任务

我们时常会遇到需要定时处理某个任务的情况,比如定时发送邮件至某个或几个相关人员的邮箱,那么应该怎么做呢。接下来我们就看看如何通过定时任务将邮件发送至指定邮箱。

1、添加定时任务的依赖

<dependency>
   <groupId>org.quartz-scheduler</groupId>
   <artifactId>quartz</artifactId>
   <version>2.3.0</version>
   <exclusions>
      <exclusion>
         <artifactId>slf4j-api</artifactId>
         <groupId>org.slf4j</groupId>
      </exclusion>
      <exclusion>
         <artifactId>HikariCP-java6</artifactId>
         <groupId>com.zaxxer</groupId>
      </exclusion>
   </exclusions>
</dependency>

这里我没有使用springboot自带的定时任务触发器,而是使用quartz,话不多说,直接上代码。

@RestController
@RequestMapping("/job")public class JobController {

    private static final Logger LOGGER = LoggerFactory.getLogger(JobController.class);

    @Autowired
    @Qualifier("scheduler")
    private Scheduler scheduler;


    @SuppressWarnings({"unchecked", "rawtypes"})
    @RequestMapping("/add")
    @ApiOperation(value = "新建任务", notes = "新建任务", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "jobName", dataType = "String", value = "任务名称"),
            @ApiImplicitParam(paramType = "query", name = "jobGroup", dataType = "String", value = "任务分组"),
            @ApiImplicitParam(paramType = "query", name = "jobClassName", dataType = "String", value = "任务类全路径"),
            @ApiImplicitParam(paramType = "query", name = "description", dataType = "String", value = "任务描述"),
            @ApiImplicitParam(paramType = "query", name = "cronExpression", dataType = "String", value = "执行时间"),
            @ApiImplicitParam(paramType = "query", name = "oldJobName", dataType = "String", value = "原任务名称"),
            @ApiImplicitParam(paramType = "query", name = "oldJobGroup", dataType = "String", value = "原任务分组"),
            @ApiImplicitParam(paramType = "query", name = "endTime", dataType = "String", value = "任务结束时间")
    })
    public String save(Quartz quartz) {

        LOGGER.info("新增任务");
        //时间格式化
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        try {
//            Date parse = sdf.parse("2019-07-25 16:30:00");
            //将输入的任务过期时间格式化为特定格式
            Date parse = sdf.parse(quartz.getEndTime());
            //将任务开始时间格式化
            Date startTime = sdf.parse("2019-07-01 22:32:12");
            // 获取Scheduler实例、废弃、使用自动注入的scheduler、否则spring的service将无法注入
            // Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
            // 如果是修改,展示旧的任务
            if (quartz.getOldJobGroup() != null) {
                //生成任务唯一key
                JobKey key = new JobKey(quartz.getOldJobName(), quartz.getOldJobGroup());
                scheduler.deleteJob(key);
            }
            //任务执行类
            Class cls = Class.forName(quartz.getJobClassName());
            cls.newInstance();
            // 构建job信息
            JobDetail job = JobBuilder.newJob(cls).withIdentity(quartz.getJobName(),
                    quartz.getJobGroup())
                    .withDescription(quartz.getDescription()).build();
            // 触发时间点
            CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(quartz.getCronExpression());
            Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger" + quartz.getJobName(), quartz.getJobGroup())
                    .startNow().withSchedule(cronScheduleBuilder).endAt(parse).startAt(startTime).build();
            // 交由scheduler安排触发
            scheduler.scheduleJob(job, trigger);
        } catch (Exception e) {
            e.printStackTrace();
            return "failure";
        }
        return "success";
    }

    @PostMapping("/remove")
    @ApiOperation(value = "移除任务", notes = "移除任务", httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "jobName", dataType = "String", value = "任务名称"),
            @ApiImplicitParam(paramType = "query", name = "jobGroup", dataType = "String", value = "任务分组")
    })
    public String remove(Quartz quartz) {
        try {

            TriggerKey triggerKey = TriggerKey.triggerKey(quartz.getJobName(), quartz.getJobGroup());
            // 停止触发器
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            scheduler.deleteJob(JobKey.jobKey(quartz.getJobName(), quartz.getJobGroup()));
            LOGGER.info("removeJob:" + JobKey.jobKey(quartz.getJobName()));
        } catch (Exception e) {
            e.printStackTrace();
            return "failer";
        }
        return "success";
    }

}

任务job:

public class MailSendJob implements Job, Serializable {

    private static final Logger LOGGER = LoggerFactory.getLogger(MailSendJob.class);
    private static final long serialVersionUID = 1L;

    private static final String URL = "";
    private static final String NAME = "";
    private static final String PASSWORD = "";

    @Autowired
    private JavaMailSender mailSender;//启动类添加注解后,注入这个注解会自动加载配置文件中的邮件配置

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
       
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper;
        String[] strings = new String[2];//构建需要发送邮件的邮箱数组
        strings[1] = "mail3";
        strings[0] = "mail";
        String filePath = writeCsv("test");
        try {
            helper = new MimeMessageHelper(mimeMessage, true);
            helper.setFrom("mail1");//发送人
            helper.setTo("mail2");//邮件接收人
            helper.setCc(strings);//抄送邮件接收人
            helper.setSubject("发送带抄送的邮件");//邮件标题
            helper.setText("<html><body> <div>发送带抄送的邮件</div></body></html>", true);//可以使用html
            FileSystemResource file = new FileSystemResource(new File(filePath));//获取需要发送的附件文件
            String fileName = filePath.substring(filePath.lastIndexOf(File.pathSeparator) + 1);//获取文件名
            helper.addAttachment(fileName, file);//添加附件
            mailSender.send(mimeMessage);//发送带附件的邮件

        } catch (MessagingException e) {
            e.printStackTrace();
            LOGGER.error("任務執行失敗");
        } finally {
            //最后删除在磁盘上生成的文件
            File file1 = new File(filePath);
            if (file1.exists() && file1.isFile()) {
                file1.delete();
            }
        }
    }


    private String writeCsv(String name) {

        String home = System.getProperty("user.home") + "\\Downloads\\" + name + "." + "csv";
//        String home = "d:/detail.csv";
        try {
            //1.加载驱动程序
            Class.forName("com.mysql.jdbc.Driver");
//        Class.forName("org.postgresql.Driver");
            //2.获得数据库的连接
            Connection conn = DriverManager.getConnection(URL, NAME, PASSWORD);
            //3.通过数据库的连接操作数据库,实现增删改查
            Statement stmt = conn.createStatement();
            Statement statement = conn.createStatement();
            // TODO 获取数据
            ResultSet resultSet = statement.executeQuery(" select * from area_code order by code limit 50");
//        ResultSet resultSet = statement.executeQuery("select a.*,b.* from  a join b on a.id=b.id where a.id<1000");
            ResultSetMetaData metaData = resultSet.getMetaData();
            int columnCount = metaData.getColumnCount();
            FileOutputStream out = new FileOutputStream(home);

            CsvWriter csvWriter = new CsvWriter(home, ',', Charset.forName("UTF-8"));
            //写入表头信息
            String[] header = new String[columnCount];
            for (int i = 0; i < columnCount; i++) {
                header[i] = metaData.getColumnName(i + 1);
            }
            csvWriter.writeRecord(header);
            //写入内容信息
            while (resultSet.next()) {

                for (int i = 0; i < columnCount; i++) {

                    csvWriter.write(resultSet.getString(metaData.getColumnName(i + 1)));
                }
                csvWriter.endRecord();
            }

            //关闭写入的流
            csvWriter.close();
            File fileLoad = new File(home);
            FileInputStream in = new java.io.FileInputStream(fileLoad);
            //每次写入10240个字节
            byte[] b = new byte[10240];
            int n;
            while ((n = in.read(b)) != -1) {
                out.write(b, 0, n); //每次写入out1024字节
            }
            out.close();
            in.close();
            System.out.println(home);
            return home;
        } catch (Exception e) {

            e.printStackTrace();
            return null;
        }

    }
}

需要几个配置:

@Configuration
public class QuartzConfig {

    @Autowired
    private SpringJobFactory springJobFactory;

    @Bean(name = "schedulerFactory")
    public SchedulerFactoryBean schedulerFactoryBean() throws IOException {
        SchedulerFactoryBean factory = new SchedulerFactoryBean();
        factory.setAutoStartup(true);
        // 延时5秒启动
        factory.setStartupDelay(5);
        factory.setQuartzProperties(quartzProperties());
        factory.setJobFactory(springJobFactory);
        return factory;
    }

    @Bean
    public Properties quartzProperties() throws IOException {
        PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
        propertiesFactoryBean.setLocation(new ClassPathResource("/quartz.properties"));//任务信息库表信息配置文件
        propertiesFactoryBean.afterPropertiesSet();
        return propertiesFactoryBean.getObject();
    }

    /**
     * quartz初始化监听器
     *
     * @return
     */
    @Bean
    public QuartzInitializerListener executorListener() {
        return new QuartzInitializerListener();
    }

    /**
     * 通过SchedulerFactoryBean获取Scheduler的实例
     *
     * @return
     * @throws IOException
     */
    @Bean(name = "scheduler")
    public Scheduler scheduler() throws IOException {
        return schedulerFactoryBean().getScheduler();
    }

}

@Component
public class SpringJobFactory extends AdaptableJobFactory {
    @Autowired
    private AutowireCapableBeanFactory capableBeanFactory;

    @Override
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        // 调用父类的方法    
        Object jobInstance = super.createJobInstance(bundle);
        // 进行注入    
        capableBeanFactory.autowireBean(jobInstance);
        return jobInstance;
    }
}  

任务说明:使用定时任务定时获取数据库中的数据信息,将统计数据以excel定时发送到指定负责人的邮箱

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
11个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k