十五,java高级程序员面试宝典

简介: 十五,java高级程序员面试宝典


defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/
instance:
prefer-ip-address: true #使用ip注册到Eureka
instance-id: stream-consumer-server:1090 #指定客户端实例的ID
spring:
application:
name: stream-consumer-server
cloud:
stream:
bindings:
input: #消息输入配置,我们这里是消费者,如果是生成者就用output
content-type: application/json #内容类型
destination: myStream #消息目的地 , 会在RabbitMQ创建一个名字叫mySteram的交换机
rabbitmq: #RabbitMQ的链接配置
host: localhost
port: 5672
username: guest
password: guest
server:
port: 1090

这里除了要注册到Eureak Server之外,通过spring.cloud.stream.bindings.input 来定义了消息的输入配置。

  • content-type :用来指定消息的类型
  • destination :用来指定消息的目的地,其实就是指定MQ中的交换机

spring.rabbitmq是用来配置RabbitMQ的链接参数。

Stream的消息通道绑定接口
public interface StreamClient {
//对应配置中的bindings
String INPUT = “input”;
//用来输入消息
@Input(StreamClient.INPUT)
SubscribableChannel input();
}

创建 StreamClient 接口,通过 @Input注解定义输入通道,另外,@Input 还有一个 value 属性,该属性可以用来设置消息通道的名称,这里指定的消息通道名称是 input对应yml配置。如果直接使用两个注解而没有指定具体的 value 值,则会默认使用方法名作为消息通道的名称,定义输入通道时,需要返回 SubscribableChannel 接口对象,该接口集成自 MessageChannel 接口,它定义了维护消息通道订阅者的方法。简而言之,就是用来定义消息接收的。

消息接收
@Component
//绑定消息接口
@EnableBinding(value = {StreamClient.class})
public class StreamConsumer {
private Logger logger = LoggerFactory.getLogger(StreamConsumer .class);
@StreamListener(StreamClient.INPUT)
public void receive(String message) {
logger.info(“收到消息: {}”, message);
}
}

@EnableBinding 注解用来指定一个或多个定义了 @Input 注解的接口,以此实现对消息通道(Channel)的绑定。上面我们通过 @EnableBinding(value = {StreamClient.class}) 绑定了 StreamClient 接口,该接口是我们自己实现的对输入输出消息通道绑定的定义

@StreamListener,主要定义在方法上,作用是将被修饰的方法注册为消息中间件上数据流的事件监听器,注解中的属性值对应了监听的消息通道名。上面我们将 receive 方法注册为StreamClient.INPUT 消息通道的监听处理器,当我们往这个消息通道发送信息的时候,receiver 方法会执行。

简单理解就是当我们往 StreamClient.INPUT 这个输入通道发消息的时候 ,应用程序通过@StreamListener 标签监听到消息,然后调用receive方法接收数据进行消费。

启动测试

启动消费者程序,打开RabbitMQ控制界面,可以看到这里创建了一个交换机 , 类型默认是Topic定向 ,routingkey是“#”

2.3.提供者服务

搭建工程

创建工程

springcloud-stream-provider-server-1100 ,导入依赖,和消费者服务一样。

org.springframework.cloud

spring-cloud-starter-netflix-eureka-client

org.springframework.boot

spring-boot-starter-web

org.springframework.cloud

spring-cloud-starter-stream-rabbit

yml配置文件
eureka:
client:
serviceUrl:
defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/
instance:
prefer-ip-address: true #使用ip注册到Eureka
instance-id: stream-consumer-server:1100 #指定客户端实例的ID
spring:
application:
name: stream-provider-server
cloud:
stream:
bindings:
output: #消息输出配置
content-type: application/json
destination: myStream #消息目的地
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
server:
port: 1100
主配置类
//服务注册与发现
@SpringBootApplication
@EnableDiscoveryClient
@EnableBinding(StreamClient.class) //绑定stream的API接口
public class StreamProviderServerApplication1100 {
public static void main(String[] args) {
SpringApplication.run(StreamProviderServerApplication1100.class);
}
}

这里的主配置通过 @EnableBinding(StreamClient.class) 绑定stream的接口实现对消息通道的绑定。下面是Stream消息通道绑定接口:

Stream的消息通道绑定接口
public interface StreamClient {
//对应配置中的bindings
String OUTPUT = “output”;
//用来输出消息
@Output(StreamClient.OUTPUT)
MessageChannel output();
}

这里和消费者的绑定输入通道差不多,这里在提供者方绑定的是输出通道,“output”对应了yml配置中的“bindings.output”配置。应用程序通过 MessageChannel 来发送消息,通过 @Output(StreamClient.OUTPUT)绑定的通道把消息发送到RabbitMQ中。

编写消息发送测试controller
@RestController
public class StreamProvider {
@Autowired
StreamClient streamClient ;
@RequestMapping(“/send”)
public void send(){
streamClient.output().send(MessageBuilder.withPayload(“我是消息我是消息”).build());
}
}

注入 streamClient,通过output()得到消息输出通道(MessageChannel ),通过send方法去发送消息到MQ

访问测试

