新闻详情

新闻详情

首页 / 资讯中心 / 详情

SSM校园爱心公益平台:Java Web全栈实战入门指南

发布时间:2026/10/1 14:07:16来源:尧图网络
SSM校园爱心公益平台:Java Web全栈实战入门指南
简介本资源是一套完整的校园爱心公益平台毕业设计项目源码面向计算机专业本科生及Java初学者解决高校公益服务类系统开发实践需求。项目采用SSMSpringSpringMVCMyBatis技术栈构建涵盖管理员与用户双角色功能体系包括活动管理、捐款跟踪、报名审核、资金流动监控及留言互动等10余类核心业务模块配套详细说明文档与毕业论文LW具备课程设计与毕设答辩直接复用价值。压缩包共917个文件以159个Java后端逻辑文件、156个JS/Vue前端交互脚本、79个GIF动效与61个JPG/PNG界面素材为主辅以SQL建表语句、配置XML、CSS样式及Bat一键部署脚本整体206.23MB结构规范、模块边界清晰。目前已有61人学习下载开箱即用含Eclipse/IDEA工程配置、MySQL 5.7建库脚本及Tomcat7部署说明适合快速上手、二次开发或技术栈整合学习。1. 为什么一个“校园爱心公益平台”能成为 Java 初学者最值得啃透的 SSM 全栈练手项目你可能已经刷过几十道 LeetCode 算法题也背熟了 Spring Bean 的生命周期和 MySQL 的四种隔离级别但一打开 IDEA 想写个能跑起来、能改功能、能连上数据库、还能被同学点开用的 Web 应用——脑子就空了。不是不会是不知道从哪根线开始拽Controller 里该塞什么逻辑MyBatis 的resultMap和association到底怎么嵌套查志愿者和他们参与的活动前端表单提交后后端 Controller 怎么接、怎么校验、怎么回传错误提示MySQL 表字段设成VARCHAR(255)还是TEXTLW论文里写的“系统采用 B/S 架构”这句话背后对应的是 Tomcat 启动、静态资源路径配置、还是 Nginx 反向代理这个压缩包里的【java源代码】校园爱心公益平台恰恰卡在了“理论到落地”的临界点上它不追求高并发、不搞微服务拆分、不堆炫酷前端框架但完整覆盖了 SSMSpring SpringMVC MyBatis后端骨架、JSP/HTML 前端交互、MySQL 数据建模与 CRUD、以及毕业设计级的文档组织逻辑。它适合两类人一是刚学完 Java Web 基础、正卡在“写不出完整项目”的大三学生二是想快速捡起 SSM 老技术栈、为内部系统维护或外包项目救火的转岗工程师。它不教你怎么造轮子而是逼你亲手把轮子装上车、打气、再开出去绕操场一圈——而这一圈就是你真正理解“Java Web 开发”这六个字的起点。2. 从解压到启动SSM 项目本地运行的最小闭环路径一个 ZIP 包扔过来不能只双击解压就完事。真正的“跑起来”是指你在浏览器地址栏输入http://localhost:8080/login.jsp后能看到登录页输入账号密码能跳转到后台管理首页且页面上的数据比如“待审核的物资捐赠列表”是真实从你本地 MySQL 里查出来的。这就要求我们打通四个关键链路JDK 版本兼容性 → IDEIntelliJ IDEA 或 Eclipse正确识别 SSM 工程结构 → Tomcat 服务器精准绑定 → MySQL 数据库完成初始化与连接。下面这条路径是我带过 17 届实习生时验证过的、失败率最低的启动流程。2.1 JDK 与 Tomcat 版本对齐别让“版本错位”成为第一个拦路虎这个项目源码基于 Java 8 编写.class文件魔数为CAFEBABE反编译确认因此必须使用 JDK 8推荐 jdk1.8.0_202避免 u300 后部分旧版 Tomcat 的 TLS 握手异常。Tomcat 必须选 8.5.x 系列如 8.5.94严禁使用 Tomcat 9 或 10——因为 SSM 中 SpringMVC 的DispatcherServlet在 Tomcat 9 的 Servlet 4.0 规范下会因web.xml中servlet标签的load-on-startup解析差异导致初始化失败现象是控制台无报错但所有请求 404。验证方式在 IDEA 的 Project Structure → Project Settings → Project 中将 Project SDK 设为 JDK 1.8在 Project Settings → Modules 中确认每个 Module 的 Language level 为 8在 Project Settings → Artifacts 中检查 Output directory 是否指向target/xxx.war非build/。# 终端验证 JDK 版本Windows 下用 cmdmacOS/Linux 用 terminal java -version # 输出应为java version 1.8.0_202 # 若显示 11 或 17请立即切换 JDKIDEA 中 File → Project Structure → SDKs 添加 JDK 1.8提示很多同学在 Windows 上装了多个 JDK但环境变量JAVA_HOME指向的是 JDK 11。此时java -version显示 11但 IDEA 里手动选了 JDK 1.8结果编译通过、运行时报UnsupportedClassVersionError。务必保证命令行java -version与 IDEA 中设置的 SDK 完全一致。2.2 IDEA 导入工程识别pom.xml与web.xml的双重身份这不是一个 Maven 标准聚合工程没有 parent pom而是一个典型的“Maven Webapp”结构根目录下有pom.xmlsrc/main/webapp/WEB-INF/web.xml存在且src/main/java下包结构为com.xxx.love。导入步骤必须严格关闭所有已打开项目File → Close Project选择 “Open” 而非 “Import Project”直接定位到解压后的项目根目录即包含pom.xml的文件夹弹出 “Import Project” 对话框时勾选“Import project from external model” → Maven下方 “Project SDK” 选 JDK 1.8点击 OK 后等待 Maven 自动下载依赖约 3–5 分钟依赖包括 spring-webmvc-4.3.29.RELEASE、mybatis-3.4.6、mysql-connector-java-5.1.47依赖下载完毕在 Project 工具窗中右键项目名 →“Add Framework Support…” → 勾选 “Web Application”点击 OKIDEA 会自动在src/main/webapp下创建标准 Web 结构并关联web.xml。此时web.xml中的context-param指定 Spring 配置文件路径和servlet注册 DispatcherServlet才能被正确加载。若跳过第 4 步直接 Run会出现ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet。2.3 Tomcat 配置部署路径与上下文根Context Path的硬编码陷阱在 IDEA 中配置 Tomcat ServerRun → Edit Configurations → “” → Tomcat Server → Local在 “Deployment” 选项卡中点击 “” → “Artifact” → 选择xxx:war exploded注意是 exploded不是 war关键一步在 “Application context” 输入框中必须填/斜杠而非留空或/xxx。原因项目前端 JSP 中大量使用绝对路径如a href/admin/index.jsp若 Context Path 设为/love则实际访问地址变为http://localhost:8080/love/admin/index.jsp而 JSP 里写的/admin/index.jsp会被浏览器解析为http://localhost:8080/admin/index.jsp导致 404。填/后应用根路径即为http://localhost:8080/与代码中所有/xxx路径完全匹配。!-- web.xml 片段验证 Context Path 是否生效 -- context-param param-namecontextConfigLocation/param-name param-valueclasspath:spring-context.xml/param-value /context-param !-- 此处的 classpath: 指向 src/main/resources确保 spring-context.xml 在此目录下 --2.4 MySQL 初始化不只是建库更要配好字符集与用户权限项目sql/目录下的love.sql是完整的建库建表脚本。但直接执行会翻车字符集问题脚本开头有CREATE DATABASE love DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;但 MySQL 5.7 默认utf8是utf8mb3不支持 emoji而utf8mb4才是真·UTF-8。必须手动修改为CREATE DATABASE love DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;用户权限问题脚本末尾GRANT ALL PRIVILEGES ON love.* TO rootlocalhost IDENTIFIED BY 123456;是危险操作。本地开发应创建专用用户CREATE USER love_devlocalhost IDENTIFIED BY love123; GRANT SELECT, INSERT, UPDATE, DELETE ON love.* TO love_devlocalhost; FLUSH PRIVILEGES;JDBC URL 修正src/main/resources/jdbc.properties中的jdbc.url必须显式指定characterEncodingutf8mb4和serverTimezoneGMT%2B8防时区错乱jdbc.urljdbc:mysql://localhost:3306/love?useUnicodetruecharacterEncodingutf8mb4serverTimezoneGMT%2B8 jdbc.usernamelove_dev jdbc.passwordlove123完成以上四步点击 IDEA 右上角绿色三角形 Run控制台出现INFO: Server startup in [xxx] ms浏览器访问http://localhost:8080/login.jsp看到登录表单——第一个闭环成了。3. 后端核心逻辑拆解SSM 三层如何协作完成一次“发布爱心活动”光能启动没用得知道代码怎么“活”起来。我们以“管理员发布一条新的校园爱心活动”为例对应前端admin/activity_add.jsp表单提交逆向追踪从 HTTP 请求到数据库落盘的完整链条。这不是为了炫技而是建立对 SSM 各层职责的肌肉记忆Controller 只做参数搬运与流程调度Service 封装业务规则Dao 专注数据存取。任何一层的混乱都会让后续维护变成噩梦。3.1 Controller 层接收请求、校验基础参数、调用 ServiceActivityController.java中的addActivity方法是入口Controller RequestMapping(/admin) public class ActivityController { Autowired private ActivityService activityService; RequestMapping(value /addActivity, method RequestMethod.POST) public String addActivity( RequestParam(title) String title, RequestParam(content) String content, RequestParam(startTime) String startTimeStr, RequestParam(endTime) String endTimeStr, RequestParam(location) String location, RequestParam(maxParticipants) Integer maxParticipants, Model model) { // 1. 基础非空校验真正的业务校验应在 Service 层 if (StringUtils.isBlank(title) || StringUtils.isBlank(content)) { model.addAttribute(error, 标题和内容不能为空); return admin/activity_add; // 返回原页面错误信息由 JSP 中 ${error} 显示 } // 2. 时间字符串转 Date此处是血泪经验必须用 SimpleDateFormat且线程不安全 SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd HH:mm:ss); Date startTime null, endTime null; try { startTime sdf.parse(startTimeStr); endTime sdf.parse(endTimeStr); } catch (ParseException e) { model.addAttribute(error, 时间格式错误请使用 yyyy-MM-dd HH:mm:ss); return admin/activity_add; } // 3. 构建 Activity 对象VO → DTO → Entity 转换在此处发生 Activity activity new Activity(); activity.setTitle(title); activity.setContent(content); activity.setStartTime(startTime); activity.setEndTime(endTime); activity.setLocation(location); activity.setMaxParticipants(maxParticipants); activity.setStatus(1); // 1-待审核0-已取消2-已结束 activity.setCreateTime(new Date()); // 4. 调用 Service不处理返回值成功则跳转失败则捕获异常 try { activityService.addActivity(activity); model.addAttribute(msg, 活动发布成功等待审核); return admin/activity_list; // 重定向到活动列表页 } catch (Exception e) { model.addAttribute(error, 发布失败 e.getMessage()); return admin/activity_add; } } }关键点说明RequestParam明确指定从前端表单哪个name属性取值比RequestBody用于 JSON更符合传统表单场景SimpleDateFormat是线程不安全的生产环境必须每次 new或改用DateTimeFormatterJava 8Controller绝不包含 SQL、不操作数据库、不处理复杂业务逻辑如“判断活动时间是否与已有活动冲突”这些都交给 Servicereturn admin/activity_list是逻辑视图名由 SpringMVC 的InternalResourceViewResolver解析为WEB-INF/jsp/admin/activity_list.jsp。3.2 Service 层事务边界、业务规则、跨 Dao 协作ActivityServiceImpl.java实现了真正的业务逻辑Service Transactional // 整个方法在同一个数据库事务中执行 public class ActivityServiceImpl implements ActivityService { Autowired private ActivityDao activityDao; Autowired private VolunteerDao volunteerDao; // 假设需要关联查询志愿者 Override public void addActivity(Activity activity) throws Exception { // 1. 业务规则校验活动结束时间必须晚于开始时间 if (activity.getEndTime().before(activity.getStartTime())) { throw new IllegalArgumentException(结束时间不能早于开始时间); } // 2. 业务规则校验同一时间段内同一地点不能有超过 3 个进行中的活动示例规则 int conflictCount activityDao.countConflictingActivities( activity.getStartTime(), activity.getEndTime(), activity.getLocation() ); if (conflictCount 3) { throw new IllegalStateException(该时间段和地点活动已满请选择其他时间或地点); } // 3. 执行插入Dao 层 activityDao.insertActivity(activity); // 4. 记录操作日志可选体现 Service 层协调能力 Log log new Log(); log.setOperator(admin); log.setOperation(add_activity); log.setTargetId(activity.getId().toString()); log.setCreateTime(new Date()); // 假设有 LogDao此处省略注入与调用 // logDao.insertLog(log); } }关键点说明Transactional注解是事务的开关确保insertActivity()和潜在的insertLog()要么全成功要么全回滚所有throw new XxxException都会被 Controller 的catch (Exception e)捕获实现错误统一处理countConflictingActivities是一个典型的跨表/复杂查询其 SQL 写在ActivityDao.xml中见下节体现了 Service 层“指挥”多个 Dao 的能力Service 方法签名是void不返回 Entity因为 Controller 不需要新插入的 ID除非后续要重定向到详情页此时需返回activity.getId()。3.3 Dao 层MyBatis 的 XML 映射与动态 SQL 实战ActivityDao.java是接口ActivityDao.xml是实现。这是 SSM 中最易出错也最体现功底的一环。!-- ActivityDao.xml -- mapper namespacecom.xxx.love.dao.ActivityDao !-- 1. 主键自增插入 -- insert idinsertActivity parameterTypeActivity useGeneratedKeystrue keyPropertyid INSERT INTO t_activity ( title, content, start_time, end_time, location, max_participants, status, create_time ) VALUES ( #{title}, #{content}, #{startTime}, #{endTime}, #{location}, #{maxParticipants}, #{status}, #{createTime} ) /insert !-- 2. 复杂条件查询统计时间地点冲突数量 -- select idcountConflictingActivities resultTypeint SELECT COUNT(*) FROM t_activity WHERE status 1 !-- 只查“进行中”状态 -- AND location #{location} AND ( (#{startTime} BETWEEN start_time AND end_time) -- 新活动开始时间在旧活动期间 OR (#{endTime} BETWEEN start_time AND end_time) -- 新活动结束时间在旧活动期间 OR (start_time BETWEEN #{startTime} AND #{endTime}) -- 旧活动开始时间在新活动期间 ) /select /mapper关键点说明useGeneratedKeystrue keyPropertyid是让 MyBatis 将数据库生成的主键AUTO_INCREMENT自动回填到activity.getId()否则 Controller 无法获取新 ID动态 SQLif、where在此例未体现但在“活动列表分页查询”中会大量使用例如根据status参数动态拼接AND status #{status}#{}是预编译占位符防止 SQL 注入${} 是字符串拼接仅用于ORDER BY字段名等极少数场景此处禁用resultTypeint明确告诉 MyBatis 返回一个整数而非Activity对象。至此“发布活动”从点击按钮到数据入库SSM 三层各司其职清晰可溯。4. 前端与后端的胶水JSP JSTL EL 表达式如何驱动页面渲染很多人觉得前端只是“套模板”但在这个项目里JSP 不是静态 HTML而是运行在 Tomcat 上的 Java Servlet它能直接调用 Java 对象、执行逻辑、甚至访问数据库虽不推荐。理解 JSP 如何与后端联动是解决“页面数据显示为空”、“列表循环不出来”这类高频问题的关键。4.1 JSP 页面结构指令、脚本、EL、JSTL 的四层混合以admin/activity_list.jsp为例它展示了如何将 Controller 查询出的ListActivity渲染成 HTML 表格% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt % html head title活动列表/title link relstylesheet href${pageContext.request.contextPath}/css/bootstrap.min.css /head body div classcontainer mt-4 h2爱心活动管理/h2 a href${pageContext.request.contextPath}/admin/activity_add.jsp classbtn btn-primary mb-3发布新活动/a !-- 1. 使用 JSTL c:if 判断是否有数据 -- c:if test${empty activityList} div classalert alert-info暂无活动数据/div /c:if !-- 2. 使用 JSTL c:forEach 循环遍历 List -- c:if test${not empty activityList} table classtable table-striped thead tr th标题/th th时间/th th地点/th th状态/th th操作/th /tr /thead tbody c:forEach items${activityList} varact tr !-- 3. 使用 EL 表达式 ${} 访问对象属性 -- td${act.title}/td !-- 4. 使用 JSTL fmt:formatDate 格式化日期 -- td fmt:formatDate value${act.startTime} patternyyyy-MM-dd HH:mm/ 至 fmt:formatDate value${act.endTime} patternyyyy-MM-dd HH:mm/ /td td${act.location}/td td c:choose c:when test${act.status 1}待审核/c:when c:when test${act.status 2}进行中/c:when c:otherwise已结束/c:otherwise /c:choose /td td a href${pageContext.request.contextPath}/admin/activity_detail.jsp?id${act.id} classbtn btn-sm btn-info详情/a a href${pageContext.request.contextPath}/admin/deleteActivity?id${act.id} classbtn btn-sm btn-danger onclickreturn confirm(确定删除)删除/a /td /tr /c:forEach /tbody /table /c:if /div /body /html关键点说明% taglib %指令引入 JSTL 核心库c:和格式化库fmt:这是使用c:forEach和fmt:formatDate的前提${pageContext.request.contextPath}是 JSP 内置对象动态获取应用上下文路径如/避免硬编码/css/bootstrap.min.css导致路径失效${empty activityList}和${not empty activityList}是 EL 的空值判断比 Java 代码list null || list.size() 0更简洁c:forEach的items属性绑定 Controller 放入Model的activityListvaract定义循环变量其属性用${act.title}访问fmt:formatDate是处理日期显示的唯一可靠方式直接${act.startTime}会输出java.util.Datexxxxx的哈希值。4.2 Model 数据传递Controller 如何把数据“喂”给 JSP回到ActivityController的listActivity方法RequestMapping(/listActivity) public String listActivity(Model model) { ListActivity activityList activityService.findAllActivities(); model.addAttribute(activityList, activityList); // 关键key 是 activityList return admin/activity_list; // 逻辑视图名 }model.addAttribute(activityList, activityList)将ListActivity对象以activityList为键存入HttpServletRequest的request.setAttribute()SpringMVC 的InternalResourceViewResolver将admin/activity_list解析为WEB-INF/jsp/admin/activity_list.jsp并RequestDispatcher.forward()JSP 中的${activityList}即是从request.getAttribute(activityList)取出的对象。注意如果 Controller 中写的是model.addAttribute(activities, activityList)那么 JSP 中必须用${activities}否则 EL 表达式求值为nullc:forEach不会执行。4.3 前端表单提交GET vs POST以及中文乱码的终极解法activity_add.jsp中的表单form action${pageContext.request.contextPath}/admin/addActivity methodpost div classform-group label标题/label input typetext nametitle classform-control required /div div classform-group label内容/label textarea namecontent classform-control rows5 required/textarea /div !-- 其他字段... -- button typesubmit classbtn btn-success发布/button /formmethodpost是必须的因为数据量大content是长文本且涉及数据修改符合 RESTful 原则action地址必须带${pageContext.request.contextPath}否则提交到http://localhost:8080/addActivity根路径而非http://localhost:8080/admin/addActivity中文乱码问题Tomcat 8.5 默认URIEncoding为ISO-8859-1GET 请求的 URL 参数如搜索关键词会乱码。解决方案是在conf/server.xml的Connector标签中添加URIEncodingUTF-8Connector port8080 protocolHTTP/1.1 connectionTimeout20000 redirectPort8443 URIEncodingUTF-8 /POST 请求的乱码则由CharacterEncodingFilter过滤器解决项目web.xml中已配置filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping5. 避坑指南SSM 项目启动与运行的 5 个高频翻车现场别笑这 5 个问题我见过太多人卡住一整天甚至放弃项目。它们不是冷门 Bug而是 SSM 生态里最顽固的“玄学”陷阱。按顺序排查90% 的启动失败都能解决。5.1 现象Tomcat 启动成功但访问http://localhost:8080/login.jsp报 404原因IDEA 的 Artifact 配置错误或web.xml中welcome-file-list未指向login.jsp。解决检查web.xml是否有以下配置项目中通常有welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list在 IDEA 的 Run Configuration → Deployment 中确认Application context是/且Artifact是xxx:war exploded不是xxx:war查看 Tomcatlogs/catalina.out搜索Deploying web application directory确认部署路径是webapps/ROOT对应/而非webapps/xxx。5.2 现象登录时用户名密码正确但始终跳转回login.jsp控制台无报错原因LoginController中的登录验证逻辑有误或User对象的password字段在数据库中是明文存储但代码中却用了 MD5 加密比对。解决在LoginController.login()方法中System.out.println(DB pwd: dbUser.getPassword() , Input pwd: password);打印对比查看sql/love.sql中t_user表的password字段值如果是123456则数据库是明文如果是一串 32 位十六进制如e10adc3949ba59abbe56e057f20f883e则是 MD5确保UserService.login()中的比对逻辑与数据库存储方式一致// 若数据库是明文 if (dbUser.getPassword().equals(password)) { ... } // 若数据库是 MD5项目中常见 String inputMd5 DigestUtils.md5Hex(password); if (dbUser.getPassword().equals(inputMd5)) { ... }5.3 现象JSP 页面中${activityList}显示正常但c:forEach循环体内的${act.title}全是空白原因Activity实体类缺少符合 JavaBean 规范的 getter 方法或web.xml中未声明 JSTL 标签库。解决检查Activity.java是否有public String getTitle() { return this.title; }方法名必须是getXXX()首字母大写不能是getTitle()检查activity_list.jsp顶部是否有% taglib prefixc urihttp://java.sun.com/jsp/jstl/core %且WEB-INF/lib/下存在jstl-1.2.jar和standard-1.1.2.jarMaven 依赖jstl:jstl:1.2会自动提供在 JSP 中加% pageContext.getAttribute(activityList) ! null ? NOT NULL : NULL %确认activityList确实传入了。5.4 现象MySQL 连接报错java.sql.SQLException: The server time zone value XXX is unrecognized原因MySQL 服务器时区与 JDBC 驱动不匹配尤其在 macOS 或 Linux 上常见。解决登录 MySQL执行SELECT global.time_zone, session.time_zone;查看当前时区修改jdbc.properties中的 URL强制指定serverTimezonejdbc.urljdbc:mysql://localhost:3306/love?useUnicodetruecharacterEncodingutf8mb4serverTimezoneGMT%2B8%2B8是8的 URL 编码不可写成8否则解析失败若仍报错可在 MySQL 中执行SET GLOBAL time_zone 8:00;并重启 MySQL 服务。5.5 现象新增活动后数据库t_activity表中create_time字段为0000-00-00 00:00:00原因MySQL 的 SQL mode 包含NO_ZERO_DATE或STRICT_TRANS_TABLES拒绝插入零值时间。解决查看当前 modeSELECT sql_mode;临时修改重启 MySQL 会失效SET sql_mode(SELECT REPLACE(sql_mode,NO_ZERO_DATE,));永久修改编辑 MySQL 配置文件Linux:/etc/my.cnfWindows:my.ini在[mysqld]下添加sql_modeSTRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION移除了NO_ZERO_DATE和NO_ZERO_IN_DATE重启 MySQL 服务。6. 从“能跑”到“能改”三个实战技巧让你真正掌控这个项目跑通只是开始毕业设计答辩、课程验收、甚至未来把它改成自己的简历项目都需要你具备“改”的能力。这里不讲虚的只给三个我反复验证、立刻见效的技巧一个是改数据库字段一个是加新功能模块一个是让论文LW和代码严丝合缝。6.1 技巧一安全地为t_activity表增加“活动封面图片”字段varchar → blob需求来了老师说“爱心活动应该有封面图提升吸引力”。你不能直接在 MySQL Workbench 里右键t_activity→ “Alter Table”然后加一个cover_img LONGBLOB—— 因为 Java 实体类、MyBatis 映射、JSP 表单、Controller 接收逻辑全部要同步更新。安全路径如下Step 1数据库变更SQL-- 在 love 数据库中执行 ALTER TABLE t_activity ADD COLUMN cover_img_url VARCHAR(255) DEFAULT NULL COMMENT 封面图片URL存储相对路径如 /upload/20240510/abc.jpg;为什么用VARCHAR(255)而不用BLOB因为图片文件本身不存数据库只存路径节省空间、提高查询速度、方便 CDN 加速。BLOB是反模式。Step 2Java 实体类更新在Activity.java中添加private String coverImgUrl; // 字段名与数据库列名一致下划线转驼峰是 MyBatis 自动做的 // getter/setter 方法IDEA 快捷键 AltInsert → Getter and Setter public String getCoverImgUrl() { return coverImgUrl; } public void setCoverImgUrl(String coverImgUrl) { this.coverImgUrl coverImgUrl; }Step 3MyBatis 映射更新在ActivityDao.xml的insert和select语句中加入cover_img_urlinsert idinsertActivity ... INSERT INTO t_activity (..., cover_img_url) VALUES (..., #{coverImgUrl}) /insert select idselectActivityById resultTypeActivity SELECT ..., cover_img_url FROM t_activity WHERE id #{id} /selectStep 4JSP 表单与页面展示在activity_add.jsp中加上传控件用input typefilediv classform-group label封面图片/label input typefile namecoverImgFile classform-control-file small classform-text text-muted建议尺寸 800x400px格式 JPG/PNG/small /div在activity_list.jsp的表格中加一列td c:if test${not empty act.coverImgUrl} img src${pageContext.request.contextPath}${act.coverImgUrl} width80 height40 alt封面 /c:if /tdStep 5Controller 与 Service 补充逻辑ActivityController.addActivity()中用RequestParam(coverImgFile) MultipartFile file接收文件用file.isEmpty()判断是否上传用file.getOriginalFilename()获取文件名用file.transferTo(new File(uploadDir, filename))保存到本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

