Java阶段五Day14
Java阶段五Day14
文章目录
- Java阶段五Day14
- 分布式事务
- 整合demo案例中
- 架构,代码关系
- 发送半消息
- 本地事务
- 完成检查补偿
- 购物车消费
- 鲁班周边环境调整
- 前端启动
- 介绍
- 启动前端
- 直接启动的项目
- gateway(网关)
- login(登录注册)
- attach(上传图片)
- 分层开发和整洁架构
- 分层开发(横向拆分)
- 整洁架构
- 整洁架构落地方案
- 搭建worker项目架构
- 顶级夫工程继承操作
- 创建项目架构
- 根据分层架构依赖关系,搭建创建8个模块
- 附录
- maven加载私服无法下载
- 前端启动问题
- mac运行passport
- jar运行节省内存问题
- 连接mysql失败
- 演示项目和本地项目
- 注册失败
分布式事务
整合demo案例中
架构,代码关系
发送半消息
OrderServiceImpl
package cn.tedu.csmall.all.adapter.service.impl;import cn.tedu.csmall.all.adapter.mapper.OrderMapper;
import cn.tedu.csmall.all.service.ICartService;
import cn.tedu.csmall.all.service.IOrderService;
import cn.tedu.csmall.all.service.IStockService;
import cn.tedu.csmall.commons.exception.CoolSharkServiceException;
import cn.tedu.csmall.commons.pojo.order.dto.OrderAddDTO;
import cn.tedu.csmall.commons.pojo.order.entity.Order;
import cn.tedu.csmall.commons.pojo.stock.dto.StockReduceCountDTO;
import cn.tedu.csmall.commons.restful.JsonPage;
import cn.tedu.csmall.commons.restful.ResponseCode;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.util.List;
import java.util.Map;import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;// order模块是具备生产者特征的,它会被business模块调用,所以也要加@DubboService注解
@DubboService(loadbalance = "random")
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {@Autowiredprivate OrderMapper orderMapper;/*** 防止消息异步消费逻辑中,重复消费的问题,业务方法* 设计成幂等的* @param orderAddDTO*/@Autowiredprivate RocketMQTemplate rocketMQTemplate;@Overridepublic void orderAdd(OrderAddDTO orderAddDTO) {int count=orderMapper.selectExists(orderAddDTO);if (count>0){log.debug("订单已经新增了");return;}//发送一个半消息,消息如果发送成功,是给购物车用的//只要包含当前订单用户,的订单商品是什么 消息特点精简准确//消息不仅只有消费者在使用,还有本地事务,和检查事务的方法都在使用//主要考虑check检查,如果消息本身携带的内容不足以支持检查逻辑//需要想办法携带更多信息String msgData=orderAddDTO.getUserId()+":"+orderAddDTO.getCommodityCode();Message message= MessageBuilder.withPayload(msgData).setHeader("name","王翠花").setHeader("orderId","1").build();//object参数表示业务数据,当前业务逻辑 减库存生单rocketMQTemplate.sendMessageInTransaction("order-add-topic",message,orderAddDTO);}// 分页查询所有订单的业务逻辑层方法// page是页码,pageSize是每页条数public JsonPage<Order> getAllOrdersByPage(Integer page, Integer pageSize){// PageHelper框架实现分页的核心操作:// 在要执行分页的查询运行之前,设置分页的条件// 设置的方式如下(固定的格式,PageHelper框架设计的)// PageHelper设置page为1就是查询第一页PageHelper.startPage(page,pageSize);// 下面开始持久层方法的调用// 此方法运行时因为上面设置了分页条件,sql语句中会自动出现limit关键字List<Order> list = orderMapper.findAllOrders();// 查询结果list中包含的就是分页查询范围的数据了// 但是这个数据不包含分页信息(总页数,总条数,是否是首页,是否是末页等)// 我们要利用PageHelper框架提供的PageInfo类型,来进行返回// PageInfo对象可以既包含分页数据,又包含分页信息// 这些信息会在PageInfo对象实例化时自动计算,并赋值到PageInfo对象中return JsonPage.restPage(new PageInfo<>(list));}
}
本地事务
本地事务方法调用顺序,在发送半消息之后执行
OrderAddTransactionListener
package cn.tedu.csmall.all.adapter.transaction;import cn.tedu.csmall.all.adapter.mapper.OrderMapper;
import cn.tedu.csmall.all.service.IStockService;
import cn.tedu.csmall.commons.exception.CoolSharkServiceException;
import cn.tedu.csmall.commons.pojo.order.dto.OrderAddDTO;
import cn.tedu.csmall.commons.pojo.order.entity.Order;
import cn.tedu.csmall.commons.pojo.stock.dto.StockReduceCountDTO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.spring.annotation.RocketMQTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionListener;
import org.apache.rocketmq.spring.core.RocketMQLocalTransactionState;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;/*** @author liner* @version 1.0*/
@Component
@RocketMQTransactionListener
public class OrderAddTransactionListener implements RocketMQLocalTransactionListener {@DubboReferenceprivate IStockService stockService;@Autowiredprivate OrderMapper orderMapper;/*** 1.减库存* 1.1 减成功 进入第二步生单* 1.2 减失败 rollback* 2.生单* 2.1 生单成功 commit* 2.2 生单失败 补偿库存 unkonwn* 其他异常问题 unknown* @param message userId":"commodityCode* @param o OrderAddDTO* @return*/@Overridepublic RocketMQLocalTransactionState executeLocalTransaction(Message message, Object o) {OrderAddDTO orderAddDTO=(OrderAddDTO)o;try{StockReduceCountDTO countDTO=new StockReduceCountDTO();countDTO.setCommodityCode(orderAddDTO.getCommodityCode());countDTO.setReduceCount(orderAddDTO.getCount());// 利用Dubbo调用stock模块减少库存的业务逻辑层方法实现功能stockService.reduceCommodityCount(countDTO);}catch (CoolSharkServiceException e){//返回rollbackreturn RocketMQLocalTransactionState.ROLLBACK;}catch (Throwable e){//返回unknownreturn RocketMQLocalTransactionState.UNKNOWN;}try{Order order=new Order();BeanUtils.copyProperties(orderAddDTO,order);orderMapper.insertOrder(order);}catch (Exception e){return RocketMQLocalTransactionState.UNKNOWN;}return RocketMQLocalTransactionState.COMMIT;}/*** 1. 检查订单是否成功.* 1.1 成功 commit* 1.2 没有成功 进入第2步* 2. 库存对当前订单是否已经减成功* 2.1 减成功,回退 第3步* 2.2 没减成功 rollback* 3.回退库存* 3.1 可能失败 unknown* 3.2 回退成功 rollback* @param message* @return*/@Overridepublic RocketMQLocalTransactionState checkLocalTransaction(Message message) {return null;}
}
完成检查补偿
利用检查补偿的方法,画的业务流程图
OrderAddTransactionListener
@Override
public RocketMQLocalTransactionState checkLocalTransaction(Message message) {//状态不明确,回调check方法,检查库存是否减少,检查订单是否生成String userIdAndCommodityCode = (String) message.getPayload();Object name = message.getHeaders().get("name");Object orderId = message.getHeaders().get("orderId");String userId=userIdAndCommodityCode.split(":")[0];String commodityCode=userIdAndCommodityCode.split(":")[1];OrderAddDTO orderAddDTO=new OrderAddDTO();orderAddDTO.setUserId(userId);orderAddDTO.setCommodityCode(commodityCode);int exist = orderMapper.selectExists(orderAddDTO);if (exist>0){//当前检查的这个订单已经生成,说明库存肯定减了return RocketMQLocalTransactionState.COMMIT;}//存在一个库存的日志表格,记录减库存的日志数据//通过传递订单信息,查询日志,如果减了就回退,如果没减,没有操作//返回给调用者检查结果是成功还是失败try{stockService.checkStockData();}catch (CoolSharkServiceException e){//没有库存减少的日志 没有任何减库存的操作return RocketMQLocalTransactionState.ROLLBACK;}//补偿回退 TODOtry{//补偿System.out.println("订单没有生成.库存减少了,开始补偿");}catch (Exception e){//补偿失败return RocketMQLocalTransactionState.UNKNOWN;}return RocketMQLocalTransactionState.ROLLBACK;
}
购物车消费
购物车整合rocketmq
购物车编写消费逻辑
package cn.tedu.csmall.all.adapter.consumer;import cn.tedu.csmall.all.service.ICartService;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ScopeMetadata;
import org.springframework.stereotype.Component;/*** @author liner* @version 1.0*/
@Component
@RocketMQMessageListener(topic="order-add-topic",consumerGroup = "${rocketmq.consumer.group}",selectorExpression = "*")
public class CartDeleteConsumerListener implements RocketMQListener<String> {@Autowiredprivate ICartService cartService;@Overridepublic void onMessage(String msg) {String userId=msg.split(":")[0];String commodityCode=msg.split(":")[1];//删除购物车cartService.deleteUserCart(userId, commodityCode);}
}
鲁班周边环境调整
前端启动
介绍
luban-front
前台
前台主要是给师傅用的
师傅抢单
签到 / 上传施工图片 / 完成订单
luban-admin-front
后台是管理用的
需求单
厂商 / 供应商 入住
启动前端
node.js
版本是 16 X
保证能运行
luban-admin-front
启动顺序
1. npm install
2. npm run dev
luban-front
启动顺序
1. npm install
2. npm run dev:h5
直接启动的项目
gateway(网关)
- 只需要
nacos
运行,默认连接localhost:8848 public DEFAULT_GROUP
login(登录注册)
- 导入登录的数据库表格
- 本地有
redis
(略) nacos localhost:8848
(略)- 运行
bat
文件 /sh
文件
通过 idea 配置 bat
/ sh
attach(上传图片)
- 文件上传路径,和访问的关系
图片上传关系到鲁班中许多功能的业务流转
spring.resources.static-lcations
:上传图片存放的路径,也是访问这个项目静态资源的路径
spring.mvc.static-path-pattern
:访问attach
服务时,匹配静态资源的规则
例如:
在
E:/home/images/dev/attach/haha.txt
E:/home/images/dev/attach/123456.png
attach 启动默认运行端口8092
http://localhost:8092/static/123456.png
http://localhost:8092/static/a/b/c/d/1.png
E:/home/images/dev/attach/a/b/c/d/1.png
- 导入数据库 sql 文件
分层开发和整洁架构
目标
- 了解分层开发的概念
- 理解分层开发实现结构的功能
- 落地整洁架构最终鲁班的项目
概念:纵向拆分(横向拆分)
分层开发(横向拆分)
分层开发的概念:
maven 多模块开发项目管理
可以利用这种管理功能,实现一个项目的多层次模块开发——分层开发
比如,当前项目HelloController
依赖HelloService
这样做目的: 复杂开发过程,解耦(不调整依赖关系,无法解耦)
分层开发(横向拆分)和纵向拆分的区别在于,拆出多层,最终运行也是一个项目
整洁架构
《代码整洁之道》作者Bob大叔曾经说过
翻译过来:
程序架构总是一样的
让程序运行很简单
让程序"正确"很难
让程序维护简单,扩展简单就是正确
以 controller--service-mapper
为例,按照直觉分层开发,做依赖关系
问题1: 没有实现控制层,对持久层之间的隔离关系,可以随意的在controller
中注入,依赖mapper
问题2:架构分层之间是纯粹强耦合
分层开发没有达到最终的目的,实现解耦,实现扩展维护方便
对应以上问题,在bob大叔的 《整洁架构之道》中,提到的解决的思想
整洁架构落地方案
核心点: 分层的众多模块中,有最核心的业务模块(service)
其他的模块,包括controller
,redis
,rocketmq
,mysql
,mybatis
这些模块切分出来,都是容易被替换掉的
核心稳定的模块,如果依赖了容易变动不稳定模块,不满足整洁架构的思想
解决方案: 依赖倒置(开发原则)
是程序要依赖于抽象接口,不要依赖于具体实现*
- 分层数据封装
- 入参(接收的参数)
- query: 查询使用
- param:写入使用(持久层写入转化成DO)
- 远程调用:DTO
- 出参(返回值)
- service出参:BO
- infrustructure出参: BO
- dao出参:DO
- adapter出参:VO
- 远程调用: DTO
- 入参(接收的参数)
搭建worker项目架构
顶级夫工程继承操作
继承私服的父级项目tarena-mall-bom
创建项目架构
worker-admin
:后台后端worker-common
(代码和依赖):worker公用worker-po
(代码和依赖):包含的内容就是 worker 所有数据库 entity 对象worker-server
:前台后端
根据分层架构依赖关系,搭建创建8个模块
worker-server
- adapter
- main
- client-api
- infrustructure
- dao-api
- dao-impl
- daomain
- protocol
附录
maven加载私服无法下载
现象: 拒绝连接远程私服,settings配置的
关键字: http://0.0.0.0 blocked
原因: idea默认的 maven 中settings.xml
配置,禁止使用 http 协议访问私服
解决方法: 拦截删除
- 使用一个正常的 maven项目 执行
mvn clean compile -X
- 进入文件夹,修改内容,将mirror(不是mirrors)注释或者删除
前端启动问题
现象: npm install
报错 npm run
报错
原因:
-
命令执行错了
-
网络不通畅
-
node.js(16.X) npm(8.5)版本
mac运行passport
现象: 无法运行java -jar
命令
原因: 代码内配置属性,不是针对mac设置的
解决方案:
master 提交了新版本
jar运行节省内存问题
可以在java -jar
命令中添加选项,限制内存上限
128m 参数:
java -jar ***.jar -Xmx128M -Xms128M -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=128M
idea跑的 java 程序能加
连接mysql失败
现象: Access to "root@localhost:3306" denied
原因: 你的数据库 密码用户名 不是root root
解决方案: 运行passport.jar
默认使用root / root
需要覆盖 jar 内的springboot项目代码配置文件application.yaml
java -jar passport-provider-1.0-SNAPSHOT.jar -Xmx128M -Xms128M -XX:MaxMetaspaceSize=128M -XX:MetaspaceSize=128M --server.port=8099 --spring.profiles.active=local –spring.datasource.password=root
演示项目和本地项目
现象:
http://dev.front.luban.p.yufeiworld.com/
http://localhost:8989
访问演示页面测试本地代码功能
注册失败
现象: insert
语句中缺少 avator
字段
关键字: unknown column 'avator'
原因: 导入的不是commont-passport.sql
而是common_passort.sql
相关文章:

Java阶段五Day14
Java阶段五Day14 文章目录 Java阶段五Day14分布式事务整合demo案例中架构,代码关系发送半消息本地事务完成检查补偿购物车消费 鲁班周边环境调整前端启动介绍启动前端 直接启动的项目gateway(网关)login(登录注册)atta…...

【计算机网络】应用层协议 -- 安全的HTTPS协议
文章目录 1. 认识HTTPS2. 使用HTTPS加密的必要性3. 常见的加密方式3.1 对称加密3.2 非对称加密3.3 非对称加密对称加密 4. 引入CA证书4.1 CA认证4.2 数据签名4.3 非对称机密对称加密证书认证4.4 常见问题 5. 总结 1. 认识HTTPS HTTPS全称为 Hyper Text Tranfer Protocol over …...

小程序通过ip+port+路径获取服务器中的图片
配置IIS 首先需要配置IIS。 打开控制面板,接下来的流程按下图所示。 安装好后,按“win”键,搜索IIS 选择一个ip地址,或手动填写,端口号按需更改...

Codeforces Round 888 (Div. 3)(A-F)
文章目录 ABCDEF A 题意: 就是有一个m步的楼梯。每一层都有k厘米高,现在A的身高是H,给了你n个人的身高问有多少个人与A站在不同层的楼梯高度相同。 思路: 我们只需要去枚举对于A来说每一层和他一样高(人的身高和楼…...

【人工智能】深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化
深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化) 文章目录 深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化)深度神经网络训练训练深度神经网络参数共享卷积神经网络(CNN)卷积多卷积核卷积全连接最大池化卷积+池化拉平向量激活函数优化小结深度神经…...

失去SSL证书,会对网站安全造成什么影响?
作为网络世界中的“身份证”,SSL证书可以在网络世界中证明你是一个真实可信的企业或个人网站,而不是一个钓鱼网站。且在网站的服务器上部署SSL证书后,可以使网站与访问者之间通过SSL协议建立安全的加密连接,确保在Web服务器和浏览…...

gitee中fork了其他仓库,如何在本地进行同步
GitHub 操作:同步 Fork 来的仓库(上游仓库)_sigmarising的博客-CSDN博客 1. 设置upstream 2. git pull --rebase 3. 然后再执行pull、push操作...

java项目之社区生活超市管理系统(ssm+mysql+jsp)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的社区生活超市管理系统。技术交流和部署相关看文章末尾! 开发环境: 后端: 开发语言:Java 框…...

WebGPU(七):C++头部封装
WebGPU(七):C头部封装 在前面的学习中,我们使用的都是原生态的WebGPU API,那是基于C语言的API,但是为了更高效的开发,我们可以使用一个基于C的库。 根据参考的教程,这个github库提供更加纤细的描述。它提…...

Linux 网络通信epoll详解( 10 ) -【Linux通信架构系列 】
系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everything is for the…...

java源码-List源码解析
Java中的List是一个接口,它定义了一组操作列表的方法。List接口的常见子类包括ArrayList、LinkedList和Vector等。 以下是Java中List接口及其常见方法的源码解析: 1. List接口定义 public interface List<E> extends Collection<E> { …...

Mybatis的动态SQL
动态 sql 是Mybatis的强⼤特性之⼀,能够完成动态的 sql 语句拼接。 动态 SQL 大大减少了编写代码的工作量,更体现了 MyBatis 的灵活性、高度可配置性和可维护性。 Mybatis里的动态标签主要有: <if><trim><where><set><forea…...

嵌入式系统中的GPIO控制:从理论到实践与高级应用
本文将探讨嵌入式系统中的GPIO(通用输入输出)控制,着重介绍GPIO的原理和基本用法。我们将使用一个实际的示例项目来演示如何通过编程配置和控制GPIO引脚。将基于ARM Cortex-M微控制器,并使用C语言进行编写。 GPIO是嵌入式系统中最常见且功能最强大的接口之一。它允许硬件工…...

7D透明屏的市场应用广泛,在智能家居中有哪些应用表现?
7D透明屏是一种新型的显示技术,它能够实现透明度高达70%以上的显示效果。这种屏幕可以应用于各种领域,如商业广告、展览展示、智能家居等,具有广阔的市场前景。 7D透明屏的工作原理是利用光学投影技术,将图像通过透明屏幕投射出来…...

[游戏开发][Unity] 打包Xcode工程模拟器+真机调试
苹果开发者账号 账号分三类,个人,公司,企业,价格99/99/299美金 新注册账号的基本设置按网上的教程来就行 我们公司是企业账号,我的苹果开发者账号是公司一个User 下面讲述一下一个全新的打包机处理流程 首先是要把…...

python 添加环境变量
1 查看是否设置环境变量 和 使用的python在哪里安装 import sys import os# 获取Python的安装目录 import os import syspython_path sys.executable # 这个是python.exe的路径python_path os.path.dirname(python_path) print("Python安装路径:", python_path)# …...

如何用DHTMLX组件为Web应用创建甘特图?(一)
dhtmlxGantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求,是最完善的甘特图图表库。甘特图仍然是项目管理应用程序中最需要的工具之一,DHTMLX Gantt组件提供了能提升研发甘特图功能所需的重要工具。 在这篇…...

网站SEO优化:提升搜索排名与流量引爆
导言: 在互联网时代,网站SEO(搜索引擎优化)是提高网站搜索排名、吸引流量、增加曝光的重要策略。通过优化网站结构、内容和链接等方面,让搜索引擎更好地理解和收录网站内容,从而为网站带来更多有价值的有机…...

Java lamda对List<JSONObject>里多个动态属性字段进行动态的降序或者升序
最近做到一个需求,需要把业务侧返回的数据(格式为List<JSONObject>),然后根据前端传来的排序字段、以及升降序属性来排序并返回给前端。要对List<JSONObject>中的多个属性字段进行动态的升序或降序排序,我们可以根据需…...

Lua脚本解决多条命令原子性问题
Redis是一个流行的键值存储数据库,它提供了丰富的功能和命令。在Redis中,我们可以使用Lua脚本来编写多条命令,以确保这些命令的原子性执行。Lua是一种简单易学的编程语言,下面将介绍如何使用Redis提供的调用函数来操作Redis并保证…...

NAT详解(网络地址转换)
一句话说清楚它是干什么的: 网络地址转换:是指通过专用网络地址转换为公用地址,从而对外隐藏内部管理的IP地址,它使得整个专用网只需要一个全球IP就可以访问互联网,由于专用网IP地址是可以重用的,所以NAT大…...

【第一阶段】ktolin的函数
在Java中我们称之为方法,方法必须写在类里面,依赖于类。 在kotlin中函数写在类里面和外面都是可以的。称之为函数 class test{fun view(){} }fun main() {println("Hello, world!!!") }执行结果 Hello, world!!!main函数的返回值类型为Unit等…...

pytorch模型的保存与加载
1 pytorch保存和加载模型的三种方法 PyTorch提供了三种种方式来保存和加载模型,在这三种方式中,加载模型的代码和保存模型的代码必须相匹配,才能保证模型的加载成功。通常情况下,使用第一种方式(保存和加载模型状态字…...

IDE /完整分析C4819编译错误的本质原因
文章目录 概述基本概念代码页标识符字符集和字符编码方案源字符集和执行字符集 编译器使用的字符集VS字符集配置 有何作用编译器 - 源字符集编译器 -执行字符集 Qt Creator下配置MSVC编译器参数动态库DLL字符集配置不同于可执行程序EXE总结 概述 本文将从根本原因上来分析和解…...

前端学习路线(2023)
这个前端学习路线看起来很详细和全面,涵盖了从基础知识到高级框架,从单机开发到全栈项目,从混合应用到原生应用,从性能优化到架构设计的各个方面。如果你能够按照这个路线学习和实践,我相信你一定能够成为一名优秀的前…...

景区如何对旅行社进行分销管理?
旅行社的买票能力强,一般景区会跟多家旅行社合作门票分销。其中卖票下单、价格设定、财务对账结算都出现了很多问题,导致对账困难,查询困难,甚至可能有偷票漏票的情况出现,给景区收入造成损失。那要怎么处理呢…...

四步从菜鸟到高手,Python编程真的很简单(送书第一期:文末送书2本)
🍁博主简介 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 🐋 希望大家多多支持,我…...

Thread类的常用结构(java))
1 构造器 public Thread() :分配一个新的线程对象。public Thread(String name) :分配一个指定名字的新的线程对象。public Thread(Runnable target) :指定创建线程的目标对象,它实现了Runnable接口中的run方法public Thread(Runnable target,String name) :分配一…...

CSS :nth-child
CSS :nth-child :nth-child 伪类根据元素在同级元素中的位置来匹配元素. CSS :nth-child 语法 值是关键词 odd/evenAnB最新的 [of S] 语法权重 浏览器兼容性 很简单的例子, 来直觉上理解这个伪类的意思 <ul><li class"me">Apple</li><li>B…...

国内好用的企业级在线文档有哪些?
在当今数字化时代,企业级在线文档已经成为了现代办公环境中不可或缺的一部分。它不仅能够提高工作效率,还能够实现多人协同编辑,满足团队协作的需求。那么,在国内市场上,哪些企业级在线文档产品备受企业青睐呢…...