启动消费者,再启动提供者,访问提供者:http://localhost:1100/send ,观察消费者的控制台应该收到了消息,并且RabbitMQ产生了一个的队列

修改消费者 的端口为 1091 ,再启动一个消费者,然后访问 http://localhost:1100/send 观察两个消费者应该都受到消息了

2.4.消息分组

上面的案例Stream是通过topic方式进行消息广播 ,有的时候我们希望一个消息只是被一个消费者收到,因为有些消息不能被重复消费,我们可以使用消组。通过配置消息分组的方式来达到如上效果,下面修改下配置文件,修改如下:注意,我这里修改的是消费者

eureka:

client:

serviceUrl:

defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/

instance:

prefer-ip-address: true #使用ip注册到Eureka

instance-id: stream-consumer-server:1090 #指定客户端实例的ID

spring:

application:

name: stream-consumer-server

cloud:

stream:

bindings:

input: #消息输入配置,我们这里是消费者,如果是生成者就用output

content-type: application/json #内容类型

destination: myStream #消息目的地 , 会在RabbitMQ创建一个名字叫mySteram的交换机

group: stream #指定组,多个消费者在同一个组,那么一个消息就只会给到一个消费者

rabbitmq: #RabbitMQ的链接配置

host: localhost

port: 5672

username: guest

password: guest

server:

port: 1090

group: stream #指定组,多个消费者在同一个组,那么一个消息就只会给到一个消费者 , 重启多个消费者,查看MQ,这里多个一个:myStream.stream的队列,这个stream的后缀就是组名。

我们启动测试,多次发送消息,同一个消息只会被一个消息者获取。

2.5.消息分区

有的时候我们可能不满足于一个消息被一个消费者消费,对于特殊业务情况,除了要保证单个消费者消费之外,还希望有相同特点的消费都可以同一个消费者消费,这里就可以使用 Spring Cloud Stream 提供的消息分区功能。

消费者

Spring Cloud Stream 实现消息分区只需要在配置文件里进行相应的配置即可,消费者修改配置文件如下:

eureka:

client:

serviceUrl:

defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/

instance:

prefer-ip-address: true #使用ip注册到Eureka

instance-id: stream-consumer-server:1090 #指定客户端实例的ID

spring:

application:

name: stream-consumer-server

cloud:

stream:

bindings:

input: #消息输入配置,我们这里是消费者,如果是生成者就用output

content-type: application/json #内容类型

destination: myStream #消息目的地 , 会在RabbitMQ创建一个名字叫mySteram的交换机

group: stream #指定组,多个消费者在同一个组,那么一个消息就只会给到一个消费者

#通过该参数开启消费者分区功能

partitioned: true

#配置总共有多少个消费者

instance-count: 2

#当前消费者是第几个,从 0 开始,最大值为instance-count 减 1 。

instance-index: 0

rabbitmq: #RabbitMQ的链接配置

host: localhost

port: 5672

username: guest

password: guest

server:

port: 1090

启动两个消费者 ,注意修改端口,第二个消费者需要将 instance-index: 0 改为1 , 观察MQ

提供者

修改提供者springcloud-stream-provider-1100工程,修改配置文件,指定分区个数

eureka:
client:
serviceUrl:
defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/
instance:
prefer-ip-address: true #使用ip注册到Eureka
instance-id: stream-consumer-server:1100 #指定客户端实例的ID
spring:
application:
name: stream-provider-server
cloud:
stream:
bindings:
output: #消息输出配置
content-type: application/json
destination: myStream #消息目的地
partitionCount: 2 #分区个数
#分区规则表达式配置,从header中获取分区索引
partitionKeyExpression: headers[‘partitionKey’]
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
server:





