一.
创建项目
注意:项目属性选择java 构建系统选择Maven 演示图片所用jdk版本为21.0.8

二.
连接数据库
注意:演示图片Mysql版本为9.4 确保数据库已经打开
(1)首先检查Mysql是否已经打开
同时按住win+R,显示如下界面,输入services.msc

进入后找到Mysql 显示如下界面则已经成功打开

(2)在idea中接入Mysql
在项目右侧找到DataBase按键,打开后显示如下

点击左上角加号,选择Data Source,选择其中的Mysql

打开后可以选择更改名字,然后填入User(一般为root),再输入Password(你的Mysql密码)

填完后点击下方的Test Connection,若显示如下图所示,则连接成功,点击Applay和OK后返回即可

三.
部署Tomcat
注意:演示图片所用Tomcat版本为11版
选择Project Structure创建Artifact

选择From moudles后选择此项目

上方选择Edit configurations

进入后点击左上角加号,进去后寻找Tomcat Server

application server选择你的Tomcat安装的位置

点击Deployment,选择加号添加Artifact,选择之前创建好的Artifact

四.
搭建项目结构
如下图所示

文件说明:
1.配置文件:
pom.xml :项目的Maven配置文件 定义项目的基本信息和依赖库(Servlet API、Mysql驱动 )
db.properties:数据库连接配置文件 存储数据库中的URL、用户名和密码,用于DBUtil类加载,建立和管理数据库连接
2.实体类(Bean)
Project.java:项目实体类,封装项目所有属性(项目ID、名称、位置等),提供构造方法,getter和setter方法
DBUtil.java:数据库工具类,负责数据库的创建,通过静态代码加载db.properties配置,提供getConnection()方法获取数据库连接,提供close()方法关闭数据库
3.数据访问层(DAO):
ProjectDao.java:项目数据访问对象,封装与项目相关的数据库操作,主要方法addProject():项目立项(插入数据)、getProjectByNo()根据项目编号查询项、updateProject():修改项目信息、deleteProject()删除项目、auditProject():审核项目、fuzzyQuery():多条件模糊查询项目
4.过滤器(Filter)
主要用于解决中文乱码问题,确保系统能够正确处理中文数据
5.控制器层(servlet)
MainServlet:系统的入口控制器,负责将用户请求转发到主页面
ProjectCreateServlet:处理项目立项功能,包括显示表单和提交数据
ProjectAuditServlet:处理项目审核功能,包括项目查询和审核操作
ProjectUpdateServlet:处理项目信息修改功能
ProjectDeleteServlet:处理项目删除功能
6. 视图层(JSP页面)
main.jsp:系统的主页面,提供功能菜单入口,包含四个主要功能模块的导航链接:项目立项、修改项目、删除项目、项目审核
createProject.jsp:项目立项信息录入页面
auditProject.jsp:项目审核管理页面
updateProject.jsp:项目信息更新页面
deleteProject.jsp:项目删除页面
五. 文件内容
1.bean
(1.DBUtil)
`package com.project.bean;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class DBUtil {
private static String driver;
private static String url;
private static String username;
private static String password;
static {try (InputStream is = DBUtil.class.getClassLoader().getResourceAsStream("db.properties")) {Properties prop = new Properties();prop.load(is);driver = prop.getProperty("driver");url = prop.getProperty("url");username = prop.getProperty("username");password = prop.getProperty("password");Class.forName(driver);} catch (Exception e) {throw new RuntimeException("数据库配置加载失败", e);}
}public static Connection getConnection() throws SQLException {return DriverManager.getConnection(url, username, password);
}public static void close(Connection conn, PreparedStatement pstmt, ResultSet rs) {try {if (rs != null) rs.close();if (pstmt != null) pstmt.close();if (conn != null) conn.close();} catch (SQLException e) {e.printStackTrace();}
}
}(2.Project)package com.project.bean;
import java.sql.Date;
public class Project {
private String projectId;
private String projectName;
private String projectLocation;
private String projectType;
private int totalInvestment;
private int currentInvestment;
private Date startDate;
private Date endDate;
private String constructionContent;
private int auditStatus;
private String auditOpinion;
// 构造方法
public Project(String projectId, String projectName, String projectLocation, String projectType,int totalInvestment, int currentInvestment, Date startDate, Date endDate,String constructionContent) {this.projectId = projectId;this.projectName = projectName;this.projectLocation = projectLocation;this.projectType = projectType;this.totalInvestment = totalInvestment;this.currentInvestment = currentInvestment;this.startDate = startDate;this.endDate = endDate;this.constructionContent = constructionContent;this.auditStatus = 0;this.auditOpinion = null;
}// 所有字段的 Getter/Setter 方法
public String getProjectId() { return projectId; }
public void setProjectId(String projectId) { this.projectId = projectId; }public String getProjectName() { return projectName; }
public void setProjectName(String projectName) { this.projectName = projectName; }public String getProjectLocation() { return projectLocation; }
public void setProjectLocation(String projectLocation) { this.projectLocation = projectLocation; }public String getProjectType() { return projectType; }
public void setProjectType(String projectType) { this.projectType = projectType; }public int getTotalInvestment() { return totalInvestment; }
public void setTotalInvestment(int totalInvestment) { this.totalInvestment = totalInvestment; }public int getCurrentInvestment() { return currentInvestment; }
public void setCurrentInvestment(int currentInvestment) { this.currentInvestment = currentInvestment; }public Date getStartDate() { return startDate; }
public void setStartDate(Date startDate) { this.startDate = startDate; }public Date getEndDate() { return endDate; }
public void setEndDate(Date endDate) { this.endDate = endDate; }public String getConstructionContent() { return constructionContent; }
public void setConstructionContent(String constructionContent) { this.constructionContent = constructionContent; }public int getAuditStatus() { return auditStatus; }
public void setAuditStatus(int auditStatus) { this.auditStatus = auditStatus; }public String getAuditOpinion() { return auditOpinion; }
public void setAuditOpinion(String auditOpinion) { this.auditOpinion = auditOpinion; }
}`
2.dao
(ProjectDao)
`package com.project.dao;
import com.project.bean.DBUtil;
import com.project.bean.Project;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class ProjectDao {
// 项目立项(插入数据)
public boolean addProject(Project project) throws SQLException {
String sql = "INSERT INTO project (project_id, project_name, project_location, project_type, " +
"total_investment, current_investment, start_date, end_date, construction_content, " +
"audit_status, audit_opinion) " +
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = DBUtil.getConnection();
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, project.getProjectId());
pstmt.setString(2, project.getProjectName());
pstmt.setString(3, project.getProjectLocation());
pstmt.setString(4, project.getProjectType());
pstmt.setInt(5, project.getTotalInvestment());
pstmt.setInt(6, project.getCurrentInvestment());
pstmt.setDate(7, project.getStartDate());
pstmt.setDate(8, project.getEndDate());
pstmt.setString(9, project.getConstructionContent());
pstmt.setInt(10, project.getAuditStatus());
pstmt.setString(11, project.getAuditOpinion());
return pstmt.executeUpdate() > 0;
} finally {
DBUtil.close(conn, pstmt, null);
}
}
// 根据项目编号查询项目
public Project getProjectByNo(String projectId) throws SQLException {String sql = "SELECT * FROM project WHERE project_id = ?";Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;try {conn = DBUtil.getConnection();pstmt = conn.prepareStatement(sql);pstmt.setString(1, projectId);rs = pstmt.executeQuery();if (rs.next()) {Project project = new Project(rs.getString("project_id"),rs.getString("project_name"),rs.getString("project_location"),rs.getString("project_type"),rs.getInt("total_investment"),rs.getInt("current_investment"),rs.getDate("start_date"),rs.getDate("end_date"),rs.getString("construction_content"));project.setAuditStatus(rs.getInt("audit_status"));project.setAuditOpinion(rs.getString("audit_opinion"));return project;}return null;} finally {DBUtil.close(conn, pstmt, rs);}
}// 修改项目(仅更新未审核项目的非关键字段)
public boolean updateProject(Project project) throws SQLException {String sql = "UPDATE project SET current_investment = ?, start_date = ?, end_date = ?, " +"construction_content = ? WHERE project_id = ? AND audit_status = 0";Connection conn = null;PreparedStatement pstmt = null;try {conn = DBUtil.getConnection();pstmt = conn.prepareStatement(sql);pstmt.setInt(1, project.getCurrentInvestment());pstmt.setDate(2, project.getStartDate());pstmt.setDate(3, project.getEndDate());pstmt.setString(4, project.getConstructionContent());pstmt.setString(5, project.getProjectId());return pstmt.executeUpdate() > 0;} finally {DBUtil.close(conn, pstmt, null);}
}// 删除项目(仅删除未审核项目)
public boolean deleteProject(String projectId) throws SQLException {String sql = "DELETE FROM project WHERE project_id = ? AND audit_status = 0";Connection conn = null;PreparedStatement pstmt = null;try {conn = DBUtil.getConnection();pstmt = conn.prepareStatement(sql);pstmt.setString(1, projectId);return pstmt.executeUpdate() > 0;} finally {DBUtil.close(conn, pstmt, null);}
}// 审核项目(更新审核状态与意见)
public boolean auditProject(String projectId, int auditStatus, String auditOpinion) throws SQLException {String sql = "UPDATE project SET audit_status = ?, audit_opinion = ? WHERE project_id = ?";Connection conn = null;PreparedStatement pstmt = null;try {conn = DBUtil.getConnection();pstmt = conn.prepareStatement(sql);pstmt.setInt(1, auditStatus);pstmt.setString(2, auditOpinion);pstmt.setString(3, projectId);return pstmt.executeUpdate() > 0;} finally {DBUtil.close(conn, pstmt, null);}
}// 多条件模糊查询项目
public List<Project> fuzzyQuery(String projectId, String projectName) throws SQLException {String sql = "SELECT * FROM project WHERE 1=1";List<Object> params = new ArrayList<>();if (projectId != null && !projectId.isEmpty()) {sql += " AND project_id LIKE ?";params.add("%" + projectId + "%");}if (projectName != null && !projectName.isEmpty()) {sql += " AND project_name LIKE ?";params.add("%" + projectName + "%");}Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;List<Project> projectList = new ArrayList<>();try {conn = DBUtil.getConnection();pstmt = conn.prepareStatement(sql);for (int i = 0; i < params.size(); i++) {pstmt.setObject(i + 1, params.get(i));}rs = pstmt.executeQuery();while (rs.next()) {Project project = new Project(rs.getString("project_id"),rs.getString("project_name"),rs.getString("project_location"),rs.getString("project_type"),rs.getInt("total_investment"),rs.getInt("current_investment"),rs.getDate("start_date"),rs.getDate("end_date"),rs.getString("construction_content"));project.setAuditStatus(rs.getInt("audit_status"));project.setAuditOpinion(rs.getString("audit_opinion"));projectList.add(project);}return projectList;} finally {DBUtil.close(conn, pstmt, rs);}
}
}`
3.filter
(CharacterEncodingFilter)
`package com.project.filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import java.io.IOException;
/**
-
自定义字符编码过滤器
-
用于解决中文乱码问题
*/
public class CharacterEncodingFilter implements Filter {
private String encoding = "UTF-8";@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 从web.xml中获取编码参数
String encodingParam = filterConfig.getInitParameter("encoding");
if (encodingParam != null && !encodingParam.trim().isEmpty()) {
this.encoding = encodingParam;
}
}@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 设置请求和响应的字符编码
request.setCharacterEncoding(encoding);
response.setCharacterEncoding(encoding);
response.setContentType("text/html;charset=" + encoding);// 继续执行过滤器链chain.doFilter(request, response);}
@Override
public void destroy() {
// 过滤器销毁时的清理工作
}
}`
4.servlet
(1.MainServlet)
`package com.project.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/main")
public class MainServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("main.jsp").forward(req, resp);
}
}`
(2.ProjectAuditServlet)
`package com.project.servlet;
import com.project.bean.Project;
import com.project.dao.ProjectDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
@WebServlet("/auditProject")
public class ProjectAuditServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(ProjectAuditServlet.class);
private final ProjectDao projectDao = new ProjectDao();
// 处理GET请求:显示审核页面,支持多条件模糊查询
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");// 获取查询条件(项目编号、项目名称,支持模糊查询)String projectId = req.getParameter("projectId");String projectName = req.getParameter("projectName");List<Project> projectList = null;String errorMsg = "";try {// 调用DAO执行模糊查询(无条件时查询所有项目)projectList = projectDao.fuzzyQuery(projectId, projectName);} catch (SQLException e) {logger.error("项目查询异常", e);errorMsg = "查询失败:系统错误,请重试";}// 回显查询条件和结果到页面req.setAttribute("projectList", projectList);req.setAttribute("errorMsg", errorMsg);req.setAttribute("echoProjectId", projectId);req.setAttribute("echoProjectName", projectName);req.getRequestDispatcher("auditProject.jsp").forward(req, resp);
}// 处理POST请求:执行审核操作(同意/不同意)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=UTF-8");// 获取审核参数String projectId = req.getParameter("projectId");String auditStatusStr = req.getParameter("auditStatus"); // 1-同意,2-不同意String auditOpinion = req.getParameter("auditOpinion");String errorMsg = "";String successMsg = "";// 参数校验if (projectId == null || projectId.isEmpty() || auditStatusStr == null) {errorMsg = "参数错误:未指定项目或审核状态";} else {try {int auditStatus = "1".equals(auditStatusStr) ? 1 : 0; // 1-已审核(同意),0-未审核(逻辑保留,实际用状态区分)// 不同意时必须填写审核意见if ("2".equals(auditStatusStr) && (auditOpinion == null || auditOpinion.trim().isEmpty())) {errorMsg = "审核不同意时,必须填写审核意见";} else {// 执行审核(更新审核状态为1,无论同意/不同意均标记为“已审核”)boolean isAudited = projectDao.auditProject(projectId,1, // 审核状态:1-已审核(区分于0-未审核)"1".equals(auditStatusStr) ? "同意" : auditOpinion // 同意时意见为“同意”,不同意时为用户输入);if (isAudited) {successMsg = "项目【" + projectId + "】审核成功";} else {errorMsg = "审核失败:项目不存在或已被删除";}}} catch (SQLException e) {logger.error("项目审核异常", e);errorMsg = "审核失败:系统错误,请重试";}}// 审核后重新查询并跳转回审核页面,显示结果req.setAttribute("successMsg", successMsg);req.setAttribute("errorMsg", errorMsg);// 回显查询条件(保持用户之前的查询状态)req.setAttribute("echoProjectId", req.getParameter("echoProjectId"));req.setAttribute("echoProjectName", req.getParameter("echoProjectName"));doGet(req, resp); // 复用GET方法的查询逻辑
}
}`
(3.ProjectCreateServlet)
`package com.project.servlet;
import com.project.bean.Project;
import com.project.dao.ProjectDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;
@WebServlet("/createProject")
public class ProjectCreateServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(ProjectCreateServlet.class);
private final ProjectDao projectDao = new ProjectDao();
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 项目编号规则:8位数字(前4位“年+月”,如2410代表2024年10月,后4位序号)
private final Pattern projectIdPattern = Pattern.compile("^\d{4}\d{4}$");
// 项目位置规则:省市区三级(如“河北省石家庄市长安区XX路”)
private final Pattern locationPattern = Pattern.compile("^.{2,}省.{2,}市.{2,}区.*$");
// 处理GET请求:显示立项表单页面
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.getRequestDispatcher("createProject.jsp").forward(req, resp);
}// 处理POST请求:提交立项数据并入库
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=UTF-8");// 1. 获取表单参数String projectId = req.getParameter("projectId");String projectName = req.getParameter("projectName");String projectLocation = req.getParameter("projectLocation");String projectType = req.getParameter("projectType");String totalInvestmentStr = req.getParameter("totalInvestment");String currentInvestmentStr = req.getParameter("currentInvestment");String startDateStr = req.getParameter("startDate");String endDateStr = req.getParameter("endDate");String constructionContent = req.getParameter("constructionContent");// 2. 参数校验(格式+逻辑)String errorMsg = "";// 项目编号校验if (projectId == null || !projectIdPattern.matcher(projectId).matches()) {errorMsg = "项目编号格式错误(8位数字,前4位年+月,后4位序号,如24100130)";}// 项目名称校验(非空+长度≤50字)else if (projectName == null || projectName.trim().isEmpty() || projectName.length() > 50) {errorMsg = "项目名称不能为空且长度不超过50个汉字";}// 项目位置校验(符合省市区格式)else if (projectLocation == null || !locationPattern.matcher(projectLocation).matches()) {errorMsg = "项目位置格式错误(需包含省、市、区,如“河北省石家庄市长安区XX路”)";}// 项目属性校验(必选)else if (projectType == null || projectType.trim().isEmpty()) {errorMsg = "请选择项目属性";}// 投资金额转换与校验(正整数)Integer totalInvestment = null, currentInvestment = null;try {totalInvestment = Integer.parseInt(totalInvestmentStr);currentInvestment = Integer.parseInt(currentInvestmentStr);if (totalInvestment <= 0 || currentInvestment < 0 || currentInvestment > totalInvestment) {errorMsg = "总投资需为正数,已投资需≥0且≤总投资";}} catch (NumberFormatException e) {errorMsg = "总投资和已投资需为整数";}// 日期转换与校验(开工日期≤竣工日期)Date startDate = null, endDate = null;try {startDate = new Date(sdf.parse(startDateStr).getTime());endDate = new Date(sdf.parse(endDateStr).getTime());if (startDate.after(endDate)) {errorMsg = "开工日期不能晚于竣工日期";}} catch (ParseException e) {logger.error("日期解析异常", e);errorMsg = "日期格式错误(需yyyy-MM-dd)";}// 建设内容校验(非空+长度≤500字)if (errorMsg.isEmpty() && (constructionContent == null || constructionContent.trim().isEmpty() || constructionContent.length() > 500)) {errorMsg = "建设内容不能为空且长度不超过500个汉字";}// 3. 校验失败:返回表单页面并显示错误if (!errorMsg.isEmpty()) {req.setAttribute("errorMsg", errorMsg);// 回显表单数据(避免用户重新输入)req.setAttribute("echoProjectId", projectId);req.setAttribute("echoProjectName", projectName);req.setAttribute("echoProjectLocation", projectLocation);req.setAttribute("echoProjectType", projectType);req.setAttribute("echoTotalInvestment", totalInvestmentStr);req.setAttribute("echoCurrentInvestment", currentInvestmentStr);req.setAttribute("echoStartDate", startDateStr);req.setAttribute("echoEndDate", endDateStr);req.setAttribute("echoConstructionContent", constructionContent);req.getRequestDispatcher("createProject.jsp").forward(req, resp);return;}// 4. 校验成功:封装实体并入库try {Project project = new Project(projectId,projectName,projectLocation,projectType,totalInvestment,currentInvestment,startDate,endDate,constructionContent);// 检查项目编号是否已存在if (projectDao.getProjectByNo(projectId) != null) {errorMsg = "项目编号已存在,请更换";req.setAttribute("errorMsg", errorMsg);req.getRequestDispatcher("createProject.jsp").forward(req, resp);return;}// 执行插入boolean isSuccess = projectDao.addProject(project);if (isSuccess) {// 立项成功后跳转审核页面,默认查询当前项目resp.sendRedirect(req.getContextPath() + "/auditProject?projectId=" + projectId);} else {errorMsg = "立项失败,请重试";req.setAttribute("errorMsg", errorMsg);req.getRequestDispatcher("createProject.jsp").forward(req, resp);}} catch (Exception e) {logger.error("项目立项异常", e);errorMsg = "系统错误,立项失败";req.setAttribute("errorMsg", errorMsg);req.getRequestDispatcher("createProject.jsp").forward(req, resp);}
}
}`
(4.ProjectDeleteServlet)
`package com.project.servlet;
import com.project.bean.Project;
import com.project.dao.ProjectDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
@WebServlet("/deleteProject")
public class ProjectDeleteServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(ProjectDeleteServlet.class);
private final ProjectDao projectDao = new ProjectDao();
// 项目编号规则:8位数字(与立项功能保持一致)
private final String PROJECT_ID_PATTERN = "^\d{8}$";
// 处理GET请求:显示删除页面,支持根据项目编号查询
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");String projectId = req.getParameter("projectId");Project project = null;String errorMsg = "";// 如果传入项目编号,则查询项目信息if (projectId != null && !projectId.trim().isEmpty()) {// 校验项目编号格式if (!projectId.matches(PROJECT_ID_PATTERN)) {errorMsg = "项目编号格式错误(需8位数字)";} else {try {project = projectDao.getProjectByNo(projectId);if (project == null) {errorMsg = "未查询到编号为【" + projectId + "】的项目";}} catch (SQLException e) {logger.error("项目查询异常", e);errorMsg = "查询失败:系统错误,请重试";}}}// 传递数据到页面req.setAttribute("project", project);req.setAttribute("errorMsg", errorMsg);req.setAttribute("echoProjectId", projectId); // 回显查询的项目编号req.getRequestDispatcher("deleteProject.jsp").forward(req, resp);
}// 处理POST请求:执行删除操作(仅允许删除未审核项目)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=UTF-8");String projectId = req.getParameter("projectId");String errorMsg = "";String successMsg = "";// 参数校验if (projectId == null || !projectId.matches(PROJECT_ID_PATTERN)) {errorMsg = "参数错误:项目编号格式不正确";} else {try {// 1. 查询项目是否存在及审核状态Project project = projectDao.getProjectByNo(projectId);if (project == null) {errorMsg = "删除失败:未查询到编号为【" + projectId + "】的项目";} else if (project.getAuditStatus() == 1) {// 已审核项目不允许删除errorMsg = "删除失败:项目【" + projectId + "】已审核,不能删除";} else {// 2. 执行删除(仅删除未审核项目)boolean isDeleted = projectDao.deleteProject(projectId);if (isDeleted) {successMsg = "项目【" + projectId + "】删除成功";} else {errorMsg = "删除失败:系统异常,请重试";}}} catch (SQLException e) {logger.error("项目删除异常", e);errorMsg = "删除失败:系统错误,请重试";}}// 传递结果到页面,复用GET方法的查询逻辑req.setAttribute("successMsg", successMsg);req.setAttribute("errorMsg", errorMsg);req.setAttribute("echoProjectId", projectId); // 回显项目编号doGet(req, resp);
}
}`
(5.ProjectUpdateServlet)
`package com.project.servlet;
import com.project.bean.Project;
import com.project.dao.ProjectDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;
@WebServlet("/updateProject")
public class ProjectUpdateServlet extends HttpServlet {
private static final Logger logger = LoggerFactory.getLogger(ProjectUpdateServlet.class);
private final ProjectDao projectDao = new ProjectDao();
private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private final Pattern projectIdPattern = Pattern.compile("^\d{8}$");
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");String projectId = req.getParameter("projectId");Project project = null;String errorMsg = "";if (projectId != null && !projectId.trim().isEmpty()) {if (!projectIdPattern.matcher(projectId).matches()) {errorMsg = "项目编号格式错误(需8位数字)";} else {try {project = projectDao.getProjectByNo(projectId);if (project == null) {errorMsg = "未查询到编号为【" + projectId + "】的项目";} else if (project.getAuditStatus() == 1) {errorMsg = "项目【" + projectId + "】已审核,不允许修改";}} catch (Exception e) {logger.error("项目查询异常", e);errorMsg = "查询失败:系统错误,请重试";}}}req.setAttribute("project", project);req.setAttribute("errorMsg", errorMsg);req.setAttribute("echoProjectId", projectId);req.getRequestDispatcher("updateProject.jsp").forward(req, resp);
}@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {req.setCharacterEncoding("UTF-8");resp.setContentType("text/html;charset=UTF-8");String projectId = req.getParameter("projectId");String currentInvestmentStr = req.getParameter("currentInvestment");String startDateStr = req.getParameter("startDate");String endDateStr = req.getParameter("endDate");String constructionContent = req.getParameter("constructionContent");String errorMsg = "";Project project = null;if (projectId == null || !projectIdPattern.matcher(projectId).matches()) {errorMsg = "参数错误:项目编号格式不正确";} else {try {project = projectDao.getProjectByNo(projectId);if (project == null) {errorMsg = "修改失败:未查询到编号为【" + projectId + "】的项目";} else if (project.getAuditStatus() == 1) {errorMsg = "修改失败:项目【" + projectId + "】已审核,不允许修改";}} catch (Exception e) {logger.error("项目查询异常", e);errorMsg = "查询失败:系统错误,请重试";}}if (errorMsg.isEmpty()) {Integer currentInvestment = null;try {currentInvestment = Integer.parseInt(currentInvestmentStr);if (currentInvestment < 0 || currentInvestment > project.getTotalInvestment()) {errorMsg = "已投资需≥0且≤总投资(" + project.getTotalInvestment() + "万元)";}} catch (NumberFormatException e) {errorMsg = "已投资需为整数";}Date startDate = null, endDate = null;try {startDate = new Date(sdf.parse(startDateStr).getTime());endDate = new Date(sdf.parse(endDateStr).getTime());if (startDate.after(endDate)) {errorMsg = "开工日期不能晚于竣工日期";}} catch (ParseException e) {logger.error("日期解析异常", e);errorMsg = "日期格式错误(需yyyy-MM-dd)";}if (errorMsg.isEmpty() && (constructionContent == null || constructionContent.trim().isEmpty() || constructionContent.length() > 500)) {errorMsg = "建设内容不能为空且长度不超过500个汉字";}}if (!errorMsg.isEmpty()) {req.setAttribute("errorMsg", errorMsg);req.setAttribute("project", project);req.setAttribute("echoProjectId", projectId);req.getRequestDispatcher("updateProject.jsp").forward(req, resp);return;}try {Project updatedProject = new Project(project.getProjectId(),project.getProjectName(),project.getProjectLocation(),project.getProjectType(),project.getTotalInvestment(),Integer.parseInt(currentInvestmentStr),new Date(sdf.parse(startDateStr).getTime()),new Date(sdf.parse(endDateStr).getTime()),constructionContent);updatedProject.setAuditStatus(project.getAuditStatus());boolean isUpdated = projectDao.updateProject(updatedProject);if (isUpdated) {req.setAttribute("successMsg", "项目【" + projectId + "】修改成功");} else {errorMsg = "修改失败:系统异常,请重试";req.setAttribute("errorMsg", errorMsg);}} catch (Exception e) {logger.error("项目修改异常", e);errorMsg = "修改失败:系统错误,请重试";req.setAttribute("errorMsg", errorMsg);}req.setAttribute("project", project);req.setAttribute("echoProjectId", projectId);req.getRequestDispatcher("updateProject.jsp").forward(req, resp);
}
}`
5.resources
(db.properties)
url=jdbc:mysql://localhost:3306/project_db?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true username=root password=#你的密码 driver=com.mysql.cj.jdbc.Driver
6.jsp
(1.auditProject)
`<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.project.bean.Project" %>
<%@ page import="java.util.List" %>
<%
// 从请求域获取数据
List
String errorMsg = (String) request.getAttribute("errorMsg");
String successMsg = (String) request.getAttribute("successMsg");
// 回显查询条件
String echoProjectId = (String) request.getAttribute("echoProjectId");
String echoProjectName = (String) request.getAttribute("echoProjectName");
// 处理空值
if (echoProjectId == null) echoProjectId = "";
if (echoProjectName == null) echoProjectName = "";
%>
项目审核管理
<!-- 消息提示区域 -->
<% if (errorMsg != null && !errorMsg.isEmpty()) { %>
<div class="msg error"><%= errorMsg %></div>
<% } %>
<% if (successMsg != null && !successMsg.isEmpty()) { %>
<div class="msg success"><%= successMsg %></div>
<% } %><!-- 1. 多条件模糊查询表单 -->
<form action="${pageContext.request.contextPath}/auditProject" method="get" class="query-form"><div class="form-item"><label>项目编号:</label><input type="text" name="projectId" value="<%= echoProjectId %>" placeholder="支持模糊查询,如2410"></div><div class="form-item"><label>项目名称:</label><input type="text" name="projectName" value="<%= echoProjectName %>" placeholder="支持模糊查询,如道路"></div><button type="submit" class="btn query-btn">查询项目</button>
</form><!-- 2. 项目列表与审核操作 -->
<% if (projectList != null && !projectList.isEmpty()) { %>
<table class="data-table"><thead><tr><th>项目编号</th><th>项目名称</th><th>项目位置</th><th>项目属性</th><th>总投资(万元)</th><th>开工日期</th><th>竣工日期</th><th>审核状态</th><th>操作</th></tr></thead><tbody><% for (Project project : projectList) { %><tr><td><%= project.getProjectId() %></td><td><%= project.getProjectName() %></td><td><%= project.getProjectLocation() %></td><td><%= project.getProjectType() %></td><td><%= project.getTotalInvestment() %></td><td><%= project.getStartDate() %></td><td><%= project.getEndDate() %></td><td><%= project.getAuditStatus() == 0 ? "未审核" :(project.getAuditOpinion().startsWith("同意") ? "已同意" : "已拒绝") %></td><td><% if (project.getAuditStatus() == 0) { %><!-- 未审核项目显示审核按钮 --><button type="button" class="btn audit-btn"onclick="showAuditModal('<%= project.getProjectId() %>')">审核</button><% } else { %><!-- 已审核项目显示审核结果 --><span><%= project.getAuditOpinion() %></span><% } %></td></tr><% } %></tbody>
</table>
<% } else if (echoProjectId != null || echoProjectName != null) { %>
<div class="msg error">未查询到符合条件的项目</div>
<% } %><!-- 3. 返回主页面按钮 -->
<div style="margin-top: 30px; text-align: center;"><a href="${pageContext.request.contextPath}/main"><button type="button" class="btn">返回主页面</button></a>
</div>
(2.createProject)
`<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
// 获取回显数据和错误信息
String errorMsg = (String) request.getAttribute("errorMsg");
String echoProjectId = (String) request.getAttribute("echoProjectId");
String echoProjectName = (String) request.getAttribute("echoProjectName");
String echoProjectLocation = (String) request.getAttribute("echoProjectLocation");
String echoProjectType = (String) request.getAttribute("echoProjectType");
String echoTotalInvestment = (String) request.getAttribute("echoTotalInvestment");
String echoCurrentInvestment = (String) request.getAttribute("echoCurrentInvestment");
String echoStartDate = (String) request.getAttribute("echoStartDate");
String echoEndDate = (String) request.getAttribute("echoEndDate");
String echoConstructionContent = (String) request.getAttribute("echoConstructionContent");
// 处理空值,避免页面显示null
if (echoProjectId == null) echoProjectId = "";
if (echoProjectName == null) echoProjectName = "";
if (echoProjectLocation == null) echoProjectLocation = "";
if (echoProjectType == null) echoProjectType = "";
if (echoTotalInvestment == null) echoTotalInvestment = "";
if (echoCurrentInvestment == null) echoCurrentInvestment = "";
if (echoStartDate == null) echoStartDate = "";
if (echoEndDate == null) echoEndDate = "";
if (echoConstructionContent == null) echoConstructionContent = "";
%>
项目立项信息录入
<!-- 错误提示 -->
<% if (errorMsg != null && !errorMsg.isEmpty()) { %>
<div class="error"><%= errorMsg %></div>
<% } %><!-- 立项表单 -->
<form action="${pageContext.request.contextPath}/createProject" method="post"><div class="form-item"><label>项目编号:</label><div><input type="text" name="projectId" value="<%= echoProjectId %>"placeholder="8位数字(前4位年+月,后4位序号,如24100130)" required><div class="tips">示例:24100130(2024年10月第130个项目)</div></div></div><div class="form-item"><label>项目名称:</label><div><input type="text" name="projectName" value="<%= echoProjectName %>"placeholder="不超过50个汉字" required><div class="tips">例如:石家庄市长安区XX道路改造工程</div></div></div><div class="form-item"><label>项目位置:</label><div><input type="text" name="projectLocation" value="<%= echoProjectLocation %>"placeholder="需包含省、市、区,如“河北省石家庄市长安区XX路”" required><div class="tips">必须包含三级行政区划(省/市/区)</div></div></div><div class="form-item"><label>项目属性:</label><select name="projectType" required><option value="">--请选择项目属性--</option><option value="道路" <%= "道路".equals(echoProjectType) ? "selected" : "" %>>道路</option><option value="管廊" <%= "管廊".equals(echoProjectType) ? "selected" : "" %>>管廊</option><option value="住宅" <%= "住宅".equals(echoProjectType) ? "selected" : "" %>>住宅</option><option value="商业" <%= "商业".equals(echoProjectType) ? "selected" : "" %>>商业</option><option value="公建" <%= "公建".equals(echoProjectType) ? "selected" : "" %>>公建</option><option value="园林绿化" <%= "园林绿化".equals(echoProjectType) ? "selected" : "" %>>园林绿化</option><option value="产业类" <%= "产业类".equals(echoProjectType) ? "selected" : "" %>>产业类</option></select></div><div class="form-item"><label>总投资(万元):</label><div><input type="number" name="totalInvestment" value="<%= echoTotalInvestment %>"min="1" placeholder="正整数" required><div class="tips">单位:万元,需为正数</div></div></div><div class="form-item"><label>已投资(万元):</label><div><input type="number" name="currentInvestment" value="<%= echoCurrentInvestment %>"min="0" placeholder="≥0且≤总投资" required><div class="tips">单位:万元,不能超过总投资</div></div></div><div class="form-item"><label>开工日期:</label><input type="date" name="startDate" value="<%= echoStartDate %>" required></div><div class="form-item"><label>竣工日期:</label><input type="date" name="endDate" value="<%= echoEndDate %>" required></div><div class="form-item"><label>建设内容:</label><div><textarea name="constructionContent" placeholder="不超过500个汉字,描述项目主要建设内容" required><%= echoConstructionContent %></textarea><div class="tips">例如:道路全长XX米,宽XX米,包含XX等配套设施...</div></div></div><button type="submit" class="btn">提交立项</button>
</form><!-- 返回主页面链接 -->
<a href="${pageContext.request.contextPath}/main" class="back-link">返回主页面</a>
(3.deleteProject)
`<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.project.bean.Project" %>
<%
// 从请求域获取数据
Project project = (Project) request.getAttribute("project");
String errorMsg = (String) request.getAttribute("errorMsg");
String successMsg = (String) request.getAttribute("successMsg");
String echoProjectId = (String) request.getAttribute("echoProjectId");
if (echoProjectId == null) echoProjectId = "";
%>
项目删除管理
<!-- 消息提示区域 -->
<% if (errorMsg != null && !errorMsg.isEmpty()) { %>
<div class="msg error"><%= errorMsg %></div>
<% } %>
<% if (successMsg != null && !successMsg.isEmpty()) { %>
<div class="msg success"><%= successMsg %></div>
<% } %><!-- 1. 查询项目表单 -->
<form action="${pageContext.request.contextPath}/deleteProject" method="get" class="query-form"><div class="form-item"><label>项目编号:</label><input type="text" name="projectId" value="<%= echoProjectId %>"placeholder="8位数字,如24100130" required><button type="submit" class="btn query-btn">查询项目</button></div>
</form><!-- 2. 项目信息与删除操作(查询到项目时显示) -->
<% if (project != null) { %>
<div class="project-info"><h3>项目信息(编号:<%= project.getProjectId() %>)</h3><table class="data-table"><thead><tr><th>项目名称</th><th>项目位置</th><th>项目属性</th><th>总投资(万元)</th><th>审核状态</th><th>操作</th></tr></thead><tbody><tr><td><%= project.getProjectName() %></td><td><%= project.getProjectLocation() %></td><td><%= project.getProjectType() %></td><td><%= project.getTotalInvestment() %></td><td><%= project.getAuditStatus() == 0 ? "未审核" : "已审核" %></td><td><% if (project.getAuditStatus() == 0) { %><!-- 未审核项目显示删除按钮 --><button type="button" class="btn delete-btn"onclick="showDeleteModal('<%= project.getProjectId() %>')">删除项目</button><% } else { %><!-- 已审核项目禁用删除按钮 --><button type="button" class="btn delete-btn" disabled>已审核,不可删除</button><% } %></td></tr></tbody></table>
</div>
<% } %><!-- 3. 返回主页面按钮 -->
<div style="margin-top: 30px; text-align: center;"><a href="${pageContext.request.contextPath}/main"><button type="button" class="btn back-btn">返回主页面</button></a>
</div>
(4.main)
`<%@ page contentType="text/html;charset=UTF-8" language="java" %>
项目计划管理系统
(5.updateProject)
`<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="com.project.bean.Project" %>
<%@ page import="java.sql.Date" %>
<%
// 从请求域获取数据
Project project = (Project) request.getAttribute("project");
String errorMsg = (String) request.getAttribute("errorMsg");
String successMsg = (String) request.getAttribute("successMsg");
String echoProjectId = (String) request.getAttribute("echoProjectId");
if (echoProjectId == null) echoProjectId = "";
%>
项目信息修改
<!-- 消息提示区域 -->
<% if (errorMsg != null && !errorMsg.isEmpty()) { %>
<div class="msg error"><%= errorMsg %></div>
<% } %>
<% if (successMsg != null && !successMsg.isEmpty()) { %>
<div class="msg success"><%= successMsg %></div>
<% } %><!-- 1. 查询项目表单 -->
<form action="${pageContext.request.contextPath}/updateProject" method="get" class="query-form"><div class="form-item"><label>项目编号:</label><input type="text" name="projectId" value="<%= echoProjectId %>"placeholder="8位数字,如24100130" required><button type="submit" class="btn query-btn">查询项目</button></div>
</form><!-- 2. 修改表单(查询到未审核项目时显示) -->
<% if (project != null && project.getAuditStatus() == 0) { %>
<form action="${pageContext.request.contextPath}/updateProject" method="post"><!-- 隐藏字段:项目编号(关键字段,不允许修改) --><input type="hidden" name="projectId" value="<%= project.getProjectId() %>"><div class="form-item"><label>项目编号:</label><div><input type="text" value="<%= project.getProjectId() %>" readonly><div class="readonly-tip">关键字段,不允许修改</div></div></div><div class="form-item"><label>项目名称:</label><div><input type="text" value="<%= project.getProjectName() %>" readonly><div class="readonly-tip">关键字段,不允许修改</div></div></div><div class="form-item"><label>项目位置:</label><div><input type="text" value="<%= project.getProjectLocation() %>" readonly><div class="readonly-tip">关键字段,不允许修改</div></div></div><div class="form-item"><label>项目属性:</label><div><input type="text" value="<%= project.getProjectType() %>" readonly><div class="readonly-tip">关键字段,不允许修改</div></div></div><div class="form-item"><label>总投资(万元):</label><div><input type="number" value="<%= project.getTotalInvestment() %>" readonly><div class="readonly-tip">关键字段,不允许修改</div></div></div><div class="form-item"><label>已投资(万元):</label><div><input type="number" name="currentInvestment"value="<%= project.getCurrentInvestment() %>"min="0" max="<%= project.getTotalInvestment() %>" required><div class="tips">≤总投资(<%= project.getTotalInvestment() %>万元)</div></div></div><div class="form-item"><label>开工日期:</label><input type="date" name="startDate"value="<%= project.getStartDate() != null ? project.getStartDate() : "" %>" required></div><div class="form-item"><label>竣工日期:</label><input type="date" name="endDate"value="<%= project.getEndDate() != null ? project.getEndDate() : "" %>" required></div><div class="form-item"><label>建设内容:</label><div><textarea name="constructionContent"placeholder="不超过500个汉字" required><%= project.getConstructionContent() %></textarea><div class="tips">描述项目主要建设内容,不超过500个汉字</div></div></div><button type="submit" class="btn update-btn">保存修改</button><a href="${pageContext.request.contextPath}/main"><button type="button" class="btn back-btn">返回主页面</button></a>
</form>
<% } %>
(web.xml)
`
<!-- 欢迎文件列表 -->
<welcome-file-list><welcome-file>main.jsp</welcome-file>
</welcome-file-list><!-- 配置字符编码过滤器 -->
<filter><filter-name>encodingFilter</filter-name><filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>ignore</param-name><param-value>false</param-value></init-param>
</filter>
<filter-mapping><filter-name>encodingFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>
`
(pom.xml)
`
<!-- 依赖配置需直接在 project 下 -->
<dependencies><!-- Servlet 依赖 --><dependency><groupId>jakarta.servlet</groupId><artifactId>jakarta.servlet-api</artifactId><version>6.0.0</version><scope>provided</scope></dependency><!-- MySQL 驱动依赖 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version><scope>runtime</scope></dependency><!-- SLF4J 日志依赖 --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.9</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.4.11</version></dependency>
</dependencies><build><!-- 编译插件等配置 -->
</build>
`
六.
文件填写完后,从右侧Maven中点击Reload

完成上述操作后,项目管理系统完成