快速开发框架若依的基础使用详解
Hi I’m Shendi
快速开发框架若依的基础使用详解
最近在为公司制作新的项目,经过了一段时间的技术沉淀,我开始尝试接触市面上用的比较多的快速开发框架,听的最多的当属若依吧
于是就选用了若依
介绍
为什么选?目的是为了提高开发效率,至于能不能提高,得实践才能知晓。
若依的官网:http://www.ruoyi.vip/
是一个快速开发框架,典型的一个后台管理系统。
RuoYi-Vue 是一个 Java EE 企业级快速开发平台,基于经典技术组合(Spring Boot、Spring Security、MyBatis、Jwt、Vue),内置模块如:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理、代码生成等。在线定时任务配置;支持集群,支持多数据源,支持分布式事务。
可以通过官网的在线演示看到效果,当然,没有具体使用并没有这方面经验的话,看这些大概都是云里雾里的
若依分几个版本,但都是基于SpringBoot的,这点没有问题,因为SpringBoot是目前Java用的最多的JavaWeb框架了
我目前挑选的是前后端分离版本,若依除此之外还有
- 微服务版(公司有一定规模了,有很多台服务器的话可以用)
- 不分离版(现在基本上都前后端分离了,不分离的基本上没人用了吧)
从侧边栏讲起,先大概有一个了解
首先若依表面上的有三个大部分
- 系统管理
- 系统监控
- 系统工具
其中系统管理是最核心的部分,包含了用户,角色,菜单,部门…,可以说是一个ERP系统了
而这些都是已经做好了的,我们使用的话就不需要自己写登录,做权限,菜单这些了,需要根据自己的业务去更改
若依是使用了目前市面上流行的一些开源框架。Spring系列,比如做权限验证,前后端分离版是用的Spring Security…
我使用了的这段时间,给我的感觉就是”还行“,对我来说,重要的部分就是将权限都做好了,我只需要专心写接口就可以了。大体我也讲不上来,所以写下这篇文章来总结一下。
架构
使用了 Java,Mysql,Redis
具体参考官方文档
项目的下载与导入
我选的前后端分离版,前端使用的vue系列
首先从git上拉项目。或者下载压缩包也行,在官网上进入对应的仓库地址
我这里直接使用 Git 下载了,因为这样比较快(至于没有 Git 的先要去下载 Git)
打开 Git bash,进入到自己新建的文件夹中,使用 git clone
命令从网络上将git项目克隆下来
git clone https://gitee.com/y_project/RuoYi-Vue.git
ps: 至于 git 的地址,在官方源码的Gitee中点击克隆就可以获取到了
下载下来的目录结构和仓库展示的目录结构是差不多的
有的时候我们会给文件夹改名称,但是建议如果对这些不是很熟练的话最好先不要改。不然就会和我一样花一些时间去补错误了
其中,ruoyi-ui
是前端项目,这里需要注意一下,前端项目和后端项目不要放到一起,因为前端项目构建的时候会生成 node_modules 文件夹,这个文件夹内会有很多的文件,然后后端导入就会卡死(我Eclipse导入就卡死了,然后改IDEA,后来才想到是不是这个的原因,然后将前端项目移出来就没问题了…)
后端导入
首先从后端开始,导入是非常简单的,如果是IDEA的话,那么直接打开这个项目就可以了,这是一个Maven多模块项目。
如果是 Eclipse 的话,使用Maven的方式导入,方法如下
File -> Import -> Maven -> Exists Maven Project,然后 Root Directory 选择若依的文件夹就好了。
然后等待右下角进度条开始编译之类的,完成后是这样的
我现在这个是Eclipse的Java视图,在Eclipse的JavaEE视图或者使用IDEA的话,那么子maven模块会在父maven模块的里面而不是展示为同级
如果你导入不能成功的话,大概率是网络的问题或者Maven的问题,带着报错去参考网上解决方案进行解决
前端导入
那个 ruoyi-ui 就是前端项目。
如果没有 Node 则需要先安装Node,因为这个是基于 Vue 的。
在前端这个地方环境问题可搞了我好久的时间…
就照着基础的vue项目一样,打开命令行,进入前端项目文件夹,使用 npm install
或者 cnpm install
先安装需要的依赖。
npm配置了镜像的话可以用,不然就照着网上的先安装 cnpm。
网络没问题的话,执行命令完成后,依赖安装完后,一般都会出现一大堆的Depar…什么的红色文字的错误,可以先不用去管
执行 npm run dev
先看看能不能跑起来,一般情况下,从官网拉下里的是可以直接跑起来的。
像我这样,就跑起来了,会自动打开浏览器,打开前端地址。
下面的 Proxy error 是我没有打开后端,访问不到后端的问题。
当然,我第一次其实是跑不起来的,问题是没有 vue-cli-service,现在能跑起来是因为全局安装了这么个东西。
如果你没有安装的话,找到前端项目下的 package.json
,从中找到devDependencies,在里面找到对应的版本
然后使用 npm install 或者 cnpm install 安装就可以了
例如
cnpm install @vue/cli-service@4.4.6
版本号也是使用 @
分隔
如果缺少的是其他依赖也可以使用这样的方式解决
后端运行与配置
首先可以看一下若依官方文档给的项目结构介绍
主要模块是 admin,所有的接口都在这个模块,包括后面自己写的业务接口建议都放到这个模块
然后是system与common模块
system模块是将增删改查操作都放到里面了,做了分层,Service(提供给接口的服务层),Mapper(与数据库的操作,带xml),domain(JavaBean)
common模块比较杂,工具类都在这里面,包括:
- Redis工具(直接与Redis操作)
- SpringUtils(可以拿到SpringBoot的Context,getBean之类的)
- ServletUtils(使用的ThreadLocal,可以拿到当前的请求与响应,接口参数之类的)
- …
更多的需要自己发现了
framework模块是若依自己编写的包装(框架),这部分让我印象最深的就是权限认证了#-_-#,需求是做第三方登录,但要自定义登陆的话。卡了我一天多时间,主要原因是因为我没接触过Spring Security,关于有做第三方登陆需求的,这部分我会在这篇文章中将经验写出来。
还有几个模块,目前我的需求基本上不需要动这几部分,ruoyi-generator 这个代码生成,可以根据需要去修改配置(yml)
配置
都是SpringBoot项目,首先进入 admin 模块,找到 application.yml,进入,根据自己的需要进行修改。
比较需要注意的地方是
- ruoyi:profile(上传文件保存的地址)
- spring:redis:(Redis的配置)
然后进入 application-druid.yml,这个是数据库的配置,其中要配置数据库的密码,数据库名称等看注释操作就行
在父模块文件夹中(RuoYi-Vue),有个sql文件夹,里面有两个sql,需要新建一个数据库进入,然后执行这两个sql
这样就可以运行后端了
运行后,启动成功的话可以在控制台看到启动成功的字样的
这样,将前面说前端也运行起来,就可以正常使用了。
还有很多地方可以进行配置,但在这里就不过多进行赘述了,熟悉SpringBoot的使用基本上没有什么太大压力。
前端配置
首先可能需要配置的是后端的地址。在 vue.config.js
中
我们可能会发现,前端请求的后端地址路由前缀带上了 /dev-api
,这是因为做了多环境,使用了代理,后端并不是这样的,所以可以忽略这个。
其余的就是业务的编写了,组件部分都在 Component 文件夹,而页面布局在 layou 文件夹
我们自己写的页面在放 views 文件夹下。
使用
可以先查阅官方文档,有很多使用上面都有写
代码生成
首先需要建立一个sql表,表名称以在generator模块的yml配置前缀开头,如果没有更改的话就是 sys_
,可以有多个,使用逗号分隔
然后在系统工具 - 代码生成界面中导入表(可视化的,不多赘述了),有编辑预览和生成,编辑是设置生成代码的参数之类的,觉得没问题就生成
生成后的压缩包里有很多文件(大概好像是9个),包含了一个sql(菜单的增删改查sql语句以及权限等),后端controller、mapper、xml…前端 api.js、view…照着目录结构放到对应目录结构就可以了。
公开接口
这部分官网文档上有,不过不是很显眼,我找了半天,在这里记录下
直接加上 @Anonymous
注解就可以了(前后端分离版),在类上加,类内的所有接口都可访问,在接口上加那就单独公开这个接口
日志
使用 @Log
注解,可以参考若依里的代码,有很多地方都用到了
但需要注意的是,必须要有登录信息,也就是说公开接口不能使用这个注解。
例如
@Log(title = "字典数据", businessType = BusinessType.EXPORT)
还有一个是登录日志,这个可以在登陆类中找到,直接照葫芦画瓢就行了。
国际化
若依是做了国际化的,但不多。用的 i18n,在 admin 模块的 resources 下可以看到 i18n 文件夹,有个message.properties 文件,其中包含了所有的文字…
使用的话就是
MessageUtils.message("message.properties中的key")
第三方登录注册
这篇文章记下这里就结尾吧,因为若依是使用了很多框架的一个快速开发框架。如果熟悉若依所使用的那些框架,那么上手起来没有什么太大的压力。
对于第三方登录,有一个特点,只会给你一个第三方的唯一用户标识,而在若依中,使用的Spring Security(这个我没学过,所以这里记录的可能并不是一个比较好的方法)。
我的方法如下
第三方登录,用户不存在就注册并登录,存在就直接登录
注册很简单,参考若依的注册接口 System 模块的 web.service.SysRegisterService
,但因为是第三方登录,没有账号密码,我的做法是生成一个随机的账号,与默认密码…因为照葫芦画瓢,登录是必须要账号和密码的
下面描述的是整个验证流程部分
首先查阅参考若依的登录接口,在 system 模块中 web.service.SysLoginService
它登陆部分代码是这样的
/*** 登录验证* * @param username 用户名* @param password 密码* @param code 验证码* @param uuid 唯一标识* @return 结果*/
public String login(String username, String password, String code, String uuid)
{// 验证码校验validateCaptcha(username, code, uuid);// 登录前置校验loginPreCheck(username, password);// 用户验证Authentication authentication = null;try{UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);AuthenticationContextHolder.setContext(authenticationToken);// 该方法会去调用UserDetailsServiceImpl.loadUserByUsernameauthentication = authenticationManager.authenticate(authenticationToken);}catch (Exception e){if (e instanceof BadCredentialsException){// 记录登录日志AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));throw new UserPasswordNotMatchException();}else{AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));throw new ServiceException(e.getMessage());}}finally{AuthenticationContextHolder.clearContext();}AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));LoginUser loginUser = (LoginUser) authentication.getPrincipal();recordLoginInfo(loginUser.getUserId());// 生成tokenreturn tokenService.createToken(loginUser);
}
熟悉 Security 的看起来是非常简单的,核心部分就下面这三行。
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
AuthenticationContextHolder.setContext(authenticationToken);
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager.authenticate(authenticationToken);
将账号和密码构建一个UsernamePasswordAuthenticationToken
,然后加入context,最后去调用验证,这是 Spring Security 的一个基础的做法
通过注释找到 UserDetailsServiceImpl 类,就在同一个包下,核心代码是这样的
(这部分我已经改过了,将这个类当作验证类了。)
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{SysUser user = userService.selectUserByUserName(username);if (StringUtils.isNull(user)){log.info("登录用户:{} 不存在.", username);throw new ServiceException("登录用户:" + username + " 不存在");}else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())){log.info("登录用户:{} 已被删除.", username);throw new ServiceException("对不起,您的账号:" + username + " 已被删除");}else if (UserStatus.DISABLE.getCode().equals(user.getStatus())){log.info("登录用户:{} 已被停用.", username);throw new ServiceException("对不起,您的账号:" + username + " 已停用");}Object type = ServletUtils.getRequest().getAttribute("type");if (type != null) {switch ((int) type) {case SecurityConfig.TYPE_OTHER:passwordService.validateOther(user);break;}} else {passwordService.validate(user);}return createLoginUser(user);
}
看起来就好像是在这验证账号密码,虽然可以这样,但 Spring Security 定义的并不是这样的…
查阅 SecurityConfig 类,这个是 Spring Security 的配置类,在System模块的config下,我们需要在意的是最后一个函数,
/*** 身份认证接口*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception{auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}
在这里如果没学过 Spring Security 就开始懵逼起来了,所以我先去学习了Spring Security,流程还是很简单,反正就是在这里设置的 UserDetailsService
因为是第三方登录,用户不需要输入账号密码,那么我拿到的密码就是加密后的密码,这样就和普通登录不一样了,就会导致认证不通过
经过 debug 后发现,首先走的是 AuthenticationManagerBuilder,这个不用管,只要知道这个里面有 ProviderManager 就行了,ProviderManager 是个管理器,具体的我也不记得了,它里面有AuthenticationProvider列表,而AuthenticationProvider这个东西就是需要解决掉的东西
private List<AuthenticationProvider> providers = Collections.emptyList();
Spring Security 默认使用的是 DaoAuthenticationProvider
,跟着debug可以看到
需要注意的就两个函数,一个additionalAuthenticationChecks,一个retrieveUser
@Override@SuppressWarnings("deprecation")protected void additionalAuthenticationChecks(UserDetails userDetails,UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {if (authentication.getCredentials() == null) {this.logger.debug("Failed to authenticate since no credentials provided");throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}String presentedPassword = authentication.getCredentials().toString();if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {this.logger.debug("Failed to authenticate since password does not match stored value");throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}}@Overrideprotected final UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)throws AuthenticationException {prepareTimingAttackProtection();try {UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);if (loadedUser == null) {throw new InternalAuthenticationServiceException("UserDetailsService returned null, which is an interface contract violation");}return loadedUser;}catch (UsernameNotFoundException ex) {mitigateAgainstTimingAttack(authentication);throw ex;}catch (InternalAuthenticationServiceException ex) {throw ex;}catch (Exception ex) {throw new InternalAuthenticationServiceException(ex.getMessage(), ex);}}
首先执行的是 retrieveUser 函数,这个函数会去调用若依的 UserDetailsServiceImpl 的 loadUserByUsername 函数
执行完后,会执行 additionalAuthenticationChecks 函数,这个函数进行账号密码验证,而若依是在 UserDetailsServiceImpl 的 loadUserByUsername 验证的,验证完后还会在验证一遍,因为账号密码的方式相同,所以不会有什么问题,但对我来说,传递的密码是加密的,所以不需要函数内进行加密,于是就要干掉这个类,在网上找了很久都找不到办法,就只能自己慢慢尝试了,这里直接写结果了
首先新建一个类,继承 DaoAuthenticationProvider 类,然后覆盖 additionalAuthenticationChecks 函数,在这个函数内做自己的操作。
然后还要覆盖一个函数 supports,这个是代表支持不支持当前传递的 authentication,例如UsernamePasswordAuthenticationToken
我直接返回 true 就行了,不支持的话那么就不会被覆盖
代码如下
/*** 自定义* 创建时间 2023年7月29日* @author Shendi*/
public class MyAuthenticationProvider extends DaoAuthenticationProvider {@Overrideprotected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {// 有两种类型Object type = ServletUtils.getRequest().getAttribute("type");if (type != null) {// 已经在 UserDetailsService 做了判断switch ((int) type) {case SecurityConfig.TYPE_OTHER:break;}} else {if (authentication.getCredentials() == null) {this.logger.debug("Failed to authenticate since no credentials provided");throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}String presentedPassword = authentication.getCredentials().toString();if (!this.getPasswordEncoder().matches(presentedPassword, userDetails.getPassword())) {this.logger.debug("Failed to authenticate since password does not match stored value");throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));}}}/** 是否支持指定类型的 authentication */public boolean supports(Class<?> authentication) {
// return (MyAuthenticationProvider.class.isAssignableFrom(authentication));return true;}}
然后就是在 SecurityConfig 中配置了,直接上代码
@Bean
public MyAuthenticationProvider myAuP() { MyAuthenticationProvider myAuP = new MyAuthenticationProvider(); myAuP.setUserDetailsService(userDetailsService); myAuP.setPasswordEncoder(bCryptPasswordEncoder()); return myAuP;
}/*** 身份认证接口*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{auth.authenticationProvider(myAuP());
// auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
这样就ok了.
END
相关文章:

快速开发框架若依的基础使用详解
Hi I’m Shendi 快速开发框架若依的基础使用详解 最近在为公司制作新的项目,经过了一段时间的技术沉淀,我开始尝试接触市面上用的比较多的快速开发框架,听的最多的当属若依吧 于是就选用了若依 介绍 为什么选?目的是为了提高开发…...

RabbitMQ 教程 | 第4章 RabbitMQ 进阶
👨🏻💻 热爱摄影的程序员 👨🏻🎨 喜欢编码的设计师 🧕🏻 擅长设计的剪辑师 🧑🏻🏫 一位高冷无情的编码爱好者 大家好,我是 DevO…...

小程序如何从分类中移除商品
有时候商家可能需要在商品分类中删除某些商品,无论是因为商品已下架、库存不足还是其他原因。在这篇文章中,我们将介绍如何从分类中移除商品。 方式一:分类管理中删除商品。 进入小程序管理后台,找到分类管理,在分…...

P1219 [USACO1.5] 八皇后 Checker Challenge
题目 思路 非常经典的dfs题,需要一点点的剪枝 剪枝①:行、列,对角线的标记 剪枝②:记录每个皇后位置 代码 #include<bits/stdc.h> using namespace std; const int maxn105; int a[maxn];int n,ans; bool vis1[maxn],vis…...

如何在不使用脚本和插件的情况下手动删除 3Ds Max 中的病毒?
如何加快3D项目的渲染速度? 3D项目渲染慢、渲染卡顿、渲染崩溃,本地硬件配置不够,想要加速渲染,在不增加额外的硬件成本投入的情况下,最好的解决方式是使用渲云云渲染,在云端批量渲染,批量出结…...

SpringCloud Gateway 在微服务架构下的最佳实践
作者:徐靖峰(岛风) 前言 本文整理自云原生技术实践营广州站 Meetup 的分享,其中的经验来自于我们团队开发的阿里云 CSB 2.0 这款产品,其基于开源 SpringCloud Gateway 开发,在完全兼容开源用法的前提下&a…...

Android studio修改app图标
步骤如下: 1.右键app名称→New→ImageAsset 2. 进行下面的配置 图源:https://blog.csdn.net/Qingshan_z/article/details/126661650 3.配置分辨率 4.图标自动保存在mipmap文件夹下 再启动就更换成功了!!! 参考&…...

<C++> 三、内存管理
1.C/C内存分布 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";const char *pChar3 "abcd";int *ptr1…...

大模型开发(十五):从0到1构建一个高度自动化的AI项目开发流程(上)
全文共5600余字,预计阅读时间约13~20分钟 | 满满干货(附全部代码),建议收藏! 本文目标:提出一种利用大语言模型(LLMs)加快项目的开发效率的解决思路,本文作为第一部分,主要集中在如何完整的执行引导Chat模…...

HarmonyOS 开发基础(二)组件拼凑简单登录页面
一、简单登录页面 Entry Component /* 组件可以基于struct实现,组件不能有继承关系,struct可以比class更加快速的创建和销毁。*/ struct Index {State message: string Hello Worldbuild() {// https://developer.harmonyos.com/cn/docs/documentation/…...

flutter minio
背景 前端 经常需要上传文件 图片 视频等等 到后端服务器, 如果到自己服务器 一般会有安全隐患。也不方便管理这些文件。如果要想使用一些骚操作 比如 按照前端请求生成不同分辨率的图片,那就有点不太方便了。 这里介绍以下 minio,࿰…...
ChatGPT:人工智能交互的新时代
ChatGPT的背景和发展: ChatGPT是OpenAI公司在GPT-3基础上的进一步升级。GPT(Generative Pre-trained Transformer)是一种基于Transformer架构的深度学习模型,它能够处理自然语言,实现自动对话、写作等任务。而ChatGPT在…...

C. Binary String Copying - 思维
分析: 赛时我是直接模拟的,tle然后mle,补提,发现规律,每一个改变的字符串都只会对应一个需要改变的区间,例如第一个样例前两个101100 -> 011100和101100 -> 011100,对应区间在确定改变的范…...

哈工大计算机网络课程网络安全基本原理详解之:密钥分发中心与公钥认证中心
哈工大计算机网络课程网络安全基本原理详解之:密钥分发中心与公钥认证中心 在介绍密钥分发中心的概念前,先来回顾一下之前介绍的身份认证协议AP4.0:利用随机数R来避免“回放攻击”,并借助于对称加密算法来保证R的加密传输和解密&…...

md5sum
概念作用及原理 md5sum是一种常用的哈希算法,用于计算数据的MD5哈希值。MD5(Message Digest Algorithm 5)是一种广泛使用的加密散列函数,用于将任意长度的数据映射为固定长度的哈希值(通常是128位)。这个哈…...

图文档数字化:实现高效管理的几大步骤
在当今数字化时代,企业越来越意识到数字化管理对于图文档的重要性。传统的纸质文件管理往往效率低下,容易出现丢失和混乱的情况。为了提高工作效率、降低成本并确保数据安全,许多企业选择采用PDM(产品数据管理)系统来实…...
服务器磁盘占用过高分析
使用命令 du -sh查看出占用较大的目录,如下: 目录大小处理办法/usr/local/mysql/data16G转移部分文件/usr/local/nacos2.1G维持现状/logs4.4G删除部分文件/var1.9G删除部分文件 du -sh命令使用示例: du -sh /* 查看根目录各文件(夹)占用大小…...

【C语言】通讯录3.0 (文件存储版)
前言 通讯录是一种记录联系人信息的工具,包括姓名、电话号码、电子邮件地址、住址等。 文章的一二三章均于上一篇相同,可以直接看第四章改造内容。 此通讯录是基于通讯录2.0(动态增长版)的基础上进行增加文件操作功能,…...
【C#常用操作】
excel相关操作 using Excel Microsoft.Office.Interop.Excel;public Excel.Application app; public Excel.Workbooks wbs; public Excel.Workbook wb; public Excel.Worksheets wss; public Excel.Worksheet ws;/// <summary> /// 取得打开excel句柄 /// </summary…...

深入理解CountDownLatch计数器
入理解CountDownLatch计数器 其他知识点 Java 多线程基础 深入理解aqs ReentrantLock用法详解 深入理解信号量Semaphore 深入理解并发三大特性 并发编程之深入理解CAS 深入理解CountDownLatch Java 线程池 使用用法 CountDownLatch用法详解 CountDownLatch实现原理 下面例子来…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...