news 2026/10/20 3:13:51

SpringBoot+Vue企业客户管理系统全栈开发实战:从数据库到部署解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot+Vue企业客户管理系统全栈开发实战:从数据库到部署解析

最近帮几个做毕设的同学排查项目代码,发现一个很有意思的现象:十个里面有八个选题都落在“企业客户管理系统”上。不是大家偷懒,而是这个题目确实太适合做Java Web毕业设计了——既有实体业务可以建模,又有前后端交互可以展示,还能轻松加一点权限、统计、报表的亮点。市面上相关的源码项目也特别多,但很多同学手里拿到一套源码,却不知道从哪儿看起,SQL脚本导入报错,接口文档看不懂,前端起不来,最后只能干瞪眼。

这篇就结合我实际带看项目的经验,把SpringBoot+Vue这套企业客户管理系统从整体设计到数据库、后端接口、前端联调,再到打包部署和常见坑位,完整地梳理一遍。不管你是打算拿这套系统做毕设,还是想自己练手写一个完整项目,都可以直接照着思路来。

1. 项目整体思路与选型分析

1.1 为什么是SpringBoot+Vue组合

企业客户管理系统本质上是一个标准的CRUD业务系统,但它又比单纯的学生管理系统、图书管理系统多了一点“业务感”。一个真实的企业客户生命周期里,有线索、有客户、有联系人、有商机、有合同、有跟进记录,数据表之间是有关联的,操作流程是有状态的。这种系统用传统JSP或Servlet写也能跑,但代码会非常冗长,维护起来也费劲。SpringBoot的自动配置和内嵌服务器能力,让后端开发变得极其轻量;前端用Vue做组件化开发,配合Element UI这种现成的UI库,能快速画出符合企业管理风格的界面。

前后端分离这个架构,本身也是目前企业里最主流的开发模式。毕设答辩的时候,老师大概率会问“为什么选择前后端分离”,你可以理直气壮地说:前端和后端可以并行开发,接口定义清楚以后,两边互不阻塞;部署时前端静态资源交给Nginx,后端API单独跑Java进程,扩容和排错都更清晰。这个理由就比“别人都用这个”要扎实得多。

1.2 系统功能结构拆解

一套完整的企业客户管理系统,功能模块大致可以拆成这样:

  • 客户信息管理:客户的增删改查、客户分级(如普通、重要、VIP)、客户来源、所属行业、地址等基础信息。
  • 联系人管理:一个客户下面可以挂多个联系人,包含姓名、电话、邮箱、职位、是否默认联系人。
  • 商机管理:记录潜在销售机会,关联客户和联系人,包含预估金额、预计成交日期、销售阶段。
  • 合同管理:商机成交后生成合同,包含合同编号、金额、签署日期、有效期、状态。
  • 跟进记录:每次回访客户都能写跟进记录,记录下次跟进时间,形成客户跟进时间线。
  • 数据分析看板:用ECharts展示客户数量趋势、商机金额分布、销售漏斗等图表。
  • 系统管理:用户登录、角色权限、菜单管理、操作日志。

这些功能不是拍脑袋加上去的,而是围绕“客户生命周期”这条主线展开的。你做毕设如果只是单张表增删改查,那叫“系统”有点勉强;但当你把客户、联系人、商机、合同串起来以后,整个系统的业务逻辑就立体了。这也是为什么这个项目深受毕设选题青睐的核心原因:它有业务深度,但难度又控制在本科阶段能搞定的范围内。

1.3 技术栈清单与版本建议

我见过不少人拿着一套源码,结果本地环境跟项目要求的版本对不上,各种报错。这里给出一份比较稳妥的版本组合,无论你是刚拿到的源码,还是自己从零搭建,都建议优先对齐这个组合:

