当前位置: 首页 > news >正文

苍穹外卖技术栈

重难点详解

1、定义全局异常

在这里插入图片描述

2、ThreadLocal

  • ThreadLocal 并不是一个Thread,而是Thread的一个局部变量
  • ThreadLocal 为每一个线程提供独立的存储空间,具有线程隔离的效果,只有在线程内才能取到值,线程外则不能访问
public void set(T value) 设置当前线程的线程局部变量的值public T get() 返回当前线程所对应的线程局部变量的值public void remove() 移除当前线程的线程局部变量

注意:客户端每次发送http请求,对应的服务端都会分配一个新的线程,在处理过程中涉及到系列方法属于同一个线程:
【1】LoginCheckFilter的doFilter方法
【2】EmployeeController的update方法
【3】MyMetaObjectHandler的updateFill方法

3、BaseContext上下文

BaseContext是基于ThreadLocal类封装的工具类,用于在同一线程中的封装数据和获取数据

> BaseContext工具类用于存放和取出当前登录的用户的id
> 
public class BaseContext {public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();/*** 设置当前线程的线程局部变量的值* @param id*/public static void setCurrentId(Long id) {threadLocal.set(id);}public static Long getCurrentId() {return threadLocal.get();}public static void removeCurrentId() {threadLocal.remove();}

4、PageHelper分页

pagehelper是mybatis 提供的分页插件

开始分页

PageHelper.startPage(1, 10)// selectlist查询数据库的时候会自动加上limit 1,10。

在CategoryServiceImpl声明pageQuery方法,及其父类接口:

