最近写javaweb出现的一个小bug---前端利用 form 表单传多项数据,后端 Servlet 取出的各项数据均为空

目录:

  • 一. 问题引入
  • 二 解决问题

一. 问题引入

近在写一个 java web 项目时,遇到一个让我头疼了晚上的问题:前端通过 post 提交的 form 表单数据可以传到后端,但当我从 Servlet 中通过 request.getParameter(“name”) 拿取各项数据时,得到的内容均为 Null !

为便于读者理解,我先描述下当前的业务场景:弹窗界面用于提示录入合同名称,合同类型和合同文件(这些信息将被组织在一个 form 表单中)。在点击 “归档合同” 后,该 form 表单会提交全部数据至后台,并将这些数据存放至数据库中。
在这里插入图片描述
下面是这部分内容对应的代码

前端代码(仅展示 form 表单和对应的 JS 代码):

<!-- Contract archiving form --><form id="contractArchivingForm" class="bg-light p-3" action="file.do" method="post" enctype="multipart/form-data" ><input type="hidden" name="flag" value="insert"/><div class="form-group"><label for="contractName">合同名称</label><input type="text" class="form-control" id="contractName"  name="contractName" placeholder="输入合同名称" required></div><div class="form-group"><label for="contractCategory">合同类别</label><select class="form-control" id="contractCategory" name="contractCategory"><option>租赁协议</option><option>销售合同</option><option>服务协议</option><!-- More contract categories can be added as needed --></select></div><div class="form-group"><label for="contractFileUpload">上传合同文件</label><input type="file" class="form-control-file" id="contractFileUpload" name="contractFileUpload" required><small class="form-text text-muted">请上传PDF格式的文件,大小不超过10MB。</small></div><div class="form-group form-check"><input type="checkbox" class="form-check-input" id="agreement"><label class="form-check-label" for="agreement">我确认合同信息准确无误,并同意归档。</label></div><input type="submit" class="btn btn-primary" value="归档合同" ></form>

后端代码

package com.jjy.web.servlet;import com.jjy.pojo.FileInfo;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@WebServlet("/file.do")
public class FileInfoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String flag = req.getParameter("flag");System.out.println("未进入"+flag);if ("insert".equals(flag)) {System.out.println(flag);insertFileinfo(req, resp);}}private void insertFileinfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String contractName = request.getParameter("contractName");String contractCategory = request.getParameter("contractCategory");FileInfo fileInfo = new FileInfo();Part part = request.getPart("contractFileUpload");//通过Part对象得到上传的文件名String fileName = part.getSubmittedFileName();System.out.println("上传文件名:" + fileName);//得到文件存放的路径String filePath = request.getServletContext().getRealPath("/");System.out.println("文件存放路径:" + filePath);part.write(filePath + "/" + fileName);fileInfo.setFilename(contractName);fileInfo.setFiletype(contractCategory);LocalDateTime currentDateTime = LocalDateTime.now();// 定义日期时间格式DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 将LocalDateTime转换为StringString formattedDateTime = currentDateTime.format(formatter);fileInfo.setFiletime(formattedDateTime);System.out.println(fileInfo);// 处理完毕后重定向或者显示成功消息response.sendRedirect("guidang.html");}
}

以上代码的逻辑很清晰:
1、前端获取输入;
2、后端拿取输入,并完成添加。

但在运行时,后端 Servlet 取出的值始终为 null:
当我用 F12 在浏览器中查看包的信息时,发现 post 请求中的确含数据!!!
在这里插入图片描述

二 解决问题

这时候通过网上查询,基本可以得到以下排错手段

1、form 表单中未写 name 属性;
2、jsp 的提交方式与 servlet 不一致(如:在 jsp 中用的 post ,但是在对应 servlet 中写的是 doGet);
3、form 表单的 enctype 属性与 servlet 不一致;
4、servlet 中的 getParameter() 参数与 form 表单不一致。

但遗憾的是,我都正确配置了这些参数,可取出的就是 null 。

最后发现

在前端用了 multipart/form-data 封装 form 表单数据,后端接受到的数据是一个含文本、二进制数据的复杂数据对象,这时候肯定不能直接通过 getParameter() 获取。因为 getParameter() 方法是不能对这种 “打包数据对象” 进行解析的。这时候最简单的解决办法就是在 servlet 处添加 @MultipartConfig 注解,以告知 servlet,此时接受到的数据是同时含文本、二进制数据的,需要在 getParameter() 前进行适当预处理。这样一来, getParameter() 才能从前端发来的数据对象中正确解析出各项 name 对应的值。

所以,正确的后端代码应改为:

