java - Servlet/JSP 流程控制 : Enums, 异常,还是其他原因?

标签 java jsp exception enums

我最近继承了一个使用裸 servlet 和 JSP(即:无框架)开发的应用程序。我的任务是清理错误处理工作流程。目前,每个<form>在工作流中提交给 servlet,并根据表单提交的结果,servlet 执行以下两件事之一:

  1. 如果一切正常,Servlet 将转发或重定向到工作流程中的下一页。
  2. 如果出现问题,例如用户名或密码无效,servlet 会转发到特定于问题情况的页面。例如,有AccountDisabled.jsp、AccountExpired.jsp、AuthenticationFailed.jsp、SecurityQuestionIn Correct.jsp等页面。

我需要重新设计这个系统,以集中处理问题情况的方式。到目前为止,我已经考虑了两种可能的解决方案:

  • Exception s
    • 创建一个特定于我的需求的异常类,例如AuthException 。必要时从此类继承以更加具体(例如: InvalidUsernameExceptionInvalidPasswordExceptionAccountDisabledException 等)。每当出现问题情况时,就抛出特定于该情况的异常。通过 web.xml 捕获所有异常,并使用 <error-page> 将它们路由到适当的页面。标签。
  • enum s
    • 采用错误代码方法, enum跟踪错误代码和描述。可以从成品的资源包中读取描述。

我更倾向于 enum方法,因为身份验证失败并不是真正的“异常(exception)情况”,而且我认为向服务器日志添加困惑没有任何好处。另外,我只是用另一种令人头痛的维护问题来代替。我不需要维护单独的 JSP,而是拥有单独的 Exception类。

我计划在专门为此目的编写的 servlet 中实现“错误”处理。我还将消除所有单独的错误页面,而不是设置 error request 属性,其中包含要显示给用户并转发回引荐来源网址的错误消息。每个目标 servlet(登录、更改密码、AnswerProfileQuestions 等)都会向请求添加错误代码,并在出现问题时重定向到我的新 servlet。我的新 servlet 看起来像这样:

public enum Error {
    INVALID_PASSWORD(5000, "You have entered an invalid password."),
    ACCOUNT_DISABLED(5002, "Your account has been disabled."),
    SESSION_EXPIRED(5003, "Your session has expired. Please log in again."),
    INVALID_SECURITY_QUESTION(5004, "You have answered a security question incorrectly.");

    private final int code;
    private final String description;

    Error(int code, String description) {
        this.code = code;
        this.description = description;
    }

    public int getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }
};

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    String sendTo = "UnknownError.jsp";
    String message = "An unknown error has occurred.";

    int errorCode = Integer.parseInt((String)request.getAttribute("errorCode"), 10);

    Error errors[] = Error.values();
    Error error = null;

    for (int i = 0; error == null && i < errors.length; i++) {
        if (errors[i].getCode() == errorCode) {
            error = errors[i];
        }
    }

    if (error != null) {
        sendTo = request.getHeader("referer");
        message = error.getDescription();
    }

    request.setAttribute("error", message);

    request.getRequestDispatcher(sendTo).forward(request, response);
}

protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    doGet(request, response);
}

由于对 Java EE 相当缺乏经验(这是我第一次真正接触 JSP 和 servlet),我确信我遗漏了一些东西,或者我的方法不是最佳的。我是否走在正确的道路上,或者我是否需要重新考虑我的策略?

最佳答案

(网络)应用程序中的异常/错误处理是一个敏感话题。有些人可能会选择抛出硬异常并在单个位置捕获它们,其他人可能会选择传递错误消息的集合。

我自己更喜欢抛出异常。这样更加清晰简洁,并且具有更好的可重用性、可维护性和可测试性。设计Validatorvalidate() 的接口(interface)抛出 ValidatorException 的方法。相应地实现所需的 validator 。收集 validator 并在 try/catch block 中一一运行它们,并在那里收集异常。例如

Map<String, String> messages = new HashMap<String, String>();
for (Validator validator : validators) {
    try {
        validator.validate(value);
    } catch (ValidatorException e) { 
        messages.add(fieldname, e.getMessage());
    }
}

然后通常会将请求转发回同一页面(您在其中输入表单),并在输入字段旁边或表单顶部或底部的某处显示错误消息。这比不同的错误页面更加用户友好,后者需要用户再单击一个按钮/链接才能返回表单,并且用户必须记住/弄清楚错误实际上是什么。

所有标准错误消息当然可以存储在 enum 中,或更优选地在外部资源文件中,例如属性文件。这样就更容易维护,也更容易向您的网络应用程序添加多种语言。

对于不可恢复的错误,例如死数据库或代码中的错误(运行时错误、内部服务器错误等),我只是让异常遍历所有层,以便您可以通过以下方式“捕获”它:通用和自定义错误页面,您可以将其定义为 <error-page>web.xml 。您可以为每种类型 Exception 定义单独的错误页面和/或 HTTP 状态代码。

顺便说一句,这也是普通 MVC 框架的工作原理。

关于java - Servlet/JSP 流程控制 : Enums, 异常,还是其他原因?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2547486/

相关文章:

java - 对象为空,但应用程序的行为就像不是

java - 捕获 JSP 输出,保存到文件

java - 发生异常时显示完整的堆栈跟踪

php - 困惑的: PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0?

exception - 类的成员函数之间的异常处理

java - java中如何处理字节序列?

java - 掷骰子游戏 : How do i get the while loop in this code from going into an infinite loop?

java - ANDROID--如何找到手机相对于周围世界的位置?

java - JSP属性查找错误

java - 即使不需要 ScrollView,如何使 Activity 可滚动?