技术分类推荐技术版本建议
后端框架Spring Boot2.5.x 或 2.6.x
ORMMyBatis-Plus3.4.x 或 3.5.x
数据库MySQL5.7+ 或 8.0
权限认证JWT + Spring Security 或拦截器2.5.x 对应Security 5.x
工具库Lombok、Hutool最新稳定版
前端框架Vue2.6.x(或Vue3配Element Plus)
UI组件库Element UI2.15.x
HTTP请求Axios0.21+
数据可视化ECharts5.x
项目构建Maven、npmMaven 3.6+,Node 14+

为什么要强调版本?因为很多源码项目是两三年以前的,当时用的是Spring Boot 2.1甚至更老,如果你本地装的是JDK 17,加上新版Spring Boot的兼容性问题,启动起来能折磨你一个通宵。所以拿到源码第一件事,就是看pom.xml和package.json里的版本定义,跟自己的环境对齐,而不是先急着跑起来。

2. 数据库设计与SQL脚本解读

2.1 核心数据表设计

SQL脚本是整个项目的地基。很多同学拿到.sql文件就双击导入,结果报错一堆。不是脚本本身有问题,而是脚本里可能包含建库语句、外键约束、表顺序、字符集设置,一旦执行顺序乱了就很容易失败。

这套系统的核心表通常有这么几张:

sys_user:系统用户表,字段包含id、username、password、real_name、role_id、status、create_time。密码字段存储的是加密后的密文,不是明文。

sys_role:角色表,字段包含id、role_name、role_code、description。

sys_menu:菜单权限表,字段包含id、parent_id、menu_name、menu_type、path、component、perms、icon。

cus_customer:客户表,字段包含id、customer_name、customer_level、industry、source、phone、address、status、create_time、update_time。

cus_contact:联系人表,字段包含id、customer_id、contact_name、phone、email、position、is_default。

cus_business:商机表,字段包含id、customer_id、contact_id、business_name、amount、stage、expect_close_date、create_time。

cus_contract:合同表,字段包含id、contract_no、business_id、customer_id、amount、sign_date、start_date、end_date、status。

cus_follow_record:跟进记录表,字段包含id、customer_id、content、next_time、create_by、create_time。

这七张表基本就能支撑起整个系统的业务闭环了。注意看,这里没有特意设计“客户创建人”归属字段吗?其实很多项目会加一个user_id字段到客户表,用来做数据权限,也就是每个销售只能看到自己的客户。如果源码里有这个字段,做权限控制就更有发挥空间;如果没有,你在答辩时可以提“后面可以扩展数据权限”,也算是一种思路。

2.2 表关系与关键字段说明

表关系不难理解:

  • sys_user与sys_role是多对一,角色表是权限的集合。
  • sys_menu与sys_role之间通过中间表sys_role_menu关联,实现角色的菜单权限。
  • cus_customer是一方,cus_contact是多对一,一个客户下有多个联系人。
  • cus_business同时关联客户和联系人。
  • cus_contract关联商机和客户,合同从商机转化而来。
  • cus_follow_record只关联客户,记录每一次跟进动作。

设计里面有一个关键点:尽量避免在业务表里存冗余的客户名称、联系人名称,而是存id外键。比如商机表里存customer_id,查询时通过关联或者连表查询拿到客户名称。很多新手容易图省事,直接在商机表里加一个customer_name字段,结果客户改名了,商机表数据就脏了。规范的第三范式虽然不用背大道理,但记住“尽量存id”这个原则,数据质量会好很多。

另一个关键点是有意设计status字段。比如客户表会有status区分“已成交”“跟进中”“流失”,合同表会有status区分“待签署”“执行中”“已完成”“已终止”。这些状态字段是业务流转的标记,前端列表页的筛选和看板图表的分组统计,都靠它们。千万不要把这几个字段省掉,否则后期做数据分析功能时你会后悔到拍大腿。

2.3 SQL脚本使用注意事项