package com.jjy.web.servlet;import com.jjy.pojo.FileInfo;import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@MultipartConfig
@WebServlet("/file.do")
public class FileInfoServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {super.doPost(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String flag = req.getParameter("flag");System.out.println("未进入"+flag);if ("insert".equals(flag)) {System.out.println(flag);insertFileinfo(req, resp);}}private void insertFileinfo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String contractName = request.getParameter("contractName");String contractCategory = request.getParameter("contractCategory");FileInfo fileInfo = new FileInfo();Part part = request.getPart("contractFileUpload");//通过Part对象得到上传的文件名String fileName = part.getSubmittedFileName();System.out.println("上传文件名:" + fileName);//得到文件存放的路径String filePath = request.getServletContext().getRealPath("/");System.out.println("文件存放路径:" + filePath);part.write(filePath + "/" + fileName);fileInfo.setFilename(contractName);fileInfo.setFiletype(contractCategory);LocalDateTime currentDateTime = LocalDateTime.now();// 定义日期时间格式DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");// 将LocalDateTime转换为StringString formattedDateTime = currentDateTime.format(formatter);fileInfo.setFiletime(formattedDateTime);System.out.println(fileInfo);// 处理完毕后重定向或者显示成功消息response.sendRedirect("guidang.html");}
}

即:添加 @MultipartConfig 注解。

这时,所有的数据均能正确地取出!

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/36860.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【小沐学AI】Python实现语音识别(faster-whisper-webui)

文章目录 1、简介1.1 whisper1.2 faster-whisper 2、安装3、测试结语 1、简介 1.1 whisper https://github.com/openai/whisper Whisper 是一种通用语音识别模型。它是在各种音频的大型数据集上训练的&#xff0c;也是一个多任务模型&#xff0c;可以执行多语言语音识别、语音…

软考初级网络管理员_04_硬件单选题

1.进程是程序的一次执行&#xff0c;()是进程存在的唯一标志。 程序 数据 进程控制块 进程标识符 2.(请作答此空)是计算机内部运算部件一次能同时处理的二进制数据位数。计算机的运行速度使用每秒钟所能执行的()指令数目来评估。 字长 带宽 内存 寄存器 3.某银行的一…

安装ant-design-vue的报错集合

20240629vue版本&#xff1a;4.x vue/cli5.x运行项目报错error Replace xxx with xxx prettier/prettier 解决办法_replace 路路路路路路路路 with 路路路路-CSDN博客 Ant Design 使用出现 Error_ Can‘t resolve ‘_antd_dist_antd.css‘-CSDN博客

【JVM基础篇】垃圾回收

文章目录 垃圾回收常见内存管理方式手动回收&#xff1a;C内存管理自动回收(GC)&#xff1a;Java内存管理自动、手动回收优缺点 应用场景垃圾回收器需要对哪些部分内存进行回收&#xff1f;不需要垃圾回收器回收需要垃圾回收器回收 方法区的回收代码测试手动调用垃圾回收方法Sy…

Matlab|分时电价环境下用户负荷需求响应分析方法

主要内容 本程序复现《分时电价环境下用户负荷需求响应分析方法》文献中的方法&#xff0c;通过用户对不同时间下用电需求的自弹性和交叉弹性系数分析获得用户需求响应矩阵&#xff0c;进而利用该矩阵对用户在实行基于电价的需求侧管理后的负荷变化情况进行快速分析。 1.1…

Linux 文件系统详解:ext4、XFS、Btrfs

1. 引言 Linux 操作系统支持多种文件系统&#xff0c;其中 ext4、XFS 和 Btrfs 是最为常用的三种。它们各自具有独特的特点和优势&#xff0c;适用于不同的使用场景。本文将详细介绍这三种文件系统的概念、结构、使用场景以及常用命令&#xff0c;帮助读者更好地理解和使用这些…

ONLYOFFICE8.1版本桌面编辑器简单测评

ONLYOFFICE官网链接&#xff1a;在线PDF查看器和转换器 | ONLYOFFICE ONLYOFFICE介绍&#xff1a;https://www.onlyoffice.com/zh/office-suite.aspx OnlyOffice 是一款免费且开源的 Office 协作办公套件&#xff0c;支持桌面端和移动端等多平台&#xff0c;由一家领先的 IT 公…

【python】OpenCV—Aruco

文章目录 Detect ArucoGuess Aruco Type Detect Aruco 学习参考来自&#xff1a;OpenCV基础&#xff08;19&#xff09;使用 OpenCV 和 Python 检测 ArUco 标记 更多使用细节可以参考&#xff1a;【python】OpenCV—Color Correction 源码&#xff1a; 链接&#xff1a;http…

