恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

JavaWeb请求响应模型深度解析:从HTTP报文到Servlet实战

  • 首页
  • 资讯中心
  • /
  • JavaWeb请求响应模型深度解析:从HTTP报文到Servlet实战

相关资讯

VOI架构vDisk IO瓶颈优化实战:从系统减负到缓存调优 2026/9/18 3:20:56
运动相机素材总是晃?Gyroflow 陀螺仪防抖从安装到导出实战 2026/9/18 3:20:56
tiny11builder 快速上手:6 步把 Windows 11 官方 ISO 瘦成 tiny11.iso 2026/9/18 3:20:56

最新资讯

MySQL UPDATE语句深度解析:从执行原理到安全实战
Linux操作系统课程教学落地:从虚拟环境到权限建模与cgroups实战
Agent-Reach:让 AI Agent 联网查证与可追溯引用
B站数据分析毕业设计:基于大数据的全流程实战指南
51单片机光控路灯设计:ADC采样、迟滞控制与Proteus仿真
二叉树中序遍历全攻略:从递归到Morris遍历

今日推荐

2026年AI设计工具在PPT制作中的核心应用与评测
Matlab手写逻辑回归:从数学原理到多变量概率预测模型实现
高值医用耗材研报PDF:用Python完成字段抽取、清洗与趋势预测

本周热门

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化
Flutter应用改名全指南:从Android到iOS的配置与工具实践

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

JavaWeb请求响应模型深度解析:从HTTP报文到Servlet实战

