开发环境
Java JDK 1.8 Java SE Development Kit 8 Downloads(opens new window) Maven 3.8 Installing Apache Maven(opens new window) Mac : Docker Desktop For Mac(opens new window) Windows : Docker Desktop For Windows(opens new window)
**使用 Taro.redirectTo
替代 Taro.navigateTo
**: 在退出登录的按钮点击事件处理函数中,使用 Taro.redirectTo
而不是 Taro.navigateTo
来导航到登录页面。这将替换当前页面,使用户无法通过返回按钮返回到之前的页面。
MAC系统 JDK 卸载及彻底删除
▌1.删除运行路径和运行环境等
sudo rm -fr /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin
sudo rm -fr /Library/PreferencesPanes/JavaControlPanel.prefPane
sudo rm -fr ~/Library/Application\ Support/Java
▌2.删除当前版本的jdk
sudo rm -rf /Library/Java/JavaVirtualMachines/jdk-9.0.1.jdk
(注:不确定版本号先查看当前版本 ls /Library/Java/JavaVirtualMachines/
)
▌3.检查是否卸载成功
java -version
在 macOS 上切换 Java 版本通常涉及到使用 java_home
或其他工具来选择要使用的 Java 版本。以下是一些常见的步骤:
使用
java_home
:macOS 提供了
java_home
命令,可以用来切换 Java 版本。打开终端应用(Terminal)并执行以下命令:
查看已安装的 Java 版本:
/usr/libexec/java_home -V
这将列出你系统上已安装的 Java 版本及其标识。
切换到特定版本(例如 Java 11):
export JAVA_HOME=`/usr/libexec/java_home -v 11`
这会将
JAVA_HOME
环境变量设置为 Java 11 的安装路径。你可以根据你的需求替换版本号。
使用 Homebrew(仅适用于 OpenJDK):
如果你使用 Homebrew 来安装 OpenJDK,你可以使用 brew
命令来切换版本。
安装 OpenJDK:使用 Homebrew 安装你需要的 OpenJDK 版本。
brew install openjdk@11 # 安装 OpenJDK 11
切换版本:使用
brew link
命令来切换已安装的 OpenJDK 版本。brew link --overwrite openjdk@11 # 切换到 OpenJDK 11
如果你希望查看 Homebrew 的安装目录,可以打开终端并运行以下命令:
brew --prefix
EMQX
大规模分布式 MQTT 消息服务器
基于 APL 2.0 开放源码协议 完整 MQTT 3.x 和 5.0 规范 Masterless 高可用集群架构 高并发、低时延、高性能 可扩展的网关和插件体系
CentOS/RHEL
配置 EMQX Yum 源
curl -s https://assets.emqx.com/scripts/install-emqx-rpm.sh | sudo bash
安装 EMQX
sudo yum install emqx -y
启动 EMQX
sudo systemctl start emqx
@ApiModelProperty(value = "业务:")
@ApiModelProperty(value = "组织ID过滤集")//权限过滤
private List<String> orgIds;
@ApiModelProperty(value = "组织序号过滤集")//权限过滤
private List<Integer> oNums;
@ApiModelProperty(value = "Cassandra分页标签")
private String pageStateStr;
cd /usr/lib/emqx/bin
启动EMQ X
进入解压出的文件夹:
cd emqx
然后使用如下命令启动emqx:
sudo ./bin/emqx start
查询一下emqx的状态,检查一下是否真正成功启动:
sudo ./bin/emqx_ctl status
admins
用于创建、修改、删除管理员账户,子命令如下:
命令 | 描述 |
---|---|
admins add | 添加 Dashboard 用户 |
admins passwd | 重置 Dashboard 指定用户的密码 |
admins del | 删除指定 Dashboard 用户 |
version: '3'
services:
kafka:
container_name: ${CONTAINER_NAME}
restart: always
environment:
ALLOW_PLAINTEXT_LISTENER: 'yes'
KAFKA_CFG_LOG_RETENTION_MS: 60000
KAFKA_CFG_MAX_REQUEST_SIZE: 524288000
KAFKA_CFG_MESSAGE_MAX_BYTES: 524288000
KAFKA_CFG_REPLICA_FETCH_MAX_BYTES: 524288000
KAFKA_CFG_FETCH_MESSAGE_MAX_BYTES: 524288000
KAFKA_CFG_PARTITION_FETCH_BYTES: 524288000
KAFKA_CFG_NODE_ID: 0
KAFKA_CFG_PROCESS_ROLES: controller,broker
KAFKA_CFG_LISTENERS: PLAINTEXT://:9092,CONTROLLER://:9093
KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://${CONTAINER_NAME}:${PANEL_APP_PORT_HTTP}
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT
KAFKA_CFG_CONTROLLER_QUORUM_VOTERS: 0@127.0.0.1:9093
KAFKA_CFG_CONTROLLER_LISTENER_NAMES: CONTROLLER
networks:
- 1panel-network
ports:
- "${PANEL_APP_PORT_HTTP}:9092"
image: bitnami/kafka:3.6.0
labels:
createdBy: "Apps"
networks:
1panel-network:
external: true
9092
version: '3'
services:
memos:
image: neosmemo/memos:0.17.0
container_name: ${CONTAINER_NAME}
restart: always
networks:
- 1panel-network
ports:
- ${PANEL_APP_PORT_HTTP}:5230
volumes:
- ./memos:/var/opt/memos
labels:
createdBy: "Apps"
networks:
1panel-network:
external: true
并发,指的是多个事情,在同一时间段内同时发生了。 并行,指的是多个事情,在同一时间点上同时发生了。 只有在多CPU的情况中,才会发生并行。 否则,看似同时发生的事情,其实都是并发执行的。
Redis作为一款高性能的NoSQL数据库,具备快速读写、高并发、数据持久化等特点,非常适合用于实现延迟队列。Redis提供了丰富的数据结构,其中利用Redis的ZSET(有序集合)数据结构就可以实现一个简单的延迟队列。
Redis的zset数据结构中的每个元素都有一个分数score和一个值value,我们可以将任务的执行时间戳作为score,将任务数据作为value,将任务插入到zset中,每个任务有一个唯一的id(比如订单id),以及任务执行时间(比如30min),任务内容(比如订单超时支付系统自动取消)等信息体。然后另起一个线程,该线程会周期性地从zset中取出score最小(即最早要执行的)的任务,如果该任务的score小于当前时间戳,则执行任务,否则等待一段时间再次检查,直到任务可以执行,执行任务后,通过Redis的remove命令删除已经成功执行的任务即可。
如何利用Redis实现延迟队列的一些实现步骤?同学们请看:
引入spring-boot-starter-data-redis 和spring-boot-starter-test依赖。
配置redis。
创建消息类 DelayMessage
编写延时队列类 DelayQueue,提供添加消息、删除消息和获取消息方法。
创建消息处理器 DelayMessageHandler,处理已到期的消息。
编写测试类 DelayQueueTest,测试延时队列的添加、删除和处理消息功能。
在Spring Boot启动类中启动延时队列。
测试用例方法启动测试。
@AllArgsConstructor
和 @NoArgsConstructor
是 Java 中的注解,通常与 Lombok 库一起使用。它们有助于减少 Java 类中的样板代码。
**
@AllArgsConstructor
**:@AllArgsConstructor
public class MyClass {
private String field1;
private int field2;
}public MyClass(String field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
Lombok 将生成如下构造函数: 为类中的所有字段生成一个带有参数的构造函数。 当你希望有一个一次性初始化所有字段的构造函数时很有用。 例如:
**@NoArgsConstructor
**:
@NoArgsConstructor
public class MyClass {
private String field1;
private int field2;
}
public MyClass() {
// 无参数的默认构造函数
}
Lombok 将生成如下构造函数: 为类生成一个无参数的默认构造函数。 当需要一个无参数构造函数时很有用,例如在使用需要它的框架或库时。 例如:
使用这些注解,你可以减少在 Java 类中手动编写构造函数的需求,使你的代码更为简洁和可读。请注意,要使用 Lombok,你需要在项目中包含 Lombok 库。
@Component
public class DelayQueue {
private static final String KEY = "delay_queue";
@Autowired
private RedisTemplate redisTemplate;
/**
* 添加消息到延时队列中
*/
public void put(DelayMessage message) {
redisTemplate.opsForZSet().add(KEY, message, message.getExpireTime());
}
/**
* 从延时队列中删除消息
*/
public void remove(DelayMessage message) {
redisTemplate.opsForZSet().remove(KEY, message);
}
/**
* 获取延时队列中已到期的消息
*/
public List<DelayMessage> getExpiredMessages() {
long minScore = 0;
long maxScore = System.currentTimeMillis();
Set<Object> messages = redisTemplate.opsForZSet().rangeByScore(KEY, minScore, maxScore);
if (messages == null || messages.isEmpty()) {
return Collections.emptyList();
}
List<DelayMessage> result = new ArrayList<>();
for (Object message : messages) {
result.add((DelayMessage) message);
}
return result;
}
}
@Component
public class DelayMessageHandler {
@Autowired
private DelayQueue delayQueue;
/**
* 处理已到期的消息(轮询)
*/
@Scheduled(fixedDelay = 1000)
public void handleExpiredMessages() {
//获取当前系统时间
String dateTime = DateFormatUtils.format(new Date(), "hh:MM:ss");
//扫描任务,并将需要执行的任务加入到任务队列中
List<DelayMessage> messages = delayQueue.getExpiredMessages();
System.out.println(dateTime + " 待处理消息:" + messages);
//处理消息
if (!messages.isEmpty()) {
for (DelayMessage message : messages) {
System.out.println(dateTime + " 处理消息:" + message.getContent());
//成功处理消息后,便将消息进行移除。
delayQueue.remove(message);
}
}
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DelayQueueTest {
@Autowired
private DelayQueue delayQueue;
@Test
public void testDelayQueue() {
//获取当前系统时间
long newDate = System.currentTimeMillis();
// 添加消息:1秒后到期
DelayMessage message1 = new DelayMessage("1", "delay message 1", newDate + 1000);
// 添加消息:3秒后到期
DelayMessage message2 = new DelayMessage("2", "delay message 2", newDate + 3000);
// 添加消息:6秒后到期
DelayMessage message3 = new DelayMessage("3", "delay message 3", newDate + 6000);
// 添加消息:10秒后到期
DelayMessage message4 = new DelayMessage("4", "delay message 4", newDate + 10000);
delayQueue.put(message1);//1s后执行
delayQueue.put(message2);//3s后执行
delayQueue.put(message3);//6s后执行
delayQueue.put(message4);//10s后执行
}
}
在前端,你可以使用逗号分隔的字符串表示 List<String>
。例如,如果你要传递一个包含三个 SOC 值的列表,可以这样表示:
在这个例子中,前端将 soc
作为一个字符串传递给后端,后端在接收到这个字符串后,可以通过逗号分隔符解析为一个 List<String>
。具体的解析方法取决于后端使用的编程语言和框架。例如,在 Java 中,可以使用 String.split
方法将字符串拆分为数组:
String socString = "75,80,60"; List<String> socList = Arrays.asList(socString.split(","));
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
List<String> soc0 = null; // 你的第一个列表
List<String> soc1 = null; // 你的第二个列表
// 合并两个列表成一个
List<String> combinedList = Stream.of(soc0, soc1)
.filter(list -> list != null)
.flatMap(List::stream)
.collect(Collectors.toList());
// 打印合并后的列表
System.out.println(combinedList);
}
}
Spring如何管理Mybaits的Mapper接口的
首先MyBatis的Mapper接口核心是JDK动态代理 Spring会排除接口,无法注册到IOC容器中 MyBatis实现了BeanDefinitionRegistryPostProcessor可以动态注册BeanDefinition 需要自定义扫描器(继承Spring内部扫描器ClassPathBeanDefinitionScanner)重写排除接口的方法(isCandidateComponent) 但是接口虽然注册成了BeanDefinition但是无法实例化Bean,因为接口无法实例划 需要将BeanDefinition的BeanClass替换成JDK动态代理的实例 Mybatis通过FactoryBean的工厂方法设计模式可以自由控制Bean的实例划过程,可以在getObject方法中创建JDK动态代理
过程
读取配置信息(xml javaconfig)api: BeanDefinitionReader 解析配置:解析@ComponentScan @Bean @Configuration @Import 目的:为了注册BeanDefinition @ComponentScan解析:扫描制定包的路径所有.class类 api:ClassPathBeanDefinitionSacnner 判断类上面是否有@Component 判断你的类是否接口、抽象类
MyFactoryBean
阿里微服务Spring Cloud Alibaba 三高架构实战
StockController.java
@RestController
@RequestMapping("/stock")
public class StockController {
@Autowired
private StockService stockService;
@Autowired
private Registration registration;
@GetMapping(value = "/deduct/{productId}/{stockCount}")
public String deductStock(@PathVariable("productId") Long productId,
@PathVariable("stockCount") Integer stockCount) {
return stockService.deductStock(productId, stockCount);
}
@GetMapping("/getIpAndPort")
public String getIpAndPort() {
return registration.getHost() + ":" + registration.getPort();
}
}
@GetMapping(value = "/create")
public String createOrder(@RequestParam("productId") Long productId, @RequestParam("userId") Long userId, @RequestParam("stockCount") Integer stockCount, @RequestParam("creditCount") Integer creditCount) {
orderService.createOrder(productId, userId, stockCount, creditCount);
return "success";
}
组件
Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
RocketMQ: 一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
Alibaba Cloud OSS:阿里云对象储存服务(Object Storage Service,简称OSS),是阿里云提供的海量、安全、低成本、高可靠的云储存服务。您可以在任何应用、任何时间、任何地点储存和访问任意类型的数据。
Alibaba Clound SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级,精准,高可靠,高可用的定时(基于Cron表达式)任务调度服务。
Alibaba Cloud SMS: 覆盖全球的短信服务,友好,高效,智能的互联网通讯能力,帮助企业迅速搭建客户接触通道。
限流,熔断,降级
30-60w程序员
掌握操作系统原理,Linux核心开发技能,计算网络与IO底层原理,必备做数据结构与算法 掌握常用框架SSM以及Spring Boot核心功能以及源码级架构原理 掌握常用设计模式以及在实际开发场景中的应用 掌握多线程并发编程核心原理,具备开发高性能高并发程序能力 掌握JVM,Mysql,Tomcat,Nginx等技术的核心原理以及性能调优 掌握分布式缓存,MQ,搜索,分布式调度,RPC通信,海量数据分库分表等中间件核心功能与原理 掌握微服务架构Spring Cloud以及阿里微服务全栈技术功能与架构原理 具备一定海量数据处理以及架构能力 具备一定大型互联网系统设计,开发以及架构实战经验
描述Spring的Aop的完整实现流程?
Aop的实现大致分为三大步:
当@EnableAspectJAutoProxy会通过@Import注册一个BeanPostProcessor处理AOP
在创建Bean时调用BeanPostProcessor解析切面@Aspect,将切面中所有的通知解析为advisor(该对象包含通知,切点,通知方法)排好序放入List并缓存。 在Bean初始化后调用BeanPostProcessor拿到之前缓存的advisor判断当前Bean是否被切点表达式命中,如果匹配为Bean创建动态代理。 调用:通过之前创建的动态代理 调用方法 执行增强,通过调用链设计模式依次调用通知方法。
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';
# MySQL8: Client does not support authentication protocol requested by server
ALTER USER 'customuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
FLUSH PRIVILEGES;
在 Spring Boot 中查询附近的数据通常涉及到地理位置的计算。你可以选择在 MySQL 中使用空间函数,也可以使用 Elasticsearch(ES)进行地理位置的索引和查询。
使用 MySQL 实现:
数据库表设计: 在你的表中添加经度和纬度字段,这两个字段用于存储地理位置信息。
CREATE TABLE your_table (
id INT PRIMARY KEY,
name VARCHAR(255),
latitude DOUBLE,
longitude DOUBLE
);查询附近的数据: 使用 MySQL 的空间函数,比如
ST_Distance
,来计算距离。以下是一个简单的例子:SELECT id, name, latitude, longitude,
ST_Distance(
POINT(your_latitude, your_longitude),
POINT(latitude, longitude)
) AS distance
FROM your_table
HAVING distance <= 50
ORDER BY distance;替换
your_latitude
和your_longitude
为你的当前位置的经度和纬度。
使用 Elasticsearch 实现:
安装 Elasticsearch: 首先确保你已经安装并启动了 Elasticsearch。
索引数据: 在索引中添加地理位置映射:
PUT /your_index
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}保证你的文档包含一个
location
字段,其值为经纬度数组。查询附近的数据: 使用 Elasticsearch 的地理位置查询。以下是一个例子:
SearchRequest searchRequest = new SearchRequest("your_index");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
GeoDistanceQueryBuilder queryBuilder = QueryBuilders.geoDistanceQuery("location")
.point(your_latitude, your_longitude)
.distance(50, DistanceUnit.KILOMETERS);
searchSourceBuilder.query(queryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);替换
your_latitude
和your_longitude
为你的当前位置的经度和纬度。
// const AMap = (window as any).AMap
// const moveAnimation = new AMap.moveAnimation({
// marker: marker.value,
// path: lineArr.value,
// duration: 500
// })
// moveAnimation.start();
常见微服务架构
dubbo: zookeeper +dubbo + SpringMVC/SpringBoot 配套 通信方式:rpc 注册中心:zookeeper / redis 配置中心:diamond
SpringCloud:全家桶+轻松嵌入第三方组件(Netflix) 配套 通信方式:http restful 注册中心:eruka / consul 配置中心:config 断 路 器:hystrix 网关:zuul 分布式追踪系统:sleuth + zipkin
Spring Cloud Alibaba 是所有的实现方案中功能最齐全的。尤其是在 Netflix 停止更新了以后,Spring Cloud Alibaba 依然在持续更新和 迭代。
高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务. 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道. 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时任务调度服务. Nacos Service Discovery 通过nacos实现的服务发现平台. Spring Cloud Alibaba Sentinel 提供 Sentinel 自动接入和配置支持,提供 Spring Web/WebFlux、Feign、RestTemplate、注解等适配 Spring Cloud Alibaba Sentinel DataSource 提供 Sentinel 动态数据源接入支持,方便用户整合 Nacos 等数据源动态管理规则 Spring Cloud Alibaba Sentinel Gateway 提供 Sentinel 网关流控自动接入支持,目前支持 Spring Cloud Gateway 和 Zuul 阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案. 一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务. 通过Alibaba Nacos实现配置管理:支持分布式系统中的外部化配置、配置更改时自动刷新功能 Lombok Java 注释库有助于减少样板代码。 Spring Web 使用 Spring MVC 构建 Web,包括 RESTful 应用程序。使用 Apache Tomcat 作为默认嵌入式容器。 Spring Session 提供用于管理用户会话信息的 API 和实现。 Spring Security 用于 Spring 应用程序的高度可定制的身份验证和访问控制框架。 MyBatis Framework 持久性框架,支持自定义 SQL、存储过程和高级映射。 MyBatis 使用 XML 描述符或注释将对象与存储过程或 SQL 语句结合起来。 MySQL 驱动程序 MySQL JDBC 和 R2DBC 驱动程序。 Spring Data Redis (Access+Driver) 高级且线程安全的 Java Redis 客户端,用于同步、异步和反应式使用。支持集群、哨兵、管道、自动重新连接、编解码器等。 Spring Data Elasticsearch (Access+Driver) 使用 Spring Data Elasticsearch 的分布式 RESTful 搜索和分析引擎。 Spring Data for Apache Cassandra 一个免费开源的分布式 NoSQL 数据库管理系统,提供高可扩展性和高性能。 Spring Data Reactive for Apache Cassandra 以响应方式访问 Cassandra NoSQL 数据库。 Spring for Apache Kafka 发布、订阅、存储,并处理记录流。 Spring for RabbitMQ 为您的应用程序提供一个发送和接收消息的通用平台,并为您的消息提供一个安全的存放位置,直到收到为止。 Spring for Apache Kafka Streams 使用 Apache Kafka Streams 构建流处理应用程序。 WebSocket 使用 SockJS 和 STOMP 构建 WebSocket 应用程序。 Quartz Scheduler 使用 Quartz 安排作业。 分布式跟踪 在日志中启用跨度和跟踪 ID。 Spring REST 文档通过结合使用 Asciidoctor 手写和使用 Spring MVC Test 生成的自动生成的片段来记录 RESTful 服务。 网关 提供一种简单而有效的方法来路由到 API 并为它们提供横切关注点,例如安全性、监控/指标和弹性。 OpenFeign 声明式 REST 客户端。 OpenFeign 创建一个用 JAX-RS 或 Spring MVC 注释修饰的接口的动态实现。 Cloud LoadBalancer 使用 Spring Cloud LoadBalancer 进行客户端负载均衡。
db.createUser(
{
user: "gd",
pwd: "123456",
roles: [ { role: "readWrite", db: "base_db" } ]
}
)
问题
单点容错率低 & 无法针对不同模块进行针对性优化和水平扩展 & 系统间耦合度变高 & 一个调度中心对集群进行实时管理 & 资源调度和治理中心(SOA Service Oriented Architecture) & 服务间会有依赖关系,一旦某个环节出错会影响较大( 服务雪崩 ) & 服务关系复杂,运维、测试部署困难 & 微服务架构比 SOA架构粒度会更加精细,让专业的人去做专业的事情(专注),目的提高效率,每个服务于服务之间互不影响,微服务架构中,每个服务必须独立部署,微服务架构更加轻巧,轻量级 & SOA 架构中可能数据库存储会发生共享,微服务强调独每个服务都是单独数据库,保证每个服务于服务之间互不影响。 & 项目体现特征微服务架构比 SOA 架构更加适合与互联网公司敏捷开发、快速迭代版本,因为粒度非常精细 & 分布式系统开发的技术成本高(容错、分布式事务等)& 各个微服务进行分布式独立部署,当进行模块调用的时候,分布式将会变得更加麻烦。
这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除]) nacos
这么多小服务,他们之间如何通讯?(restful rpc dubbo feign)
这么多小服务,客户端怎么访问他们?(网关) gateway
这么多小服务,一旦出现问题了,应该如何自处理?(容错) sentinel
这么多小服务,一旦出现问题了,应该如何排错? (链路追踪) skywalking
加群联系作者vx:xiaoda0423
仓库地址:https://github.com/webVueBlog/JavaGuideInterview