JavaEE网上考试系统设计:Servlet+JSP+JDBC三层架构大作业资源解析

发布时间:2026/10/21 12:58:15
JavaEE网上考试系统设计:Servlet+JSP+JDBC三层架构大作业资源解析 简介这是一套面向软件工程专业课程设计的JavaEE网上考试系统完整项目涵盖源代码、设计报告与使用说明适合正在完成大作业、需要参考成熟考试系统设计与实现思路的学生。压缩包共包含74个文件其中16个Java文件负责后台核心逻辑与数据库操作16个JSP页面构建前端交互界面16个class编译文件与对应源码配套另有CSS样式表、GIF与JPG图片资源用于页面美化以及doc格式的设计报告和使用说明文档。整个资源包大小6.75MB目录结构清晰源码注释详细、难度适中导入后只需修改姓名、学号等个人信息即可顺利运行。目前已有3475人学习下载资源作者为软件工程学生内容经实际课程验证保证正确完善。通过学习这份资料读者可以了解JavaEE项目从页面到后台的完整架构掌握JSP、Servlet、JavaBean等核心技术的协作方式并借助配套文档快速完成报告撰写与答辩准备取得理想成绩。1. 网上考试系统设计这份 JavaEE 大作业资源比你自己从零写快三倍“网上考试系统设计”几乎是 JavaEE 大作业里出现频率最高的题目没有之一。我见过太多人卡在同一道坎上代码写了一半发现要补设计报告结果报告还没写完演示又出了问题。这份资源好就好在它不是一个光秃秃的源码包而是把代码、设计报告、使用说明三样东西一次性配齐了正好对应大作业验收的三件套能跑、能讲、能演示。适合正在做 JavaEE 课程设计的学生也适合想拿现成项目二次开发、改造成自己期末作品的开发者。你不需要理解每一个类的细节才能交差但你需要知道它怎么部署、怎么改、哪些地方容易翻车——这篇就把这些讲透。2. 经典 JavaEE 三层结构这份资源的技术栈与模块划分逻辑2.1 为什么是 Servlet JSP JDBC而不是 Spring Boot先别急着嫌弃这套技术栈老。网上考试系统作为大作业验收老师最看重的是你能不能讲清楚一次请求从浏览器到数据库再返回的完整链路。Servlet JSP JDBC 这套组合恰好把所有环节都暴露在明面上Servlet 接收请求、JSP 渲染页面、JDBC 操作数据库每一层你都能指着代码说“这里做了什么”。换成 Spring Boot 反而容易变成黑匣子答辩时老师问“请求怎么进来的”你只能回答“框架自动处理的”这就被动了。这份资源走的是标准 MVC 分层表现层用 JSP 加 ServletJSP 负责页面展示Servlet 负责接收请求、跳转页面业务层独立封装考试相关的规则比如组卷逻辑、自动判分逻辑数据访问层用 DAO 模式加 JDBC每个表对应一个 DAO 类里面的方法就是增删改查。这种分层看起来笨但有一个实打实的好处写设计报告的时候架构图、流程图、类图都能直接画出来甚至可以把三层结构的描述原封不动搬进报告里。从资源包里带的源码目录来看典型结构是这样的src ├── com.xxx.entity // 实体类Student、Teacher、Question、ExamPaper ├── com.xxx.dao // 数据访问StudentDao、QuestionDao、ExamDao ├── com.xxx.service // 业务逻辑ExamService、ScoreService └── com.xxx.servlet // 控制器LoginServlet、ExamServlet、ScoreServlet webapp ├── jsp │ ├── student // 学生端页面 │ ├── teacher // 教师端页面 │ └── admin // 管理端页面 ├── WEB-INF │ ├── web.xml │ └── lib // JDBC 驱动 jar 包实体类对应数据库表字段DAO 类封装所有 SQL 语句Service 类处理考试规则。你在改造的时候凡是涉及“规则”的改动比如改判分逻辑、改组卷策略都去 Service 层找凡是涉及“页面”的改动都去 jsp 目录下找这样定位文件会很快。2.2 核心数据表学生、教师、管理员与考试业务的关系这套系统的角色分三类学生、教师、管理员。权限边界很清晰学生登录后只看到“参加考试”和“查看成绩”教师登录后能管理题库和批改试卷管理员则负责课程、账号、基础数据。数据库设计也围绕这三个角色展开。我建议你在拿到资源后先用可视化工具Navicat 或 DataGrip 都行打开数据库把这几个表的关系理一遍比直接看代码效率高得多表名作用关键字段t_user统一用户表用 role 字段区分角色id, username, password, rolet_course课程表试卷归属于某门课程id, course_namet_question试题表含单选题、多选题、判断题id, question_type, content, option_a/b/c/d, answer, scoret_paper试卷表记录试卷基本信息和总分id, paper_name, course_id, total_score, creator_idt_paper_question试卷与试题关联表多对多关系id, paper_id, question_idt_exam_record考试记录表记录学生某次考试的开始时间与状态id, student_id, paper_id, start_time, submit_statust_answer答题明细表每道题一行id, exam_record_id, question_id, student_answert_score成绩表记录总分、得分、交卷时间id, student_id, paper_id, score, submit_time这张表结构不算复杂但 t_paper_question 这张关联表很关键它决定了组卷功能怎么实现。后面讲到组卷和自动判分时你还会再遇到它。2.3 从使用说明书反推这套系统的功能边界在哪拿到资源第一步我建议先看使用说明文档而不是急着跑代码。使用说明会告诉你默认管理员账号是什么、数据库脚本怎么导入、端口怎么配。这些信息写代码的人最清楚也是你最容易踩坑的地方。从使用说明和代码倒推这套系统实现的功能大致是这些学生端注册、登录、查看待考列表、在线答题、交卷后立即看到成绩。教师端维护题库增删改查试题、手动组卷、查看学生的考试成绩和答题详情。管理员端管理用户账号、管理课程信息、查看系统整体考试数据。有一个常见误会是拿它和商用考试系统比它是课程设计级别不是生产级系统。只有单选、多选、判断三类客观题没有主观题和人工阅卷流程。也没有考试防作弊的功能这个我后面会讲怎么自己加。如果你的大作业要求里有“随机组卷”“限时交卷”那需要你自己动手补一点逻辑。换句话说这份资源能帮你稳过 70 分的验收但要拿 90 分得按后文的方法做局部强化。3. 核心功能实现解析从登录到自动判分的完整链路3.1 登录与角色鉴权一个方法完成权限跳转登录功能是所有模块的入口。我看到很多学生在自己写登录时习惯把用户名密码拼进 SQL 字符串里这非常危险而且答辩时如果被问到 SQL 注入很难解释。这套资源的价值在于它给出了一套能被答辩老师接受的规范写法。先看它的登录处理逻辑public User login(String username, String password) { String sql SELECT * FROM t_user WHERE username ? AND password ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); ps.setString(2, password); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { User user new User(); user.setId(rs.getInt(id)); user.setUsername(rs.getString(username)); user.setPassword(rs.getString(password)); user.setRole(rs.getString(role)); return user; } } } catch (SQLException e) { e.printStackTrace(); } return null; }这段代码有两点值得注意。第一用 PreparedStatement 做参数化查询而不是字符串拼接这是 JDBC 编程的基本功也是答辩时老师大概率会追问的点。第二返回的 User 对象包含了 role 字段LoginServlet 拿到 User 后根据 role 的值做跳转。LoginServlet 里的跳转逻辑通常是这样的HttpSession session request.getSession(); session.setAttribute(currentUser, user); if (admin.equals(user.getRole())) { response.sendRedirect(jsp/admin/index.jsp); } else if (teacher.equals(user.getRole())) { response.sendRedirect(jsp/teacher/index.jsp); } else if (student.equals(user.getRole())) { response.sendRedirect(jsp/student/index.jsp); } else { response.sendRedirect(jsp/login.jsp?error2); }参数说明sendRedirect 是重定向地址栏会变化适合登录成功后跳转到新的页面RequestDispatcher 的 forward 是转发地址栏不变适合登录失败后回显错误信息。很多学生在这两个 API 上混淆导致刷新页面时表单重复提交答辩时被问“为什么不用转发”就答不上来。如果你希望登录失败后保留用户输入的用户名就改成 forward 方式。3.2 题库管理DAO 层如何承接四种题型题库管理模块的核心是 t_question 表。它用 question_type 字段区分题型1 代表单选2 代表多选3 代表判断。教师端题库管理页面会提供三个 Tab 或者一个下拉框新增试题时选择题目类型其余字段动态变化。看这段新增试题的 DAO 方法public boolean addQuestion(Question q) { String sql INSERT INTO t_question (question_type, content, option_a, option_b, option_c, option_d, answer, score) VALUES (?, ?, ?, ?, ?, ?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, q.getQuestionType()); ps.setString(2, q.getContent()); ps.setString(3, q.getOptionA()); ps.setString(4, q.getOptionB()); ps.setString(5, q.getOptionC()); ps.setString(6, q.getOptionD()); ps.setString(7, q.getAnswer()); ps.setInt(8, q.getScore()); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } }参数说明单选题的答案默认存储格式是 A 这种大写字母判断题的选项 A/B 写的是“正确”和“错误”答案也是 A 或 B多选题的答案是 ABC 这种组合格式。存储格式直接决定了后面自动判分的实现方式这就是为什么你不能乱改答案字段的存储格式——一旦改了判分逻辑必须同步改。改题库代码时要注意删除试题前先看它有没有被试卷引用不然会把试卷中的题删出一个空位。资源包里如果没做外键级联处理我建议你在删除前加一个判断先查 t_paper_question 里有没有记录有则提示“该试题已被试卷引用不能删除”。3.3 在线组卷与答题关联表的灵活运用组卷功能是这套系统里最有含金量的一块。它的数据模型是试卷表 t_paper 不直接存试题内容而是通过 t_paper_question 关联表建立试卷和试题的多对多关系。手动组卷时教师勾选若干道试题系统将 paper_id 和 question_id 成对写入关联表。为什么不用冗余字段直接存试题因为你改了一道题所有引用它的试卷自动更新不会出现同一张试卷里新旧题目并存的问题这也体现了数据库第三范式的要求。写设计报告的时候这个点值得展开讲。答题环节的关键在于学生提交的是每道题的选项值而不是“第几题的什么选项”。看这段保存答题结果的代码public boolean saveAnswer(int recordId, int questionId, String studentAnswer) { String sql INSERT INTO t_answer (exam_record_id, question_id, student_answer) VALUES (?, ?, ?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setInt(1, recordId); ps.setInt(2, questionId); ps.setString(3, studentAnswer); return ps.executeUpdate() 0; } catch (SQLException e) { e.printStackTrace(); return false; } }注意 recordId 来自 t_exam_record代表“某学生某次考试”的唯一记录。学生在答题过程中每点一次“下一题”前端就用 Ajax 调用这个接口保存一次答案。这种做法比交卷时一次性提交数组更稳——学生中途浏览器崩溃了已答的题还在数据库里交卷时只需要把所有答案从 t_answer 表里读出来判分而不是再从请求参数里获取。这里面有个小陷阱如果学生反复点击“下一题”保存答案同一道题可能被写入多条 t_answer 记录。资源包里如果没做“先删后插”处理你需要改一下保存前先 DELETE 掉该 recordId questionId 的旧记录再 INSERT 新答案。我能确认这个坑在不少类似的源码包中真实存在建议你改掉。3.4 自动判分为什么正确答案可以放心保存在数据库里自动判分的逻辑不复杂但容易在细节上翻车。核心思路是遍历 t_answer 表里某次考试记录的所有答题明细把每条明细的 questionId 拿去 t_question 表查标准答案两相对比后计算得分。public int computeScore(int recordId) { // 1. 查出该次考试涉及的所有题目的正确答案 String questionSql SELECT q.id, q.answer, q.score FROM t_question q JOIN t_answer a ON q.id a.question_id WHERE a.exam_record_id ?; // 2. 查出学生的所有答案 String answerSql SELECT question_id, student_answer FROM t_answer WHERE exam_record_id ?; // 3. 遍历比对累加得分 int totalScore 0; // 伪代码对每个 question_id判断 student_answer.equalsIgnoreCase(correctAnswer) // 相等则 totalScore score return totalScore; }注意多选题的判分不能直接用 equals因为多选题答案顺序可能不同。如果学生选的是 BC 而标准答案是 CB这里需要先把字符串拆成字符数组排序再重组比较。这是自动判分模块最容易漏掉的一种情况。资源包里如果没做这个处理答辩演示时出现“正确答案反而判错”就会很尴尬。关于“正确答案存在数据库里会不会被学生查到”这个疑惑课程设计阶段不用过度担心。t_question 表里的 answer 字段只有教师端接口能访问学生端 JSP 页面没有输出答案的逻辑。商用系统才会考虑把题目和答案分库存储这不是你这份作业需要解决的问题。4. 部署与配置把源码从压缩包变成能演示的系统4.1 环境准备JDK、Tomcat、MySQL 的版本搭配先把环境对齐能省掉后面一大半的玄学报错。这套 JavaEE 资源对应的技术栈是 JDK 1.8 或以上、Tomcat 8.5 或 9.0、MySQL 5.7 或 8.0。IDE 用 Eclipse 或 IntelliJ IDEA 都行但 IDEA 导入 JavaEE 项目时要特别注意 Web 目录的识别。Tomcat 版本是个大坑。如果你用的是 Tomcat 10 及以上代码里所有的 javax.servlet 都要换成 jakarta.servlet这套老资源基本跑不起来。我一般会直接装 Tomcat 8.5一劳永逸。MySQL 用 8.0 时JDBC 驱动要换成 mysql-connector-j 8.x并且连接 URL 要加时区参数后面避坑章节会细说。4.2 导入 IDEA 的完整步骤与 Web 目录识别IDEA 导入 Eclipse 风格的 JavaEE 项目时最容易犯的错是把项目当成普通 Java 项目导入结果 webapp 目录没被识别启动 Tomcat 时找不到页面。正确做法如下第一步新建一个空项目选择 File → New → Project → Empty Project。第二步把解压后的源码整个拷贝到项目目录下。第三步File → Project Structure → Modules点击加号选择 Import Module找到源码的根目录IDEA 会提示识别为 Eclipse 项目的 Module确认导入。导入完成后进入 File → Project Structure → Facets确认 Web facet 已添加并且 Web Resource Directory 指向项目里的 webapp 目录。这一步是关键。如果 ID 没识别到这个目录Deployment 时会提示找不到 web.xml 或静态资源。最后一步File → Project Structure → Libraries添加 WEB-INF/lib 下所有 jar 包以及 Tomcat 的 lib 目录里的 servlet-api.jar。很多学生部署时报 ClassNotFoundException就是这一步骤漏了。4.3 创建数据库脚本的导入与连接配置修改数据库初始化通常有两种形式一种是 resource/sql/exam_system.sql 建库脚本另一种是 db.sql 加 exam_data.sql 分离脚本。我建议用命令行导入避免 Navicat 在导入时因为字符集炸出中文乱码。打开命令行进入 MySQL 后执行source D:/examSystem/resource/sql/exam_system.sql;注意 source 命令的路径要用正斜杠。导入成功后执行 SHOW TABLES; 确认 8 张表都在。导入失败时先看报错是不是 “Unknown database”如果是就得先手动创建库CREATE DATABASE IF NOT EXISTS exam_system DEFAULT CHARSET utf8mb4;然后改数据库连接配置。这套资源通常把连接信息写在 src/util/DBUtil.java 或者 src/db.properties 里。关键参数如下jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/exam_system?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8 jdbc.usernameroot jdbc.password你的数据库密码重点说三个参数。serverTimezone 不加会报 “The server time zone value” 错误characterEncodingutf8 不加会导致数据库中文字符乱码useSSLfalse 是关掉 MySQL 8.0 默认的 SSL 警告。如果本地 MySQL 是 8.0 而资源包驱动 jar 还是 5.x 的去资源包里看看 lib 下有没有 mysql-connector-java-8.0.x.jar没有就自己下载替换。4.4 启动 Tomcat 与验证登录流程IDEA 里配置 Tomcat 的方式是Run → Edit Configurations → Tomcat Server → Local。Deployment 选项卡里点击加号选择 Artifact 为 war exploded 类型Application context 设置为 /examSystem然后启动。启动成功后浏览器访问 http://localhost:8080/examSystem看到登录页说明部署成功。接下来用使用说明里提供的默认账号登录通常管理员是 admin / admin123学生或教师账号会写在账号初始化表里。如果使用说明书没写默认账号去数据库里查SELECT * FROM t_user LIMIT 10;建议你登录后立刻做三件事管理员登录创建一个新课程、教师登录添加 5 道试题并组一张试卷、学生登录完成答题看分数。这三步能跑通你的大作业演示环节就稳了。5. 常见问题与排查我实际用这套代码时踩过的四个坑5.1 连不上数据库时区与驱动类名同时报错现象是启动 Tomcat 后访问登录页输入账号密码点登录页面直接抛出 500 错误控制台提示 Communications link failure 或者 The server time zone value ???.原因是 MySQL 8.0 改了 JDBC 驱动类名和默认时区行为。老资源包里写的是 com.mysql.jdbc.Driver这个类在 8.0 驱动里已经过时但仍然能加载真正报错的根因是 URL 里没带 serverTimezone。解决方法是把 DBUtil 或 db.properties 里的 URL 改成 jdbc:mysql://localhost:3306/exam_system?useSSLfalseserverTimezoneAsia/Shanghai。如果驱动 jar 本身太旧干脆换成 mysql-connector-java 8.0.33。改完重启 Tomcat问题就消失了。5.2 中文乱码导入数据库时就变成了问号现象是登录后所有页面显示的中文都是问号或乱码。去数据库里查 SELECT * FROM t_user中文同样是 ??。原因常常是 SQL 脚本文件本身的字符集和 MySQL 客户端的字符集不一致或者建库时没指定 utf8mb4。这一步在导入前就应该处理。解决方法是导入前先用记事本打开 SQL 文件另存为 UTF-8 编码然后执行前先设置客户端字符集SET NAMES utf8mb4; source D:/examSystem/resource/sql/exam_system.sql;如果已经导入成问号了最简单的办法是删库重来。别试图 UPDATE 修复除非你想把每一条中文重新敲一遍。从这次之后我就养成习惯任何源码包的 SQL 文件都先查一下编码再导入。5.3 端口被占用Tomcat 起不来或项目加载失败现象是 IDEA 启动 Tomcat 时控制台提示 Port 8080 was already in use或者是 Sever 选项卡报 Address already in use。原因是之前启动的 Tomcat 实例没被杀掉或者其它软件占用了 8080。处理方式有两种。最简单的是换端口在 IDEA 的 Tomcat 配置里把 HTTP port 改成 8081同时把 Deployment 里的 Application context 保持 /examSystem访问地址变成 http://localhost:8081/examSystem。第二种是找到占用进程杀掉。Windows 下执行netstat -ano | findstr 8080 taskkill /PID 你看到的进程号 /F注意杀掉前确认一下这个 PID 确实是 Tomcat 进程别误杀系统进程。如果能换端口解决我一般直接换端口速战速决。5.4 刷新页面导致考试重复提交现象是学生交完卷后按 F5 刷新成绩页面弹出来一个“再次提交”的提示浏览器询问是否重新发送表单数据。此时如果点了确认数据库里可能出现两条考试记录。原因是交卷按钮用的 form 表单 POST 提交交卷后没有做重定向跳转导致刷新时浏览器重新提交。解决办法是在交卷的 Servlet 里改成 Post/Redirect/Get 模式处理完交卷逻辑后不要 forward 到成绩页面而是重定向到一个查询成绩的地址。// 交卷逻辑结束后 request.getSession().setAttribute(recordId, recordId); response.sendRedirect(scoreServlet?actionview);重定向之后地址栏变成 scoreServlet浏览器不再保留 POST 提交的表单数据刷新多少次都不会重复交卷。这是一个 JavaEE 项目里很经典的细节答辩老师问“你如何防止表单重复提交”你把这个改动的原理讲清楚比背一百行代码都加分。6. 二次开发进阶给网上考试系统加“题目乱序”和“限时交卷”6.1 乱序出题一行代码让试卷每次都不一样很多课程设计题目要求里有“系统自动组卷”但这份资源只做了教师手动组卷。加一个乱序功能其实成本很低。找到 ExamServlet 里加载试题列表的地方通常是这样一句ListQuestion questionList questionDao.findQuestionsByPaperId(paperId);在处理学生请求时改成ListQuestion questionList questionDao.findQuestionsByPaperId(paperId); Collections.shuffle(questionList);逻辑说明Collections.shuffle 会把列表顺序打乱。关键在于判分时不要依赖数组下标t_answer 表里存的是 question_id所以题目顺序变了不影响判分。这也是当初为什么设计答题明细表时用了 question_id 而不是下标这个好处现在体现出来了。但要做两处配套修改。第一显示试题编号时不要用循环变量 i1 硬编码题号而是遍历第几题就显示第几题第二JSP 页面中选项的 name 属性要带 questionId比如 nameanswer_${question.id}保证后端能区分每一题的答案。改完后多跑两次答题流程确认提交和判分都正常。6.2 限时交卷前端倒计时加后端双重校验考试系统没有倒计时会被老师说“这不合理”。加一个限时功能也分两步。前端在考试页面加一个 JavaScript 倒计时时间到自动提交表单var leftTime 30 * 60; window.setInterval(function () { leftTime--; document.getElementById(timer).innerText Math.floor(leftTime / 60) : (leftTime % 60); if (leftTime 0) { document.forms[examForm].submit(); // 时间到自动交卷 } }, 1000);但前端倒计时是可绕过的学生把网络安全法除外用 F12 改一下变量就能无限续杯。所以后端必须配合在交卷 Servlet 里判断当前时间与考试开始时的时间差是否超过 30 分钟。HttpSession session request.getSession(); User user (User) session.getAttribute(currentUser); ExamRecord record examRecordDao.findUnsubmittedRecord(user.getId(), paperId); if (record null) { request.setAttribute(msg, 没有找到进行中的考试记录); request.getRequestDispatcher(jsp/student/error.jsp).forward(request, response); return; } long usedTime System.currentTimeMillis() - record.getStartTime().getTime(); if (usedTime 30 * 60 * 1000) { // 超时强制交卷 scoreService.submitExam(record.getId()); }参数说明startTime 来自 t_exam_record 表在学生开始考试时写入。那个 if 判断里 30 * 60 * 1000 是毫秒数如果你想把限时改成 45 分钟改成 45 * 60 * 1000 就行。注意 record.getStartTime() 从数据库查出的是 java.sql.TimestampgetTime() 返回毫秒所以这里能直接做减法。我这次负责拆包时A同学第二次遇到的问题是他把后端限时写成“每次请求都判断一次是否超时”结果学生还在答题每点一次“下一题”就触发一次强制交卷。原因是没有区分“超时未交”和“正常做题中”的状态。解决办法是在超时判断前先检查提交状态只有 submit_status 为 0 时才执行强制交卷交完就把状态改成 1。从那以后我每次拿到 JavaEE 资源都会强制走一遍这套流程先看使用说明确认默认账号再导入数据库查三张核心表然后跑通登录答题判分闭环最后才动手改代码。这套流程帮我避开过三次数据库乱码、两次 Tomcat 版本不兼容希望帮到你。如果你手里这份资源也卡在某个报错上按上面避坑章节的顺序逐条对一遍多半能找到问题。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询