在公共卫生管理领域,高效、透明的信息流转是有效应对突发疫情的关键。传统的信息发布方式,如公告栏、微信群通知等,往往存在信息分散、更新不及时、缺乏互动反馈机制等问题。为解决这些痛点,我们设计并实现了一套基于JSP+Servlet技术的疫情防控信息发布与交流平台。该平台采用经典的MVC架构,旨在为社区、学校、企事业单位提供一个集中、可控、高效的数字化疫情防控管理中心。
平台的核心架构清晰地区分了表示层、控制层和业务逻辑层。表示层由JSP页面构成,负责数据的最终渲染和用户交互。JSP页面中大量使用了JSTL标签库和EL表达式,极大地简化了页面中的Java代码,使页面结构更清晰,更易于前端开发者维护。例如,在展示疫情数据列表时,使用 <c:forEach> 标签可以优雅地遍历数据集合。
<%-- 使用JSTL与EL表达式展示疫情数据列表 --%>
<table class="data-table">
<thead>
<tr>
<th>区域名称</th>
<th>新增确诊</th>
<th>现有确诊</th>
<th>累计确诊</th>
<th>更新日期</th>
</tr>
</thead>
<tbody>
<c:forEach var="data" items="${covidDataList}">
<tr>
<td>${data.regionName}</td>
<td>${data.newConfirmed}</td>
<td>${data.currentConfirmed}</td>
<td>${data.totalConfirmed}</td>
<td><fmt:formatDate value="${data.updateTime}" pattern="yyyy-MM-dd"/></td>
</tr>
</c:forEach>
</tbody>
</table>
控制层由Servlet实现,作为整个应用的交通枢纽,负责接收所有HTTP请求。每个功能模块通常对应一个或多个Servlet,通过web.xml配置文件或@WebServlet注解进行URL映射。Servlet解析请求参数,调用相应的业务逻辑处理单元(Service层),并根据处理结果决定将请求转发至哪个JSP页面进行渲染,或进行重定向。
// 处理疫情数据查询请求的Servlet核心代码
@WebServlet("/admin/CovidDataQueryServlet")
public class CovidDataQueryServlet extends HttpServlet {
private CovidDataService covidDataService = new CovidDataServiceImpl();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String regionId = request.getParameter("regionId");
String date = request.getParameter("date");
try {
List<CovidData> dataList = covidDataService.queryCovidData(regionId, date);
request.setAttribute("covidDataList", dataList);
RequestDispatcher dispatcher = request.getRequestDispatcher("/admin/covid_data_list.jsp");
dispatcher.forward(request, response);
} catch (Exception e) {
e.printStackTrace();
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "数据查询失败");
}
}
}
业务逻辑层由JavaBean和Service类构成,封装了核心的业务规则和数据处理流程。数据持久层采用JDBC技术,并通过DAO设计模式进行抽象,将数据访问细节与业务逻辑分离,使得代码结构清晰,易于测试和维护。数据库连接使用连接池进行管理,以提升性能。
// 疫情数据访问对象接口
public interface CovidDataDAO {
List<CovidData> findByRegionAndDate(String regionId, String date) throws SQLException;
int insert(CovidData data) throws SQLException;
int update(CovidData data) throws SQLException;
}
// JDBC实现类
public class CovidDataDAOImpl implements CovidDataDAO {
@Override
public List<CovidData> findByRegionAndDate(String regionId, String date) throws SQLException {
List<CovidData> list = new ArrayList<>();
String sql = "SELECT * FROM t_covid_data WHERE region_id = ? AND data_date = ?";
try (Connection conn = DataSourceUtil.getConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, regionId);
pstmt.setString(2, date);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
// ... 将ResultSet映射为CovidData对象
list.add(covidData);
}
}
return list;
}
}
数据库设计是平台稳定运行的基石,共包含18张表,涵盖了用户、区域、疫情数据、疫苗、通知、留言等核心实体。其中,t_covid_data(疫情数据表)的设计尤为关键,它负责存储每日各区域的疫情统计信息。
CREATE TABLE `t_covid_data` (
`data_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '数据ID',
`region_id` int(11) NOT NULL COMMENT '区域ID,关联t_region表',
`data_date` date NOT NULL COMMENT '数据日期',
`new_confirmed` int(11) DEFAULT '0' COMMENT '新增确诊',
`current_confirmed` int(11) DEFAULT '0' COMMENT '现有确诊',
`total_confirmed` int(11) DEFAULT '0' COMMENT '累计确诊',
`new_recovered` int(11) DEFAULT '0' COMMENT '新增治愈',
`total_recovered` int(11) DEFAULT '0' COMMENT '累计治愈',
`new_death` int(11) DEFAULT '0' COMMENT '新增死亡',
`total_death` int(11) DEFAULT '0' COMMENT '累计死亡',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`data_source` varchar(255) DEFAULT NULL COMMENT '数据来源',
PRIMARY KEY (`data_id`),
UNIQUE KEY `uk_region_date` (`region_id`,`data_date`),
KEY `idx_date` (`data_date`),
CONSTRAINT `fk_covid_data_region` FOREIGN KEY (`region_id`) REFERENCES `t_region` (`region_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='新冠疫情数据表';
该表的设计亮点在于:
- 唯一性约束:通过
uk_region_date唯一键,确保同一区域在同一天只会有一条数据记录,防止数据重复。 - 索引优化:对
data_date字段建立了索引,便于按时间范围进行快速查询和统计。 - 外键约束:通过外键
fk_covid_data_region与区域表t_region关联,保证了数据的参照完整性。 - 字段完备性:涵盖了疫情统计的各类关键指标,并包含数据来源和更新时间,增强了数据的可信度和可追溯性。
另一张核心表是t_user(用户表),它管理着平台的所有用户信息,并区分管理员和普通用户角色。
CREATE TABLE `t_user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码(加密存储)',
`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
`id_card` varchar(18) DEFAULT NULL COMMENT '身份证号',
`phone` varchar(11) DEFAULT NULL COMMENT '手机号',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`region_id` int(11) DEFAULT NULL COMMENT '所属区域ID',
`user_type` tinyint(1) DEFAULT '2' COMMENT '用户类型:1-管理员,2-普通用户',
`registration_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '注册时间',
`last_login_time` datetime DEFAULT NULL COMMENT '最后登录时间',
`status` tinyint(1) DEFAULT '1' COMMENT '状态:0-禁用,1-启用',
PRIMARY KEY (`user_id`),
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_id_card` (`id_card`),
KEY `idx_region` (`region_id`),
KEY `idx_phone` (`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
该表设计考虑了安全性与查询效率:
- 密码安全:
password字段预留足够长度,用于存储经过哈希加密(如BCrypt)后的密码,而非明文。 - 唯一性保障:对
username和id_card设置了唯一约束,防止重复注册。 - 查询优化:对
region_id和phone等常用查询条件建立了索引。 - 状态管理:通过
status字段实现用户的软删除或启用/禁用功能。
用户登录与会话管理是平台安全的基础。登录Servlet负责验证用户凭证,成功后会将用户对象存入Session。
// 用户登录Servlet核心逻辑
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private UserService userService = new UserServiceImpl();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String userType = request.getParameter("userType"); // "admin" or "user"
User user = userService.login(username, password, userType);
if (user != null) {
if (user.getStatus() == 1) {
// 登录成功,将用户信息存入Session
HttpSession session = request.getSession();
session.setAttribute("currentUser", user);
session.setMaxInactiveInterval(30 * 60); // 会话有效期30分钟
// 根据用户类型跳转到不同首页
if ("admin".equals(userType)) {
response.sendRedirect(request.getContextPath() + "/admin/index.jsp");
} else {
response.sendRedirect(request.getContextPath() + "/user/index.jsp");
}
} else {
request.setAttribute("errorMsg", "该账户已被禁用,请联系管理员");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
} else {
request.setAttribute("errorMsg", "用户名或密码错误");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}

平台的核心功能之一是疫情数据的管理与可视化。管理员可以通过专门的数据管理界面,录入、编辑和查询各区域的疫情统计数据。
// 疫情数据服务层实现
public class CovidDataServiceImpl implements CovidDataService {
private CovidDataDAO covidDataDAO = new CovidDataDAOImpl();
@Override
public boolean addOrUpdateCovidData(CovidData data) {
try {
// 检查当天该区域数据是否已存在
List<CovidData> existingData = covidDataDAO.findByRegionAndDate(
data.getRegionId().toString(),
new SimpleDateFormat("yyyy-MM-dd").format(data.getDataDate())
);
if (existingData.isEmpty()) {
return covidDataDAO.insert(data) > 0;
} else {
data.setDataId(existingData.get(0).getDataId());
return covidDataDAO.update(data) > 0;
}
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
}

实时通知功能确保了重要信息能够第一时间触达用户。管理员可以发布通知,系统会将其展示在用户端的显著位置。
<%-- 用户首页展示实时通知 --%>
<div class="notification-panel">
<h3>最新通知</h3>
<c:forEach var="notice" items="${latestNotices}">
<div class="notice-item">
<h4>${notice.title}</h4>
<p>${notice.content}</p>
<span class="notice-time"><fmt:formatDate value="${notice.publishTime}" pattern="yyyy-MM-dd HH:mm"/></span>
</div>
</c:forEach>
</div>

留言交流功能构建了用户与管理者之间的沟通桥梁。用户可以提交问题或建议,管理员则可以在后台进行回复和管理。
// 留言服务层核心方法
public class MessageServiceImpl implements MessageService {
private MessageDAO messageDAO = new MessageDAOImpl();
@Override
public boolean submitMessage(Message message) {
try {
return messageDAO.insert(message) > 0;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
@Override
public List<Message> getMessagesByUserId(int userId, int page, int size) {
try {
return messageDAO.findByUserIdWithPagination(userId, (page - 1) * size, size);
} catch (SQLException e) {
e.printStackTrace();
return new ArrayList<>();
}
}
}

在实体模型设计上,平台通过清晰的JavaBean对象映射数据库表结构,并通过DAO模式实现数据访问的封装。以CovidData实体为例:
public class CovidData {
private Integer dataId;
private Integer regionId;
private Date dataDate;
private Integer newConfirmed;
private Integer currentConfirmed;
private Integer totalConfirmed;
private Integer newRecovered;
private Integer totalRecovered;
private Integer newDeath;
private Integer totalDeath;
private Date updateTime;
private String dataSource;
// 省略getter和setter方法
}
这种规整的实体设计使得业务逻辑处理和数据传输变得非常清晰。
尽管平台已经实现了核心的疫情防控信息管理功能,但从长远发展和提升用户体验的角度,仍有若干值得优化的方向:
引入前端框架与前后端分离:当前架构下,JSP承担了过多的渲染逻辑。未来可以考虑采用Vue.js、React等前端框架,通过RESTful API与后端Servlet进行数据交互,实现真正的前后端分离。这将极大提升前端开发效率和用户体验,并使后端接口更具通用性。实现思路是:将Servlet改造为仅返回JSON数据的API控制器,前端通过Ajax调用这些接口并动态渲染页面。
数据可视化增强:目前的疫情数据主要以表格形式呈现。可以集成ECharts等图表库,实现疫情趋势折线图、区域风险热力图、疫苗接种进度饼图等丰富的可视化展示,使数据更加直观易懂。实现时,后端提供按时间、区域等维度聚合数据的API,前端图表库调用这些API获取数据并进行渲染。
消息推送机制:对于紧急通知,目前依赖用户主动刷新页面查看。可以集成WebSocket技术,实现服务端向客户端的实时消息推送。当管理员发布紧急通知时,在线用户能立即收到弹窗提醒,显著提升重要信息的到达率。
移动端适配与小程序开发:随着移动互联网的普及,开发配套的微信小程序或React Native移动应用是必然趋势。这需要后端提供一套完善的、支持移动端认证的API体系。初期可以先将核心的数据查询、通知查看、留言等功能通过API暴露,供移动端调用。
数据权限与多租户支持:如果平台需要服务于多个互不隶属的组织(如多个不同的社区或公司),可以引入多租户架构。在数据库设计中增加租户ID字段,在业务逻辑层实现数据隔离,使不同组织的管理员只能管理和查看本组织的数据。这能显著提升平台的商业化潜力。
该疫情防控信息枢纽平台凭借其清晰的MVC架构、严谨的数据库设计和完善的核心功能,为各类组织提供了强有力的数字化防疫工具。其采用的技术栈成熟稳定,易于理解和维护,为后续的功能扩展和性能优化奠定了坚实的基础。通过持续迭代,该平台有望成为应对突发公共卫生事件不可或缺的信息化基础设施。