发布时间:2026/9/18 3:20:56
JavaWeb请求响应模型深度解析:从HTTP报文到Servlet实战 写这篇笔记之前我刚刚用 IDEA 2026 新建了一个 JavaWeb 项目把前几天配置的 Tomcat 重新跑了一遍。每次敲完一个 Servlet心里其实都在重复同一件事浏览器发过来的请求到底是怎么变成代码里的req和resp两个对象的反过来我往resp里写的那一行行内容又是怎么回到浏览器变成页面的这就是 JavaWeb 里最核心的请求响应模型。这篇笔记把 Day05 关于请求响应的内容做一次系统梳理从 HTTP 请求报文的构成到 HttpServletRequest 怎么取参数、HttpServletResponse 怎么写响应再到转发和重定向的区别最后用一个带 MySQL 的完整小案例把所有知识点串起来。如果你刚过完 Servlet 基础、准备深入请求响应这块这篇笔记可以直接照着敲。1. 一次请求从浏览器到 Tomcat 的完整旅程1.1 先看 HTTP 请求报文里到底写了什么很多初学者一上来就直接getParameter根本不看请求本身长什么样后面遇到问题就一头雾水。其实 HTTP 请求报文非常朴素就是一个纯文本块比如POST /javaweb_demo/user/login HTTP/1.1 Host: localhost:8080 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) Content-Length: 29 usernamezhangsanpassword123456这段报文分成三块请求行、请求头、请求体。请求行第一行POST /javaweb_demo/user/login HTTP/1.1依次是请求方式、请求路径、协议版本。如果是 GET 请求这行后面会直接跟?usernamezhangsan这样的查询字符串请求体为空。请求头从第二行到空行之前都是Key: Value结构描述客户端能接收什么类型的数据、用的什么浏览器、Cookie 是什么等。请求头和请求体之间有一个空行这个空行是固定的分隔符。请求体POST 提交的参数在这里格式一般是key1value1key2value2也就是常见的表单application/x-www-form-urlencoded编码格式。如果是上传文件格式会变成multipart/form-data。理解这一段很关键因为后面的中文乱码、参数获取、响应头设置全都是围绕这三块内容做文章。你在浏览器地址栏访问一个 URL浏览器负责把这个报文拼好Tomat 负责解析它。1.2 Tomcat 怎么把请求变成 Servlet 里的两个对象你在 Servlet 里写的doGet(HttpServletRequest req, HttpServletResponse resp)这两个对象不是你自己 new 的也不是凭空出现的而是 Tomcat 在收到请求后创建并传给你的。整个流程大概是Tomcat 监听 8080 端口接收到上文那种报文。解析请求行和请求头根据 URL 路径去匹配映射关系。这个映射来自WebServlet(/user/login)注解或者web.xml里的servlet-mapping。匹配到目标 Servlet 后Servlet 容器创建一份HttpServletRequest对象封装请求行、请求头、请求体和一份HttpServletResponse对象用来承载响应数据。调用 Servlet 实例的service()方法service()根据请求方式是 GET 还是 POST自动调用对应的doGet()或doPost()。你的业务代码跑完后容器把resp里写过的东西组装成 HTTP 响应报文返回给浏览器然后回收这次请求的 request/response 对象。这里有一个很重要的认知Servlet 本身在容器里是单实例多线程的所有请求共享同一个 Servlet 实例但每次请求都会创建独立的 request/response 对象。所以你在 Servlet 里定义的成员变量如果有状态并发下会出问题而存在 request 里的数据天然是线程隔离的。这个点现在不理解也没关系学并发和状态管理时会反复碰到。1.3 IDEA 2026 创建 JavaWeb 项目的环境铺垫想做请求响应实验首先得有一个能跑起来的项目。以 IDEA 2026 为例新建项目时选择 Web 项目或者 Maven 的 webapp 骨架关键不是选哪个模板而是要把三件事确认清楚JDK 和 Tomcat 版本匹配现在很多新项目直接用 Tomcat 10对应的是jakarta.servlet包名不是老教程里的javax.servlet。直接复制网上老代码会出现Cannot resolve symbol javax。Tomcat 配置在 Run/Debug Configurations 中新增 Tomcat Server把本地解压好的 Tomcat 路径指过去。Deployment 部署把构建产物 Artifact 加到 Tomcat 的 Deployment 里Application context 建议改成明确的路径比如/javaweb_demo。改完之后访问地址就是http://localhost:8080/javaweb_demo/。环境通了之后再学请求响应每写一个功能都能立刻在浏览器里验证效果比死记结论强太多。2. HttpServletRequest请求参数的三种取法与封装思路2.1 getParameter 与 getParameterValues单值和多值的区别实际开发中最常打交道的请求参数大多来自表单。假设有一个注册页面里面有用户名文本框和爱好复选框form action/javaweb_demo/register methodpost 用户名input typetext nameusernamebr 爱好 input typecheckbox namehobby valuejavaJava input typecheckbox namehobby valuemysqlMySQL input typecheckbox namehobby valuevueVue br input typesubmit value注册 /form后端接收时要注意区分两类String username req.getParameter(username); String[] hobbies req.getParameterValues(hobby);getParameter(username)按照参数名取一个值适合单值参数。如果同一个名字提交了多个值这个方法只返回第一个。getParameterValues(hobby)返回 String 数组专门处理复选框、多选下拉这种同名多值场景。一个特别坑的细节当参数不存在时getParameter返回的是null不是空字符串。在实际项目中我见过不少新手直接拿返回值去和做比较结果出现 NPE 或者判断逻辑失效。正确做法是先判空比如if (username null || username.isEmpty())。2.2 getParameterMap参数全量取回的进阶玩法除了单取和数组取还可以一次性把所有参数全拿出来MapString, String[] parameterMap req.getParameterMap();这个 Map 的 key 是参数名value 是 String 数组。看着简单但它有两个非常实用的价值。第一可以用它打印完整的参数日志排查问题特别方便parameterMap.forEach((k, v) - System.out.println(k Arrays.toString(v)));第二它是很多框架做参数绑定的基础。后面你接触 SpringMVC 时会发现它能自动把请求参数填充到方法入参的 JavaBean 里底层逻辑就是从这样一个 Map 出发按属性名做映射。理解了getParameterMap()再去看框架的源码会豁然开朗。2.3 参数到 JavaBean 的封装从手写到 BeanUtils如果表单字段很少手动取值不觉得什么。但字段一多比如联系人表单有十来个字段每个字段都getParameter再setXxx代码会非常啰嗦User user new User(); user.setUsername(req.getParameter(username)); user.setPassword(req.getParameter(password)); user.setAge(Integer.parseInt(req.getParameter(age))); user.setAddress(req.getParameter(address)); // 后面还有别的字段每个都这样写更优雅的方式是用 Apache 的 BeanUtils 工具一行完成封装User user new User(); BeanUtils.populate(user, req.getParameterMap());使用前需要引入依赖dependency groupIdcommons-beanutils/groupId artifactIdcommons-beanutils/artifactId version1.9.4/version /dependencypopulate的原理很简单遍历参数 Map用参数名去匹配 User 类的属性名如果匹配上就调用对应的 setter 把值填进去。它在内部会把 String 类型的参数自动转成目标类型比如 String 转 int。不过有三个前提要注意User 类必须有无参构造方法属性要提供标准的 getter/setter参数名必须和属性名完全一致否则对应字段会填不进去。使用 BeanUtils 之后Servlet 里处理参数的代码量至少减一半而且后续字段增减不用改 Servlet只改 JavaBean 就行。虽然现在很多项目已经用 SpringMVC 或 Spring Boot 了但理解这个封装思想对你读懂框架的请求参数绑定机制非常有帮助。3. 中文乱码这块硬骨头请求和响应分开治3.1 POST 请求乱码的根因和 setCharacterEncoding 的时机中文乱码是 JavaWeb 新手最容易栽的坑而且请求乱码和响应乱码是两码事处理方式完全不同。先说 POST 请求。浏览器在提交表单时会按照当前页面的编码通常是 UTF-8把参数编码成字节写给请求体。但 Tomcat 收到请求体后默认用 ISO-8859-1 去解码。ISO-8859-1 是单字节字符集一个 UTF-8 汉字占 3 个字节结果被拆成三个“不认识”的拉丁字符自然就乱套了。解决办法是告诉 Tomcat 请求体用什么字符集解码request.setCharacterEncoding(UTF-8);这句话有两个关键点。第一它只对请求体有效对 GET 请求 URL 里的参数无效因为 GET 参数不经过请求体。第二它必须出现在第一次读取参数之前最好放在doPost方法的第一行。如果你先调用了req.getParameter()Tomcat 已经按 ISO-8859-1 把参数解析完了这时候再设置编码就晚了。所以doPost里我的习惯写法是Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); // 之后再 getParameter 才不会乱 }3.2 GET 请求乱码的差异Tomcat 8 前后完全不同GET 请求的参数是拼在 URL 的查询字符串里的Tomcat 在解析 URL 时使用server.xml里配置的URIEncoding来解码。这个配置在 Tomcat 版本之间变化很大Tomcat 7 及更早版本默认URIEncoding是 ISO-8859-1所以 GET 请求中文参数很容易乱码。Tomcat 8.0 开始默认URIEncoding改成了 UTF-8GET 请求中文参数基本不会再乱。老代码里经常能看到这种手动转换的写法String name req.getParameter(name); name new String(name.getBytes(ISO-8859-1), UTF-8);这是在 Tomcat 7 时代的通用解法先把错误解码的字节还原回来再按 UTF-8 重新解码。如果你现在用的是 Tomcat 8加这一行反而可能把正常的中文搞乱。这也是为什么看到网上老教程里的乱码处理代码不建议直接照抄要先确认你本地的 Tomcat 版本。3.3 响应乱码setContentType 为什么必须写最前面请求乱码解决的是“服务端拿到什么数据”的问题响应乱码解决的是“浏览器显示什么内容”的问题。两者经常同时出现但本质上不是一回事。响应输出文字时我们写的是resp.setContentType(text/html;charsetUTF-8);这一行写对位置很关键。它做了两件事一是往响应头里写Content-Type: text/html;charsetUTF-8告诉浏览器用 UTF-8 来解码响应体二是让resp.getWriter()输出的字符流按 UTF-8 编码字节。也就是说它同时控制了服务端的编码和浏览器的解码。所以必须在调用getWriter()之前设置。如果先拿输出流写了内容再 setContentType已经写出去的内容编码方式已经定了后面的设置对已经输出的内容没有意义。3.4 实测排查乱码的完整链路结合我自己的踩坑经历遇到乱码时最忌讳东改一下西改一下。一定要先判断是哪一类乱码再精准下手。一个完整的排查顺序是这样打开浏览器开发者工具F12切到 Network 面板刷新页面点击具体请求。看 Request Headers 或 Form Data 里中文参数有没有乱。如果乱是请求乱码。POST 就检查代码里request.setCharacterEncoding(UTF-8)是否在 getParameter 之前GET 就检查 Tomcat 版本和server.xml的URIEncoding。如果请求没问题但页面显示乱码就是响应乱码。点开 Response Headers看有没有Content-Type: text/html;charsetUTF-8。没有的话检查setContentType是否在getWriter()之前执行。还有一种容易混淆的情况浏览器正常、IDEA 控制台打印乱码那不是请求响应的问题是 IDEA 控制台本身的显示编码没设成 UTF-8不要往代码里瞎加转换。我自己最初卡了很长时间的就是把“IDEA 控制台乱码”和“页面乱码”当成同一个问题处理结果越改越乱。分清类型之后乱码问题其实就是几个固定位置的固定写法。4. HttpServletResponse字符流与字节流的选择题4.1 getWriter 与 getOutputStream 的区别和运用场景HttpServletResponse给开发者提供了两个写出响应内容的流理解它们的适用场景很重要getWriter()返回PrintWriter输出的是字符。适合 HTML、JSON、XML 这些文本内容。getOutputStream()返回ServletOutputStream输出的是字节。适合图片、文件压缩包、PDF 等二进制数据。它们的边界划得很死一次请求里两个流不能同时使用。因为底层是同一个响应体谁先调用了另一个再用就可能会抛IllegalStateException或者拿不到数据。实际开发中绝大多数 API 接口返回 JSON 用getWriter()就够了文件下载才需要走getOutputStream()。比如返回一个 JSON 字符串resp.setContentType(application/json;charsetUTF-8); resp.getWriter().write({\code\:0,\msg\:\操作成功\});setContentType要写在获取输出流之前和第三章节说的一样这行同时决定了响应头和字符流的编码。4.2 设置响应头从 Content-Type 到文件下载平时写代码时可能只关注响应体内容不太在意响应头。其实浏览器很多关键行为都是读响应头来决定的。最常用的是Content-Type告诉浏览器响应体是什么类型。常见的有Content-Type含义text/html;charsetUTF-8HTML 页面application/json;charsetUTF-8JSON 数据image/pngPNG 图片application/octet-stream二进制文件流一般用于下载除了Content-Type还有几个响应头值得了解Content-Disposition控制浏览器是展示内容还是下载附件。Refresh让页面定时跳转比如3;url/login.jsp表示 3 秒后跳转。Location配合状态码 302浏览器会跳转到指定地址。sendRedirect()实际上就是在底层帮你设置了 302 和 Location。响应状态码也建议顺手记几个200 表示成功302 表示重定向404 表示资源不存在500 表示服务端内部出错。排错时看到状态码基本能定位一半问题。4.3 文件下载功能一个最常用的综合场景文件下载是响应头设置和字节流输出结合的经典场景。先上代码WebServlet(/download) public class DownloadServlet extends HttpServlet { Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String fileName JavaWeb笔记.txt; resp.setContentType(application/octet-stream); resp.setHeader(Content-Disposition, attachment;filename URLEncoder.encode(fileName, UTF-8)); ServletOutputStream out resp.getOutputStream(); FileInputStream fis new FileInputStream(D:/files/ fileName); byte[] buffer new byte[1024]; int len; while ((len fis.read(buffer)) ! -1) { out.write(buffer, 0, len); } fis.close(); out.close(); } }这段代码有三个细节容易踩坑。第一Content-Disposition写成attachment表示弹出“下载”框。如果你改成inline浏览器会尝试直接打开附件内容对于 txt、图片这类文件效果就是直接展示而不是下载。第二文件名里有中文时必须用URLEncoder.encode(fileName, UTF-8)编码后再拼到响应头里。不编码的话下载对话框里文件名大概率是乱码甚至请求失败。第三用完流要关闭而且注意关闭顺序先关文件输入流再关响应输出流。实际操作时我更推荐用 try-with-resources 或者 finally 块来确保关闭防止连接未释放。5. 请求转发与重定向服务端跳转和客户端跳转的本质差异5.1 两种跳转的底层机制拆解请求转发和重定向是两个外观相似、底层完全不同的跳转方式。很多新手在二选一时拿不准其实是没真正理解它们的机制。请求转发的代码是req.getRequestDispatcher(/user/detail.jsp).forward(req, resp);它发生在服务端内部。客户端先把请求发给 ServletServlet 拿到 request 和 response 对象后不做任何回应而是直接把请求“转交”给另一个资源比如另一个 Servlet 或 JSP。整个过程浏览器是不知道的它只发了一个请求也只收到一个响应。所以地址栏不变。重定向的代码是resp.sendRedirect(req.getContextPath() /login.jsp);它分两步。第一步服务端返回一个 302 状态码响应头里带上 Location 字段告诉浏览器“你要的资源在别处去这里找”。第二步浏览器拿到 302 后主动向 Location 里的地址再发起一次全新的 GET 请求。整个过程发生了两次请求地址栏也会变成新地址。这就引出了一个常见错误重定向的地址最好用req.getContextPath()拼接上下文路径。如果你直接写/login.jsp浏览器会把这个路径理解为站点根目录下的资源很容易 404。请求转发则正好相反它的路径是相对于当前 Web 应用根的不用加 ContextPath。5.2 表格对比转发和重定向的六项关键区别用一张表把核心差异说清楚对比维度请求转发 forward重定向 sendRedirect地址栏不变化会变成新地址浏览器感知不感知感知收到 302 后重新请求请求次数1 次2 次request 域数据可以共享丢失因为是新请求跳转范围只能当前应用内可以跨应用甚至跨域名响应状态码默认 200302最关键的一条是 request 域数据的可用性。你往req.setAttribute(key, value)里放的数据只要在转发目标资源里就能取出来但重定向之后request 对象已经是一个全新的对象了原来的数据全没了。如果业务里必须把查询结果在跳转后的页面里展示重定向会直接翻车。5.3 业务场景怎么选登录跳转、表单防重复提交实际项目里选哪种不是凭喜好而是看业务需求。典型的场景是表单提交后跳转。如果用户在注册页提交 POST 请求后你用转发跳转到成功页地址栏还是原来的注册地址用户按 F5 刷新浏览器会再次提交表单造成重复数据。这时候应该用重定向POST 请求返回 302浏览器跳到全新地址再刷新也只是 GET 成功页不会重复提交。典型场景二是查询结果展示。Servlet 查询出数据后想展示到 JSP 页面就必须用转发因为要把数据放到 request 域里带过去。如果用重定向request 域数据丢了页面只能拿到空的集合或者报空指针。还有一个小技巧WEB-INF目录下的资源外部浏览器没法直接访问但请求转发可以访问到。利用这一点可以把一些只允许服务端跳转进入的 JSP 页面放进WEB-INF防止用户绕过 Servlet 直接访问页面相当于一层轻量级的访问控制。6. 串一条完整链路请求参数 Servlet MySQL 用户查询6.1 建表和 JDBC 工具类准备前面零散的知识点到这里串成一个完整的真实案例页面提交关键词Servlet 接收参数去 MySQL 里模糊查询用户然后把结果响应给页面。这个案例覆盖了请求参数获取、请求转发、request 域传递、JDBC 查询、响应输出是一套很标准的 JavaWeb 小业务闭环。先建数据库和表CREATE DATABASE javaweb_demo DEFAULT CHARACTER SET utf8mb4; USE javaweb_demo; CREATE TABLE tb_user ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, age INT, address VARCHAR(100) ); INSERT INTO tb_user(name, age, address) VALUES (张三, 24, 北京), (李四, 30, 上海), (王五, 28, 广州);接着写一个 JDBC 工具类。为了代码简单直接用静态块加载驱动方法里用 try-with-resources 管理连接避免手动 close 忘写。public class JdbcUtils { static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection( jdbc:mysql://localhost:3306/javaweb_demo?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8, root, 123456); } }注意连接串里的characterEncodingutf8同样是在解决编码问题它保证的是 JDBC 驱动读写 MySQL 时使用 UTF-8不乱码。6.2 Servlet 接收参数并查询数据库建一个 User 类和 DAO。DAO 里用PreparedStatement做 LIKE 模糊查询比直接拼接 SQL 安全能避免 SQL 注入隐患。public class UserDao { public ListUser findByKeyword(String keyword) { ListUser users new ArrayList(); String sql SELECT * FROM tb_user WHERE name LIKE ?; try (Connection conn JdbcUtils.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, % keyword %); try (ResultSet rs ps.executeQuery()) { while (rs.next()) { User user new User(); user.setId(rs.getInt(id)); user.setName(rs.getString(name)); user.setAge(rs.getInt(age)); user.setAddress(rs.getString(address)); users.add(user); } } } catch (SQLException e) { throw new RuntimeException(e); } return users; } }然后写核心的 ServletWebServlet(/user/list) public class UserListServlet extends HttpServlet { private UserDao userDao new UserDao(); Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType(text/html;charsetUTF-8); String keyword req.getParameter(keyword); if (keyword null) { keyword ; } req.setAttribute(users, userDao.findByKeyword(keyword)); req.getRequestDispatcher(/list.jsp).forward(req, resp); } }这里要注意几个细节req.getParameter(keyword)在 URL 没有带参数时返回 null所以先处理成空字符串避免 SQL 里出现LIKE %%查询出全部数据时页面提示不清楚。查询结果放在 request 域里然后用转发跳到 JSP因为重定向会丢失 request 域数据这一点上一章刚强调过。JSP 页面用 JSTL 遍历输出% page contentTypetext/html;charsetUTF-8 languagejava % % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % html body h3用户列表关键词${param.keyword}/h3 table border1 tr thID/thth姓名/thth年龄/thth地址/th /tr c:forEach items${users} varu tr td${u.id}/td td${u.name}/td td${u.age}/td td${u.address}/td /tr /c:forEach /table /body /html如果用 JSTL项目里需要引入 jstl 依赖并且在页面里加 taglib 指令否则c:forEach无法识别。在 IDEA 里创建的支持 JSP 的 Web 项目一般也要手动补这个依赖。6.3 借助浏览器开发者工具实测请求响应细节代码写完跑起来。访问http://localhost:8080/javaweb_demo/user/list?keyword张按 F12 打开 Network 面板能看到这次请求的完整信息。在 General 区域可以看到 Request URL 和 Status Code 是 200。在 Request Headers 里能看到 User-Agent、Accept、Cookie 等字段。因为你传的是中文张看 Query String Parameters 里会显示keyword: 张如果在 Tomcat 8 上这里正常显示中文说明 GET 请求的 URI 编码没有问题。再点开 Response Headers能看到Content-Type: text/html;charsetUTF-8这就是resp.setContentType(text/html;charsetUTF-8)写进去的。页面能正常显示中文说明服务端的响应编码和浏览器的解码方式一致。如果只是手动改 URL 测试不够方便还可以用 Postman 或者 IDEA 自带的 HTTP Client 来发请求。特别是排查重定向时用 Postman 能直观看到客户端先收到一个 302 响应然后自动跟着 Location 再发一个新的请求两条记录清清楚楚比背多少概念都管用。最后再分享一个小技巧我自己刚开始练习请求响应时会把每个请求里常见的关键信息打印到控制台比如请求方法、URI、参数、响应状态码。在 Servlet 里加几行日志配合 F12 对比观察很快就能建立“代码写了什么 - 报文里看到了什么”的对应关系。这个习惯帮我少走了不少弯路建议你也在练习时试试。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号