[黑马程序员SpringBoot2]——开发实用篇3
目录:
- jetcache远程缓存方案
- jetcache本地缓存方案
- jetcache方法缓存
- j2cache基本操作
- springboot整合quartz
- springboot整合task
- 发送简单邮件
- 发送多部件邮件
- 消息简介
- 购物订单案例-发送短信
- ActiveMQ安装
- springboot整合ActiveMQ
- RabbitMQ安装
- springboot整合RabbitMQ(direct模式)
- springboot整合RabbitMQ(topic模式)
- RocketMQ安装
- springboot整合RockeMQ
- Kafka安装
- springboot整合Kafka
- 监控的意义
- SpringBootAdmin
- actuator
- info端点指标控制
- health端点指标控制
- metrics端点指标控制
- 自定义端点
1.jetcache远程缓存方案
- jetCache对SpningCache进行了封装,在原有功能基础上实现了多级缓存、缓存统计、自动刷新、异步调用、数据报表等功能
- jetcache设定了本地缓存与远程缓存的多级缓存解决方案
- 本地缓存(local)
- LlinkedHashMap
- Caffeine
- 远程缓存(remote)
- Redis
- Tair
加入jetcache坐标
配置远程缓存必要属性
配置本地缓存必要属性
配置范例
配置属性说明
开启jetcache注解支持
声明缓存对象
操作缓存
代码示例:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>sprintboot_20_jetcache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sprintboot_20_jetcache</name>
<description>sprintboot_20_jetcache</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alicp.jetcache</groupId>
<artifactId>jetcache-starter-redis</artifactId>
<version>2.6.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 8080
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3308/test_db
username: root
password: 666666
jetcache:
remote:
default:
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50
sms:
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50
BookController.class
package com.example.springboot_20_jetcache.controller;
import com.example.springboot_20_jetcache.domain.Book;
import com.example.springboot_20_jetcache.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private BookService bookService;
@GetMapping("{id}")
public Book getById(@PathVariable Integer id) {
return bookService.getById(id);
}
@PostMapping
public boolean save(@RequestBody Book book) {
return bookService.save(book);
}
@PutMapping
public boolean update(@RequestBody Book book) {
return bookService.update(book);
}
@DeleteMapping("{id}")
public boolean delete(@PathVariable Integer id) {
return bookService.delete(id);
}
@GetMapping
public List<Book> getAll() {
return bookService.getAll();
}
}
SMSCodeController.class
package com.example.springboot_20_jetcache.controller;
import com.example.springboot_20_jetcache.domain.SMSCode;
import com.example.springboot_20_jetcache.service.SMSCodeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/sms")
public class SMSCodeController {
@Autowired
private SMSCodeService smsCodeService;
@GetMapping
public String getCode(String tele) {
String code = smsCodeService.sendCodeToSMS(tele);
return code;
}
@PostMapping
public boolean checkCode(SMSCode smsCode) {
return smsCodeService.checkCode(smsCode);
}
}
BookDao.interface
package com.example.springboot_20_jetcache.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.springboot_20_jetcache.domain.Book;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BookDao extends BaseMapper<Book> {
}
Book.class
package com.example.springboot_20_jetcache.domain;
import lombok.Data;
@Data
public class Book {
private Integer id;
private String type;
private String name;
private String description;
}
SMSCode.class
package com.example.springboot_20_jetcache.domain;
import lombok.Data;
@Data
public class SMSCode {
private String tele;
private String code;
}
BookServiceImpl.class
package com.example.springboot_20_jetcache.service.impl;
import com.example.springboot_20_jetcache.dao.BookDao;
import com.example.springboot_20_jetcache.domain.Book;
import com.example.springboot_20_jetcache.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Override
public Book getById(Integer id) {
Book queryBook = bookDao.selectById(id);
return queryBook;
}
@Override
public boolean save(Book book) {
return bookDao.insert(book) > 0;
}
@Override
public boolean update(Book book) {
return bookDao.updateById(book) > 0;
}
@Override
public boolean delete(Integer id) {
return bookDao.deleteById(id) > 0;
}
@Override
public List<Book> getAll() {
return bookDao.selectList(null);
}
}
SMSCodeServiceImpl.class
package com.example.springboot_20_jetcache.service.impl;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CreateCache;
import com.example.springboot_20_jetcache.domain.SMSCode;
import com.example.springboot_20_jetcache.service.SMSCodeService;
import com.example.springboot_20_jetcache.utils.CodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
@Autowired
private CodeUtils codeUtils;
@CreateCache(name = "jetCache", expire = 10, timeUnit = TimeUnit.SECONDS)
private Cache<String, String> jetCache;
@CreateCache(area = "sms", name = "jetCache2", expire = 10, timeUnit = TimeUnit.SECONDS)
private Cache<String, String> jetCache2;
@Override
public String sendCodeToSMS(String tele) {
String code = codeUtils.generator(tele);
jetCache.put(tele, code);
return code;
}
@Override
public boolean checkCode(SMSCode smsCode) {
String code = jetCache.get(smsCode.getTele());
return smsCode.getCode().equals(code);
}
}
BookService.interface
package com.example.springboot_20_jetcache.service;
import com.example.springboot_20_jetcache.domain.Book;
import java.util.List;
public interface BookService {
public boolean save(Book book);
public Book getById(Integer id);
public boolean update(Book book);
public boolean delete(Integer id);
public List<Book> getAll();
}
SMSCodeService.interface
package com.example.springboot_20_jetcache.service;
import com.example.springboot_20_jetcache.domain.SMSCode;
public interface SMSCodeService {
public String sendCodeToSMS(String tele);
public boolean checkCode(SMSCode smsCode);
}
CodeUtils.class
package com.example.springboot_20_jetcache.utils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class CodeUtils {
private String[] patch = {"000000", "00000", "0000", "000", "00", "0", ""};
public String generator(String tele) {
int hash = tele.hashCode();
int encryption = 20206666;
long result = hash ^ encryption;
long nowTime = System.currentTimeMillis();
result = result ^ nowTime;
long code = result % 1000000;
code = code < 0 ? -code : code;
String codeStr = code + "";
int len = codeStr.length();
return patch[len] + codeStr;
}
@Cacheable(value = "smsCode", key = "#tele")
public String get(String tele) {
return null;
}
public static void main(String[] args) {
System.out.println(new CodeUtils().generator("15033657967"));
}
}
Springboot20JetcacheApplication.class
package com.example.springboot_20_jetcache;
import com.alicp.jetcache.anno.config.EnableCreateCacheAnnotation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableCreateCacheAnnotation
public class Springboot20JetcacheApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot20JetcacheApplication.class, args);
}
}
2.jetcache本地缓存方案
application.yml
server:
port: 8080
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3308/test_db
username: root
password: 666666
jetcache:
local:
default:
type: linkedhashmap
keyConvertor: fastjson
remote:
default:
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50
sms:
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50
SMSCodeServiceImpl.class
package com.example.springboot_20_jetcache.service.impl;
import com.alicp.jetcache.Cache;
import com.alicp.jetcache.anno.CacheType;
import com.alicp.jetcache.anno.CreateCache;
import com.example.springboot_20_jetcache.domain.SMSCode;
import com.example.springboot_20_jetcache.service.SMSCodeService;
import com.example.springboot_20_jetcache.utils.CodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Service
public class SMSCodeServiceImpl implements SMSCodeService {
@Autowired
private CodeUtils codeUtils;
// @CreateCache(name = "jetCache", expire = 10, timeUnit = TimeUnit.SECONDS)
// private Cache<String, String> jetCache;
//
// @CreateCache(area = "sms", name = "jetCache2", expire = 10, timeUnit = TimeUnit.SECONDS)
// private Cache<String, String> jetCache2;
@CreateCache(name = "jetCache", expire = 1000, timeUnit = TimeUnit.SECONDS,cacheType = CacheType.LOCAL)
private Cache<String, String> jetCache;
@Override
public String sendCodeToSMS(String tele) {
String code = codeUtils.generator(tele);
jetCache.put(tele, code);
return code;
}
@Override
public boolean checkCode(SMSCode smsCode) {
String code = jetCache.get(smsCode.getTele());
return smsCode.getCode().equals(code);
}
}
3.jetcache方法缓存
启用方法注解
使用方法注解操作缓存
缓存对象必须保障可序列化
查看缓存统计报告
application.yml
server:
port: 8080
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
id-type: auto
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3308/test_db
username: root
password: 666666
jetcache:
statIntervalMinutes: 1
local:
default:
type: linkedhashmap
keyConvertor: fastjson
remote:
default:
type: redis
host: localhost
port: 6379
keyConvertor: fastjson
valueEncode: java
valueDecode: java
poolConfig:
maxTotal: 50
sms:
type: redis
host: localhost
port: 6379
poolConfig:
maxTotal: 50
BookServiceImpl.class
package com.example.springboot_20_jetcache.service.impl;
import com.alicp.jetcache.anno.*;
import com.example.springboot_20_jetcache.dao.BookDao;
import com.example.springboot_20_jetcache.domain.Book;
import com.example.springboot_20_jetcache.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class BookServiceImpl implements BookService {
@Autowired
private BookDao bookDao;
@Override
@Cached(area = "default", name = "book", key = "#id", expire = 3600, cacheType = CacheType.REMOTE)
// @CacheRefresh(refresh = 5)
public Book getById(Integer id) {
Book queryBook = bookDao.selectById(id);
return queryBook;
}
@Override
public boolean save(Book book) {
return bookDao.insert(book) > 0;
}
@Override
@CacheUpdate(name = "book", key = "#book.id", value = "#book")
public boolean update(Book book) {
return bookDao.updateById(book) > 0;
}
@Override
@CacheInvalidate(name = "book", key = "#id")
public boolean delete(Integer id) {
return bookDao.deleteById(id) > 0;
}
@Override
public List<Book> getAll() {
return bookDao.selectList(null);
}
}
4.j2cache基本操作
- j2cache是一个缓存整合框架,可以提供缓存的整合方案,使各种缓存搭配使用,自身不提供缓存功能
- 基于ehcache + nedis.进行整合
加入j2cache坐标,加入整合缓存的坐标
配置使用j2cache (application.yml)
配置─级缓存与二级缓存以及一级缓存数据到二级缓存的发送方式 (j2cache.properties)
设置使用缓存
5.springboot整合quartz
- 定时任务是企业级应用中的常见操作
- 年度报表
- 缓存统计报告
- 市面上流行的定时任务技术
- Quartz
- Spring Task
相关概念
- 工作 (Job)∶用于定义具体执行的工作
- 工作明细(JobDetail):用于描述定时工作相关的信息
- 触发器(Trigger)∶用于描述触发工作的规则,通常使用cron表达式定义调度规则
- 调度器(Scheduler):描述了工作明细与触发器的对应关系
导入SpringBoot整合quartz的坐标
定义具体要执行的任务,继承QuartzJobBean
定义工作明细与触发器,并绑定对应关系
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot_22_task</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_22_task</name>
<description>springboot_22_task</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
QuartzConfig.class
package com.example.springboot_22_task.config;
import com.example.springboot_22_task.quartz.MyQuartz;
import org.quartz.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QuartzConfig {
@Bean
public JobDetail printJobDetail() {
return JobBuilder.newJob(MyQuartz.class).storeDurably().build();
}
@Bean
public Trigger printJobTrigger() {
ScheduleBuilder schedBuilder = CronScheduleBuilder.cronSchedule("0/5 * * * * ?");
return TriggerBuilder.newTrigger().forJob(printJobDetail()).withSchedule(schedBuilder).build();
}
}
MyQuartz.class
package com.example.springboot_22_task.quartz;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
public class MyQuartz extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
System.out.println("quartz task run...");
}
}
6.springboot整合task
开启定时任务功能
设置定时执行的任务,并设定执行周期
定时任务相关配置
MyBean.class
package com.example.springboot_22_task.quartz;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@Scheduled(cron = "0/1 * * * * ?")
public void print() {
System.out.println(Thread.currentThread().getName() + " :spring task run...");
}
}
Springboot22TaskApplication.class
package com.example.springboot_22_task;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class Springboot22TaskApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot22TaskApplication.class, args);
}
}
application.yml
spring:
task:
scheduling:
thread-name-prefix: spring_tasks_
7.发送简单邮件
- SMTP (Simple Mail Transfer Protocol):简单邮件传输协议,用于发送电子邮件的传输协议
- POP3 ( Post Office Protocol - Version 3):用于接收电子邮件的标准协议
- IMAP ( Internet Mail Access Protocol) :互联网消息协议,是POP3的替代协议
导入SpringBoot整合JavaMail的坐标
配置JavaMail
代码示例:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot_23_mail</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_23_mail</name>
<description>springboot_23_mail</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
SendMailService.interface
package com.example.springboot_23_mail.service;
public interface SendMailService {
void sendMail();
}
SendMailServiceImpl.class
package com.example.springboot_23_mail.service.impl;
import com.example.springboot_23_mail.service.SendMailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
@Service
public class SendMailServiceImpl implements SendMailService {
@Autowired
private JavaMailSender javaMailSender;
private String from = "348904@qq.com";
private String to = "ter@126.com";
private String subject = "测试邮件";
private String context = "测试邮件正文内容";
@Override
public void sendMail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from + "(小甜甜)");
message.setTo(to);
message.setSubject(subject);
message.setText(context);
javaMailSender.send(message);
}
}
Springboot23MailApplicationTests.class
package com.example.springboot_23_mail;
import com.example.springboot_23_mail.service.SendMailService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class Springboot23MailApplicationTests {
@Autowired
private SendMailService sendMailService;
@Test
void contextLoads() {
sendMailService.sendMail();
}
}
application.yml
spring:
mail:
username: 3864@qq.com
password: pn............qcjbc
host: smtp.qq.com
8.发送多部件邮件
附件与HTML文本支持
SendMailServiceImpl2.class
package com.example.springboot_23_mail.service.impl;
import com.example.springboot_23_mail.service.SendMailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
//@Service
public class SendMailServiceImpl2 implements SendMailService {
@Autowired
private JavaMailSender javaMailSender;
private String from = "344@qq.com";
private String to = "tar@126.com";
private String subject = "测试邮件";
private String context = "<a href='https://www.baidu.com'>点开有惊喜</a>";
@Override
public void sendMail() {
try {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from + "(小甜甜)");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(context, true);
File f1 = new File("D:\\hdc\\test.txt");
File f2 = new File("D:\\hdc\\test2.txt");
helper.addAttachment(f1.getName(), f1);
helper.addAttachment(f2.getName(), f2);
javaMailSender.send(message);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}
SendMailServiceImpl3.class
package com.example.springboot_23_mail.service.impl;
import com.example.springboot_23_mail.service.SendMailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
@Service
public class SendMailServiceImpl3 implements SendMailService {
@Autowired
private JavaMailSender javaMailSender;
private String to = "34@qq.com";
private String from = "ter@126.com";
private String subject = "测试邮件";
private String context = "<a href='https://www.baidu.com'>点开有惊喜</a>";
@Override
public void sendMail() {
try {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from + "(小甜甜)");
helper.setTo(to);
helper.setSubject(subject);
helper.setText(context, true);
File f1 = new File("D:\\hdc\\test.txt");
File f2 = new File("D:\\hdc\\test2.txt");
helper.addAttachment(f1.getName(), f1);
helper.addAttachment(f2.getName(), f2);
javaMailSender.send(message);
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}
application.yml
#spring:
# mail:
# username: 34864@qq.com
# password: pndkzucx
# host: smtp.qq.com
spring:
mail:
username: ter@126.com
password: HESHJP
host: smtp.126.com
9.消息简介
企业级应用中广泛使用的三种异步消息传递技术
- JMS
- AMQP
- MQTT
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
- AMQP(advanced message queuing protocol):一种协议(高级消息队列协议,也是消息代理规范),规范了网络交换的数据格式,兼容JMS
- 优点:具有跨平台性,服务器供应商,生产者,消费者可以使用不同的语言来实现
- AMQP消息模型
- direct exchange
- fanout exchange
- topic exchange
- headers exchange
- system exchange
- AMQP消息种类: byte[]
- AMQP实现:RabbitMQ.StormMQ..RocketMQ
MQTT
MQTT(Message Queueing Telemetry Transport))消息队列遥测传输,专为小设备设计,是物联网(IOT)生态系统中主要成分之一.
Kafka
- Kafka,一种高吞吐量的分布式发布订阅消息系统,提供实时消息功能。
消息
- ActiveMQ
- RabbitMQ
- RocketMQ
- Kafka
10.购物订单案例-发送短信
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot_24_mq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_24_mq</name>
<description>springboot_24_mq</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
MessageController.class
package com.example.springboot_24_mq.controller;
import com.example.springboot_24_mq.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/msgs")
public class MessageController {
@Autowired
private MessageService messageService;
@GetMapping
public String doMessage() {
String id = messageService.doMessage();
return id;
}
}
OrderController.class
package com.example.springboot_24_mq.controller;
import com.example.springboot_24_mq.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("{id}")
public void order(@PathVariable String id) {
orderService.order(id);
}
}
MessageServiceImpl.class
package com.example.springboot_24_mq.service.impl;
import com.example.springboot_24_mq.service.MessageService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@Service
public class MessageServiceImpl implements MessageService {
private ArrayList<String> msgList = new ArrayList<>();
@Override
public void sendMessage(String id) {
System.out.println("待发送短信的订单已纳入待处理队列,id:" + id);
msgList.add(id);
}
@Override
public String doMessage() {
String id = msgList.remove(0);
System.out.println("已完成短信发送业务,id:" + id);
return id;
}
}
OrderServiceImpl.class
package com.example.springboot_24_mq.service.impl;
import com.example.springboot_24_mq.service.MessageService;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@Service
public class MessageServiceImpl implements MessageService {
private ArrayList<String> msgList = new ArrayList<>();
@Override
public void sendMessage(String id) {
System.out.println("待发送短信的订单已纳入待处理队列,id:" + id);
msgList.add(id);
}
@Override
public String doMessage() {
String id = msgList.remove(0);
System.out.println("已完成短信发送业务,id:" + id);
return id;
}
}
MessageService.interface
package com.example.springboot_24_mq.service;
public interface MessageService {
void sendMessage(String id);
String doMessage();
}
OrderService.interface
package com.example.springboot_24_mq.service;
public interface OrderService {
void order(String id);
}
application.yml
server:
port: 8080
11.ActiveMQ安装
- 下载地址: https://activemq.apache.org/components/classic/download/
- 安装:解压缩
启动服务
访问服务器
服务端口:61616,管理后台端口:8161
用户名&密码:admin
12.springboot整合ActiveMQ
导入SpringBoot整合ActiveMQ坐标
配置ActiveMQ(采用默认配置)
生产与消费消息(使用默认消息存储队列)
生产与消费消息(指定消息存储队列)
使用消息监听器对消息队列监听
流程性业务消息消费完转入下一个消息队列
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.17</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot_24_mq</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot_24_mq</name>
<description>springboot_24_mq</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder-jammy-base:latest</builder>
</image>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.yml
server:
port: 8080
spring:
activemq:
broker-url: tcp://localhost:61616
jms:
template:
default-destination: itheima
MessageListener.class
package com.example.springboot_24_mq.service.impl.activemq.listener;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;
@Component
public class MessageListener {
@JmsListener(destination = "order.queue.id")
@SendTo("order.other.queue.id")
public String receive(String id) {
System.out.println("已完成短信发送业务,id:" + id);
return "new:" + id;
}
}
MessageServiceActivemqImpl.class
package com.example.springboot_24_mq.service.impl.activemq;
import com.example.springboot_24_mq.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@Service
public class MessageServiceActivemqImpl implements MessageService {
@Autowired
private JmsMessagingTemplate messagingTemplate;
@Override
public void sendMessage(String id) {
System.out.println("待发送短信的订单已纳入待处理队列,id:" + id);
messagingTemplate.convertAndSend("order.queue.id", id);
}
@Override
public String doMessage() {
String id = messagingTemplate.receiveAndConvert("order.queue.id", String.class);
System.out.println("已完成短信发送业务,id:" + id);
return id;
}
}
13.RabbitMQ安装
- RabbitMQ基于Erlang语言编写,需要安装Erlang
- Erlang
- 下载地址: https://www.erlang.org/downloads
- 安装:一键傻瓜式安装,安装完毕需要重启,需要依赖Windows组件
- 环境变量配置
- ERLANG_HOME
- PATH
- 下载地址: https://rabbitmq.com/install-windows.html
- 安装:一键傻瓜式安装
RabbitMQ
启动服务
关闭服务
查看服务状态
服务管理可视化(插件形式)
查看已安装的插件列表
开启服务管理插件
访问服务器
服务端口:5672,管理后台端口:15672
用户名&密码:guest
14.springboot整合RabbitMQ(direct模式)
配置RabbitMQ(采用默认配置)
定义消息队列(direct)
生产与消费消息(direct)
使用消息监听器对消息队列监听(direct)
使用多消息监听器对消息队列监听进行消息轮循处理(direct)
15. springboot整合RabbitMQ(topic模式)
定义消息队列(topic)
绑定键匹配规则
- *(星号):用来表示—个单词,且该单词是必须出现的
- #(井号):用来表示任意数量
生产与消费消息(topic)
使用消息监听器对消息队列监听(topic)
16.RocketMQ安装
- 下载地址: https://rocketmq.apache.org/
- 安装:解压缩
- 默认服务端口:9876
- 环境变量配置
- ROCKETMQ_HOME
- PATH
- NAMESRV_ADDR (建议) : 127.0.0.1:9876
命名服务器与broker
启动命名服务器
启动broker
服务器功能测试:生产者
服务器功能测试:消费者
17.springboot整合RockeMQ
导入SpringBoot整合RocketMQ坐标
配置RocketMQ(采用默认配置)
生产消息
生产异步消息
使用消息监听器对消息队列监听
18.Kafka安装
- 下载地址: https://kafka.apache.org/downloads
- windows系统下3.0.0版本存在BUG,建议使用2.X版本
- 安装:解压缩
启动zookeeper
默认端口:2181
启动kafka
默认端口:9092
创建topic
查看topic
册除topic
生产者功能测试
消费者功能测试
19.springboot整合Kafka
导入SpringBoot整合Kafka坐标
配置Kafka(采用默认配置)
生产消息
使用消息监听器对消息队列监听
20.监控的意义
- 监控服务状态是否宕机
- 监控服务运行指标(内存、虚拟机、线程、请求等)
- 监控日志
- 管理服务(服务下线)
监控的实施方式
- 显示监控信息的服务器:用于获取服务信息,并显示对应的信息
- 运行的服务:启动时主动上报,告知监控服务器自己需要受到监控
21.SpringBootAdmin
可视化监控平台
- Spring Boot Admin,开源社区项目,用于管理和监控SpringBoot应用程序。客户端注册到服务端后,通过HTTP请求方式,服务端定期从客户端获取对应的信息,并通过UIl界面展示对应信息。
- Admin服务端
Admin客户端
Admin服务端
Admin客户端
Admin服务端
设置启用Spring-Admin
Admin客户端
22.actuator
- Actuator提供了SpringBoot生产就绪功能,通过端点的配置与访问,获取端点信息
- 端点描述了一组监控信息,SpringBoot提供了多个内置端点,也可以根据需要自定义端点信息
- 访问当前应用所有端点信息:/actuator
- 访问端点详细信息:/actuator/端点名称
ID | 描述 | 默认启用 |
auditevents | 暴露当前应用程序的审计事件信息。 | 是 |
beans | 显示应用程序中所有 Spring bean 的完整列表。 | 是 |
caches | 暴露可用的缓存。 | 是 |
conditions | 显示在配置和自动配置类上评估的条件以及它们匹配或不匹配的原因。 | 是 |
configprops | 显示所有 @ConfigurationProperties 的校对清单。 | 是 |
env | 暴露 Spring ConfigurableEnvironment 中的属性。 | 是 |
flyway | 显示已应用的 Flyway 数据库迁移。 | 是 |
health | 显示应用程序健康信息 | 是 |
httptrace | 显示 HTTP 追踪信息(默认情况下,最后 100 个 HTTP 请求/响应交换)。 | 是 |
info | 显示应用程序信息。 | 是 |
integrationgraph | 显示 Spring Integration 图。 | 是 |
ID | 描述 | 默认启用 |
loggers | 显示和修改应用程序中日志记录器的配置。 | 是 |
liquibase | 显示已应用的 Liquibase 数据库迁移。 | 是 |
metrics | 显示当前应用程序的指标度量信息。 | 是 |
mappings | 显示所有 @RequestMapping 路径的整理清单。 | 是 |
scheduledtasks | 显示应用程序中的调度任务。 | 是 |
sessions | 允许从 Spring Session 支持的会话存储中检索和删除用户会话。当使用 Spring Session 的响应式 Web 应用程序支持时不可用。 | 是 |
shutdown | 正常关闭应用程序。 | 否 |
threaddump | 执行线程 dump。 | 是 |
Web程序专用端点
ID | 描述 | 默认启用 |
heapdump | 返回一个 hprof 堆 dump 文件。 | 是 |
jolokia | 通过 HTTP 暴露 JMX bean(当 Jolokia 在 classpath 上时,不适用于 WebFlux)。 | 是 |
logfile | 返回日志文件的内容(如果已设置 logging.file 或 logging.path 属性)。支持使用 HTTP Range 头来检索部分日志文件的内容。 | 是 |
prometheus | 以可以由 Prometheus 服务器抓取的格式暴露指标。 | 是 |
启用指定端点
启用所有端点
暴露端点功能
- 端点中包含的信息存在敏感信息,需要对外暴露端点功能时手动设定指定端点信息
属性 | 默认 |
management.endpoints.jmx.exposure.exclude | |
management.endpoints.jmx.exposure.include | * |
management.endpoints.web.exposure.exclude | |
management.endpoints.web.exposure.include | info, health |
ID | JMX | Web |
auditevents | 是 | 否 |
beans | 是 | 否 |
caches | 是 | 否 |
conditions | 是 | 否 |
configprops | 是 | 否 |
env | 是 | 否 |
flyway | 是 | 否 |
health | 是 | 是 |
heapdump | N/A | 否 |
httptrace | 是 | 否 |
info | 是 | 是 |
ID | JMX | Web |
integrationgraph | 是 | 否 |
jolokia | N/A | 否 |
logfile | N/A | 否 |
loggers | 是 | 否 |
liquibase | 是 | 否 |
metrics | 是 | 否 |
mappings | 是 | 否 |
prometheus | N/A | 否 |
scheduledtasks | 是 | 否 |
sessions | 是 | 否 |
shutdown | 是 | 否 |
threaddump | 是 | 否 |
23.info端点指标控制
为info端点添加自定义指标
24.health端点指标控制
为Health端点添加自定义指标
25.metrics端点指标控制
为Metrics端点添加自定义指标
26.自定义端点
自定义端点