avatar

SpringBoot

SpringBoot与缓存

Spring缓存抽象

缓存注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Cache

缓存接口,定义缓存操作。实现又:RedisCache、EhCacheCache、ConcurrentMapCaChe等

CacheManager

缓存管理器,管理各种缓存(Cache)组件

@Cacheable

主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

@CacheEvict

清空缓存

@CachePut

保证方法被调用,又希望结果被缓存

@EnableCaching

开启基于注解的缓存

keyGenerator

缓存数据时key生成策略

serialize

缓存数据时value序列化策略

导入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>

启动类添加注解

1
@EnableCaching

详解

@Cacheable

主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

在ServerImpl方法上添加@Cacheable

@Cacheable参数说明

  1. cacheName/value:指定缓存组件的名字;将方法的返回值结果放在哪个缓存中,是数组的方式,可以指定多个缓存

  2. key:缓存数据使用的key:可以用它来指定,默认是使用方法参数的值

    编写SpEL指定 key

  3. keyGenerator:key生成器,可以自己指定key的生成器的组件id

    key/keyGenertor 二选一

  4. cacheManager:指定缓存管理器:或者cacheResolver指定获取解析器

  5. condition:指定符合条件情况下才缓存

  6. unless:否定缓存:当unless指定的条件为true,方法的返回值就不会被缓存,可以获得结果进行判断

  7. sync:是否使用异步模式

@CachPut

即调用方法,又更新缓存数据,修改了数据库的某个数据,同时更新缓存

运行时机:先调用目标方法,在将结果缓存

key要和要更新缓存的key一样

@CacheEvict

缓存清除,如删除数据之后删除缓存

参数说明:

  1. allEntries = false 删除对应key里的所有缓存数据,true为删除所有

  2. beforeInvocation = false, 缓存的清除是否在方法之前执行,true为是

    注意:开启之后如果方法出错,缓存还是会被清除

@Caching

指定多个缓存规则

1
2
3
4
5
6
7
8
9
@Caching(
cacheable = {
@Cacheable(value="xxx",key="xxx")
},
put = {
@CachePut(value="xxx",key="xxx"),
@CachePut(Value="xxx",key="xxx")
}
)

@CacheConfig

定义在类上,抽取缓存的公共配置

@CacheConfig(cacheNames=”xxx”)意思是所有的key都叫这个名字

使用Redis缓存数据

导入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

spring会自动配置Redis,实实用缓存注解缓存数据的时候默认就使用Redis缓存数据了

SpringBoot与消息

RabbitMQ简介

https://jingganghuluwa.github.io/2020/03/19/RabbitMQ/

SpringBoot与检索

中文网https://www.elastic.co/guide/cn/elasticsearch/guide/current/_retrieving_a_document.html

检索

使用docker安装elasticsearch

运行

1
docker run -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -d -p 9200:9200 -p 9300:9300 --name ES01 容器ID

配置elasticsearch

进入elasticsearch,安装vim

1
yum install vim

进入config目录下修改elasticsearch.yml

1
2
3
4
cluster.name: "docker-cluster"   
network.host: 0.0.0.0
http.cors.enabled: true
http.cors.allow-origin: "*"

测试连接成功

浏览器安装插件 Elasticsearch Head方便查看信息

浏览器打开http://192.168.156.128:9200/

概念

关系图

类似于MySQL

索引 = 数据库

类型 = 表

文档 = 一行数据

属性 = 一行数据的某个属性

创建一个雇员目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
PUT /megacorp/employee/1
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}

PUT /megacorp/employee/2
{
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ]
}

PUT /megacorp/employee/3
{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}

使用postman操作

检索刚刚存入的数据

其他请求类型

DELETE 删除

HEAD 判断是否有数据,有数据状态码为200,没有的话就404

轻量搜索

查询所有的信息

1
GET http://192.168.156.128:9200/_search

文档里都有不写了

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_search_lite.html

SpringBoot整合elasticsearch

导入依赖

1
2
3
4
5
6
7
8
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

配置application.properties

1
2
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=192.168.156.128:9300

在 pojo包下 编写实体类Book

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package cn.duxiu.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private Integer id;
private String bookName;
private String author;
}

在repository包下编写BookRepository接口

1
2
3
4
5
6
7
package cn.duxiu.repository;

import cn.duxiu.pojo.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

public interface BookRepository extends ElasticsearchRepository<Book,Integer> {
}

编写测试类测试

1
2
3
4
5
6
7
@Test
public void t1(){
Book book = new Book();
bookRepository.index(book);
}

}

在BookRepository中自定义方法,规则和SpringDataJPA相似

1
2
//定义根据BookName模糊查询方法
public List<Book> findByBookNameLike(String bookName);