导入脚本前,先确认你本地的MySQL版本。我遇到最典型的问题是:脚本里用了utf8mb4字符集和emoji字段注释,MySQL 5.5以下版本不支持,但现在大家基本都装5.7或8.0,所以问题不大。更常见的问题是因为表之间外键关联,导入时表顺序不对导致失败。解决方法是:先看脚本里有没有DROP TABLE IF EXISTS,有没有CREATE DATABASE IF NOT EXISTS。如果有,直接在命令行里source整个文件就好;如果没有,建议先手动建好库,再按用户表、角色表、菜单表、客户表、联系人表、商机表、合同表、跟进记录表的顺序依次导入。

导入完成以后,别急着启动项目,先在数据库客户端里执行几条查询,验证一下种子数据是否存在。比如系统预设的几个账号,admin,密码一般加密后写在脚本里,你自己可以通过日志里的打印信息或者手动往库里插一条BCrypt加密后的数据。这一步能帮你提前发现“数据库没连上”这个经典问题,节省后面联调的大量时间。

3. 后端核心实现与接口设计

3.1 项目分层结构与启动流程

一套规整的SpringBoot后端工程,目录结构通常是这个样子的:

src/main/java/com/example/crm/ ├── common/ │ ├── config/ # 跨域配置、MybatisPlus配置、拦截器注册 │ ├── exception/ # 全局异常处理 │ ├── result/ # 统一返回封装Result │ └── utils/ # JwtUtils等工具类 ├── controller/ # REST接口层 ├── service/ # 业务逻辑层,含impl ├── mapper/ # MyBatis-Plus的Mapper接口 ├── entity/ # 数据库实体类 └── dto/ # 请求和响应的数据封装 src/main/resources/ ├── application.yml └── mapper/ # XML文件(如果不用纯注解)

启动就是一个带@SpringBootApplication注解的主类,右键运行就行。关键问题在于application.yml里的配置:数据源地址、用户名密码、MyBatis-Plus的逻辑删除配置、JWT的密钥和过期时间。我见过不止一个同学把别人的配置文件原封不动地拿来用,数据库密码写的是别人本机的密码,最后启动报错Access denied,然后一脸茫然。

这里提醒一句:拿到源码以后,第一步不是看代码,而是打开application.yml,把所有环境相关的配置改成本地的。包括数据库账号密码、服务器端口、文件上传路径、日志输出目录。否则项目永远只能在作者电脑上跑,换一台机器就是一堆红线错误。

3.2 权限认证方案选型

企业客户管理系统一般有两种权限方案:一种是Spring Security + JWT,还有一种是拦截器 + JWT。用Spring Security会显得更加“重工”,但配置类里一大堆写法,对新手并不友好;用拦截器实现的话,逻辑简单直观,核心就是自定义一个Interceptor,在preHandle方法里校验请求头中的token,然后把用户信息放到ThreadLocal里。

如果你的毕设希望展示权限控制能力,我个人更推荐先用拦截器做一个简洁的版本,原因很简单:你能在答辩时清晰讲出“token怎么发”、“拦截器怎么拦”、“怎么放行登录接口”。这一套讲下来,比照抄Spring Security的过滤链背概念要扎实得多。当然,如果源码本身用的是Spring Security,也没有必要去狂改,顺着源码思路吃透也是一样的。

JWT的核心流程是:用户登录时,校验用户名密码成功后,生成一个包含用户id和角色的token返回给前端;前端每次请求都在header里带上Authorization;后端拦截器解析token,如果解析成功就放行,失败就返回401。要做到这个,你在pom.xml里需要引入jwt相关依赖,比如jjwt,然后写一个JwtUtils工具类,里面包含生成令牌、解析令牌的方法。这部分代码网上很多,但关键是密钥和过期时间要写在配置里,而不是硬编码在类里,这是工程化和毕设评分的一个加分点。

3.3 核心接口实现讲解

以客户列表的分页查询接口为例,这个接口几乎是整个系统被调用最频繁的接口。它的核心逻辑是:接收前端传来的页码、每页条数、客户名称关键字、客户等级过滤条件,然后构造查询条件,返回分页结果。

使用MyBatis-Plus后,代码可以精简到这种程度:

