前言
项目主体源码可以从SpringBoot获得,喜欢的朋友可以点个star~。
springboot与缓存
缓存注解
命令 | 介绍 |
---|---|
Cache | 缓存接口,定义缓存操作。实现有:RedisCache、EhCacheCache、ConcurrentMapCache等 |
CacheManager | 缓存管理器,管理各种缓存(cache)组件 |
@Cacheable | 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存 |
@CacheEvit | 清空缓存 |
@CachePut | 保证方法被调用,又希望结果被缓存 |
@EnableCache | 开启基于注解的缓存 |
KeyGenerator | 缓存数据时key的生成策略 |
serialize | 缓存数据时value序列化策略 |
缓存基本步骤
a、在application里添加注解@EnableCaching
b、在service层添加注解@Cacheable(cacheNames = {“tUser”})
将方法的运行结果进行缓存,以后要相同的数据直接从缓存中取
CacheManager管理多个Cache组件,对缓存的真正的CRUD操作在Cache组件中,每个缓存组件都有唯一的名字
以下介绍几个常用属性:
属性名 | 介绍 |
---|---|
cacheNames/value | 指定缓存组件的名字 |
key | 缓存数据使用的key;可以用它指定。默认是使用方法参数的值;1-方法的返回值; |
keyGenerator | key的生成器;可以自己指定key的生成器的组件id;key/keyGenerator二选一 |
cacheManager/cacheResolver | 指定缓存管理器,或者使用cacheResolver指定获取解析器 |
condition | 指定符合条件情况下才缓存 |
unless | 否定缓存;当unless指定条件为true,方法的返回值不会被缓存;可以获取到结果进行判断 |
sycn | 是否使用异步模式,异步模式unless就不支持了 |
cache简单使用
//MyCacheConfig.class
@Configuration
public class MyCacheConfig {
@Bean("myKeyGenerator")
public KeyGenerator keyGenerator(){
return (o, method, objects) -> method.getName()+"["+ Arrays.asList(objects).toString() +"]";
}
}
//控制器实现demo
//默认key的方式
//@Cacheable(cacheNames = {"tUser"}, key = "#root.methodName+'['+#id+']'")
//keyGenerator
@Cacheable(cacheNames = {"tUser"}, keyGenerator = "myKeyGenerator", condition = "#a0 > 1", unless = "#a1 == 2")
@Override
public tUser findTUserById(Long id) {
tUser tUser = tUserMapper.findTUserById(id);
return tUser;
}
//@CachePut:即调用方法,又更新缓存数据;同步更新缓存
@CachePut(cacheNames = {"tUser"}, key = "#root.methodName+'['+#id+']'")
@Override
public int updateByPrimaryKeySelective(tUser record) {
return tUserMapper.updateByPrimaryKeySelective(record);
}
//allEntries是否删除所有缓存,allEntries=true
//beforeInvocation = false,缓存清除是否在方法执行之前
@CacheEvict(cacheNames = {"tUser"}, key = "#id")
@Override
public int deleteById(Long id) {
return tUserMapper.deleteById(id);
}
//@CacheConfig注解处理复杂缓存
redis添加
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Autowired
RedisTemplate redisTemplate;
/**
* Redis常见的五大数据类型
* String(字符串)、List(列表)、Set(集合)、Hash(散列)、ZSet(有序集合)
* stringRedisTemplate.opsForValue():字符串
* stringRedisTemplate.opsForList():列表
* stringRedisTemplate.opsForSet():集合
* stringRedisTemplate.opsForHash():散列
* stringRedisTemplate.opsForZSet():有序集合
*/
@Test
public void contextLoads() {
//stringRedisTemplate.opsForValue().append("msg", "hello");
String msg = stringRedisTemplate.opsForValue().get("msg");
System.out.println(msg);
}
}
Springboot&消息
概述
1、大多应用中,可以通过消息服务中间件来提升系统异步通信,扩展解耦合能力。
2、消息服务中的两个重要概念:消息代理(message broker)和目的地(destination),当消息发送者发送消息以后,将由消息代理接管,消息代理保证消息传递到指定的目的地。
3、消息队列主要有两种形式的目的地:a、队列(queue):点对点消息通信(point-to-point)。b、主题(topic):发布者(publish)/订阅者(subscribe)消息通信。
4、点对点式:a、消息发送者发送消息,消息代理将其放入一个队列中,消息接收者从队列中获取消息内容,消息读取后移除队列。b、消息只有唯一的发送者和接受者,但并不是说接接收者只能有一个。
5、发布订阅式:发送者发送消息到一个主题,多个接收者(订阅者)监听(订阅)这个主题,那么就会在消息到达时同时收到消息。
6、JMS(Java Message Service)Java消息服务:基于JVM消息代理规范。ActiveMQ、HornetMQ是JMS实现。
7、AMQP(Advanced Message Queuing Protocol):a、高级消息队列协议,也是一个消息代理的规范,兼容JMS。b、RabbitMQ是AMQP的实现。
8、Spring支持:a、spring-jms提供了对JMS的支持。b、spring-rabbit提供对AMQP的支持。c、需要connectionFactory的实现连接消息代理。d、提供JmsTemplate、RabbitTemplate来发送消息。e、@JmsListener(JMS)、@RabbitListener(AMQP)注解在方法上监听消息代理发布的消息。e、@EnableJms、@EnableRabbit开启支持。
9、Spring Boot自动配置:JmsAutoConfiguration、RabbitAutoConfiguration。
JMS&AMQP区别
JMS | AMQP | |
---|---|---|
定义 | Java api | 网络线级协议 |
跨语言 | 否 | 是 |
跨平台 | 否 | 是 |
Model | 提供两种消息模型:1.Peer-2-Peer。2.Pub/Sub | 提供五种消息模型:1.direct exchange。2.fanout exchange。3.topic exchange。4.headers exchange。5.system exchange。本质上讲如上四种和Pub/Sub并没有太大差别,只在路由机制上做了更详细的划分。 |
支持消息类型 | 多种消息类型:TextMessage、MapMessgae、BytesMessage、StreamMessage、ObjectMessage、Message(只有消息头和属性) | byte[]当实际应用时,有复杂的消息,可以将消息序列化后发送。 |
综合评价 | JMS定义了JAVA API层面的标准;在java体系中,多个client均可以通过JMS进行交互,不需要应用修改代码,但是其对跨平台的支持较差 | AMQP定义了wire-level层的协议标准,天然具有跨平台、跨语言特性。 |
RabbitMQ简介
RabbitMQ是一个由erlang开发的AMQP(Advanved Message Queue Protocol)的开源实现。
RabbitMQ核心概念
Message: 消息,消息是不具名的,它由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先级)、delivery-mode(指出该消息可能需要持久性存储)等。
Publish: 消息的生产者,也是一个向交换器发布消息的客户端应用程序。
Exchange:交换器,用来接收生产者发送的消息并将这些消息路由发送给服务器中的队列。Exchange有4种类型:direct(默认),fanout,topic,headers,不同的Exchange转发消息的策略有所区别。
Queue: 消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。
Binding: 绑定,用于消息队列和交换器之间的关联,一个绑定就是路由键将交换器与消息队列连接起来的路由规则,所有可以将交换器理解成一个由绑定构成的路由表。Exchange和Queue的绑定可以是多对多的关系。
Connection: 网络连接,比如一个TCP连接。
Channel: 信道,多个复用连接中的一条独立的双向数据流通道。信道是建立在TCP连接内的虚拟连接,AMPQ命令都是通过信道发送出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁TCP都是非常昂贵的开销,所以引入信道的概念,以复用一条TCP连接。
Consumer: 消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。
Virtual Host: 虚拟主机,表示一批交换器,消息队列和相关对象。虚拟主机是共享相同身份认证和加密环境的独立服务器域。每个vhost本质就是一个mini版的RabbitMQ服务器,拥有自己的队列、交换器、绑定和权限控制。vhost是AMQP概念基础,必须在连接时指定,RabbitMQ默认的vhost是"/"。
Broker: 表示消息队列服务器实体。
RabbitMQ安装
docker run -d -p 5672:5672 -p 15672:15672 --name xipikerRabbitMQ rabbitmq:management
打开浏览器输入http://[宿主机]:15672,username:guest,password:guest
direct:一对一,fanout:类似广播,topic:按照Routing key name进行选择发送。
RabbitMQ管理工具使用
打开浏览器输入http://[宿主机]:15672,username:guest,password:guest
由于比较基础使用比较简单这里不做记录,只要记住如上Rabbit简介几个基本参数,并做合理的配置
Springboot&RabbitMQ整合与基本使用
Pom.xml添加依赖
<!-- rabbitmq依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
application.yml添加依赖
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
#消息发送到交换机确认机制,是否确认回调
publisher-confirms: true
配置json序列化
@Configuration
public class MyAMQPConfig {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
测试类进行基本的测试操作
//book实体类
public class Book {
private String name;
private String code;
private Integer price;
public Book() {
}
public Book(String name, String code, Integer price) {
this.name = name;
this.code = code;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
@Autowired
AmqpAdmin amqpAdmin;
private Logger log = LoggerFactory.getLogger(this.getClass());
@Test
public void contextLoads() {
}
@Test
public void rabbitTest(){
Map<String, Object> map = new HashMap<>();
map.put("result","this is test");
map.put("status", true);
//单播,点对点
//map对象默认被序列化发送出去
rabbitTemplate.convertAndSend("exchange.direct", "atxipiker", map);
}
@Test
public void receive(){
//接收queue
Object atxipiker = rabbitTemplate.receiveAndConvert("atxipiker");
log.info("atxipiker-----{}",atxipiker);
}
//发送广播
@Test
public void sendMsg(){
Map<String, Object> map = new HashMap<>();
map.put("result","this is test three");
map.put("status", true);
rabbitTemplate.convertAndSend("exchange.fanout","", new Book("name","test",23));
}
//创建exchange
@Test
public void createExchange(){
//创建exhange
//amqpAdmin.declareExchange(new DirectExchange("amqpAdmin.exchange"));
//创建queue
//amqpAdmin.declareQueue(new Queue("amqpAdmin.queue"));
//创建绑定规则
//String destination, Binding.DestinationType destinationType, String exchange, String routingKey, Map<String, Object> arguments
//amqpAdmin.declareBinding(new Binding("amqpAdmin.queue", Binding.DestinationType.QUEUE, "amqpAdmin.exchange", "amqp.haha", null));
//删除del
}
测试消息队列监听(注意需要在启动类Application加上@EnableRabbit注解)
@Service
public class BookServiceImpl {
private Logger log = LoggerFactory.getLogger(this.getClass());
@RabbitListener(queues = "atxipiker.users")
public void receive(Book book){
log.info("book-----{}",book);
}
}
Springboot&检索
elasticsearch简介
Elasticsearch是一个分布式搜索服务,提供Restful API,底层基于Lucene,采用多shard(分片)的方式保证数据安全,并且提供自动resharding的功能。
Elasticsearch 是一个分布式、可扩展、实时的搜索与数据分析引擎。 它能从项目一开始就赋予你的数据以搜索、分析和探索的能力,这是通常没有预料到的。 它存在还因为原始数据如果只是躺在磁盘里面根本就毫无用处。
Elasticsearch 不仅仅只是全文搜索,我们还将介绍结构化搜索、数据分析、复杂的语言处理、地理位置和对象间关联关系等。 我们还将探讨如何给数据建模来充分利用 Elasticsearch 的水平伸缩性,以及在生产环境中如何配置和监视你的集群。
elasticsearch安装
docker pull elasticsearch:5.6 (注意:elasticsearch后面的版本一定要加,不然会报错,找不到镜像)
docker run -d -p 9200:9200 --name=“xipikerEs” -e ES_JAVA_OPTS="-Xms256m -Xmx256m" elasticsearch:5.6 (注意:可能由于你的物理机内存限制可以指定elasticsearch默认使用内存大小,通过"-e ES_JAVA_OPTS="-Xms256m -Xmx256m")
测试是否安装成功,浏览器输入http://[宿主机]:9200,返回一串json数据说明成功
{
"name" : "fFEqOE-",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "VpeaRq1lQaqRl_bVoPejBQ",
"version" : {
"number" : "5.6.14",
"build_hash" : "f310fe9",
"build_date" : "2018-12-05T21:20:16.416Z",
"build_snapshot" : false,
"lucene_version" : "6.6.1"
},
"tagline" : "You Know, for Search"
}
elasticsearch简单使用
插入索引 [PUT /megacorp/employee/i->i++]
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests": [ "sports", "music" ]
}
{
"first_name" : "Jane",
"last_name" : "Smith",
"age" : 32,
"about" : "I like to collect rock albums",
"interests": [ "music" ]
}
{
"first_name" : "Douglas",
"last_name" : "Fir",
"age" : 35,
"about": "I like to build cabinets",
"interests": [ "forestry" ]
}
删除索引 [DELETE /megacorp/employee/i]
检索文档 [GET /megacorp/employee/i]
轻量搜索 [GET /megacorp/employee/_search]
属性查询 [GET /megacorp/employee/_search?q=last_name:Smith]
查询表达式搜索 [GET /megacorp/employee/_search]
{
"query" : {
"match" : {
"last_name" : "Smith"
}
}
}
复杂表达式查询 [GET /megacorp/employee/_search]
{
"query" : {
"bool": {
"must": {
"match" : {
"last_name" : "smith" ![0f67842b8cc059137a88288e95115a18.png](evernotecid://9566E7CF-1AAB-48B5-A4A7-CD4AD30D20CA/appyinxiangcom/22984063/ENResource/p9)
}
},
"filter": {
"range" : {
"age" : { "gt" : 30 } ![782f998bab59d0221977c1c0eaa676c8.png](evernotecid://9566E7CF-1AAB-48B5-A4A7-CD4AD30D20CA/appyinxiangcom/22984063/ENResource/p10)
}
}
}
}
}
全文搜索 [GET /megacorp/employee/_search]
{
"query" : {
"match" : {
"about" : "rock climbing"
}
}
}
短语搜索 [GET /megacorp/employee/_search]
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
}
}
高亮搜索 [GET /megacorp/employee/_search]
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
注意如上文url有i的地方表示你需要填写的索引id
Springboot&任务
异步任务
在Application启动类加上@EnableAsync
编写测试异步方法,在方法体上需要加@Async注解
@Service
public class AsyncServiceImpl {
@Async
public void hello(){
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("数据处理中...");
}
}
编写控制器代码
@Autowired
AsyncServiceImpl asyncService;
@ResponseBody
@RequestMapping("/user/asyncTest")
public String asyncTest(){
asyncService.hello();
return "hello world!!!";
}
定时任务
介绍:项目开发中经常需要执行一些定时任务,比如需要在每天凌晨,分析前一天的日志信息。Spring为我们提供了异步执行任务调度的方式,提供TaskExecutor、TaskScheduler接口。
两个注解:@EnableScheduling、@Scheduled
cron表达式
字段 | 允许值 | 允许的特殊字符 |
---|---|---|
秒 | 0-59 | ,-*/ |
分 | 0-59 | ,-*/ |
小时 | 0-59 | ,-*/ |
日期 | 1-31 | ,-*?/L W C |
月份 | 1-12 | ,-*/ |
星期 | 0-7或SUN-SAT | ,-*?/L C # |
特殊字符 | 代表含义 |
---|---|
, | 枚举 |
- | 区间 |
* | 任意 |
/ | 步长 |
? | 日/星期冲突匹配 |
L | 最后 |
W | 工作日 |
C | 和calendar联系后计算过的值 |
# | 星期,4#2,第二个星期三 |
Springboot&安全
Springboot分布式
在分布式系统中,国内常用zookeeper+dubbo组合,而springboot推荐使用全栈spring,Spring boot + Spring Cloud。
Zookeeper&dubbo
Zookeeper是一个分布式的,开放源码的分布式应用程序协调服务。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解耦合(或者最大限度的松耦合)。从服务模型的角度来看,Dobbo采用的是一种非常简单的模型,要么是提供方提供服务,要么是消费方消费服务,所以基于这一点可以抽象出服务提供方(Provider)和服务消费方(Consumer)两个角色。