测试

1
2
3
4
5
@Test
public void t2(){
List<Book> list = bookRepository.findByBookNameLike("游");
list.forEach(System.out::println);
}

参考Spring官方文档

https://docs.spring.io/spring-data/elasticsearch/docs/3.2.6.RELEASE/reference/html/#new-featuresv

SpringBoot与任务

异步

启动类上添加注解

1
2
3
4
/**
* 开启异步注解
*/
@EnableAsync

service包下编写AsyncService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Service
public class AsyncService {
/**
* 告诉Spring这是一个异步方法
*/
@Async
public void hello(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("处理数据中...");

}
}

controller包下编写AsyncController

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class AsyncController {

@Autowired
AsyncService asyncService;

@GetMapping("/hello")
public String hello(){
asyncService.hello();
return "success";
}
}

使用了异步之后,立即响应输出了success,随后”处理数据中…”也输出完毕

而未使用异步就会等”处理数据中…”也输出完毕再打印success

定时任务

启动类上添加注解

1
2
3
4
/**
* 开启定时任务注解功能
*/
@EnableScheduling

在service包写编写ScheduledService

1
2
3
4
5
6
7
8
9
10
11
@Service
public class ScheduledService {
/**
* second(秒), minute(分), hour(时), day of month(日), month(月), day of week(周几).
* 0 * * * * MON-FRI
*/
@Scheduled(cron = "0 * * * * MON-FRI")
public void hello() {
System.out.println("hello....");
}
}

邮件任务

导入依赖

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

以QQ邮箱发送为例

设置QQ邮箱先进入QQ邮箱账户设置

得到授权码

配置application.properties

1
2
3
spring.mail.username=1839743406@qq.com
spring.mail.password=授权码
spring.mail.hot=smtp.qq.com

普通邮件发送

编写测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Autowired
JavaMailSenderImpl mailSender;

@Test
public void contextLoads() {
SimpleMailMessage message = new SimpleMailMessage();
//邮件设置
//邮件标题
message.setSubject("通知,今晚开会");
//邮件内容
message.setText("今晚七点开会");
//发给谁
message.setTo("jinganghuluwaa@gmail.com");
//谁发的
message.setFrom("1839743406@qq.com");
mailSender.send(message);
}

成功发送

复杂邮件发送

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void t2() throws Exception {
//1、创建一个复杂的消息邮件
MimeMessage mailMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mailMessage,true);

//邮件设置
//邮件标题
helper.setSubject("通知,今晚开会");
//邮件内容
helper.setText("<b style='color:red'>今晚七点开会</b>",true);
//发给谁
helper.setTo("jinganghuluwaa@gmail.com");
//谁发的
helper.setFrom("1839743406@qq.com");

//上传文件
helper.addAttachment("1.jpg",new File("F:\\壁纸\\Minecraft.jpg"));
helper.addAttachment("2.jpg",new File("F:\\壁纸\\Minecraft2.jpg"));
mailSender.send(mailMessage);
}

SpringBoot与安全

https://jingganghuluwa.github.io/2020/03/18/Shiro/

SpringBoot与分布式

分布式应用

Zookeeper和Dubbo

Docker安装Zookeeper

拉取镜像

1
docker pull zookeeper

运行

1
docker run --privileged=true --restart=always -d --name zookeeper --publish 2181:2181 -d zookeeper:latest

常用zookepper操作命令

进入容器后

1
2
3
zkCli.sh 连接客户端
ls/ 查看根目录下包含的节点
ls /services 查看已注册进来的服务

创建工程

new一个Module

创建Spring Inirializr

勾选 web 模块,这个是买票子工程

在service包下创建TicketService,模拟卖票

1
2
3
4
public interface TicketService {

public String getTicket();
}

创建实现类TicketService

1
2
3
4
5
6
7
public class TicketServiceImpl implements TicketService {

@Override
public String getTicket() {
return "《文体两开花》";
}
}

再创建一个module,模拟买票,也就是用户,消费者

service包下创建UserService

1
2
3
public class UserService {

}

服务流程

1、将服务提供则注册到注册中心

在模块 Ticket 中导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>

<!--引入zookeeper的客户端工具-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>

配置 Ticket 下的application.properties

1
2
3
dubbo.application.name=provider-ticket
dubbo.registry.address=zookeeper://192.168.156.128:2181
dubbo.scan.base-packages=cn.duxiu.ticket.service

修改 TicketServiceImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* @service为dubbo包下的Service
* 将服务发布出去
* @EnableDubbo 开启基于注解的Dubbo
*/
@Component
@Service
@EnableDubbo
public class TicketServiceImpl implements TicketService {

@Override
public String getTicket() {
return "《文体两开花》";
}
}

