package com.mzh.library.controller; import com.mzh.library.dao.impl.JdbcReaderDao; import com.mzh.library.entity.AuthenticatedUser; import com.mzh.library.entity.Reader; import com.mzh.library.entity.ReaderSearchCriteria; import com.mzh.library.entity.ReaderStatus; import com.mzh.library.service.ReaderService; import com.mzh.library.service.ServiceResult; import com.mzh.library.service.impl.ReaderServiceImpl; import com.mzh.library.util.SessionAttributes; import java.io.IOException; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Optional; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class ReaderManagementServlet extends HttpServlet { private static final String MANAGE_JSP = "/WEB-INF/jsp/readers/manage.jsp"; private static final String FORM_JSP = "/WEB-INF/jsp/readers/form.jsp"; private static final String UNAUTHORIZED_JSP = "/WEB-INF/jsp/auth/unauthorized.jsp"; private static final String FLASH_SUCCESS = "flashSuccess"; private static final String FLASH_ERROR = "flashError"; private ReaderService readerService; @Override public void init() { this.readerService = new ReaderServiceImpl(new JdbcReaderDao()); } @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path = request.getServletPath(); if ("/readers/new".equals(path)) { renderForm(request, response, "创建读者", "/readers", defaultReader(), Collections.emptyMap(), Collections.emptyMap(), null); return; } if ("/readers/edit".equals(path)) { showEditForm(request, response); return; } if (!"/readers".equals(path)) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } showManagementList(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String path = request.getServletPath(); if ("/readers".equals(path)) { createReader(request, response); return; } if ("/readers/update".equals(path)) { updateReader(request, response); return; } if ("/readers/delete".equals(path)) { deactivateReader(request, response); return; } response.sendError(HttpServletResponse.SC_NOT_FOUND); } private void showManagementList(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ReaderSearchCriteria criteria = searchCriteria(request); request.setAttribute("criteria", criteria); request.setAttribute("statuses", ReaderStatus.values()); applyFlash(request); ServiceResult> searchResult = readerService.searchReaders(criteria); request.setAttribute("readers", searchResult.isSuccessful() ? searchResult.getData() : Collections.emptyList()); if (!searchResult.isSuccessful()) { request.setAttribute("errorMessage", searchResult.getMessage()); request.setAttribute("errors", searchResult.getErrors()); } request.getRequestDispatcher(MANAGE_JSP).forward(request, response); } private void showEditForm(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long id = requiredLong(request.getParameter("id"), -1L); ServiceResult> result = readerService.findReader(id); if (!result.isSuccessful() || !result.getData().isPresent()) { flashError(request, result.isSuccessful() ? "未找到读者档案。" : result.getMessage()); response.sendRedirect(request.getContextPath() + "/readers"); return; } renderForm(request, response, "编辑读者", "/readers/update", result.getData().get(), Collections.emptyMap(), Collections.emptyMap(), null); } private void createReader(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ReaderForm form = readReaderForm(request, false); if (!form.getErrors().isEmpty()) { renderForm(request, response, "创建读者", "/readers", form.getReader(), form.getValues(), form.getErrors(), "请修正高亮的读者字段。"); return; } ServiceResult result = readerService.createReader(currentUser(request), form.getReader()); if (!result.isSuccessful()) { handleFormFailure(request, response, "创建读者", "/readers", form, result); return; } flashSuccess(request, result.getMessage()); response.sendRedirect(request.getContextPath() + "/readers"); } private void updateReader(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ReaderForm form = readReaderForm(request, true); if (!form.getErrors().isEmpty()) { renderForm(request, response, "编辑读者", "/readers/update", form.getReader(), form.getValues(), form.getErrors(), "请修正高亮的读者字段。"); return; } ServiceResult result = readerService.updateReader(currentUser(request), form.getReader()); if (!result.isSuccessful()) { handleFormFailure(request, response, "编辑读者", "/readers/update", form, result); return; } flashSuccess(request, result.getMessage()); response.sendRedirect(request.getContextPath() + "/readers"); } private void deactivateReader(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { long id = requiredLong(request.getParameter("id"), -1L); ServiceResult result = readerService.deactivateReader(currentUser(request), id); if (isPermissionDenied(result)) { forwardDenied(request, response, result.getMessage()); return; } if (result.isSuccessful()) { flashSuccess(request, result.getMessage()); } else { flashError(request, result.getMessage()); } response.sendRedirect(request.getContextPath() + "/readers"); } private void handleFormFailure(HttpServletRequest request, HttpServletResponse response, String title, String action, ReaderForm form, ServiceResult result) throws ServletException, IOException { if (isPermissionDenied(result)) { forwardDenied(request, response, result.getMessage()); return; } renderForm(request, response, title, action, form.getReader(), form.getValues(), result.getErrors(), result.getMessage()); } private void renderForm(HttpServletRequest request, HttpServletResponse response, String title, String action, Reader reader, Map formValues, Map errors, String errorMessage) throws ServletException, IOException { request.setAttribute("statuses", ReaderStatus.values()); request.setAttribute("formTitle", title); request.setAttribute("formAction", action); request.setAttribute("reader", reader); request.setAttribute("formValues", formValues); request.setAttribute("errors", errors); if (errorMessage != null && !errorMessage.isEmpty()) { request.setAttribute("errorMessage", errorMessage); } request.getRequestDispatcher(FORM_JSP).forward(request, response); } private ReaderForm readReaderForm(HttpServletRequest request, boolean requireId) { Map values = formValues(request); Map errors = new LinkedHashMap<>(); Reader reader = new Reader(); if (requireId) { reader.setId(parseLong(values.get("id"), "id", "请选择有效的读者。", errors)); } reader.setIdentifier(values.get("identifier")); reader.setUserId(optionalPositiveLong(values.get("userId"), "userId", "请输入有效的关联账户 ID。", errors)); reader.setFullName(values.get("fullName")); reader.setPhone(values.get("phone")); reader.setEmail(values.get("email")); reader.setMaxBorrowCount(parseInt(values.get("maxBorrowCount"), "maxBorrowCount", "请输入有效的最大借阅数量。", errors)); try { reader.setStatus(ReaderStatus.fromCode(values.get("status"))); } catch (IllegalArgumentException ex) { errors.put("status", "请选择状态。"); } return new ReaderForm(reader, values, errors); } private Map formValues(HttpServletRequest request) { Map values = new LinkedHashMap<>(); values.put("id", trim(request.getParameter("id"))); values.put("identifier", trim(request.getParameter("identifier"))); values.put("userId", trim(request.getParameter("userId"))); values.put("fullName", trim(request.getParameter("fullName"))); values.put("phone", trim(request.getParameter("phone"))); values.put("email", trim(request.getParameter("email"))); values.put("status", trim(request.getParameter("status"))); values.put("maxBorrowCount", trim(request.getParameter("maxBorrowCount"))); return values; } private ReaderSearchCriteria searchCriteria(HttpServletRequest request) { return new ReaderSearchCriteria( request.getParameter("identifier"), request.getParameter("name"), request.getParameter("contact"), request.getParameter("status") ); } private Reader defaultReader() { Reader reader = new Reader(); reader.setStatus(ReaderStatus.ACTIVE); reader.setMaxBorrowCount(5); return reader; } private Long optionalPositiveLong(String value, String field, String message, Map errors) { String trimmed = trim(value); if (trimmed.isEmpty()) { return null; } try { long parsed = Long.parseLong(trimmed); if (parsed <= 0) { errors.put(field, message); return null; } return parsed; } catch (NumberFormatException ex) { errors.put(field, message); return null; } } private long parseLong(String value, String field, String message, Map errors) { String trimmed = trim(value); if (trimmed.isEmpty()) { errors.put(field, message); return 0L; } try { long parsed = Long.parseLong(trimmed); if (parsed <= 0) { errors.put(field, message); } return parsed; } catch (NumberFormatException ex) { errors.put(field, message); return 0L; } } private int parseInt(String value, String field, String message, Map errors) { String trimmed = trim(value); if (trimmed.isEmpty()) { errors.put(field, message); return -1; } try { return Integer.parseInt(trimmed); } catch (NumberFormatException ex) { errors.put(field, message); return -1; } } private long requiredLong(String value, long fallback) { try { long parsed = Long.parseLong(trim(value)); return parsed > 0 ? parsed : fallback; } catch (NumberFormatException ex) { return fallback; } } private boolean isPermissionDenied(ServiceResult result) { return !result.isSuccessful() && "您无权管理读者。".equals(result.getMessage()); } private void forwardDenied(HttpServletRequest request, HttpServletResponse response, String message) throws ServletException, IOException { response.setStatus(HttpServletResponse.SC_FORBIDDEN); request.setAttribute("errorMessage", message); request.getRequestDispatcher(UNAUTHORIZED_JSP).forward(request, response); } private AuthenticatedUser currentUser(HttpServletRequest request) { HttpSession session = request.getSession(false); Object value = session == null ? null : session.getAttribute(SessionAttributes.AUTHENTICATED_USER); return value instanceof AuthenticatedUser ? (AuthenticatedUser) value : null; } private void applyFlash(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return; } moveFlash(session, request, FLASH_SUCCESS, "successMessage"); moveFlash(session, request, FLASH_ERROR, "errorMessage"); } private void moveFlash(HttpSession session, HttpServletRequest request, String sessionKey, String requestKey) { Object value = session.getAttribute(sessionKey); if (value != null) { request.setAttribute(requestKey, value); session.removeAttribute(sessionKey); } } private void flashSuccess(HttpServletRequest request, String message) { request.getSession().setAttribute(FLASH_SUCCESS, message); } private void flashError(HttpServletRequest request, String message) { request.getSession().setAttribute(FLASH_ERROR, message); } private String trim(String value) { return value == null ? "" : value.trim(); } private static final class ReaderForm { private final Reader reader; private final Map values; private final Map errors; private ReaderForm(Reader reader, Map values, Map errors) { this.reader = reader; this.values = values; this.errors = errors; } private Reader getReader() { return reader; } private Map getValues() { return values; } private Map getErrors() { return errors; } } }