You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免API Servlet中异常处理代码重复?

消除Servlet异常处理代码重复的方案

1. 抽象基类Servlet(最易落地的方案)

创建一个抽象的BaseApiServlet继承HttpServlet,把重复的异常处理逻辑统一放在基类的doGet/doPost方法中,只留一个抽象方法让子类实现具体业务逻辑:

public abstract class BaseApiServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        processRequest(req, resp);
    }

    private void processRequest(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("application/json");
        try {
            // 调用子类的业务逻辑方法
            handleBusiness(req, resp);
        } catch (ServiceException1 e) {
            writeErrorResponse(resp, 400, e.getMessage());
        } catch (ServiceException2 e) {
            writeErrorResponse(resp, 403, e.getMessage());
        }
        // 依次处理剩余的4-5种服务层异常
    }

    // 子类需实现的业务逻辑入口
    protected abstract void handleBusiness(HttpServletRequest req, HttpServletResponse resp) throws Exception;

    // 统一生成JSON错误响应的工具方法
    private void writeErrorResponse(HttpServletResponse resp, int status, String message) throws IOException {
        resp.setStatus(status);
        String json = String.format("{\"code\":%d,\"message\":\"%s\"}", status, message);
        resp.getWriter().write(json);
    }
}

现有所有API Servlet只需修改继承关系,把原有的业务代码移到handleBusiness方法中即可;新增Servlet时直接继承基类实现该方法,完全不用重复写异常处理代码。

2. 异常处理Filter(无侵入式方案)

Filter完全可以捕获Servlet抛出的异常,只需在doFilter方法中用try-catch包裹请求链路,统一处理异常:

@WebFilter(urlPatterns = "/api/*") // 拦截所有API路径的请求
public class ApiExceptionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setContentType("application/json");
        try {
            chain.doFilter(request, response);
        } catch (ServiceException1 e) {
            writeErrorResponse(resp, 400, e.getMessage());
        } catch (ServiceException2 e) {
            writeErrorResponse(resp, 403, e.getMessage());
        }
        // 处理剩余的服务层异常
    }

    private void writeErrorResponse(HttpServletResponse resp, int status, String message) throws IOException {
        resp.setStatus(status);
        String json = String.format("{\"code\":%d,\"message\":\"%s\"}", status, message);
        resp.getWriter().write(json);
    }
}

这个方案不需要修改任何现有Servlet代码,只需添加Filter并配置拦截路径即可生效,适合不想改动现有代码结构的场景。

3. 全局异常处理Servlet(基于容器配置)

通过web.xml的<error-page>标签,将特定异常类型映射到专门的错误处理Servlet:

<web-app>
    <error-page>
        <exception-type>com.yourpackage.ServiceException1</exception-type>
        <location>/error-handler</location>
    </error-page>
    <error-page>
        <exception-type>com.yourpackage.ServiceException2</exception-type>
        <location>/error-handler</location>
    </error-page>
    <!-- 依次配置剩余的服务层异常 -->
</web-app>

再编写一个ErrorHandlerServlet统一处理异常并生成JSON响应:

@WebServlet("/error-handler")
public class ErrorHandlerServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        handleError(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        handleError(req, resp);
    }

    private void handleError(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        resp.setContentType("application/json");
        Throwable exception = (Throwable) req.getAttribute("javax.servlet.error.exception");
        if (exception instanceof ServiceException1) {
            writeErrorResponse(resp, 400, exception.getMessage());
        } else if (exception instanceof ServiceException2) {
            writeErrorResponse(resp, 403, exception.getMessage());
        }
        // 处理剩余的服务层异常
    }

    private void writeErrorResponse(HttpServletResponse resp, int status, String message) throws IOException {
        resp.setStatus(status);
        String json = String.format("{\"code\":%d,\"message\":\"%s\"}", status, message);
        resp.getWriter().write(json);
    }
}

该方案完全基于容器配置,无需修改现有Servlet代码,适合实现容器级别的全局异常统一处理。


内容的提问来源于stack exchange,提问作者John Little

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 15:24:15