启动 Ticket,然之后会报错

启动后在消费者 Consumer-user 下导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--dubbo依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>

<!--引入zookeeper的客户端工具-->
<dependency>
<groupId>com.github.sgroschupf</groupId>
<artifactId>zkclient</artifactId>
<version>0.1</version>
</dependency>

配置Consumer-user下的application.properties

1
2
dubbo.application.name=consumer-user
dubbo.registry.address=zookeeper://192.168.156.128:2181

将Ticket下的 service整个包复制到 Consumer 下

只需要TicketService和包目录,其他的可以删掉

Consumer下编写测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootTest
class ConsumerUserApplicationTests {

@Autowired
UserService userService;


@Test
void contextLoads() {
userService.hello();
}

}

重启Ticket,必须要保证Ticket运行,运行测试类

完事

SpringBoot和SpringCloud

创建工程 Empty Project

创建模块 eureka-server 注册中心

依赖选择

创建第二个模块,provoder-titck 服务提供者

选择依赖, 服务注册和发现 模块

创建第三个模块,consumer-user 服务消费者

配置eureka-seerver 里的 application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server:
port: 8761
eureka:
instance:
#eraeka实例的主机名
hostname: eureka-server

client:
# 不把 eureka-server 本身注册到eureka里去
register-with-eureka: false
#不从eureka上来获取服务的注册信息
fetch-registry: false
# 指定eureka注册中心地址,其它服务就是在这注册
service-url:
defaultZone: http://192.168.156.128:8761/eureka/

eureka-seerver 启动类上添加注解

1
2
3
4
5
/**
* 注册中心
* @EnableEurekaServer启用注册中心的功能
*/
@EnableEurekaServer

运行

配置provider-ticket 服务提供者 下的application.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
server:
port: 8001
spring:
application:
name: provider-ticket

eureka:
instance:
# 注册服务的时候使用服务的ip地址
prefer-ip-address: true
client:
# 指定eureka注册中心地址,其它服务就是在这注册
service-url:
defaultZone: http://localhost:8761/eureka/

在service 包下编写 TicketService

1
2
3
4
5
6
7
@Service
public class TicketService {

public String getTicket(){
return "《文体两开花》";
}
}

在controller 下编写 TicketController

1
2
3
4
5
6
7
8
9
10
11
@RestController
public class TicketController {

@Autowired
TicketService ticketService;

@GetMapping("/ticket")
public String getTicket() {
return ticketService.getTicket();
}
}

先重启 eureka-server 再启动 provider-ticket

浏览器访问 http://localhost:8001/ticket

注册中心

同一个应用部署多个实例注册到注册中心中

为了测试方便 TicketService 加上一句输出

1
2
3
4
5
6
7
8
@Service
public class TicketService {

public String getTicket(){
System.out.println("8001");
return "《文体两开花》";
}
}

将provider-ticket 打包

双击打包

将打好的包复制出来,做好标记

继续 更改 yml 文件 端口改成 8002 输出语句改成8002 打包

从文件夹内进入CMD 运行 两个jar 包

再去注册中心瞅一眼

成功

consumer-user消费

配置consumer-user模块的application.yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
spring:
application:
name: consumer-user
server:
port: 8200
eureka:
instance:
# 注册服务的时候使用服务的ip地址
prefer-ip-address: true
client:
# 指定eureka注册中心地址,其它服务就是在这注册
service-url:
defaultZone: http://localhost:8761/eureka/

修改consumer-user模块的启动类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 消费者
* @EnableDiscoveryClient开启发现服务功能
*/
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerUserApplication {

public static void main(String[] args) {
SpringApplication.run(ConsumerUserApplication.class, args);
}

/**
* @LoadBalanced使用负载均衡机制
* restTemplate() 用来发送HTTP请求调用服务
* @return
*/
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}

controller包下创建

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class UserController {

@Autowired
RestTemplate restTemplate;

@GetMapping("/buy")
public String buyTicket(String name){
String s = restTemplate.getForObject("http://PROVIDER-TICKET/ticket", String.class);
return name + "购买了" + s;
}
}

运行 eureka-server,再运行刚刚那两个打好包的 provider-ticket,再运行consumer-user

查看注册中心

调用 consumer-user 的买票方法

因为使用了负载均衡,查看 cmd 启动的 provider- ticket

使用轮询的方式负载均衡

热部署

IDEA安装插件

JRebel and XRebel for IntelliJ

启动项目会弹个窗口出来,点击红色箭头标的地方

https://blog.csdn.net/qierkang/article/details/95095954

教程

文章作者:
文章链接: https://huohuohuohuohuohuo.github.io/2020/03/26/SpringBoot/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论