智能体工程化落地:从趋势榜看状态管理、工具调用与可观测性实践 2026/10/1 15:00:28

智能体工程化落地:从趋势榜看状态管理、工具调用与可观测性实践

1. 从本周趋势榜看智能体赛道的真实转向这周我把 GitHub Trending 上跟智能体相关的项目从头到尾翻了一遍,最大的感受是:智能体这个赛道正在经历一次非常明显的“去泡沫化”。前两年大家聊智能体,聊的是概念、是愿景、是“能不能自己订机票”…

阅读更多 →
HyperAgents安全警示与风险应对:执行模型生成代码的AI安全完整清单 2026/10/1 15:00:28

HyperAgents安全警示与风险应对:执行模型生成代码的AI安全完整清单

HyperAgents安全警示与风险应对:执行模型生成代码的AI安全完整清单 【免费下载链接】HyperAgents Self-referential self-improving agents that can optimize for any computable task 项目地址: https://gitcode.com/gh_mirrors/hy/HyperAgents HyperAgent…

阅读更多 →
Claude Code 接入 U2-Flash 第三方模型完整教程:免费额度领取与配置指南 2026/10/1 15:00:28

Claude Code 接入 U2-Flash 第三方模型完整教程:免费额度领取与配置指南

1. 为什么大家都在折腾 Claude Code 接第三方模型Claude Code 这个终端里的 AI 编程助手,用过的人基本回不去了。它跟普通代码补全工具最大的区别在于:它能直接读写你本地的文件、跑命令、看报错、改代码,整个流程像一个真人在你终端里帮你干…