    public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {// 分页器对象Page<Category> page = new Page<>();List<Category> categoryList  = categoryMapper.pageQuery(categoryPageQueryDTO);Long total = page.getTotal();// 分页return new PageResult(total,categoryList);}

在EmployeeServiceImpl声明pageQuery方法,及其父类接口

public PageResult pageQuery(EmployeePageQueryDTO dto) {PageHelper.startPage(dto.getPage(),dto.getPageSize());Page<Employee> page = employeeMapper.pageQuery(dto);return new PageResult(page.getTotal(),page.getResult());}

原理:

  • Mybatis内置了分页拦截器PageInterceptor,即在执行相关sql之前会拦截一些操作
  • 通过`setLocalPage()方法,将分页信息保存在当前线程中。分页查询方法与之处在同一个线程中,共享ThreadLocal中的数据
  • selectlist查询之后赋值给的List list。这个list是Page 类型
  • 再将list放到PageInfo<>中即可。

查询

List<Employee> list = employeeMapper.selectByExample(Example);  

分页结果展示

 PageInfo<Employee> pageInfo = new PageInfo<>(list);  System.out.println("总记录数:"+pageInfo.getTotal());  System.out.println("总页数:"+pageInfo.getPages());  System.out.println("一页的大小:"+pageInfo.getSize());  

5、日期按年月日显示

  • WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理
    protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("Spring MVC扩展消息转化器...");// 创建消息转换器对象MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();// 设置该消息转换器使用 JacksonObjectMapper 进行转换messageConverter.setObjectMapper(new JacksonObjectMapper());// 将消息转换器对象追加到 mvc 框架的转换器集合中(加到最前面)converters.add(0,messageConverter);}

在这里插入图片描述

6、启用/禁用账号

/**
* 启用禁用员工账号
*/
@Override
public void startOrStop(Integer status, Long id) {Employee employee = Employee.builder().status(status).id(id).build();employeeMapper.update(employee);
}

Employee.builder().build()建造者模式,builder构造对象;@Builder 注解

6、公共字段填充

mybatis-plus提供了公共字段自动填充功能

// 在EmployeeMapper
@AutoFill(value = OperationType.INSERT)
void insert(Employee employee);@AutoFill(value = OperationType.UPDATE)
void update(Employee employee);// CategoryMapper
@AutoFill(value = OperationType.INSERT)
void insert(Category category);@AutoFill(value = OperationType.UPDATE)
void update(Category category);

实现步骤
【1】实体类的属性上加入注解@TableField

create_time,create_user 使用 Insert
update_time,update_user 使用 Insert/update
FieldFill.DEFAULT  //默认不自动填充@ApiModelProperty(value = "创建时间")@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@ApiModelProperty(value = "更新时间")@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;

【2】元数据对象处理器,实现MetaObjectHandler接口,

@Slf4j
@Component // 交给spring管理
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill...");metaObject.setValue("createTime", LocalDateTime.now());metaObject.setValue("updateTime",LocalDateTime.now());metaObject.setValue("createUser", BaseContext.getCurrentId());metaObject.setValue("updateUser",BaseContext.getCurrentId());}@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill...");long id = Thread.currentThread().getId();log.info("当前线程id:{}",id);metaObject.setValue("updateTime",LocalDateTime.now());metaObject.setValue("updateUser",BaseContext.getCurrentId());}

7、文件上传

 @PostMapping("/upload")@ApiOperation("文件上传")public Result<String> upload(MultipartFile file){log.info("文件上传: {}", file);try {// 原始文件名String originalFilename = file.getOriginalFilename();// 截取原始文件名的后缀String suffix= originalFilename.substring(originalFilename.lastIndexOf("."));// 构造新文件名称String objectName = UUID.randomUUID().toString() + extension;
// 文件的请求路径File dir = new File(basePath);// 创建一个目录对象//	将临时文件转存到指定位置
file.transferTo(new File(basePath+fileName));

7、请求参数requestparam与requestbody

@ResquestBody要搭配@PostMapping使用,@ResquestParam要搭配@GetMapping使用
区别equestparam与requestbody

  • 【@RequestParam】接收的参数是来自HTTP请求体或请求url的QueryString中
public void aliReceive(@RequestParam("message") String message)

@RequestParam用来处理 Content-Type 为 application/x-www-form-urlencoded 编码的内容

@RequestParam 接受JSON的字符串

@RequestParam注解无法读取application/json格式数据

  • 【@RequestBody】一般用来处理application/json、application/xml等类型的数据。

POST请求中,通过HttpEntity传递的参数,必须要在请求头中声明数据的类型Content-Type,SpringMVC通过使用

  • 【@PathVariable】
// 参数名和url变量名不一致
@RequestMapping("/user/{id}")
public String testPathVariable(@PathVariable("id") String userId){System.out.println("路径上的占位符的值="+id);
}// 参数名和url变量名一致
@RequestMapping("/getUser/{name}")public User getUser(@PathVariable String name){return userService.selectUser(name);}通过@PathVariable,例如/blogs/1
通过@RequestParam,例如blogs?blogId=1

8、HttpClient

【发送请求步骤】

  • 创建HttpClient对象
  • 创建请求对象HttpGet、HttpPost等
  • 请求对象调用HttpClient的execute方法发送请求
/*** 测试通过httpclient发送GET方式的请求*/
@Test
public void testGET() throws Exception {// 创建httpclient对象CloseableHttpClient httpClient = HttpClients.createDefault();// 创建请求对象HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");// 发送请求,接收响应结果CloseableHttpResponse response = httpClient.execute(httpGet);// 获取客户端返回的状态码int statusCode = response.getStatusLine().getStatusCode();System.out.println("服务端返回的状态码为:" + statusCode);HttpEntity entity = response.getEntity();String body = EntityUtils.toString(entity);System.out.println("服务端返回的数据为:" +body);// 关闭资源response.close();httpClient.close();
}

9、微信小程序登录

在application-dev.yml中写入具体的配置属性

skywechat:appid: ${sky.wechat.appid}secret: ${sky.wechat.secret}

创建user/UserController,创建微信登录的方法

@PostMapping("/login")@ApiOperation("微信登录")public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){log.info("微信用户登录:{}",userLoginDTO);// 微信登录User user = userService.wxLogin(userLoginDTO);// 为微信用户生成jwt令牌Map<String, Object> claims = new HashMap<>();claims.put(JwtClaimsConstant.USER_ID, user.getId());String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);UserLoginVO userLoginVO = UserLoginVO.builder().id(user.getId()).openid(user.getOpenid()).token(token).build();return Result.success(userLoginVO);

在UserServiceImpl中,实现wxLogin的方法,及其父类接口

 // 微信服务接口地址public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
public User wxLogin(UserLoginDTO userLoginDTO) {String openid = getOpenid(userLoginDTO.getCode());// 判断openid是否为空,如果为空表示登录失败,抛出业务异常if (openid == null){throw new LoginFailedException(MessageConstant.LOGIN_FAILED);}// 判断当前用户是否为新用户User user = userMapper.getByOpenId(openid);// 如果是新用户,自动完成注册if (user == null){user = User.builder().openid(openid).createTime(LocalDateTime.now()).build();userMapper.insert(user);}private String getOpenid(String code){// 调用微信接口服务,获取当前微信用户的openidMap<String, String> map = new HashMap<>();map.put("appid", weChatProperties.getAppid());map.put("secret", weChatProperties.getSecret());map.put("js_code", code);map.put("grant_type", "authorization_code");String json = HttpClientUtil.doGet(WX_LOGIN, map);JSONObject jsonObject = JSON.parseObject(json);String openid = jsonObject.getString("openid");return openid;}

编写JwtTokenUserInterceptor拦截器,校验用户端token是否是合法的

public class JwtTokenUserInterceptor implements HandlerInterceptor {...}

在WebMvcConfiguration中,注册拦截器


@Autowired
private JwtTokenUserInterceptor jwtTokenUserInterceptor;protected void addInterceptors(InterceptorRegistry registry) {log.info("开始注册自定义拦截器...");registry.addInterceptor(jwtTokenAdminInterceptor).addPathPatterns("/admin/**").excludePathPatterns("/admin/employee/login");registry.addInterceptor(jwtTokenUserInterceptor).addPathPatterns("/user/**").excludePathPatterns("/user/user/login").excludePathPatterns("/user/shop/status");

10、Redis缓存

RedisTemplate是Spring Data Redis提供给用户的最高级的抽象客户端,用户可直接通过RedisTemplate进行多种操作、异常处理、序列化、发布订阅等
————————————————————
spring-data-redis的提供了如下功能:

  1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类
  2. 进行了归类封装,将同一类型操作封装为operation接口

ValueOperations:简单K-V操作 redisTemplate.opsForValue().
SetOperations:set类型数据操作 redisTemplate.opsForSet().
ZSetOperations:zset类型数据操作 redisTemplate.opsForZSet().
HashOperations:针对map类型的数据操作 redisTemplate.opsForHash()
ListOperations:针对list类型的数据操作 redisTemplate.opsForList().

  1. 针对数据的“序列化/反序列化”,提供了多种可选择策略(RedisSerializer)
  1. JdkSerializationRedisSerializer:POJO对象的存取场景,使用JDK本身序列化机制,将pojo类通过ObjectInputStream/ObjectOutputStream进行序列化操作,最终redis-server中将存储字节序列。是目前最常用的序列化策略。
  1. StringRedisSerializer:Key或者value为字符串的场景,根据指定的charset对数据的字节序列编码成string,是“newString(bytes,charset)”和“string.getBytes(charset)”的直接封装。是最轻量级和高效的策略。
  1. JacksonJsonRedisSerializer:jackson-json工具提供了javabean与json之间的转换能力,可以将pojo实例序列化成json格式存储在redis中,也可以将json格式的数据转换成pojo实例。因为jackson工具在序列化和反序列化时,需要明确指定Class类型,因此此策略封装起来稍微复杂。
  1. OxmSerializer:提供了将javabean与xml之间的转换能力,目前可用的三方支持包括jaxb,apache-xmlbeans;redis存储的数据将是xml工具。不过使用此策略,编程将会有些难度,而且效率最低;不建议使用。【需要spring-oxm模块的支持】

11.BeanUtils

BeanUtils.copyProperties的用法

常见场景:

  • 接口中将前端请求参数xxVo,转化为xxQuery对象,查询数据库条件对象
BeanUtils.copyProperties(source,target);BeanUtils.copyProperties("要转换的类", "转换后的类");
  1. 源对象source的属性拷贝值赋给目标对象target的过程中,属性名和属性类型都相同的属性才能被成功拷贝赋值
  2. 做赋值的属性一定要有对应的setter/getter才能成功赋值
  3. 1.对于类型为Boolean/Short/Integer/Float/Double的属性,它会转换为0
  4. java.util.Date/BigDecimal/java.sql.Date/java.sql.Timestamp/java.sql.Time这几个类,如果值为null,则在copy时会抛异常,需要使用对应的Conveter:

org.springframework.beans.BeanUtils BeanUtils.copyProperties(a, b):a复制到b
org.apache.commons.beanutils.BeanUtilsBeanUtils.copyProperties(a, b):b复制到a

12、Spring Task定时处理

Spring Task 是Spring框架提供的任务调度工具

【Spring Task实现步骤】

  1. 导入maven左边
  2. 启动类添加@EnableScheduling注解,开启任务调度
  3. 自定义定时任务 @Scheduled(cron=" ")
    @Scheduled(cron = "0 * * * * ? *") // 每分钟触发一次public void processTimeoutOrder(){log.info("定时处理超时订单:{}", LocalDateTime.now());

13、WebSocket

WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接, 并进行双向数据传输

创建websocket/WebSocketServer,实现WebSocket服务

@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {// 存放会话对象
private static Map<String, Session> sessionMap = new HashMap();//连接建立成功@OnOpenpublic void onOpen(Session session, @PathParam("sid") String sid) {System.out.println("客户端:" + sid + "建立连接");sessionMap.put(sid, session);}
//收到客户端消息@OnMessagepublic void onMessage(String message, @PathParam("sid") String sid) {System.out.println("收到来自客户端:" + sid + "的信息:" + message);}
// 关闭连接@OnClosepublic void onClose(@PathParam("sid") String sid) {System.out.println("连接断开:" + sid);sessionMap.remove(sid);}
// public void sendToAllClient(String message) {Collection<Session> sessions = sessionMap.values();for (Session session : sessions) {try {//服务器向客户端发送消息session.getBasicRemote().sendText(message);} catch (Exception e) {e.printStackTrace();}}}

创建WebSocketTask中,通过WebSocket向客户端发送消息

    public void sendMessageToClient() {webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));}

14、LambdaQueryWrapper

LambdaQueryWrapper是Mybatis-Plus框架中的一个查询条件构造器

LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName, "张三") // 等于eq.ne(User::getAge, 18) // 不等于ne.gt(User::getSalary, 5000) // 大于gt.like(User::getEmail, "abc") //模糊查询.orderByDesc(User::getCreateTime);// 降序
List<User> userList = userMapper.selectList(queryWrapper);

15、Nginx

  • 反向代理:允许Nginx服务器代表客户端将请求转发给后端的多个应用服务器
    在这里插入图片描述

16、Spring Cache

Spring Cache 是一个框架,实现了基于注解的缓存功能;底层可以切换不同的缓存实现,如:Redis

    @PostMapping@ApiOperation(value = "新增套餐")@CacheEvict(cacheNames = "setmealCache",key = "#setmealDTO.categoryId")public Result save(@RequestBody SetmealDTO setmealDTO){setmealService.save(setmealDTO);}// 修改信息@CacheEvict(cacheNames = "setmealCache",allEntries = true)public Result update(@RequestBody SetmealDTO setmealDTO){setmealService.update(setmealDTO);return Result.success();}

常用注解:

@EnableCaching // 开启缓存注解功能,启动类上@Cacheable //在方法执行前查询缓存中是否有数据@CachePut //将方法的返回值加入缓存中@CacheEvict //删除缓存

相关文章:

苍穹外卖技术栈

重难点详解 1、定义全局异常 2、ThreadLocal ThreadLocal 并不是一个Thread&#xff0c;而是Thread的一个局部变量ThreadLocal 为每一个线程提供独立的存储空间&#xff0c;具有线程隔离的效果&#xff0c;只有在线程内才能取到值&#xff0c;线程外则不能访问 public void …...

重新开始 杂类:C++基础

目录 1.输入输出 2 . i 与 i 3.结构体 4.二进制 1.输入输出 #include<cstdio>//cin>>,cout #include<iostream>//printf,scanf &#xff08;1&#xff09; cin , cout输入输出流可直接用于数字&#xff0c;字符 &#xff08;2&#xff09;scanf(&quo…...

自用的markdown与latex特殊符号

\triangleq \approx \xlongequal[y\arctan x]{x\tan y} \sum_{\substack{j1 \\ j\neq i}} \iiint\limits_\Omega \overset{\circ}{\vec{r}} \varphi \checkmark \stackrel{\cdot\cdot\cdot}{x}≜ ≈ y arctan ⁡ x x tan ⁡ y ∑ j 1 j ≠ i ∭ Ω r ⃗ ∘ φ ✓ x ⋅ ⋅ ⋅…...

【20期】说一说Java引用类型原理

Java中一共有4种引用类型(其实还有一些其他的引用类型比如FinalReference)&#xff1a;强引用、软引用、弱引用、虚引用。 其中强引用就是我们经常使用的Object a new Object(); 这样的形式&#xff0c;在Java中并没有对应的Reference类。 本篇文章主要是分析软引用、弱引用、…...

无锡布里渊——厘米级分布式光纤-锅炉安全监测解决方案

无锡布里渊——厘米级分布式光纤-锅炉安全监测解决方案 厘米级分布式光纤-锅炉安全监测解决方案 1、方案背景与产品简介&#xff1a; 1.1&#xff1a;背景简介&#xff1a; 锅炉作为一种把煤、石油或天燃气等化石燃料所储藏的化学能转换成水或水蒸气的热能的重要设备&#xff…...

GREASELM: GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING

本文是LLM系列文章&#xff0c;针对《GREASELM: GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING》的翻译。 GREASELM&#xff1a;图推理增强的问答语言模型 摘要1 引言2 相关工作3 提出的方法&#xff1a;GREASELM4 实验设置5 实验结果6 结论 摘要 回答关…...

QT C++ 实现网络聊天室

一、基本原理及流程 1&#xff09;知识回顾&#xff08;C语言中的TCP流程&#xff09; 2&#xff09;QT中的服务器端/客户端的操作流程 二、代码实现 1&#xff09;服务器 .ui .pro 在pro文件中添加network库 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget>…...

每日一道面试题之什么是上下文切换?

上下文切换是指在计算机操作系统中&#xff0c;当多个进程或线程同时运行时&#xff0c;系统需要将当前运行进程或线程的状态&#xff08;包括程序计数器、寄存器值、内存映像等&#xff09;保存起来&#xff0c;然后切换到另一个进程或线程继续执行的过程。上下文切换通常由操…...

2023.9.3 关于 AVL 树

目录 二叉搜索树 二叉搜索树的简介&#xff1a; 二叉搜索树的查找&#xff1a; 二叉搜索树的效率&#xff1a; AVL树 AVL 树的简介&#xff1a; AVL 树的实现&#xff1a; AVL树的旋转 右单旋 左单旋 左右双旋 右左双旋 完整 AVL树插入代码 验证 AVL 树 AVL 树的性…...

机器学习课后习题 --- 机器学习实践

&#xff08;一&#xff09;单选题 1.以下关于训练集、验证集和测试集说法不正确的是( )。 A:测试集是纯粹是用于测试模型泛化能力B:训练集是用来训练以及评估模型性能 C:验证集用于调整模型参数 D:以上说法都不对 2.当数据分布不平衡时&#xff0c;我们可采取的措施不包括…...

git常用操作

删除分支 例&#xff1a;例如想删除的分支是dev_delete,那么可以按照如下的操作进行 #查看当前所在分支 git branch#如果在当前dev_delete分支上&#xff0c;就要切换到其他分支才能删除该分支 git checkout 其他分支#删除本地名为dev_delete的分支 git branch -d dev_delete…...

QT的补充知识

一、文件 QFile QT提供了QFile类用于对文件进行读写操作&#xff0c;也提供了其他的两个类&#xff1a;文本流&#xff08;QTextSream&#xff09;和数据流&#xff08;QDataStream&#xff09; 文本流&#xff08;QTextSream&#xff09;&#xff1a;用于对文本数据的处理&am…...

【力扣周赛】第 360 场周赛(贪心 ⭐树上倍增)

文章目录 竞赛链接Q1&#xff1a;8015. 距离原点最远的点&#xff08;贪心&#xff09;Q2&#xff1a;8022. 找出美丽数组的最小和&#xff08;贪心&#xff09;Q3&#xff1a;2835. 使子序列的和等于目标的最少操作次数&#xff08;贪心&#xff09;思路竞赛时丑陋代码&#x…...

企业如何防止数据外泄——【部署智能透明加密防泄密系统】

为防止公司文件泄密&#xff0c;可以采取以下措施&#xff1a; www.drhchina.com 分部门部署&#xff1a;根据不同的部门需要&#xff0c;为不同部门用户部署灵活的加密方案。例如&#xff0c;对研发部、销售部、运营部的机密资料进行强制性自动加密&#xff0c;对普通部门的文…...

【聚类】DBCAN聚类

OPTICS是基于DBSCAN改进的一种密度聚类算法&#xff0c;对参数不敏感。当需要用到基于密度的聚类算法时&#xff0c;可以作为DBSCAN的一种替代的优化方案&#xff0c;以实现更优的效果。 原理 基于密度的聚类算法&#xff08;1&#xff09;——DBSCAN详解_dbscan聚类_root-ca…...

通过安装cpolar内网穿透在Kali上实现SSH远程连接的步骤指南

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过cpolar 内网穿透软件实现ssh 远程连接kali! 1. 启动kali ssh 服务 默认新安装的kali系统会关闭ssh 连接服务,我们通…...

UDP和TCP协议报文格式详解

在初识网络原理(初识网络原理_蜡笔小心眼子&#xff01;的博客-CSDN博客)这篇博客中,我们简单的了解了一下TCP/IP五层网络模型,这篇博客将详细的学习一下五层网络模型中传输层的两个著名协议:UDP和TCP 目录 一, 传输层的作用 二, UDP 1,UDP协议的特点 2,UDP报文格式 三, TC…...

STM32+UART串口+DMA收发

目录 1、cubemax端配置 1.1 初始化配置 1.2 GPIO配置 1.3 UART配置 1.3.1 串口基础配置 1.3.2 DMA配置 2、keil端代码设计 2.1 初始化配置 2.2 DMA接收初始化配置 2.3 DMA发送配置 2.4 接收回调函数设置 2.5 回调函数内容代码编写 2.5.1 接收回调函数 2.5.2 发送回调…...

安全基础 --- js的闭包和this属性

js闭包 简介 一个函数和对其周围状态&#xff08;lexical exviroment&#xff0c;词法环境&#xff09;的引用捆绑在一起&#xff08;或者说函数被引用包围&#xff09;&#xff0c;这样的组合就是闭包&#xff08;closure&#xff09; 在js中&#xff0c;通俗来讲&#xff0c…...

【C语言每日一题】08. 字符三角形

题目来源&#xff1a;http://noi.openjudge.cn/ch0101/08 08 字符三角形 总时间限制: 1000ms 内存限制: 65536kB 问题描述 给定一个字符&#xff0c;用它构造一个底边长5个字符&#xff0c;高3个字符的等腰字符三角形。 输入 输入只有一行&#xff0c; 包含一个字符。 输出…...

如何打war包,并用war包更新服务器版本

1.打包&#xff0c;我用的maven打包 先执行clean将已经生成的包清除掉 清除完&#xff0c;点package进行打包 控制台输出success&#xff0c;证明打包成功了 文件名.war的后缀就是生成的war包 2.将war包上传致服务器 一般会在war包加上日期版本上传至服务器 解压上传的war…...

uniApp webview 中调用底座蓝牙打印功能异常

背景: 使用uniApp, 安卓底座 webView 方式开发; 调用方式采用H5 向 底座发送消息, 底座判断消息类型, 然后连接打印机进行打印; 内容通过指令集方式传递给打印机; 过程当中发现部分标签可以正常打印, 但又有部分不行,打印机没反应, 也没有报错; 原因分析: 对比标签内容…...

Mac下安装Jmeter及其配置

一、安装JDK环境 安装方式&#xff1a;mac下配置JDK环境_只看不学的博客-CSDN博客 如果已安装JDK环境即可忽略该步骤&#xff0c;检查方式&#xff0c;在终端输入java -version,如果出现了java版本&#xff0c;即代表已经配置过JDK环境了&#xff0c;如下图所示&#xff1a; …...

js+html实现打字游戏v1

实现逻辑&#xff1a;设置定时器每秒刷新一次&#xff0c;定时器刷新多少次执行一次生成单词操作来决定单词的生成速度&#xff0c;例如初始单词生成速度为1&#xff0c;那么定时器刷新5次才生成一次单词&#xff0c;每个单词用span来装&#xff0c;每组10个单词放到div里。监听…...

Java on VS Code 8月更新|反编译器用户体验优化、新 Maven 项目工作流、代码高亮稳定性提升

作者&#xff1a;Nick Zhu 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎来到 Visual Studio Code for Java 的 8 月更新&#xff01;在这篇博客中&#xff0c;我们将为您提供有关反编译器支持的更多改进。此外&#xff0c;我们将展示如何创建没有原型的 Maven 项目以及一…...

划分Vlan时需要注意的问题

网络部分2019年才开始学习的&#xff0c;在学习过程中配置了整个公司的网络&#xff0c;心里才有了一点把握&#xff0c;算是掌握了最基本的。 不会的就上网学&#xff0c;反正网络上什么知识都有&#xff0c;只要有需求就对照着学&#xff0c;很长时间没有学习网络了&#xff…...

【广州华锐互动】利用AR远程指导系统进行机械故障排查,实现远程虚拟信息互动

随着工业自动化和智能化的不断发展&#xff0c;机械故障诊断已经成为了工业生产中的重要环节。为了提高故障诊断的准确性和效率&#xff0c;近年来&#xff0c;AR&#xff08;增强现实&#xff09;远程协助技术逐渐应用于机械故障诊断领域。本文将探讨AR远程协助技术在机械故障…...

Spring工具类--CollectionUtils的使用

原文网址&#xff1a;Spring工具类--CollectionUtils的使用_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Spring的CollectionUtils的使用。 CollectionUtils工具类的作用&#xff1a;操作Collection&#xff0c;比如&#xff1a;List、Set。 判断 方法作用static boolean is…...

Node.js 应用的御用品: Node.js 错误处理系统

开发中&#xff0c;有些开发者会积极寻求处理错误&#xff0c;力求减少开发时间&#xff0c;但也有些人完全忽略了错误的存在。正确处理错误不仅意味着能够轻松发现和纠正错误&#xff0c;而且还意味着能够为大型应用程序开发出稳健的代码库。 特别是对于 Node.js 开发人员&am…...

K210-CanMV IDE开发软件

K210-CanMV IDE开发软件 界面功能简介连接设备临时运行开机运行程序 界面功能简介 区域①菜单栏&#xff1a;操作文件&#xff0c;使用工具等。 区域②快捷按钮&#xff1a;区域①中的文件和编辑中部分功能的快捷方式。 区域③连接设备&#xff1a;连接设备和程序控制按钮。 …...