在Ubuntu 18.04上安装和配置GitLab的方法

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 简介 GitLab 是一个开源应用程序&#xff0c;主要用于托管 Git 仓库&#xff0c;并提供额外的与开发相关的功能&#xff0c;如问题跟踪…

为什么IP地址会被列入黑名单?

您是否曾经历过网站访客数量骤减或电子邮件投递失败的困扰&#xff1f;这背后或许隐藏着一个常被忽略的原因&#xff1a;您的IP地址可能已经被列入了黑名单内。尽管您并没有进行任何违法的网络操作&#xff0c;但这个问题依然可能出现。那么&#xff0c;究竟黑名单是什么&#…

PostgreSQL 性能优化与调优(六)

1. 索引优化 1.1 创建索引 索引可以显著提高查询性能。创建索引的基本语法如下&#xff1a; CREATE INDEX index_name ON table_name (column_name);例如&#xff0c;为 users 表的 username 列创建索引&#xff1a; CREATE INDEX idx_username ON users (username); 1.2 …

【VMware】VMware 开启的虚拟机无法联网的解决方案

目录 &#x1f30a;1. 问题说明 &#x1f30a;2. 解决方案 &#x1f30d;2.1 查看虚拟网络编辑器 &#x1f30d;2.2 设置 vmnet &#x1f30d;2.3 设置虚拟机网络 &#x1f30d;2.4 Xshell连接虚拟机 &#x1f30a;1. 问题说明 虚拟机 ping 其他网页显示失败,比如&#…

数据质量管理-时效性管理

前情提要 根据GB/T 36344-2018《信息技术 数据质量评价指标》的标准文档&#xff0c;当前数据质量评价指标框架中包含6评价指标&#xff0c;在实际的数据治理过程中&#xff0c;存在一个关联性指标。7个指标中存在4个定性指标&#xff0c;3个定量指标&#xff1b; 定性指标&am…

Linux内存管理--系列文章陆——可执行文件的装载

应届生面试时&#xff0c;经常会有人问程序和进程有什么区别。简单来讲&#xff0c;程序是一个静态物品&#xff0c;就是存放在磁盘上的一些预先编译好的指令和数据的文件。而进程是一种运行的实例&#xff0c;它是程序在操作系统中的一次运行活动&#xff0c;具有生命周期。进…

汇编语言中的内存管理与寻址方式

在计算机科学中&#xff0c;内存管理是确保程序和数据能够高效、安全地存储和访问的关键环节。汇编语言&#xff0c;作为最接近硬件的编程语言&#xff0c;为程序员提供了直接控制内存的能力。 内存管理基础 内存管理涉及到数据如何在内存中存储、访问和操作。在汇编语言层面…

创建一个快速、高效的网络爬虫:PHP和Selenium示例

随着互联网的不断发展&#xff0c;数据爬取已经成为了许多人的必备技能。而网络爬虫则是实现数据爬取的重要工具之一。 网络爬虫可以自动化地访问网站、获取内容、分析页面并提取所需数据。其中&#xff0c;Selenium是一款非常优秀的网络自动化测试工具&#xff0c;能够模拟真…

Window安全配置

任何本地登录的用户都属于Interactive组Ipconfig/all &#xff1a;用于显示所有网络适配器的完整TCP/IP配置信息route print&#xff1a;用于显示路由表中的当前项目tracert –d&#xff1a;禁止tracert将中间路由器的IP地址解析为名称。这样可以加速显示tracert的结果nslookup…

面向对象分析与设计

文章目录 设计的重点在于模块间的通信&#xff0c;而不在于模块的属性和方法程序就是一群对象&#xff0c;通过消息要求对方做点事情对象间相互协作(消息)以完成系统功能 设计的重点在于模块间的通信&#xff0c;而不在于模块的属性和方法 程序就是一群对象&#xff0c;通过消…

【旭日x3派】部署官方yolov5全流程

地平线旭日x3派部署yolov5--全流程 前言一、深度学习环境安装二、安装docker三、部署3.1、安装工具链镜像3.2、配置天工开物OpenExplorer工具包3.3、创建深度学习虚拟空间&#xff0c;安装依赖&#xff1a;3.4、下载yolov5项目源码并运行3.5、pytorch的pt模型文件转onnx3.6、最…

前端git约定式规范化提交-commitizen

当使用commitizen进行代码提交时&#xff0c;commitizen会提示你在提交代码时填写所必填的提交字段信息内容。 1、全局安装commitizen npm install -g commitizen4.2.4 2、安装并配置 cz-customizeable 插件 2.1 使用 npm 下载 cz-customizeable npm i cz-customizeable6.…