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

中北萌新程序员 2024-07-06 14:03:02 阅读 99

目录:

一. 问题引入二 解决问题

一. 问题引入

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

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

在这里插入图片描述

下面是这部分内容对应的代码

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

<code>

<!-- Contract archiving form -->

<form id="contractArchivingForm" class="bg-light p-3" action="file.do" method="post" enctype="multipart/form-data" >code>

<input type="hidden" name="flag" value="insert"/>code>

<div class="form-group">code>

<label for="contractName">合同名称</label>code>

<input type="text" class="form-control" id="contractName" name="contractName" placeholder="输入合同名称" required>code>

</div>

<div class="form-group">code>

<label for="contractCategory">合同类别</label>code>

<select class="form-control" id="contractCategory" name="contractCategory">code>

<option>租赁协议</option>

<option>销售合同</option>

<option>服务协议</option>

<!-- More contract categories can be added as needed -->

</select>

</div>

<div class="form-group">code>

<label for="contractFileUpload">上传合同文件</label>code>

<input type="file" class="form-control-file" id="contractFileUpload" name="contractFileUpload" required>code>

<small class="form-text text-muted">请上传PDF格式的文件,大小不超过10MB。</small>code>

</div>

<div class="form-group form-check">code>

<input type="checkbox" class="form-check-input" id="agreement">code>

<label class="form-check-label" for="agreement">我确认合同信息准确无误,并同意归档。</label>code>

</div>

<input type="submit" class="btn btn-primary" value="归档合同" >code>

</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 {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

super.doPost(req, resp);

}

@Override

protected 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转换为String

String 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 对应的值。

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

<code>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 {

@Override

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

super.doPost(req, resp);

}

@Override

protected 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转换为String

String formattedDateTime = currentDateTime.format(formatter);

fileInfo.setFiletime(formattedDateTime);

System.out.println(fileInfo);

// 处理完毕后重定向或者显示成功消息

response.sendRedirect("guidang.html");

}

}

即:添加 @MultipartConfig 注解。

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

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。