阅读更多 →
ASP.NET MVC 集成图像与视频 LLM:架构设计与工程实践 2026/10/1 15:00:28

ASP.NET MVC 集成图像与视频 LLM:架构设计与工程实践

1. 为什么要在 ASP.NET MVC 里塞进一个本机 LLM 工程先把场景说清楚。你手上有一个跑在 Visual Studio 里的 C# ASP.NET MVC 项目,可能是企业内部的管理后台、工单系统、内容平台,也可能是某个垂直行业的业务中台。现在你想让它具备"看懂图片"…

阅读更多 →
云Dify连本地MCP服务报错failed to get endpoint URL:config.toml骨架与连通性验证 2026/10/1 15:00:21

云Dify连本地MCP服务报错failed to get endpoint URL:config.toml骨架与连通性验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
CMake 3.28.6 Windows x86_64 发行包:离线手册与构建实践指南 2026/10/1 15:00:21

CMake 3.28.6 Windows x86_64 发行包:离线手册与构建实践指南

简介:CMake 3.28.6 的 Windows x86_64 文档资源包,面向需要在 Windows 平台配置构建流程、编写 CMakeLists 或调试构建脚本的开发者与运维人员。资源以官方 3.28.6 版本文档为蓝本,压缩包共 2000 个文件,包含 1171 个 txt 文本与 …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