在进行项目开发的时候经常会遇见以下的几个问题:需要进行邮件发送、定时的任务调度、系统的监控处理,
实际上这些操 作都可以通过 SpringBoot 进行整合操作。
2.1、SpringBoot 整合邮件服务
如果要进行邮件的整合处理,那么你一定需要有一个邮件服务器,实际上 java 本身提供有一套 JavaMail
组件以实现邮件服务器的搭建,但是这个搭建的服务器意义不大,因为你现在搭建完成了,向一些大型的站点
发送一封邮件,若干小时你就会被拉黑, 如果不想拉黑彼此之间就做一个白名单即可。
那么如果说现在自己搭建邮件服务器不行,就可以考虑使用 QQ 邮件服务、网易邮件服务,本次可以申请一个
QQ 邮件服务器,如果要申请你一定要登录你自己的 QQ 邮箱。
1、 如果要想实现邮件的发送服务,则首先要导入一个依赖的支持库:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
2、 修改项目中的 application.properties配置文件,实现邮件的配置:
spring.mail.host=smtp.163.com
spring.mail.username=az_app
spring.mail.password=az1234
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
3、 编写测试类,直接调用 mail 服务:
package com.microboot.test;
import javax.annotation.Resource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.microboot.StartSpringBootMain;
@SpringBootTest(classes = StartSpringBootMain.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
public class TestMail {
@Resource
private JavaMailSender javaMailSender ;
@Test
public void testSendMail() {
SimpleMailMessage message = new SimpleMailMessage() ; // 要发送的消息内容
message.setFrom("[email protected]");
message.setTo("[email protected]");
message.setSubject("测试邮件)");
message.setText("好好学习,天天向上");
this.javaMailSender.send(message);
}
}
你如果要是个人玩玩还可以,如果要进行海量发送,腾讯不会让你得逞的,你得再去申请企业的邮箱,
如果现在觉得腾讯邮 箱不能够满足于你的要求,你可以考虑使用阿里云服务。
2.2、定时调度
所有的系统开发里面定时调度绝对是一个核心的话题,对于定时调度的实现在实际开发之中可以
使用:TimerTask、Quartz、 SpringTask 配置,实际上这里面最简单的配置就是 Spring 自己
所提供的 Task 处理。
1、 如果要想实现定时调度,只需要配置一个定时调度的组件类即可:
package com.microboot.task;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyScheduler {
@Scheduled(fixedRate = 2000) // 采用间隔调度,每2秒执行一次
public void runJobA() { // 定义一个要执行的任务
System.out.println("【*** MyTaskA - 间隔调度 ***】"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.format(new Date()));
}
@Scheduled(cron = "* * * * * ?") // 每秒调用一次
public void runJobB() {
System.err.println("【*** MyTaskB - 间隔调度 ***】"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.format(new Date()));
}
}
2、 如果现在要想执行此任务,那么还需要有一个基本的前提:你的程序启动类上一定要启用调度处理。
package cn.study.microboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication // 启动SpringBoot程序,而后自带子包扫描
@EnableScheduling // 启用间隔调度
public class StartSpringBootMain {
public static void main(String[] args) throws Exception {
SpringApplication.run(StartSpringBootMain.class, args);
}
}
这个时候所实现的任务调度只是串行任务调度,也就是说所有的任务是一个一个执行的处理方式,那么如果
现在有一个任务 所花费的时间特别的长,则其它的任务都会积压,实际开发之中很明显这种处理是不可能
存在的。
3、 如果要想启用并行的调度处理,则一定要准备出一个线程调度池,进行一个线程调度的配置类:
@Component
public class MyScheduler {
@Scheduled(fixedRate = 2000) // 采用间隔调度,每2秒执行一次
public void runJobA() { // 定义一个要执行的任务
System.out.println("【*** MyTaskA - 间隔调度 ***】"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.format(new Date()));
}
@Scheduled(cron = "* * * * * ?") // 每秒调用一次
public void runJobB() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println("【*** MyTaskB - 间隔调度 ***】"
+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
.format(new Date()));
}
}
package com.microboot.config;
import java.util.concurrent.Executors;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
@Configuration // 定时调度的配置类一定要实现指定的父接口
public class SchedulerConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { // 开启一个线程调度池
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(100));
}
}
2.3、Actuator 监控
对于 SpringBoot 中的服务的监控在 SpringBoot 开发框架之中提供有一个 Actuator 监控程序,但是这个
监控程序在很多的时候 使用有一些矛盾,对于此类的信息服务,一般而言会有两类信息:
· 第一类是由系统直接提供好的信息,这个需要关闭安全控制;
· 第二类是由用户定义的,希望可以返回固定的一些信息,例如:版本、服务名称等。
1、 如果现在要想在代码之中启用 actuator 服务,那么首先一定要进行开发包的配置;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、 此时配置此依赖包的项目就具有了监控的操作能力,但是这个能力无法直接体现,如果现在要想打开默认的
系统的这些监控 信息,则需要修改 application.properties 配置文件,关闭掉当前的安全配置项:
# 现在关闭系统的安全配置
management.security.enabled=false
http://localhost/health
{"status":"UP","jms":{"status":"UP","provider":"ActiveMQ"},
"diskSpace":{"status":"UP","total":104857595904,"free":19487199232,
"threshold":10485760},"db":{"status":"UP","database":"MySQL","hello":1}}
http://localhost/env
http://localhost/beans
3、 但是如果现在将系统的安全配置关闭了之后,那么此时你的系统的服务信息就有可能被任何人看见,
那么不希望被所有人看 见,同时也希望所有的人可以看见一些能够看见的提示信息,所以在这样的状态下,
就需要去考虑自定义一些服务信息出现。例如, 现在先进行健康信息的配置;
package com.microboot.actuator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
return Health.down().withDetail("info", "老子还活着!").build();
}
}
http://localhost/health
{"status":"DOWN","my":{"status":"DOWN","info":"老子还活着!"},
"jms":{"status":"UP","provider":"ActiveMQ"},
"diskSpace":{"status":"UP","total":104857595904,"free":19486093312,
"threshold":10485760},"db":{"status":"UP","database":"MySQL","hello":1}}
但是发现这种健康的信息配置是需要打开安全策略之后才能够发现一些更加详细的内容,而如果开启了安全策略
之后可以看 见的信息只能够是一些基础的状态:UP(存活)、DOWN(关闭)。
package com.microboot.actuator;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class MyHealthIndicator implements HealthIndicator {
@Override
public Health health() {
int errorCode = 100 ; // 这个错误的码是通过其它程序获得的
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build() ;
}
}
4、 除了健康之外,还有一项数据很重要,就是一些服务的信息(/info),而这些服务的信息可以直接
通过 application.properties 文件配 置,修改 application.properties 要按照指定的格式完成:
http://localhost/info
{}
info.app.name=baidu-microboot
info.app.version=v1.0.0
info.company.name=www.baidu.cn
info.pom.artifactId=$project.artifactId$
info.pom.version=$project.version$
http://localhost/info
{"pom":{"version":"$project.version$","artifactId":"$project.artifactId$"},
"app":{"version":"v1.0.0","name":"baidu-microboot"},"company":{"name":"www.baidu.cn"}}
· 对于这样的配置信息最好的方式就是进行 pom.xml 文件的读取,所以如果要想实现这种关联操作,则必须
修改 microboot 项目中的 pom.xml 文件,追加有一个访问的插件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$</delimiter>
</delimiters>
</configuration>
</plugin>
· 对于这样的配置信息最好的方式就是进行 pom.xml 文件的读取,所以如果要想实现这种关联操作,则必须
修改 microboot 项目中的 pom.xml 文件,追加有一个访问的插件:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimiter>$</delimiter>
</delimiters>
</configuration>
</plugin>
http://localhost/info
{"pom":{"version":"0.0.1-SNAPSHOT","artifactId":"bootfirst"},
"app":{"version":"v1.0.0","name":"baidu-microboot"},
"company":{"name":"www.baidu.cn"}}
5、 由于在开发之中这种提示信息会成为微服务的重要组成部分,所以很多时候如果重复进行
application.yml 配置文件的定义,那么会比较麻烦, 最简单的做法直接做一个配置程序类进行信息的配置。
package com.microboot.actuator;
import org.springframework.boot.actuate.info.Info.Builder;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
@Component
public class ProjectInfoContributor implements InfoContributor {
@Override
public void contribute(Builder builder) {
builder.withDetail("company.name", "study") ;
builder.withDetail("version", "V1.0") ;
builder.withDetail("author", "sss") ;
}
}
http://localhost/info
{"pom":{"version":"0.0.1-SNAPSHOT","artifactId":"bootfirst"},
"app":{"version":"v1.0.0","name":"baidu-microboot"},
"company":{"name":"www.baidu.cn"},"company.name":"study",
"version":"V1.0","author":"sss"}
numpy.arrayhttps://docs.scipy.org/doc/numpy/reference/generated/numpy.array.htmlnumpy.array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)Create an array.array [əˈreɪ]:n. 数组,阵列,排列,列阵,大批,一系列,衣服 vt. 排列,部署,打扮1. Parametersobject : arra
lwIP移植工作(一)cc.h 与CPU和编译器的相关接口Lwip的移植主要是三个接口部分:1、与CPU或编译器相关接口(include中cc.h文件)2、与操作系统的接口;3、与底层网卡驱动的接口。一、与CPU或编译器相关接口与CPU或编译器相关接口(include中cc.h文件),主要包括数据长度,字的高低位顺序,编译器对c语言中struct结构字节对齐问题(c语言中s
加载影像//加载Landsat8var l8 = ee.ImageCollection("LANDSAT/LC08/C01/T1_SR")//加载sentinelvar imageCollection = ee.ImageCollection("COPERNICUS/S1_GRD"),var imageCollection2 = ee.ImageCollection("COPERNICUS/S2"),var imageCollection3 = ee.ImageCollection("COPER
文章目录一、 Log4j简介1.1 Loggers1.2 Appenders1.3 Layouts二、配置详解2.1 配置根Logger:2.2 配置日志信息输出目的地(appender)2.3 配置日志信息的输出格式(Layout)Log4j比较全面的配置输出独立日志文件一、 Log4j简介Log4j有三个主要的组件:Loggers(记录器):日志类别和级别;Appenders (输出源):日志要输出的地方;Layouts(布局):日志以何种形式输出1.1 LoggersLoggers组件在
/** * @brief General Purpose I/O */typedef struct{ __IO uint32_t CRL; __IO uint32_t CRH; __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR; __IO uint32_t BRR; __
为了把一串点连成光滑的曲线,先研究贝塞尔曲线,又搞B样条插值。。。。都没有成功(数学没那么强)。后来在“[翻译] AGG 之贝塞尔插值 ”http://liyiwen.javaeye.com/blog/705489 。看到一种比较好的方法:运用贝塞尔曲线的光滑性来穿过这些点。大致思路就是 先算出相邻原始点的中点,在把相邻中点连成的线段平移到对应的原始点,以平移后的中点作为控制点,
Returncodeis:500最近在项目中使用maven-deploy上传jar包时出现[ERROR]Failedtoexecutegoalorg.apache.maven.plugins:maven-deploy-plugin:2.7:deploy(default-deploy)onprojectwenwo-platform-parent:Failedto...
Q: 什么是Ubuntu?A: 中文名“乌邦图”,是基于debian的一个Gnu/Linux操作系统。理念是“Humanity to others”,即“人道待人”。我们Ubuntuer都是乐于助人的好兄弟,而且它是永久免费的Q: 它和其他linux发行版有什么区别?A: ubuntu基于debian,拥有debian一切的优点,还有debian所不具有的其他长处,如更为方便,更适...
1、前言因为项目需要,做了个小工具来做前期准备。这个需求实现两步:播放和显示波形。播放方面,一开始选择FMod,小工具快做好的时候偶然发现FMod需要商业授权,所以只能放弃。试了试ffmpeg+SDL又觉得大材小用过于复杂(主要是对编解码这一块有点畏惧)。最后才发现QT自带播放类其实已经满足需求,最后播放就交给QMediaPlayer。由于显示波形需要放大平移等操作,自己实现起来很费时间,所以选择现有的图表工具。目前可选的有QWT和QCustomPlot。由于QWT配置起来比较麻烦,所以显示
Windows窗体通过引发键盘事件来处理键盘输入以响应Windows消息,大多数Windows窗体应用程序都通过处理键盘事件来以独占方式处理键盘输入。Windows窗体将键盘输入标识为由按位Keys枚举表示的虚拟键代码。使用Keys枚举,可以综合一系列按键以生成单个值,这些值与WM_KEYDOWN和WM_SYSKEYDOWNWindows消息所伴随的值相对应。另外,程序开发人员可通过处理KeyDown或KeyUp 事件来检测大多数物理按键操作。字符键是Keys枚举的子集,它们与WM_CHAR和WM_
转自:http://jingyan.baidu.com/article/375c8e19b89b4125f2a2298c.htmlTPLink路由器登陆密码忘记了怎么办?由于路由器设置通常只是偶尔进行,因此时间长了可能就忘记了路由器登陆密码。当路由器登陆密码忘记后,我们可以采用暴力破解登陆路由器,也可以通过恢复路由器出厂设置来清除登陆密码。以下小编就为大家分享一下具体破解TPLink路由器
overleafoverleaf是一个 让科学更加开放、好复制、共同合作的网站。Overleaf CEO兼共同创办人是 John Hammersley 博士 在文档中国加上这个 overleaf基础入门_Junewang0614的博客-程序员秘密_overleaf教程5.插入表格 表格科研很神器给你了,自己摸索着用,认识字就行 Create LaTeX tables online – TablesGenerator.comhttps://www.tablesgenerator.com/