Dynamic Web Project GET表单创建对象及404错误排查方案
问题说明
表单提交时触发HTTP 404错误,需要实现表单参数接收、TextLog日志实例创建功能,后续还要扩展日志列表展示、数据库持久化能力。
现有代码
前端表单
<html lang="en"> <head> <title>Example</title> </head> <body> <h1>Welcome to Loggy!</h1> <form id="logForm" action="LogsServlet" method="GET"> <h3>What have you been up to today?</h3> <br> <label id="logTitleLabel" for="logTitle">Title :</label> <br> <input type="text" id="logTitle" name="logTitle"> <br> <label id="logDescriptionLabel" for="LogDescription">Description</label> <br> <input type="text" id="logDescription" name="logDescription"> <label id="logContentLabel" for="logContent">Content :</label> <br> <input type="text" id="logContent" name="logContent"> <button type="submit" id="submitLog">Submit Log</button> </form> </body> </html>
实体类代码
import java.sql.Timestamp; import java.util.Date; import java.util.UUID; public abstract class Log { private UUID id; private String title; private String description; private String content; private Timestamp createTimestamp; //Constructor Log(String title,String description, String content){ this.setTitle(title); this.description=description; this.content=content; }; public void create() { //call UUID method id(); //create new timeStamp Date date= new Date(); Timestamp createTimestamp = new Timestamp(date.getTime()); this.createTimestamp=createTimestamp; } public UUID id() { UUID uuid = UUID.randomUUID(); id = uuid; return id; } //GETTERS AND SETTERS public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public UUID getId() { return id; } public void setId(UUID id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Timestamp getCreateTimestamp() { return createTimestamp; } public void setCreateTimestamp(Timestamp createTimestamp) { this.createTimestamp = createTimestamp; } } public class TextLog extends Log { public TextLog(String title,String description, String content) { super(title,description, content); } }
Servlet代码
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class LogsServlet */ //@WebServlet(description = "Loggy Logs", urlPatterns = { "/LogsServlet" }) public class LogsServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public LogsServlet() { super(); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //set content type response.setContentType("text/html"); //get print writer PrintWriter writer = response.getWriter(); //generate content request.getParameter("logTitle"); request.getParameter("logDescription"); request.getParameter("logContent"); } }
问题修复
1. 解决404错误
404的直接原因是Servlet没有完成请求映射:代码里的@WebServlet注解被注释,容器无法把/LogsServlet请求匹配到对应Servlet类,两种修复方式二选一:
- 注解方式:去掉
@WebServlet那行的注释,确保注解里的urlPatterns = { "/LogsServlet" }配置正确,同时保证Servlet类在容器扫描的包路径下。 - 配置文件方式:在项目的
WEB-INF/web.xml中添加如下配置,替换掉你的包名为LogsServlet类的实际全路径包名:
<servlet> <servlet-name>LogsServlet</servlet-name> <servlet-class>你的包名.LogsServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LogsServlet</servlet-name> <url-pattern>/LogsServlet</url-pattern> </servlet-mapping>
2. 修正表单提交与参数处理逻辑
- 提交数据的场景不要用GET请求,把表单的
method="GET"改为method="POST",避免参数直接暴露在URL地址栏。 - 在Servlet中重写
doPost方法处理提交请求,不要把创建数据的逻辑写在doGet里。 - 调用
request.getParameter()后要用变量接收返回值,做基础非空校验后再创建TextLog实例,记得调用create()方法生成日志ID和创建时间。
修复后的doPost方法参考:
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 设置请求响应编码,避免中文乱码 request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); // 接收表单参数 String logTitle = request.getParameter("logTitle"); String logDescription = request.getParameter("logDescription"); String logContent = request.getParameter("logContent"); // 基础参数校验 if (logTitle == null || logTitle.trim().isEmpty()) { writer.write("日志标题不能为空"); return; } // 创建日志实例 TextLog textLog = new TextLog(logTitle.trim(), logDescription, logContent); textLog.create(); // 生成UUID和创建时间戳 // 临时返回提交结果,后续可替换为跳转逻辑 writer.println("<h3>日志提交成功</h3>"); writer.println("<p>日志ID:" + textLog.getId() + "</p>"); writer.println("<p>日志标题:" + textLog.getTitle() + "</p>"); writer.println("<p>创建时间:" + textLog.getCreateTimestamp() + "</p>"); }
注意:Log类的构造方法是包访问权限,要保证TextLog子类和Log类在同一个包下,否则会报编译错误。
后续功能实现指引
- 日志列表展示:初期可以把日志对象存在ServletContext域的List集合中,每次提交新日志就追加到集合里;更推荐后续用JSP+JSTL做视图层,提交完日志后通过请求转发把日志列表传到前端页面遍历渲染。
- 数据库持久化:先引入对应数据库的JDBC驱动,创建日志表,字段和Log类属性一一对应(id用字符串类型存UUID、标题/描述/内容用文本类型、创建时间用datetime/timestamp类型),封装JDBC连接工具类,创建完TextLog实例后执行INSERT语句把数据存入数据库;查询列表时执行SELECT语句把结果集封装为Log对象集合,传到前端展示即可。
- 优化点:后续可以把参数校验逻辑抽离,增加XSS过滤防止前端注入,Service层单独处理业务逻辑,和Servlet层解耦。
内容的提问来源于stack exchange,提问作者Caitlyn Gibbons
相关产品推荐
相关产品推荐