@GetMapping("/list") public Result<IPage<CustomerVO>> page(@RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "10") Integer pageSize, @RequestParam(required = false) String keyword, @RequestParam(required = false) Integer level) { LambdaQueryWrapper<Customer> wrapper = Wrappers.lambdaQuery(); wrapper.like(StringUtils.hasText(keyword), Customer::getCustomerName, keyword) .eq(level != null, Customer::getLevel, level) .orderByDesc(Customer::getCreateTime); IPage<Customer> page = customerService.page(new Page<>(pageNum, pageSize), wrapper); // 转VO,补充字段 return Result.success(convertToVO(page)); }

这里面有几个细节值得展开。第一,用LambdaQueryWrapper而不是手动写SQL,可以避免字段名拼写错误,也是MyBatis-Plus的推荐用法。第二,每个条件前面都加一个布尔表达式条件,比如StringUtils.hasText(keyword),意思是“只有传了关键字才拼like条件”,这能避免空参数导致的全表查询。第三,排序要用orderByDesc,默认按创建时间倒序,这样客户列表最新创建的才能排前面。很多新手做列表接口时,不带排序,结果数据顺序忽前忽后,答辩时被老师一问就露馅。

再看新增客户接口,它需要做几件事:把前端传来的JSON字段填充到Customer实体里,设置默认状态,补createTime和updateTime,然后执行insert。这里有个容易忽略的点:如果前端传来的字段名跟后端实体属性名不一致,必须用@JsonProperty或者@JSONField做映射,否则会一堆字段为null。我在帮别人看代码时,发现不少人用了lombok的@Data,但忘了在实体类加@TableName("cus_customer"),导致执行SQL时去查user表,报错Table 'user' doesn't exist。这种低级错误,跑起来一眼就能定位,但新手往往会被带偏到其他方向排查很久,其实答案就在眼前。

3.4 接口文档怎么啃

拿到一套带接口文档的源码,很多人都不看文档,直接去翻Controller代码,这样其实很低效。接口文档通常包含接口路径、请求方式、请求参数说明、响应示例。你要做的第一件事不是读完全部文档,而是找“模块划分”或“测试入口”部分,把常用的几个接口先勾出来:

  • 登录接口:POST /api/auth/login
  • 获取当前用户信息:GET /api/auth/info
  • 客户分页列表:GET /api/customer/list
  • 新增客户:POST /api/customer
  • 更新客户:PUT /api/customer/{id}
  • 删除客户:DELETE /api/customer/{id}

为什么先找登录和客户列表?因为这两个接口打通了,整个系统的前后端链路就通了。你可以用Postman或者Apifox先调通这两个接口,熟悉返回的JSON结构,然后在前端页面里核对接入的数据字段。接口文档里的响应示例非常重要,它告诉你后端返回到底是{code:200, msg:"成功", data:...}还是直接返回数据。如果前端代码里写的是response.data.data,而接口文档里data下面没有data,你就会在页面上看到undefined,这时候不是某个字段名不对,而是整个响应结构理解错了。

接口文档里还有一个容易被忽略的部分:错误码说明。比如code=401表示token失效,code=500表示服务器异常。联调时如果遇到401,先看token是否过期;遇到500,去后端日志里看栈信息。知道了错误码对应的语义,排查问题至少能快一半。

4. 前端Vue实现与联调要点

4.1 前端工程结构

前端项目是标准的Vue CLI或Vite工程,目录结构一般长这样:

src/ ├── api/ # 接口调用模块,按业务拆文件 ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── router/ # 路由配置 ├── store/ # Vuex状态管理 ├── styles/ # 全局样式 ├── utils/ # request.js封装等 ├── views/ # 页面组件 ├── App.vue └── main.js

拿到前端代码第一件事,去看utils/request.js。这里一般封装了Axios实例,设置了baseURL、拦截器、token注入逻辑。很多跨域问题、401跳转问题都出在这个文件。比如baseURL写的是'http://localhost:8080/api',而你的后端跑在8081端口,那所有请求都会404。所以环境不对,很可能就是前端这里没有改成自己本地的端口。

二次封装Axios的核心作用,是让所有请求自动带上token,并且统一处理错误。典型的代码是先用axios.create创建实例,设置baseURL,然后在请求拦截器里从Vuex或localStorage读取token,设置到header;在响应拦截器里判断code,如果code是401,清除本地token并跳转到登录页。很多同学写页面的时候,习惯在每个组件里直接用axios.get,结果每个请求都要重复写header,代码冗余不说,还容易漏掉token,这样接口一调就是401。封装是可维护性的关键,也是答辩时的加分项。

4.2 路由与权限控制

Vue Router里的路由配置,一般分为两种方式:静态路由和动态路由。简化版可以只用静态路由,在路由表里定义几个模块的路径和组件,比如/common/customer、/common/contact、/common/business等。稍微完整一点的项目,会结合角色权限做动态路由,在用户登录后,根据后端返回的菜单权限列表,用router.addRoute动态添加可见页面。

对于毕设而言,即使不做动态路由,也至少要在一级菜单层面对未登录状态做拦截,也就是路由守卫。这个必须加,否则用户不登录直接手动输入地址也能访问内部页面,答辩老师会质疑系统安全性。

实现很简单,在router/index.js里加beforeEach全局前置守卫:

router.beforeEach((to, from, next) => { const token = localStorage.getItem('token'); if (to.path === '/login') { next(); } else { if (token) { next(); } else { next('/login'); } } });

这个逻辑就是:没token就去登录页,有token就放行。如果你还想更严谨一点,可以在后端接口返回401时强制跳转登录页,配合响应拦截器一起用,整体体验会更完整。按钮权限这块,一般通过自定义指令v-permission来判断当前用户角色是否包含某个权限标识,这个作为亮点加上去也不错。

4.3 联调中的跨域问题

前后端分离开发,跨域几乎是必踩的坑。前端跑在http://localhost:8081,后端跑在http://localhost:8080,两个端口不一样,浏览器就会发OPTIONS预检请求,后端不处理就报CORS错误。

解决跨域有两种主流方案。开发环境用Vue CLI的devServer.proxy做代理,把/ajax请求转发到后端服务。配置在vue.config.js里:

module.exports = { devServer: { port: 8081, proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } }

这样前端axios请求写成'/api/customer/list',浏览器看到的是同源地址,实际由Node代理把请求转发到后端。好处是不用改后端跨域配置,而且不会把后端真实端口暴露给前端业务代码。

生产环境部署时,一般用Nginx做反向代理,把静态页面和/api路径都交给同一个Nginx,Nginx再将/api请求转发给后端Java进程。这个方案的跨域配置只需要在后端CorsFilter兜底就好。我遇到过一些人开发环境跑通了,打包部署之后接口全部404,原因就是Nginx没有配置api的location转发,只把dist目录指给了root,结果Vue请求/api/customer/list,Nginx把它当成静态资源去找路径,当然找不到。解决方法是加这么一段:

location /api/ { proxy_pass http://127.0.0.1:8080; }

注意proxy_pass后面的地址,要跟后端实际启动的ip和端口保持一致。这个坑非常经典,建议每个做前后端分离毕设的人都提前记住。

5. 打包部署与常见问题排查

5.1 本地开发环境准备

环境准备这块,看似无聊,但我见过太多人在这一步卡住。先说后端:安装JDK 1.8或11,配置JAVA_HOME,安装Maven并设置本地仓库路径。然后打开项目pom.xml,右键Maven -> Reload Project,让IDE把依赖全部下载完。这个过程第一次可能比较久,耐心等就是。如果下载依赖时网络慢,可以给Maven配置阿里云镜像,速度会快很多。别小看这一步,很多人在Maven依赖下载这一关就耗了半天。

前端环境的准备,需要安装Node.js 14以上的稳定版本,然后打开前端项目目录,执行npm install。这里有个常见问题:有人的电脑上装了Node 18,导致npm install的时候报错,说某些依赖的版本不支持。这种时候优先考虑切换Node版本,或者用nvm管理多个Node版本。不要硬着头皮去把项目升级到新版,因为那会牵出一连串兼容性问题,毕设没必要折腾这个。

依赖都安装好以后,先启动后端,再启动前端。后端启动成功的标志是控制台打印出Tomcat started on port 8080,前端启动成功标志是Compiled successfully。两个都出来了,再打开浏览器访问前端地址。如果页面出来了,但列表接口报错,别慌,这属于正常现象,接着往下看常见问题。

5.2 前后端打包部署

毕设一般要求能提交一个可运行的项目,很多人把源码发给老师,但老师本地没有环境,根本跑不起来。更稳妥的做法是,把后端打成jar包,前端打包成静态文件,放到一起,做成一个可以直接java -jar运行的整体。

后端打包很简单,在项目根目录执行:

mvn clean package -DskipTests

打出来的jar包在target目录下,比如crm-system-0.0.1.jar。运行它:

java -jar crm-system-0.0.1.jar

前端的打包分两步。首先修改前端请求的baseURL,让它指向正式环境的后端地址。然后执行:

npm run build

生成dist目录。如果你希望把前端静态文件放到SpringBoot的classpath里,让后端把页面和接口一起提供,那就把dist目录里的所有文件复制到springboot项目的src/main/resources/static目录下,重新打包后端jar。这样启动后端,直接访问8080端口就能看到页面,不需要额外部署前端。

这种方式对毕设演示特别方便。但要注意一个问题:如果前端打包后资源路径不对,会出现页面白屏或CSS加载不出来。原因在于publicPath默认是/,如果你的后端加了context-path,比如server.servlet.context-path=/crm,那静态资源就会找不到。解决方法是修改vue.config.js里的publicPath为'./',让资源使用相对路径,这样不管部署在哪个路径下都能正常加载。

5.3 典型问题清单

我把这段时间帮人排查时遇到的高频问题整理成一个清单,按照出现频率排序,你看一眼就能定位到自己属于哪一种:

问题现象可能原因解决方法
后端启动报数据库连接失败application.yml中的账号密码或IP不对改成本地MySQL的真实配置,检查MySQL服务是否启动
前端请求接口返回404baseURL路径不对,或Nginx未配置/api转发查看前端request.js里的baseURL,与后端@RestController的路径比对
登录接口报401token错误或过期核对登录接口路径,确认前端是否把token放到了header
登录成功但列表接口401拦截器没有放行登录接口,或者token解析失败在拦截器中配置放行路径,JWT密钥是否一致
客户列表分页显示不出来返回数据结构与前端取数不一致用Postman查看实际返回JSON,核对前端data.data
前端控制台报跨域错误开发环境未配置proxy,或后端CorsFilter缺失配置vue.config.js代理,或后端加跨域配置类
删除客户报错外键约束失败该客户已有联系人或商机等关联数据删除前先删除关联子表数据,或采用逻辑删除is_deleted
打包部署后刷新页面404前端路由是history模式,Nginx没有配置try_filesNginx配置location / { try_files $uri $uri/ /index.html; }

这些坑都不是什么高深的问题,但就是特别磨人。我个人的习惯是,遇到问题先看后端控制台日志,再看浏览器控制台,最后看网络请求。把这三个地方的错误信息对齐,基本上十秒钟就能定位到问题源头。最怕的是不看日志,盲目试各种解决方案,把配置改来改去,最后越来越乱。

6. 个人实操心得与扩展建议

最后分享一点我自己的经验。第一次拿到这种企业客户管理系统源码的时候,我自己也犯过一个错误:想着一口气把代码全部看懂,于是从第一个Controller开始逐行阅读,读到中间就忘了前面。后来我换了个策略,先跑起来,然后用“请求驱动”的方式学习——打开登录页面,输入账号密码,看网络请求发出去了什么,后端接收了什么,返回了什么。沿着一个登录请求,把前端到后端的完整链路走通一遍,整个系统的骨架就刻在你脑子里了。

对准备做毕设的同学,我特别建议不要只满足于“会跑”。你在拿到源码或者自己完成这套系统以后,至少要把数据库表结构画成ER图,把核心业务表的关系写在纸上;把登录校验和客户分页查询这两个接口的代码,自己动手默写一遍。做到这两件事,答辩的时候老师随便问,你都能对答如流。哪怕你只是把一个开源项目重新跑通,只要能清楚讲出每条数据从创建到展示的完整生命周期,这个“工作量证明”就能站得住脚。

如果想在这个项目上再拔高一点,可以重点关注三个扩展方向:一是引入Redis缓存热点客户数据,降低数据库压力;二是做文件上传,支持客户头像和合同附件上传;三是接入消息通知,比如给销售发送跟进提醒。这三个方向都是目前企业系统里很常见的能力,而且实现难度可控,不会把你的毕设拖入深水区。投入两三天加上去,系统完成度和答辩说服力都会明显提升。

写到最后想说一句:企业客户管理系统之所以能成为经典毕设题,不是因为它简单,而是因为它完美地覆盖了信息管理类系统的所有标准动作——权限、增删改查、业务流转、统计分析。把这套逻辑吃透,换一个业务领域(比如库存管理、设备维保、会员营销),你也能很快地迁移过去。这也是作为开发者,真正能从毕设里带走的底层能力。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/20 3:13:26

SELinux实战:从Permission denied到强制访问控制

上个月我给一台测试服务器部署一个静态站点&#xff0c;权限配到 755、属主也对、nginx配置检查了好几遍&#xff0c;curl 却始终给我一个 403。排到最后连 root 上去都读不了那个目录&#xff0c;整个人差点拆机器。后来随手执行了一下getenforce&#xff0c;看到那行Enforcin…

作者头像 李华
网站建设 2026/10/20 3:12:58

C# Winform 连接 SQL Server 实战:本地与网络连接及增删改查

简介&#xff1a;这份资源面向C#与数据库开发的入门学习者&#xff0c;围绕Winform桌面程序如何同时实现SQL Server的本地连接与网络连接&#xff0c;并完成增删改查这一核心场景展开。包内共28个文件&#xff0c;以cs源码、resx与resources资源文件、exe可执行程序、pdb调试文…

作者头像 李华
网站建设 2026/10/20 3:12:05

Hadoop不是单个软件:HDFS、YARN、Spark等组件如何分工协作

很多人第一次听到"Hadoop"这个词&#xff0c;可能以为它只是一个软件&#xff0c;装好之后就能"处理大数据"。但真正在真实环境里跑过之后你会发现&#xff0c;Apache Hadoop 更像是一套家族体系&#xff0c;里面每一个成员都只负责一件具体的事&#xff1…

作者头像 李华
网站建设 2026/10/20 3:11:16

YOLOv11工业目标检测实战:论文基线选择、训练踩坑与实验设计全记录

每次提到论文实验选模型&#xff0c;最常被问到的问题就是"哪个目标检测模型适合做基线&#xff1f;"。去年到今年&#xff0c;我陆陆续续帮几个研究方向偏工业视觉的同学做过实验方案&#xff0c;从缺陷检测到装配体识别都有。现在要选一个既能让论文有增量空间、又…

作者头像 李华
网站建设 2026/10/20 3:10:53

ONNX与TensorRT模型部署全流程:从转换到推理性能优化实战

接手过不少从训练到部署的项目&#xff0c;说实话&#xff0c;模型在测试集上刷点的兴奋感&#xff0c;往往会被部署上线时那口憋住的气给冲散一半。尤其是当模型要跑在边缘设备或实时服务里&#xff0c;训练框架自带的推理接口根本顶不住。这年头做推理优化&#xff0c;基本绕…

作者头像 李华