相关实践学习
5分钟轻松打造应对流量洪峰的稳定商城交易系统
本实验通过SAE极速部署一个微服务电商商城,同时结合RocketMQ异步解耦、削峰填谷的能力,带大家体验面对流量洪峰仍旧稳定可靠的商城交易系统!
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
29天前
|
存储 安全 Java
常见 JAVA 集合面试题整理 自用版持续更新
这是一份详尽的Java集合面试题总结,涵盖ArrayList与LinkedList、HashMap与HashTable、HashSet与TreeSet的区别,以及ConcurrentHashMap的实现原理。内容从底层数据结构、性能特点到应用场景逐一剖析,并提供代码示例便于理解。此外,还介绍了如何遍历HashMap和HashTable。无论是初学者还是进阶开发者,都能从中受益。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
87 3
|
28天前
|
存储 安全 Java
2025 最新史上最全 Java 面试题独家整理带详细答案及解析
本文从Java基础、面向对象、多线程与并发等方面详细解析常见面试题及答案,并结合实际应用帮助理解。内容涵盖基本数据类型、自动装箱拆箱、String类区别,面向对象三大特性(封装、继承、多态),线程创建与安全问题解决方法,以及集合框架如ArrayList与LinkedList的对比和HashMap工作原理。适合准备面试或深入学习Java的开发者参考。附代码获取链接:[点此下载](https://pan.quark.cn/s/14fcf913bae6)。
190 48
|
25天前
|
缓存 NoSQL Java
Java Redis 面试题集锦 常见高频面试题目及解析
本文总结了Redis在Java中的核心面试题,包括数据类型操作、单线程高性能原理、键过期策略及分布式锁实现等关键内容。通过Jedis代码示例展示了String、List等数据类型的操作方法,讲解了惰性删除和定期删除相结合的过期策略,并提供了Spring Boot配置Redis过期时间的方案。文章还探讨了缓存穿透、雪崩等问题解决方案,以及基于Redis的分布式锁实现,帮助开发者全面掌握Redis在Java应用中的实践要点。
82 6
|
28天前
|
NoSQL Java 微服务
2025 年最新 Java 面试从基础到微服务实战指南全解析
《Java面试实战指南:高并发与微服务架构解析》 本文针对Java开发者提供2025版面试技术要点,涵盖高并发电商系统设计、微服务架构实现及性能优化方案。核心内容包括:1)基于Spring Cloud和云原生技术的系统架构设计;2)JWT认证、Seata分布式事务等核心模块代码实现;3)数据库查询优化与高并发处理方案,响应时间从500ms优化至80ms;4)微服务调用可靠性保障方案。文章通过实战案例展现Java最新技术栈(Java 17/Spring Boot 3.2)的应用.
94 9
|
1月前
|
缓存 Java 索引
2025 年 Java 面试必备最常见 200 + 面试题及答案解析
这是一份针对Java面试的综合技术方案与应用实例文档,涵盖Java基础(JDK/JRE、字符串、IO流)、容器(ArrayList/LinkedList、HashMap)、多线程(线程创建、同步、线程池)、数据库(MySQL索引、Redis缓存穿透)及Spring框架(IOC容器、热部署)等核心模块。通过详细解析常见面试题,帮助读者深入理解并掌握Java核心技术,为应对面试提供全面指导。此外,还涉及反射、设计模式、JVM调优等进阶内容,助力开发者全面提升技能。代码示例可从提供的链接下载。
130 6
|
28天前
|
存储 缓存 安全
Java 集合篇面试题全面总结及答案解析
本文总结了Java集合框架的核心概念、常见集合类的特性与应用场景,以及开发中可能遇到的问题与解决方案。内容涵盖集合框架的基础接口(如Collection、Set、List、Map)、泛型的优点、线程安全集合类(如ConcurrentHashMap、CopyOnWriteArrayList)、常见集合类的区别(如ArrayList与LinkedList、HashMap与HashTable)等。此外,还详细介绍了如何实现LRU缓存、FIFO队列、优先级队列及栈等数据结构,并提供了相关代码示例。通过本文,读者可以全面掌握Java集合相关的面试知识点及其实际应用技巧。
50 1
|
1月前
|
算法 安全 Java
2025 校招必看:Java 开发面试核心知识点深度解析及最新笔面试题汇总
本文针对2025校招Java开发面试,系统梳理了Java基础、集合框架、多线程并发、JVM等核心知识点,并附带最新笔面试题。内容涵盖封装、继承、多态、异常处理、集合类使用、线程同步机制、JVM内存模型及垃圾回收算法等。同时深入探讨Spring、数据库(MySQL索引优化、Redis持久化)、分布式系统(CAP理论、分布式事务)等相关知识。通过理论结合实例解析,帮助考生全面掌握面试要点,提升实战能力,为成功拿下Offer奠定坚实基础。
143 2
|
28天前
|
存储 缓存 安全
Java 集合容器常见面试题及详细解析
本文全面解析Java集合框架,涵盖基础概念、常见接口与类的特点及区别、底层数据结构、线程安全等内容。通过实例讲解List(如ArrayList、LinkedList)、Set(如HashSet、TreeSet)、Map(如HashMap、TreeMap)等核心组件,帮助读者深入理解集合容器的使用场景与性能优化。适合准备面试或提升开发技能的开发者阅读。
33 0
|
1月前
|
缓存 安全 算法
2025 年 Java 秋招面试必看 Java 并发编程面试题实操篇
Java并发编程是Java技术栈中非常重要的一部分,也是面试中的高频考点。本文从基础概念、关键机制、工具类、高级技术等多个方面进行了介绍,并提供了丰富的实操示例。希望通过本文的学习,你能够掌握Java并发编程的核心知识,在面试中取得好成绩。同时,在实际工作中,也能够运用这些知识设计和实现高效、稳定的并发系统。
44 0
|
1月前
|
存储 安全 Java
2025 年 Java 秋招面试必看的 Java 并发编程面试题汇总
文章摘要: 本文系统梳理Java并发编程核心知识点,助力2025年秋招面试。内容涵盖:1)基础概念,包括线程/进程区别、创建线程的3种方式(Thread/Runnable/Callable)、6种线程状态及转换;2)关键机制,对比sleep()与wait()的锁行为差异,解释start()而非run()启动线程的原因;3)工具类与典型应用场景。通过技术原理与代码示例结合的方式,帮助开发者深入理解并发模型、线程同步等核心问题,为高并发系统设计打下坚实基础。(150字)
73 0

热门文章

最新文章