**************************************************************************************************************************************************************
1、Springboot与缓存
【1】访问量大、临时性数据
【2】JSR107(用的少)、缓存抽象
**************************************************************************************************************************************************************
2、Spring缓存抽象
【1】CacheManager与Cache获取
【2】@Cacheable、@CacheEvict、@CachePut、@EableCaching、keyGenerator、serialize
**************************************************************************************************************************************************************
3、缓存-基本环境搭建
【1】BigController
package com.day.study.controller;
import com.day.study.mapper.BigMapper;
import com.day.study.pojo.Employee;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class BigController {
@Resource
BigMapper bigMapper;
@GetMapping("/employee")
public Employee selectEmployee(Employee employee) {
return bigMapper.selectEmployeeById(employee);
}
}
**************************************************************************************************************************************************************
4、Cacheable初体验
【1】开启基于注解的缓存 @EnableCaching在SpringBoot上面;
【2】标注缓存注解即可
【3】如果没有缓存,都是每次都从数据库拿到
# log
logging.level.com.day.study.mapper=debug
【4】标记可以用缓存的Mapper中的方法
package com.day.study.mapper;
import com.day.study.pojo.Employee;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.cache.annotation.Cacheable;
@Mapper
public interface BigMapper {
// 查询
@Cacheable(cacheNames = "employee")
Employee selectEmployeeById(@Param("employee") Employee employee);
// 添加
void insertEmployee(@Param("employee") Employee employee);
// 修改
void updateEmployee(@Param("employee") Employee employee);
// 删除
void deleteEmployee(@Param("employee") Employee employee);
}
【5】Controller里也要同步
package com.day.study.controller;
import com.day.study.mapper.BigMapper;
import com.day.study.pojo.Employee;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class BigController {
@Resource
BigMapper bigMapper;
@Cacheable(cacheNames = "employee")
@GetMapping("/employee")
public Employee selectEmployee(Employee employee) {
return bigMapper.selectEmployeeById(employee);
}
}
【6】CacheManager 缓存管理器、Condition在满足条件的情况下才缓存
【7】还有异步等模式
**************************************************************************************************************************************************************
5、缓存工作原理与执行流程
【1】自动配置类、缓存配置类
【2】注册了一个缓存管理器
【3】生成Key的策略、@Cacheable标注的方法执行之前会先看缓存中是否存在,按照key去缓存查询
【4】核心:
(1)CacheManager 按照名字得到Cache组件
(2)Key是使用SimpleKeyGenerator生成的
(3)根据Key看缓存是否存在,不存在查,存在用
**************************************************************************************************************************************************************
6、@Cacheable别的属性
【1】cacheNames和value一样,可以指定多个名字
【2】key="#root.methodName+'['+#id+']'"
【3】condition 在某种条件满足的时候才缓存,如="#a0>1"
【4】unless="#a0==2" 如果第一个参数的值为2则不缓存
**************************************************************************************************************************************************************
7、缓存CachePut概述
【1】既调用方法,又更新缓存数据:典型场景-修改数据库的某个数据,同时更新缓存
【2】缓存和CachePut更新缓存的ID必须一致,不然就出现不一致了。(没有Redis好用!!!!!!!!!!!!!!!!!!!!)
package com.day.study.controller;
import com.day.study.mapper.BigMapper;
import com.day.study.pojo.Employee;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class BigController {
@Resource
BigMapper bigMapper;
@Cacheable(cacheNames = "employee", key = "#employee.id")
@GetMapping("/selectEmployee")
public Employee selectEmployee(Employee employee) {
return bigMapper.selectEmployeeById(employee);
}
@CachePut(cacheNames = "employee", key = "#employee.id")
@GetMapping("/updateEmployee")
public Employee updateEmployee(Employee employee) {
bigMapper.updateEmployee(employee);
return employee;
}
}
**************************************************************************************************************************************************************
8、缓存CacheEvict
【1】缓存删除
【2】删除后就回重新从数据库查询,不如Redis
@Resource
BigMapper bigMapper;
@Cacheable(cacheNames = "employee", key = "#employee.id")
@GetMapping("/selectEmployee")
public Employee selectEmployee(Employee employee) {
return bigMapper.selectEmployeeById(employee);
}
@CachePut(cacheNames = "employee", key = "#employee.id")
@GetMapping("/updateEmployee")
public Employee updateEmployee(Employee employee) {
bigMapper.updateEmployee(employee);
return employee;
}
@CacheEvict(cacheNames = "employee", key = "#employee.id")
@GetMapping("/deleteEmployee")
public Employee deleteEmployee(Employee employee) {
System.out.println("执行删除...");
//bigMapper.deleteEmployee(employee);
return employee;
}
**************************************************************************************************************************************************************
9、缓存Caching与CacheConfig
【1】复杂的缓存规则组合
【2】CacheConfig在Controller上面标记,这样不用每一个都单独标记了
**************************************************************************************************************************************************************
10、Redis环境配置
【1】缓存中间件redis、memcached、ehcache
【2】整合redis作为缓存,就以阿里云的redis为例(用docker也可以安装)
【3】用RDM连接后可以界面化操作redis
【4】执行一些基本的控制台操作命令
**************************************************************************************************************************************************************
11、RedisTemplate与序列化机制
【1】redis的startes
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
【2】数据类型字符串String、List 列表、Set集合、Hash散列、Zset集合
【3】properties配置
# redis
spring.redis.host=wdfgdzx.top
spring.redis.port=6379
spring.redis.password=s19911009!
spring.redis.database=0
【4】测试相关方法
(1)保存对象需要序列化
(2)以JSON保存数据
(3)存对象都是二进制,来改变其序列化规则
package com.day.study.config;
import com.day.study.pojo.Employee;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, Employee> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws Exception {
RedisTemplate<Object, Employee> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Employee> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Employee.class);
redisTemplate.setDefaultSerializer(jackson2JsonRedisSerializer);
return redisTemplate;
}
}
(4)方法
package com.day.study.controller;
import com.day.study.mapper.BigMapper;
import com.day.study.pojo.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Controller {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
RedisTemplate<Object, Employee> redisTemplate;
@Autowired
BigMapper bigMapper;
@Test
public void contextLoads() {
//stringRedisTemplate.opsForValue().append("msg", "Hello");
//System.out.println(stringRedisTemplate.opsForValue().get("msg"));
//stringRedisTemplate.opsForList().leftPush("myList", "1");
//stringRedisTemplate.opsForList().leftPush("myList", "2");
Employee employee = new Employee();
employee.setId(1);
employee.setEmail("wdfgdzx@163.com");
redisTemplate.opsForValue().set("emp01", employee);
}
}
**************************************************************************************************************************************************************
12、缓存-自定义CacheManager
【1】被RedisCacheManager接管了
【2】技术更新太快了,老师一堂课不如网上百度一下
package com.day.study.config;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
@Configuration
public class MyRedisConfig {
@Bean
public RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties) {
CacheProperties.Redis redisProperties = cacheProperties.getRedis();
RedisCacheConfiguration config = RedisCacheConfiguration
.defaultCacheConfig();
config = config.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
//还有另外一种写法
if (redisProperties.getTimeToLive() != null) {
config = config.entryTtl(redisProperties.getTimeToLive());
}
if (redisProperties.getKeyPrefix() != null) {
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
}
if (!redisProperties.isCacheNullValues()) {
config = config.disableCachingNullValues();
}
if (!redisProperties.isUseKeyPrefix()) {
config = config.disableKeyPrefix();
}
return config;
}
}
【3】名称也可以自定义 @Cacheable(value = "files", key = "'selfDefineName'")
【4】这个MyRedisConfig 就比较实用了,适用多个类
package com.day.study.controller;
import com.day.study.mapper.BigMapper;
import com.day.study.pojo.Department;
import com.day.study.pojo.Employee;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class BigController {
@Resource
BigMapper bigMapper;
@Cacheable(cacheNames = "employee", key = "#employee.id")
@GetMapping("/selectEmployee")
public Employee selectEmployee(Employee employee) {
return bigMapper.selectEmployeeById(employee);
}
@CachePut(cacheNames = "employee", key = "#employee.id")
@GetMapping("/updateEmployee")
public Employee updateEmployee(Employee employee) {
bigMapper.updateEmployee(employee);
return employee;
}
@CacheEvict(cacheNames = "employee", key = "#employee.id")
@GetMapping("/deleteEmployee")
public Employee deleteEmployee(Employee employee) {
System.out.println("执行删除...");
//bigMapper.deleteEmployee(employee);
return employee;
}
@Cacheable(cacheNames = "department", key = "'department'")
@GetMapping("/selectDepartment")
public Department department(Department department) {
return bigMapper.selectDepartmentById(department);
}
}
【5】也可以拿到缓存模板直接使用
@Resource
private StringRedisTemplate stringRedisTemplate;
**************************************************************************************************************************************************************
13、消息中间件概述
【1】用户注册—>发邮件—>发短信怎么优化处理?
(1)写数据库后:多线程边发邮件,边发短信
(2)消息队列,写数据库后,写进消息队列(消息队列再发短信、发邮件)
【2】应用解耦:订单 VS 库存
(1)订单、库存单独抽取出来
(2)订单消费、库存订阅消息队列
【3】流量削峰
用户请求—>消息队列(1W+)—>秒杀业务处理
【4】消息服务:消息代理(服务器)、目的地
(1)目的地包括:队列(Queue)-点对点通信、主体(Topic)-发布订阅模式
(2)点对点 A 发给队列—>队列—>B B从队列收
(3)发布订阅:A发布到主题里,B C D同时监听收到
【5】JMS:JAVA MESSAGE SERVICE;Java消息服务
(1)基于JVM消息代理规范,如ActiveMQ、HornetMQ就是JMS的实现
【6】AMQP高级消息队列协议,兼容JMS,大名鼎鼎的RabbitMQ就是AMQP的实现
【7】Springboot的配置
(1)RabbitAutoConfiguration
**************************************************************************************************************************************************************
14、RabbitMQ概述
【1】RMQ:核实概念-Message(消息头、消息体)
(1)路由键、优先权、是否持久化存储
(2)生产者:消息生产者、发布给交换器
(3)交换器:四种类型direct点对点;fanout、topic、headers实现发布订阅模型
(4)消息队列:用来保存消息的
(5)绑定:交换器与队列之间的绑定关系
(6)网络连接:如TCP连接
(7)Channel:信道,一个TCP连接可以开多个信道
(8)消费者
(9)虚拟主机
(10)Broke消息代理,就是服务器
**************************************************************************************************************************************************************
15、RMQ的核心运行机制
【1】增加了Exchange(四种类型)与Binding的角色
(1)direct 直连型
(2)Fanout Exchange,接收到消息后,会分发给它自己的所有队列,速度最快
(3)Topic Exchange,支持模糊匹配(感觉不实用)
**************************************************************************************************************************************************************
16、RMQ安装测试
【1】docker pull rabbitmq:3-management
【2】docker run -d -p 5672:5672 -p 15672:15672 --name my_rabbitmq 镜像ID
【3】访问http://192.168.0.105:15672/
【4】账号+密码 guest guest
【5】添加三个交换器
exchange.direct direct D
exchange.fanout fanout D
exchange.topick topic D
【6】建立四个队列
wdfgdzx
wdfgdzx.news
wdfgdzx.emps
it.news
【7】绑定交互器与队列
【8】可以在界面测试不同模式发送消息,消息的接受情况
**************************************************************************************************************************************************************
17、RabbitTemplate发送接受消息与序列化机制
【1】引入MAVEN依赖
<!--amqp-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
【2】RabbitTemplate类似于RedisTemplate
package com.day.study.controller;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Controller {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void contextLoads() {
// rabbitTemplate.send(exchange,routeKey,message);
// rabbitTemplate.convertAndSend(exchange, routeKey, object);
Map<String, Object> map = new HashMap<>();
map.put("msg", "这是第一个消息");
map.put("data", Arrays.asList("Hello", 123, false));
rabbitTemplate.convertAndSend("exchange.direct",
"wdfgdzx.news",
map);// 对象默认被序列化以后发送出去
}
@Test
public void receive() {
// 接受数据
Object object = rabbitTemplate.receiveAndConvert("wdfgdzx.news");
System.out.println(object.getClass());
System.out.println(object);
}
}
【3】配置存储JSON
package com.day.study.config;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRMQConfig {
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
}
【4】其他模式只需要指定交换器和队列就行了,听君一席话,胜过单独学RMQ,使用主义最重要!!!
**************************************************************************************************************************************************************
18、消息监听@RabbitLister与@EnableRabbit
【1】@RabbitListener(queues = "wdfgdzx.news")+@EnableRabbit // 开启基于注解RMQ
开启自动监听,并实时接受消息
【2】Service
package com.day.study.service;
import com.day.study.pojo.Employee;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
@Service
public class EmployeeService {
@RabbitListener(queues = "wdfgdzx.news")
public void receive(Employee employee) {
System.out.println("收到消息..." + employee);
}
@RabbitListener(queues = "wdfgdzx.news")
public void receive02(Message message) {
System.out.println("收到消息..." + message.getMessageProperties() + "..." + message.getBody());
}
}
【3】启动类
package com.day.study;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@EnableCaching
@SpringBootApplication
@MapperScan("com.day.study.mapper")
@EnableRabbit // 开启基于注解RMQ
public class SpringBoot {
public static void main(String[] args) {
SpringApplication.run(SpringBoot.class, args);
}
}
【4】测试控制器
package com.day.study.controller;
import com.day.study.pojo.Employee;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class Controller {
@Autowired
RabbitTemplate rabbitTemplate;
@Test
public void contextLoads() {
// rabbitTemplate.send(exchange,routeKey,message);
// rabbitTemplate.convertAndSend(exchange, routeKey, object);
Employee employee = new Employee();
employee.setId(1);
employee.setName("陈翔");
employee.setEmail("cx@163.com");
rabbitTemplate.convertAndSend("exchange.fanout",
"wdfgdzx.news",
employee);// 对象默认被序列化以后发送出去
}
@Test
public void receive() {
// 接受数据
Object object = rabbitTemplate.receiveAndConvert("wdfgdzx.news");
System.out.println(object.getClass());
System.out.println(object);
}
}
**************************************************************************************************************************************************************
19、AmqpAdmin管理组件的使用
【1】帮助我们创建删除交换器和队列
@Autowired
AmqpAdmin amqpAdmin;
@Test
public void createExchange() {
// 交换器
amqpAdmin.declareExchange(new DirectExchange("amqpadmin.exchange"));
System.out.println("创建完成");
// 队列
amqpAdmin.declareQueue(new Queue("amqpadmin.queue", true));
System.out.println("创建完成");
// 绑定关系
amqpAdmin.declareBinding(new Binding("amqpadmin.queue",
Binding.DestinationType.QUEUE,
"amqpadmin.exchange",
"amqp.Hello", null));
System.out.println("绑定成功");
}
**************************************************************************************************************************************************************
20、Elasticsearch概述与安装
【1】ElasticSearch是全文搜索引擎的首选
【2】环境搭建docker pull elasticsearch
【3】docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name es 镜像ID
【4】docker rm -f $(docker ps -a -q)
【5】访问http://192.168.0.105:9200/ 能看到JSON说明就安装成功了
**************************************************************************************************************************************************************
21、ES入门
【1】JSON代表数据对象
【2】索引(库)、类型(表)、文档(记录)、属性(列)
【3】PUT /megacorp/employee/1
{
"fristName":"陈",
"lastName":"翔",
"age":25,
"about":"I love china",
"interests":["ball","play"]
}
【4】用postman发送请求,注意是PUT方式http://192.168.0.105:9200/megacorp/employee/1
(1)然后body-raw-JSON
(2)复制粘贴数据,发起请求即可
{
"fristName":"陈",
"lastName":"翔",
"age":25,
"about":"I love china",
"interests":["ball","play"]
}
【5】寻找数据 GET http://192.168.0.105:9200/megacorp/employee/3
【6】其他操作
(1)HEAD请求,看是否存在,存在200,不存在404 http://192.168.0.105:9200/megacorp/employee/3
(2)DELETE删除请求http://192.168.0.105:9200/megacorp/employee/3
(3)更新也是用PUT,会看到_version有变化
【7】GET http://192.168.0.105:9200/megacorp/employee/_search 查所有
【8】按条件找
http://192.168.0.105:9200/megacorp/employee/_search?q=lastName:球
【9】用JSON规则匹配查找
(1)POST http://192.168.0.105:9200/megacorp/employee/_search
(2)JSON过滤规则
{
"query":{
"match":{
"lastName":"头"
}
}
}
(3)其他过滤规则
{
"query":{
"match":{
"about":"china"
}
}
}
(4)找到并高亮
{
"query":{
"match":{
"about":"china"
}
},
"highlight":{
"fields":{
"about":{}
}
}
}
**************************************************************************************************************************************************************
22、Springboot整合Jest操作ES
【1】引入依赖
<!--elasticsearch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
【2】两种技术交互Jest与SpringData ElasticSearch
(1)Jest 需要导入工具包
(2)我觉得还是用官方的SpringData操作
**************************************************************************************************************************************************************
23、整合SpringDataElasticSearch
【1】注意版本适配关系
【2】如果不适配,需要将es版本调成一致(可以从maven依赖查看版本)
(1)docker pull elasticsearch:6.4.3
(2)/usr/share/elasticsearch/config
(3)docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9200:9200 -p 9300:9300 --name es 01e5bee1e059
(4)docker rm -f $(docker ps -a -q)
(5)docker exec -it es /bin/bash 进到docker里yum install net-tools,可以用netstat -lnp|grep 9查看端口监听情况
(6)访问http://192.168.0.105:9200/,注意cluster_name对应的值,这个很重要
(7)历经艰险,ES重要配置成功了
【3】解决es与redis的netty-transport版本冲突
public class SpringBoot {
public static void main(String[] args) {
// 解决es与redis的netty-transport版本冲突
System.setProperty("es.set.netty.runtime.available.processors", "false");
SpringApplication.run(SpringBoot.class, args);
}
}
【4】插入ES数据
@Resource
EmployeeRepository employeeRepository;
@RequestMapping("/insertEs")
public String insertEs(Employee employee) {
employee.setId(110161);
employee.setName("陈翔...");
employeeRepository.index(employee);
return "es 插入成功";
}
【5】查询ES数据
http://192.168.0.105:9200/wdfgdzx/employee/_search
【6】还可以通过另一种方式
(1)service里写方法
package com.day.study.service;
import com.day.study.pojo.Employee;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
public interface EmployeeRepository extends ElasticsearchRepository<Employee, Integer> {
public List<Employee> findByEmployeeName(String name);
}
(2)controller写查询
@RequestMapping("/selectEs")
public List<Employee> selectEs(Employee employee) {
List<Employee> employeeList = employeeRepository.findByEmployeeName("陈");
return employeeList;
}
(3)浏览器查询http://localhost:8080/selectEs
[{"id":110161,"employeeName":"陈翔...","email":null}]
**************************************************************************************************************************************************************
24、Springboot执行任务
【1】异步、定时、发邮件任务
【2】异步类
package com.day.study.service;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
@Async //告诉Spring 这是一个异步方法
public void say() throws InterruptedException {
Thread.sleep(3000);
System.out.println("处理数据中...");
}
}
【3】启动类
@EnableAsync // 开启异步注解
【4】Controller
@RequestMapping("/say")
public String say() throws InterruptedException {
asyncService.say();
return "调用成功...";
}
**************************************************************************************************************************************************************
25、定时任务
【1】比如每天凌晨,跑前一天的数据
【2】类
package com.day.study.service;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
@Service
public class ScheduleService {
// 六位表达式
@Scheduled(cron = "0 * * * * MON-SAT") //每整分钟就打印一个Hello
public void say() {
System.out.println("Hello...");
}
}
【3】启动类
@EnableScheduling
【4】每分钟都会执行一次方法
【5】具体的写法可以百度
**************************************************************************************************************************************************************
26、邮件任务
【1】依赖
<!--mail-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
【2】配置
# mail
spring.mail.host=220.181.15.111
spring.mail.username=wdfgdzx@126.com
spring.mail.password=GAVHJSFHPCUOYMPP
【3】测试发送邮件
@Autowired
JavaMailSenderImpl javaMailSender;
@org.junit.Test
public void textMail() {
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
//邮件设置
simpleMailMessage.setSubject("通知-会议");
simpleMailMessage.setText("今晚7:30开会");
simpleMailMessage.setTo("wdfgdzx@163.com");
simpleMailMessage.setFrom("wdfgdzx@126.com");
javaMailSender.send(simpleMailMessage);
}
@org.junit.Test
public void textMailTwo() throws Exception {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setSubject("通知-会议");
mimeMessageHelper.setText("<b style='color:red'>今晚7:30开会</b>", true);
mimeMessageHelper.setTo("wdfgdzx@163.com");
mimeMessageHelper.setFrom("wdfgdzx@126.com");
//上传附件
mimeMessageHelper.addAttachment("1.jpg", new File("src/main/resources/mapper/BigMapper.xml"));
javaMailSender.send(mimeMessage);
}
**************************************************************************************************************************************************************
27、Springboot与安全
【1】Spring Security
【2】就是为了实现认证和授权
【3】依赖引入
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
【4】引入指定页面thymeleaf
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
【5】@org.springframework.stereotype.Controller
**************************************************************************************************************************************************************
28、权限控制-注销
【1】配置类
package com.day.study.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@EnableWebSecurity //内部带Configuration所以无需再次标注
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
//super.configure(httpSecurity);
// 定制请求的授权规则
httpSecurity.authorizeRequests().antMatchers("/index")
.permitAll()
.antMatchers("/low/**").hasRole("VIP")
.antMatchers("/high/**").hasRole("H VIP");
// 开启自动配置的登录功能
httpSecurity.formLogin();
// 1、/login来到登录页 2、重定向到error表示登录失败 3、更多详析规则
// 效果就是没有权限,就来到登录页面
// 开启自动配置的注销功能
httpSecurity.logout().logoutSuccessUrl("/index");
// 1、会清空session 2、注销成功跳转的页面
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//super.configure(auth);
// 按道理从数据库拿,但是这里演示就存内存
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("VIP").password(new BCryptPasswordEncoder().encode("123")).roles("VIP")
.and()
.withUser("H VIP").password(new BCryptPasswordEncoder().encode("123")).roles("H VIP");
}
}
【2】配置@org.springframework.stereotype.Controller
package com.day.study.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
@org.springframework.stereotype.Controller
public class Controller {
@RequestMapping("index")
public ModelAndView index() {
ModelAndView mv = new ModelAndView("index");
return mv;
}
@RequestMapping("low")
public ModelAndView low() {
ModelAndView mv = new ModelAndView("low");
return mv;
}
@RequestMapping("high")
public ModelAndView high() {
ModelAndView mv = new ModelAndView("high");
return mv;
}
}
【3】没有权限看不到,这个就不配置了
(1)界面写的也有点冗余,不如用vue写了
**************************************************************************************************************************************************************
30、定制登录页
【1】就是使用cookie记录用户信息
【2】可以定制Security的登录页面
**************************************************************************************************************************************************************
31、Springboot与分布式
【1】Dubbo/Zookeeper、Springboot/Cloud
【2】注册中心
**************************************************************************************************************************************************************
32、Zookeeper安装
【1】docker rm -f $(docker ps -a -q)
【2】docker pull zookeeper
【3】docker run --name zk -p 2181:2181 --restart always -d 979f6ccbba92
【4】启动成功
**************************************************************************************************************************************************************
33、整合Dubbo与Zookeeper
【1】整合步骤
(1)服务提供者注册到注册中心
(2)引入依赖
(3)配置properties
(4)启动服务
**************************************************************************************************************************************************************
34、SpringCloud的注册中心
【1】是分布式的整体解决方案
【2】服务发现、负载均衡、断路器、服务网关、分布式配置
【3】引依赖
<!--eureka server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
【4】配置properties
server.port=8083
# 实例的主机名
eureka.instance.hostname=eureka-server
# 不把自己注册
eureka.client.register-with-eureka=false
# 不获取服务注册信息
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://localhost:8083/eureka/
【5】访问http://localhost:8083可以看到注册中心
【6】provider
server.port=8081
spring.application.name=provider
# 实例的主机名 注册服务时使用IP地址
eureka.instance.prefer-ip-address=true
eureka.client.service-url.defaultZone=http://localhost:8083/eureka/
【7】可以配置多个端口指向注册中心的
**************************************************************************************************************************************************************
36、配置消费者
【1】properties
server.port=8082
spring.application.name=consumer
# 实例的主机名 注册服务时使用IP地址
eureka.instance.prefer-ip-address=true
eureka.client.service-url.defaultZone=http://localhost:8083/eureka/
【2】Controller
package com.day.consumer.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
public class ConsumerController {
@Resource
RestTemplate restTemplate;
@RequestMapping("buyTicket")
public String buyTicket(String name) {
String getTicketFromServer = restTemplate.getForObject("http://PROVIDER/getTicket", String.class);
return name + "购买了" + getTicketFromServer;
}
}
【3】卧槽惊艳了,挺好用的,牛批
**************************************************************************************************************************************************************
37、Springboot开发热部署
【1】推荐使用官方的spring-boot-devtools,Ctrl+F9
【2】没必要呀,手动重启不就行了
**************************************************************************************************************************************************************
38、Springboot与监控管理!!!!
【1】运维时重要的功能 spring-boot-starter-actuator
【2】依赖
<!--actuator监控模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
【3】配置properties
management.endpoints.web.exposure.include=*
management.endpoints.web.base-path=/
management.endpoint.health.show-details=always
management.endpoint.info.enabled=true
【4】访问监控信息
(1)http://localhost:8080/health 健康信息
(2)http://localhost:8080/auditevents 审计事件
(3)http://localhost:8080/beans 组件信息
(4)http://localhost:8080/info 配置文件里的info开头的配置
(5)http://localhost:8080/dump 线程信息
(6)http://localhost:8080/env 当前环境信息
(7)http://localhost:8080/mappings 请求映射信息
(8)http://localhost:8080/metrics 应用的各项指标
**************************************************************************************************************************************************************
39、定制端点
【1】改变端点的ID等信息
【2】开启和关闭某个端点
【3】定制根路径
【4】改变端点对应的端口号
**************************************************************************************************************************************************************
40、定制HealthIndicator 【1】这个监控可以检查不健康的配置 spring.redis.host=localhost <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> 【2】访问http://localhost:8080/health,redis的配置不正确 {"status":"DOWN","details":{"diskSpace":{"status":"UP","details":{"total":120032587776,"free":35320840192,"threshold":10485760}},"redis":{"status":"DOWN","details":{"error":"org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to localhost:6379"}}}} 【3】定制化: (1)实现HealthIndicator接口 (2)名字 XXXHealthIndicator (3)加入容器中 【4】定制化实例 package com.day.study.health; 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.up(); 代表健康 return Health.down().withDetail("msg", "服务异常").build(); } } 【5】访问http://localhost:8080/health 的效果 {"status":"DOWN","details":{"my":{"status":"DOWN","details":{"msg":"服务异常"}},"diskSpace":{"status":"UP","details":{"total":120032587776,"free":35317649408,"threshold":10485760}},
"redis":{"status":"DOWN","details":{"error":"org.springframework.data.redis.RedisConnectionFailureException: Unable to connect to Redis; nested exception is io.lettuce.core.
RedisConnectionException: Unable to connect to localhost:6379"}}}}