システム概要
本プロジェクトは、河北省環境保護監測センターにおける公众情報交流の促進を目的としたニュース发布プラットフォームの構築に関するものです。本システムにより、センターの活動報告や企業の環境情報などを効率的に発信し、管理者による審査フローを経た上で一般ユーザーに公開する仕組みを実現します。
機能要件と設計
システムは複数のユーザーロールに基づき、アクセス権限が厳格に管理されます。主な機能要件は以下の通りです。
- 認証機能: ホームページはログイン画面とし、データベース上でパスワードを暗号化して管理します。
- ニュース撰稿者: 記事の作成、編集、審査意見の確認、投稿履歴の閲覧が可能です。
- 一般ユーザー: 認証後にニュース欄の閲覧、コメント投稿(匿名可)、他ユーザーのコメント閲覧が可能です。
- 栏目管理员: 担当カテゴリの未公開・公開ニュースの管理、審査、コメントの監視を行います。
- システム管理者: ユーザーアカウントの管理、権限付与、ニュースカテゴリの増減・編集を行います。
また、各ページにおける検索結果は分页表示に対応し、サーバー上で動作し、クライアント側のブラウザ解像度に適応したレスポンシブな設計が求められます。
実装詳細
本システムは Java Servlet と JSP を採用し、バックエンドデータベースとして MySQL を使用します。MVC パターンを意識し、ビジネスロジックと表示層を分離する構成を目指します。
データベース接続ユーティリティ
データベース接続を管理するユーティリティクラスです。接続情報のハードコードを避け、必要に応じて設定ファイルから読み込む設計が推奨されます。
package com.env.system.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnector {
private static final String DB_URL = "jdbc:mysql://localhost:3306/env_news_db?useSSL=false&serverTimezone=UTC";
private static final String DB_USER = "admin";
private static final String DB_PASS = "secure_password";
public static Connection establishConnection() {
Connection conn = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
return conn;
}
public static void terminateConnection(Connection conn) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
認証コントローラー
ログイン処理を行い、ユーザーのロールに応じて適切なダッシュボードへリダイレクトします。
package com.env.system.controller;
import com.env.system.dao.AuthDAO;
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 jakarta.servlet.http.HttpSession;
import java.io.IOException;
import java.sql.SQLException;
@WebServlet("/auth/login")
public class LoginController extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String username = req.getParameter("username");
String password = req.getParameter("password");
int role = Integer.parseInt(req.getParameter("role"));
HttpSession session = req.getSession();
AuthDAO authDao = new AuthDAO();
try {
if (authDao.validateUser(username, password, role)) {
session.setAttribute("currentUser", username);
session.setAttribute("userRole", role);
switch (role) {
case 1: // 撰稿者
resp.sendRedirect("dashboard/writer.jsp");
break;
case 2: // 一般ユーザー
resp.sendRedirect("dashboard/user.jsp");
break;
case 3: // 管理者
resp.sendRedirect("dashboard/admin.jsp");
break;
default:
resp.sendRedirect("login.jsp?error=invalid_role");
}
} else {
resp.sendRedirect("login.jsp?error=auth_failed");
}
} catch (SQLException e) {
throw new RuntimeException("Database error during login", e);
}
}
}
ニュース投稿処理
撰稿者によるニュース作成を受け付け、データベースに保存します。ここでは SQL インジェクション対策として PreparedStatement を使用します。
package com.env.system.controller;
import com.env.system.util.DatabaseConnector;
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.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
@WebServlet("/news/submit")
public class NewsSubmissionHandler extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String content = req.getParameter("articleBody");
String category = req.getParameter("categoryName");
String author = (String) req.getSession().getAttribute("currentUser");
String sql = "INSERT INTO news_articles (content, category, author, status) VALUES (?, ?, ?, ?)";
try (Connection conn = DatabaseConnector.establishConnection();
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, content);
pstmt.setString(2, category);
pstmt.setString(3, author);
pstmt.setInt(4, 0); // 0: 待機中, 1: 公開
pstmt.executeUpdate();
resp.sendRedirect("dashboard/writer.jsp?status=success");
} catch (SQLException e) {
e.printStackTrace();
resp.sendRedirect("dashboard/writer.jsp?status=error");
}
}
}
審査意見閲覧ページ
管理者からのフィードバックを確認するためのページです。本来は JSP 内に JDBC コードを含めるべきではありませんが、簡易的な実装例として Servlet でデータを取得し、JSP に渡す構成を想定します。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="com.env.system.model.Feedback" %>
<html>
<head>
<title>審査意見一覧</title>
</head>
<body>
<h2>管理者からのフィードバック</h2>
<table border="1" width="80%" align="center">
<tr>
<th>記事 ID</th>
<th>意見内容</th>
<th>日付</th>
</tr>
<%
List<Feedback> feedbackList = (List<Feedback>) request.getAttribute("feedbackList");
if (feedbackList != null) {
for (Feedback fb : feedbackList) {
%>
<tr>
<td><%= fb.getArticleId() %></td>
<td><%= fb.getMessage() %></td>
<td><%= fb.getTimestamp() %></td>
</tr>
<%
}
}
%>
</table>
</body>
</html>
記事修正機能
審査意見に基づき、撰稿者が記事を修正するためのインターフェースです。
package com.env.system.controller;
import com.env.system.dao.NewsDAO;
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("/news/modify")
public class ArticleModificationHandler extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int articleId = Integer.parseInt(req.getParameter("newsId"));
String newContent = req.getParameter("articleBody");
String newCategory = req.getParameter("categoryName");
NewsDAO dao = new NewsDAO();
try {
dao.updateArticle(articleId, newContent, newCategory);
resp.sendRedirect("dashboard/writer.jsp");
} catch (SQLException e) {
throw new RuntimeException("Update failed", e);
}
}
}