黑马苍穹外卖学习Day6
HttpClient
介绍
HttpClient 是 Apache 提供的一个开源的 Java HTTP 客户端库,用于发送 HTTP 请求和处理 HTTP 响应。它提供了一种更简便的方式来执行 HTTP 请求,并支持多种协议,如 HTTP、HTTPS、FTP 等。
使用 HttpClient 可以方便地与远程服务器进行通信,发送 HTTP 请求并处理响应。在实际应用中,HttpClient 常被用于与 RESTful API 交互、爬虫开发、测试等场景。
入门案例
新建一个test类进行测试
package com.sky.test;import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;
import java.io.UnsupportedEncodingException;@SpringBootTest
public class HttpClientTest {/*** 测试通过HttpClientTest发送GET请求*/@Testpublic void testGet() throws Exception{//创建HTTP对象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();}/*** 测试通过HttpClientTest发送POST请求*/@Testpublic void testPost() throws Exception {//创建HTTP对象CloseableHttpClient httpClient = HttpClients.createDefault();//创建请求对象HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");//构造JSON对象JSONObject jsonObject = new JSONObject();jsonObject.put("username", "admin");jsonObject.put("password", "123456");StringEntity entity = new StringEntity(jsonObject.toString());//指定请求编码方式entity.setContentEncoding("utf-8");//数据格式entity.setContentType("application/json");httpPost.setEntity(entity);//发送请求CloseableHttpResponse response = httpClient.execute(httpPost);//解析返回结果int statusCode = response.getStatusLine().getStatusCode();System.out.println("响应码为:"+ statusCode);HttpEntity entity1 = response.getEntity();String body = EntityUtils.toString(entity1);System.out.println("响应数据为:"+body);//关闭请求response.close();httpClient.close();}
}
微信小程序开发
介绍


准备工作
注册小程序
登录微信小程序平台按照提示进行注册

完善小程序信息
登录后进入开发管理和管理,根据页面提示信息补充小程序各项基本信息并生成密钥。

下载开发者工具
根据提示创建小程序


入门案例


获取用户信息

<!--index.wxml-->
<navigation-bar title="Weixin" back="{{false}}" color="black" background="#FFF"></navigation-bar>
<scroll-view class="scrollarea" scroll-y type="list"><view class="container"><!-- 展示动态信息 --><view>{{meg}}</view><button type="primary" bind:tap="getUserInfo">获取用户信息</button>昵称: {{nickName}}<image src="{{url}}" style="width: 100px;height: 100px;"></image></view>
</scroll-view>
// index.js
Page({data:{meg:'hello world',nickName:'',url:''},//获取微信用户头像和昵称getUserInfo(){wx.getUserProfile({desc: '获取用户信息',success: (res) =>{console.log(res.userInfo)//为数据赋值this.setData({nickName: res.userInfo.nickName,url: res.userInfo.avatarUrl})}})}})
其中需要调整数据库到2.7以下版本。具体路径为右上角详情->本地设置->调试基础库。

获取用户授权码
data:{meg:'hello world',nickName:'',url:'',code:''},//微信登录,获取微信登录的授权码wxlogin(){wx.login({success: (res) => {console.log(res.code)this.setData({code: res.code})},})},
<view><button type="warn" bind:tap="wxlogin">微信登录</button>授权码:{{code}}</view>

发送请求
//发送请求sendRequest(){wx.request({url: 'http://localhost:8080/user/shop/status',method:'GET',success: (res)=>{//代表后端响应的整个JSON数据console.log(res.data)}})}
<view><button type="default" bind:tap="sendRequest">发送请求</button></view>

微信登录
微信登录流程




需求分析



代码开发
openid是微信用户的唯一标识
新建Controller层
@RestController
@RequestMapping("/user/user")
@Api(tags = "C端用户相关接口")
@Slf4j
public class UserController {@AutowiredUserService userService;@Autowiredprivate JwtProperties jwtProperties;/*** 微信登录* @param userLoginDTO* @return*/@PostMapping("/login")@ApiOperation("微信登录")public Result<UserLoginVO> login(@RequestBody UserLoginDTO userLoginDTO){log.info("微信用户登录:{}",userLoginDTO.getCode());//微信登录User user = userService.wxLogin(userLoginDTO);//为微信用户生成令牌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);}
}
Service实现类
@Service
@Slf4j
public class UserServiceImpl implements UserService {//微信服务接口登录地址public static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";@Autowiredprivate WeChatProperties weChatProperties;@Autowiredprivate UserMapper userMapper;/*** 微信登录* @param userLoginDTO* @return*/@Overridepublic 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);//返回用户对象return 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;}
}
Mapper接口
@Mapper
public interface UserMapper {@Select("select * from user where openid= #{openid}")User getByOpenID(String openid);/*** 插入数据* @param user*/void insert(User user);
}
后端对应的xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sky.mapper.UserMapper"><insert id="insert" useGeneratedKeys="true" keyProperty="id">insert into user (openid, name, phone, sex, id_number, avatar, create_time) VALUES(#{openid},#{name},#{phone},#{sex},#{idNumber},#{avatar},#{createTime})</insert>
</mapper>
配置web层、拦截器组件学习
对注射web层中WebMvcConfiguration的理解
/*** 设置静态资源映射* 当访问 /doc.html路径时,Spring MVC将会去 classpath:/META-INF/resources/目录下寻找对应的静态资源* 而访问 /webjars/** 路径时,将会去 classpath:/META-INF/resources/webjars/目录下寻找对应的静态资源。* 这样做的好处是可以将一些静态资源集中存放在指定的目录,而不需要暴露给外部直接访问项目的文件结构。* 这有助于更好地组织项目结构,同时提供对静态资源的有效管理和映射。* @param registry*/protected void addResourceHandlers(ResourceHandlerRegistry registry) {log.info("开始设置静态资源映射");registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");/*** 扩展Spring MVC框架的消息转换器* 将 Java 对象转换为 JSON 数据:当服务器端需要将 Java对象转换为 JSON数据* 以便于发送给客户端时,消息转换器负责将 Java对象序列化为JSON格式的数据。* 将 JSON数据转换为 Java对象:当客户端发送包含JSON数据的请求体给服务器时* 消息转换器负责将接收到的JSON数据反序列化为对应的 Java对象。* @param converters*/@Overrideprotected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {log.info("扩展消息转换器..");//创建一个消息转换器对象MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();//需要为消息转换器设置一个对象转换器,可以将Java对象序列化为json数据converter.setObjectMapper(new JacksonObjectMapper());//将自己的消息转换器加入容器中converters.add(0,converter);}/*** 注册自定义拦截器* 第一个拦截器 jwtTokenAdminInterceptor 注册在路径 /admin/**下,但排除了路径/admin/employee/login。* 第二个拦截器 jwtTokenUserInterceptor 注册在路径 /user/**下,但排除了路径/user/user/login和/user/shop/status。* 这样配置的效果是,当请求路径匹配拦截路径时,会触发相应的拦截器执行相应的逻辑。拦截器可以用于处理请求前的预处理、日志记录、权限验证等工作。* 通过拦截器来验证 JWT 令牌,确保请求的合法性,这在安全性要求较高的 Web 应用中是常见的做法。* @param registry*/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");}
对jwt拦截器的理解
/*** jwt令牌校验的拦截器*/
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {@Autowiredprivate JwtProperties jwtProperties;/*** 校验jwt** @param request* @param response* @param handler* @return* @throws Exception*/public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//获取当前线程idSystem.out.println("当前线程id"+Thread.currentThread().getId());//判断当前拦截到的是Controller的方法还是其他资源if (!(handler instanceof HandlerMethod)) {//当前拦截到的不是动态方法,直接放行return true;}//1、从请求头中获取令牌String token = request.getHeader(jwtProperties.getUserTokenName());//2、校验令牌try {log.info("jwt校验:{}", token);//这个方法是自定义的 JWT 解析方法,接受两个参数,第一个是用于解密的密钥//第二个是待解析的 JWT 令牌 (token)。该方法返回一个 Claims 对象,其中包含了 JWT 中的声明信息。Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);//这一行代码从 Claims 对象中获取用户ID的声明,并将其转换成Long类型。在JWT的声明中,通常会包含一些声明(比如过期时间、签发者等)// 同时也会包含自定义的声明。在这里,通过 JwtClaimsConstant.USER_ID 来获取用户ID的声明。Long userId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());log.info("当前用户id:", userId);//在拦截器中存入//这行代码的作用是将用户ID存入线程上下文。线程上下文是一个与线程关联的数据存储区域,可以在整个线程的生命周期内共享数据。//在这个具体的场景中,当用户的 JWT 令牌验证通过后,将用户的ID存入线程上下文,以便在后续的业务逻辑中能够方便地获取当前用户的ID,//而不必在每个方法参数中传递用户ID或者从其他地方再次获取。这样做的好处是简化了代码,提高了代码的可读性和可维护性。//举例来说,如果有其他地方需要使用当前用户的ID,可以通过 BaseContext.getCurrentId() 获取,//而不必传递用户ID的参数。这在涉及多个方法、类之间需要传递用户ID的情况下,可以减少重复代码,提高开发效率。BaseContext.setCurrentId(userId);//3、通过,放行return true;} catch (Exception ex) {//4、不通过,响应401状态码response.setStatus(401);return false;}}
}
导入商品浏览功能
需求分析





代码实现
C端-分类接口
Controller层注意对注释进行命名用来区别admin的相同请求,具体实现方法可以通用。
@RestController("userCategoryController")
@Api(tags = "C端-分类接口")
@RequestMapping("/user/category")
@Slf4j
public class CategoryController {@Autowiredprivate CategoryService categoryService;// Spring MVC 默认会按照参数名字和请求中的参数名字进行匹配。在你的情况下,接口路径为 /list// 而请求参数为 type,由于参数名字和请求中的参数名字一致,Spring MVC 可能会自动将参数值绑定到方法的参数上。//这是Spring MVC 的一种简化规则,适用于一些简单的情况。@GetMapping("/list")@ApiOperation("条件查询")/*** 条件查询*/public Result<List<Category>> list(Integer type){List<Category> list = categoryService.list(type);return Result.success(list);}
}
C端-菜品浏览接口
Controller层
@RestController("userDishController")
@Api(tags = "C端-菜品浏览接口")
@RequestMapping("/user/dish")
@Slf4j
public class DishController {@Autowiredprivate DishService dishService;/*** 根据分类id查询菜品* @param categoryId* @return*/@GetMapping("/list")@ApiOperation("根据分类id查询菜品")private Result<List<DishVO>> list(Long categoryId){List<DishVO> dishVOS = dishService.listWithFlavor(categoryId);return Result.success(dishVOS);}
Service实现层
/*** 根据分类id查询菜品以及口味* @param categoryId* @return*/@Overridepublic List<DishVO> listWithFlavor(Long categoryId) {Dish dish = Dish.builder().categoryId(categoryId).status(StatusConstant.ENABLE).build();List<Dish> dishList = dishMapper.list(dish);List<DishVO> dishVOList = new ArrayList<>();for (Dish d : dishList){DishVO dishVO = new DishVO();BeanUtils.copyProperties(d, dishVO);List<DishFlavor> dishFlavorList = dishFlavorMapper.getByDishId(d.getId());dishVO.setFlavors(dishFlavorList);dishVOList.add(dishVO);}return dishVOList;}
C端-套餐浏览接口
Controller层
@RestController("userSetmealController")
@Api(tags = "C端-套餐浏览接口")
@RequestMapping("/user/setmeal")
@Slf4j
public class SetmealController {@Autowiredprivate SetmealService setmealService;/*** 套餐浏览接口* @param categoryId* @return*/@GetMapping("/list")@ApiOperation("根据分类id查询套餐")public Result<List<Setmeal>> list(Long categoryId){List<Setmeal> setmeals = setmealService.list(categoryId);return Result.success(setmeals);}/*** 根据套餐id查询包含的菜品* @param id* @return*/@ApiOperation("根据套餐id查询包含的菜品")@GetMapping("/dish/{id}")public Result<List<DishItemVO>> dishList(@PathVariable("id") Long id){List<DishItemVO> dishItemVOS = setmealService.dishList(id);return Result.success(dishItemVOS);}
Service层实现类
/*** 根据分类id查询菜品* @param categoryId* @return*/@Overridepublic List<Setmeal> list(Long categoryId) {Setmeal setmeal = new Setmeal();setmeal.setCategoryId(categoryId);setmeal.setStatus(StatusConstant.ENABLE);List<Setmeal> setmeals = setmealMapper.list(setmeal);return setmeals;}/*** 根据套餐id查询包含的菜品* @param id* @return*/@Overridepublic List<DishItemVO> dishList(Long id) {return setmealMapper.dishList(id);}
Mapper接口
/*** 根据分类id查询菜品* @param Setmeal* @return*/List<Setmeal> list(Setmeal setmeal);/*** 根据套餐id查询包含的菜品* @param setmealId* @return*/@Select("select sd.name,sd.copies,d.image,d.description from setmeal_dish sd left join dish d on sd.dish_id = d.id " +"where sd.setmeal_id = #{setmealId}")List<DishItemVO> dishList(Long setmealId);
XML底层
<select id="list" resultType="com.sky.entity.Setmeal" parameterType="Setmeal">select * from setmeal<where><if test="name != null">and name like concat('%',#{name},'%')</if><if test="categoryId != null">and category_id = #{categoryId}</if><if test="status != null">and status = #{status}</if></where></select>
相关文章:
黑马苍穹外卖学习Day6
HttpClient 介绍 HttpClient 是 Apache 提供的一个开源的 Java HTTP 客户端库,用于发送 HTTP 请求和处理 HTTP 响应。它提供了一种更简便的方式来执行 HTTP 请求,并支持多种协议,如 HTTP、HTTPS、FTP 等。 使用 HttpClient 可以方便地与远程…...
【Java 设计模式】设计原则之里氏替换原则
文章目录 1. 定义2. 好处3. 应用4. 示例结语 在软件开发中,设计原则是创建灵活、可维护和可扩展软件的基础。 这些原则为我们提供了指导方针,帮助我们构建高质量、易理解的代码。 ✨单一职责原则(SRP) ✨开放/封闭原则(…...
一步步指南:从指定时长中提取需求的帧图片,高效剪辑视频
在现代多媒体时代,视频已经成生活中不可或缺的一部分。从视频中提取某一帧图片,或者对视频进行剪辑,都是常见的需求。下面一起来看云炫AI智剪如何从指定时长中提取需求的帧图片,如何高效地剪辑视频。 按指定时长提取视频某帧图片的…...
【打卡】牛客网:BM93 盛水最多的容器
题目: 考虑到盛水容器的特殊性。双指针从最两边开始遍历,遍历过程中舍弃最小的。 不知道原理。 模板的: class Solution { public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*…...
Golang 文件操作
读取 一次性读取 data, err : os.ReadFile("filename.txt") if err ! nil {log.Fatal(err) } fmt.Println(string(data))按行读取 方式1:bufio.NewScanner file, err : os.Open("filename.txt") if err ! nil {panic(err) } defer file.Clo…...
C++I/O流——(3)文件输入/输出(第二节)
归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言📝 含泪播种的人一定能含笑收获ÿ…...
内网穿透[让你在家里也能榨干学校的服务器]Yep!
内网穿透 问题:什么是内网穿透,内网穿透的作用是什么? 前提!!!!你得拥有超级管理员的权限,比如root,不然后面的一切免提! 应用场景如下:比如你…...
构建基于RHEL9系列(CentOS9,AlmaLinux9,RockyLinux9等)的支持63个常见模块的PHP8.1.20的RPM包
本文适用:rhel9系列,或同类系统(CentOS9,AlmaLinux9,RockyLinux9等) 文档形成时期:2023年 因系统版本不同,构建部署应略有差异,但本文未做细分,对稍有经验者应不存在明显障碍。 因软件世界之复杂和个人能力…...
你知道什么是Java中的类型强转吗?
强制类型转换 强转存在与父转子的时候,子转父不需要进行强转,如 Object o "hello"; //String类是Object类的子类,无需进行强转类型强转分为两种情况: Ⅰ、向下转型:将父类对象引用转换为子类对象引用&am…...
【2023】ArrayList和LinkedList详解介绍对比
一、ArrayList 1、概述 ArrayList是实现了List接口的动态数组,所谓动态数组就是他的大小是可变的。实现了所有可选列表操作,并允许包括Null在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。 …...
【软件工程】基于领域建模的产品与技术方案设计(领域驱动设计DDD)
文章目录 1、领域建模2、产品方案、技术方案3、领域驱动设计DDD 1、领域建模 领域模型(domain model) 是对领域内的概念类或现实世界中对象的可视化表示。领域模型也成为概念模型、领域对象模型和分析对象模型。域模型是一种概念模型,也叫问题域模型。它表述的是某…...
跨境电商账号频繁?你的IP可能“不干净”了
疫情促进了跨境电商行业的加速发展,许多卖家也抓住了这波流量红利,跨境电商月入数万,数十万甚至数百万的造福神话也不断在上演,但由于国内外电商运营模式不同,多店运营、用户数据收集、刷单等行为都受到了国外平台的严…...
Docker数据卷与拦截与目录拦截
目录 高级容器挂载技术深度解析引言数据卷挂载原理解析应用场景使用介绍 目录挂载原理解析应用场景使用介绍 总结 高级容器挂载技术深度解析 引言 容器技术的快速发展使得容器挂载技术变得愈发重要。在容器化应用中,数据卷挂载和目录挂载是两种常见的挂载方式&…...
Python 元类 metaclass 详解
元类(metaclass)是 Python 中一个高级且相对较少使用的概念。元类可以被视为类的类,它控制类的创建过程。 一、基本概念 在 Python 中,一切皆对象。为了避免混淆,我们约定两个术语: 类实例:当…...
HCIA基础知识
IP地址、静态路由、动态路由、交换机 OSPF RIP DHCP VLAN ACL NAT OSI TCP/IP UDP TCP 三次握手,四次挥手,报头 什么是网络? 由网络连接设备通过传输介质将网络终端设备连接起来,进行资源共享、信息传递的平台。 OSI七…...
翻译: Streamlit从入门到精通 部署一个机器学习应用程序 四
Streamlit从入门到精通 系列: 翻译: Streamlit从入门到精通 基础控件 一翻译: Streamlit从入门到精通 显示图表Graphs 地图Map 主题Themes 二翻译: Streamlit从入门到精通 构建一个机器学习应用程序 三 1. 5. 如何部署一个Streamlit应用 部署是将应用程序从开发…...
AI时代Python量化交易实战:ChatGPT引领新时代
文章目录 《AI时代Python量化交易实战:ChatGPT让量化交易插上翅膀》关键点内容简介作者简介购买链接 《AI时代架构师修炼之道:ChatGPT让架构师插上翅膀》关键点内容简介作者简介 赠书活动 《AI时代Python量化交易实战:ChatGPT让量化交易插上翅…...
国科大软件安全原理期末复习笔记
1 软件安全总论 1.软件的三大特性:复杂性、互连性、可扩展性; 2.基本概念:缺陷、漏洞、风险 缺陷(bug):软件在设计和实现上的错误;漏洞(vulnerability):漏洞…...
人工智能软件测试2024年主要趋势
人工智能软件测试领域在未来可能面临多个发展趋势,其中一些趋势可能会对测试方法、工具和流程产生深远的影响。以下是塑造人工智能软件测试未来的主要趋势: 自动化和自动学习测试:随着人工智能的发展,测试自动化将变得更加智能和自…...
【JAVA】Java 中什么叫单例设计模式?请用 Java 写出线程安全的单例模式
🍎个人博客:个人主页 🏆个人专栏:JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 懒汉式(Lazy Initialization): 双重检查锁定(Double-Checked Locking)…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
协议转换利器,profinet转ethercat网关的两大派系,各有千秋
随着工业以太网的发展,其高效、便捷、协议开放、易于冗余等诸多优点,被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口,具有实时性、开放性,使用TCP/IP和IT标准,符合基于工业以太网的…...
Matlab实现任意伪彩色图像可视化显示
Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的亮度(或…...
使用python进行图像处理—图像变换(6)
图像变换是指改变图像的几何形状或空间位置的操作。常见的几何变换包括平移、旋转、缩放、剪切(shear)以及更复杂的仿射变换和透视变换。这些变换在图像配准、图像校正、创建特效等场景中非常有用。 6.1仿射变换(Affine Transformation) 仿射变换是一种…...
无头浏览器技术:Python爬虫如何精准模拟搜索点击
1. 无头浏览器技术概述 1.1 什么是无头浏览器? 无头浏览器是一种没有图形用户界面(GUI)的浏览器,它通过程序控制浏览器内核(如Chromium、Firefox)执行页面加载、JavaScript渲染、表单提交等操作。由于不渲…...
