public static void main(String[] args) {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("task running!!!!");
}
};
// task 当前要运行的任务
// delay:什么时候开始运行 0表示程序启动就运行
// period:多久执行一次;ms为单位
timer.schedule(task,0,2000);
}
相关概念:
工作(Job):用于定义执行任务的工作
工作明细(JobDetail):用于描述定时相关的信息
触发器(Trigger):用于描述触发工作的规则,通常使用cron表达式定义
调度器(Scheduler):描述了工作明细和触发器的对应关系
1.导入坐标
org.springframework.boot spring-boot-starter-quartz
2.在启动类上加入注解: @EnableScheduling//开启定时任务功能
3.创建工作
@Component //将该类加入到spring容器中保证启动启动类时加载该bean
public class MyBean {
@Scheduled(cron = "0/1 * * * * ?")
public void print(){
System.out.println(Thread.currentThread().getName()+"running~~~~");
}
}
4.在xml文件中可以配置很多配置但大部分都有默认值
spring:
task:
scheduling:
# 调度线程池大小 默认为:1
pool:
size: 1
# 线程名称的前缀 默认为:scheduling-
thread-name-prefix: ssm_
shutdown:
# 线程池关闭时是否等待所有任务完成
await-termination: true
# 调度线程关闭前的最大等待时间,确保一定最后关闭
await-termination-period: 10s
3.springboot整合javaMail
首先了解几个协议
SMTP:发送邮件的传输协议
POP3:接受邮件的传输协议
IMAP:POP3的替代协议,互联网的消息协议
1.导入坐标
org.springframework.boot spring-boot-starter-mail
2.在配置文件中填写配置:
spring:
mail:
# 发送邮箱的客户端
host: smtp.qq.com
username: 1163ssss983@qq.com
password: uqnwrklewcnnjgac
1.发送简单邮件
@Autowired
private JavaMailSender javaMailSender;
// 创建发送人
private String from = "1162983@qq.com";
// 创建接受人
private String to = "2525889@qq.com";
// 标题
private String subject = "测试信息";
// 正文
private String text = "my name is lilong";
public void goMail(){
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);
message.setSubject(subject);
message.setText(text);
javaMailSender.send(message);
}
2.发送复杂邮件
关键:
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,true);//true是指发送附件的形式
简单的例子:
@Autowired
private JavaMailSender javaMailSender;
// 创建发送人
private String from = "11633223983@qq.com";
// 创建接受人
private String to = "2536422889@qq.com";
// 标题
private String subject = "复杂邮件的测试";
// 正文 如果是连接需要写html标签
private String text = "";
// 发送链接
private String context = "点开给你看一个好看的";
//发送一个文件
private File file = new File("C:\Users\Administrator\Desktop\1.png");
public void goMail() throws MessagingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);//true是指发送附件的形式
helper.setFrom(from + "(东东)");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text, true); //true是指以html解析
helper.setText(context, true); //true是指以html解析
helper.addAttachment("东东.png", file);
javaMailSender.send(message);
}
4.springboot整合消息中间件
JMS (Java Message Service)等同于JDBC规范,提供了与消息服务相关的API接口
JMS消息模型
peer-2-peer:点对点模型,消息发送到一个队列中,队列保存消息。队列的消息只能被一个消费者消费,或超时
publish-subscribe:发布订阅模型,消息可以被多个消费者消费,生产者和消费者完全独立,不需要感知对方的存在
JMS消息种类
TextMessage
MapMessage
BytesMessage
StreamMessage
ObjectMessage
Message (只有消息头和属性)
JMS实现:ActiveMQ、Redis、HornetMQ、RabbitMQ、RocketMQ(没有完全遵守JMS规范)
AMQP:一种协议,高级队列协议,也是消息队列的规范,规范了网络交换的数据格式,兼容JMS
重要的两个规范:direct exchange ,topic exchange
Kafka:一种高量的分布式发布订阅消息系统,提供实时消息功能。
1.ActiveMQ导入坐标:
org.springframework.boot spring-boot-starter-activemq
在yml文件中配置
server:
port: 80
spring:
activemq:
broker-url: tcp://localhost:61616
jms:
template:
default-destination: order.sm.id #随便起一个名字,一种标志
pub-sub-domain: true #开启订阅模式 默认是点对点模式
生产与消费消息:
@Service
public class MessageServiceImpl implements MessageService {
@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;
@Override
public void sendMessage(String id) {
System.out.println("待发送消息订单已纳入消息队列:"+id);
//发送消息到队列中
jmsMessagingTemplate.convertAndSend("order.sm.id",id);
}
@Override
public String doMessage() {
String id = jmsMessagingTemplate.receiveAndConvert("order.sm.id",String.class);
System.out.println("已完成短息发送业务:"+id);
return id;
}
用监听器模式监听消费消息
需要注意,如果无@sendTo注解将其转接到另一个队列中,receive获取消息时不可有返回值,否则循环报此异常
@Component
public class ActiverLisener {
@JmsListener(destination = "order.sm.id")
public void doMess(String id){
System.out.println( "已发送业务id:"+id);
}
}
需要转到另一个队列中并且在另一个队列中不消费
@Component
public class ActiverLisener {
@JmsListener(destination = "order.sm.id")
@SendTo(value = "itheima")
public String doMess(String id) {
System.out.println("已发送业务id:" + id);
return "new:" + id;
}
}
2.RabbitMq
导入坐标:
1.direct直连模式org.springframework.boot spring-boot-starter-amqp
配置文件:
# ========RabbitMq==========
spring:
rabbitmq:
host: localhost
port: 5672
定义消息队列,交换机,和交换机与队列合并
@Configuration
public class RabbitConfig {
@Bean//创建队列
public Queue creatQueue(){
return new Queue("direct_queue");//队列的名称
}
@Bean//创建交换机
public DirectExchange creatDirExchange(){
return new DirectExchange("directExchange");//交换机的名称 一个交换机可以供多geQueue使用
}
@Bean//将交换机呵呵队列合并
public Binding creatBindingBuilder(){
return BindingBuilder.bind(creatQueue()) //添加队列
.to(creatDirExchange()) //添加交换机
.with("direct");//合并的新起一个名字
}
}
生产消息
@Service
public class MessageRabbitDirectImpl implements MessageService {
@Autowired
private AmqpTemplate amqpTemplate;
@Override
public void sendMessage(String id) {
System.out.println("待发送消息订单已纳入消息队列:"+id);
//存消息队列
amqpTemplate.convertAndSend("directExchange", "direct",id);//填写交换机名称,队列和交换机的名称,和消息
}
}
消费消息:(这里是使用监听器)
@Component
public class RabbitdirectListener {
@RabbitListener(queues = "direct_queue")//这里填写队列名称
public void receive(String id){
System.out.println("你的消息已发送"+id);
}
}
这里需要注意一下:如果绑定2个监听器则轮着处理消费消息
2.topic(主题交换机/模式)topic模式与direct模式没什么区别只是交换机的类换了:
@Bean//创建交换机
public TopicExchange creatTopicExchange(){
return new TopicExchange("topicExchange");//交换机的名称 一个交换机可以供多geQueue使用
}
并且主题模式有自己的匹配规则 例如:
创建的合并名字为:“topic.*.id”
@Bean//将交换机呵呵队列合并
public Binding creatBindingBuilder(){
return BindingBuilder.bind(creatQueue()) //添加队列
.to(creatTopicExchange()) //添加交换机
.with("topic.*.id");//新起一个名字
}
在匹配的时候可以为:
amqpTemplate.convertAndSend("topicExchange", "topic.ccccc.id",id);//填写交换机名称,队列和交换机的名称,和消息
匹配规则:
*表示:必须要有,但可以为任意地
#表示:可以没有,也可以是任意数量的任意的
3.RocketMq导入坐标:
org.apache.rocketmq rocketmq-spring-boot-starter2.2.1
在yml文件中配置:
#===========RocketMqListener=======
rocketmq:
name-server: localhost:9876
producer:
group: itcast #生产者分组名
生产消息:
@Service
public class MessageRocketMqImpl implements MessageService {
@Autowired
private RocketMQTemplate recTemplate;
@Override
public void sendMessage(String id) {
System.out.println("待发送消息订单已纳入消息队列:"+id);
// recTemplate.convertAndSend("order_id",id); //主题名;这个是处理的同步消息,大部分的时候还是需要处理异步消息的
SendCallback callback = new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
//消息处理成功的处理
System.out.println("消息处理成功");
}
@Override
public void onException(Throwable throwable) {
System.out.println("消息处理失败");
}
};
recTemplate.asyncSend("order_id",id,callback);
}
}
消费消息是用监听器来实现的:
@Component @RocketMQMessageListener(consumerGroup = "itcast",topic = "order_id")//分别是值生产者分组名,和主题名 public class RocketMqListener implements RocketMQListener4.Kafka{ @Override public void onMessage(String id) { System.out.println("短信业务已消费:"+id); } }
导入坐标:
org.springframework.kafka
spring-kafka
修改yml配置文件:
#============Kafka==================
spring:
kafka:
bootstrap-servers: localhost:9092
consumer:
group-id: iffftcast #起组名
生产消息,并传入到消息队列中
@Service
public class MessageKafkaImpl implements MessageService {
@Autowired
private KafkaTemplate kafkaTemplate;
@Override
public void sendMessage(String id) {
System.out.println("待发送消息订单已纳入消息队列:"+id);
kafkaTemplate.send("dongdong",id);//主题名称
}
}
消费消息:(使用监听器)
@Component
public class Kafka_Listener {
@KafkaListener(topics = "dongdong")//主题名称
public void onMessage(ConsumerRecord record){
System.out.println("你的业务已处理(kafka):"+record.value());
}
}
5.springboot-Admin(监控)
导入坐标:
admin客户端:admin服务端: de.codecentric spring-boot-admin-starter-client2.6.2 de.codecentric spring-boot-admin-starter-server2.6.2
在被监控的yml文件中写入:
spring:
boot:
admin:
client:
url: http://localhost:81 #服务端的地址
management:
endpoint:
health:
show-details: always #显示详细信息
info:
enabled: true #显示消息端
endpoints:
web:
exposure:
include: "*" #包含所有信息,将所有信息显示出来
为info端点添加自定义指标:
@Component
public class AppInfoContributor implements InfoContributor
{
@Override
public void contribute(Info.Builder builder){
Map infoMap = new HashMap<>();
infoMap.put("buildTime","2006");
builder.withDetail("runTime",System.currentTimeMitLis())
.withDetail("company","传智教育");
builder.withDetails(infoMap);
}
为Health端点添加自定义指标:
@Component
public class AppHealthContributor extends AbstractHealthIndicator
{
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
boolean condition = true;
if(condition){
Map infoMap = new HashMap<>();
infoMap.put("buildTime","2006");
builder.withDetail("runTime",System.currentTimeMitLis())
.withDetail("company","传智教育");
builder.withDetails(infoMap);
builder.status(Status.UP);
}else{
builder.status(Status.DOWN);
}
为Metrics端点添加自定义指标 @Service public class BookServiceImpl extends ServiceImplimplements IBookService { private Counter counter; public BookServiceImpl(MeterRegistry meterRegistry){ counter = meterRegistry.counter("用户付费操作次数:"); } @Override public boolean delete(Integer id) { counter.increment(); return bookDao.deleteById(id) > 0;}}
自定义端点
@Component
@Endpoint(id="pay")
public class PayEndPoint {
@Readoperation
public Object getPay(){
//调用业务操作,获取支付相关信息结果,最终return出去
Map payMap = new HashMap();
payMap.put("level 1",103);
payMap.put("level 2",315);
payMap.put("level 3",666);
return payMap;
}}
erviceImpl extends ServiceImpl
private Counter counter;
public BookServiceImpl(MeterRegistry meterRegistry){
counter = meterRegistry.counter(“用户付费操作次数:”);
}
@Override
public boolean delete(Integer id) {
counter.increment();
return bookDao.deleteById(id) > 0;}}
自定义端点
@Component
@Endpoint(id=“pay”)
public class PayEndPoint {
@Readoperation
public Object getPay(){
//调用业务操作,获取支付相关信息结果,最终return出去
Map payMap = new HashMap();
payMap.put(“level 1”,103);
payMap.put(“level 2”,315);
payMap.put(“level 3”,666);
return payMap;
}}



