如何绕过AEM默认错误处理?在AEM Servlet中返回自定义HTTP错误响应
问题
能否在AEM运行的Sling Servlet中直接返回带自定义内容的HTTP错误响应?
背景
现有一个处理POST表单请求的Sling Servlet,代码如下:
@SlingServlet( methods = HttpConstants.METHOD_POST, resourceTypes = NameConstants.NT_PAGE, selectors = SELECTOR) public class MyServlet extends SlingAllMethodsServlet { //... @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) { //if something is wrong with the request Gson gson = new Gson(); gson.toJson(errorResponse, response.getWriter()); response.setContentType(MediaType.JSON_UTF_8.toString()); response.sendError(HttpServletResponse.SC_BAD_REQUEST); //... } //... }
当该Servlet返回HTTP 400 Bad Request时,期望获取Servlet中生成的JSON响应,但AEM会通过/apps/sling/servlet/errorhandler生成HTML页面,仅将JSON添加在内容开头:
{"errors":["The provided value is incorrect"]} <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html> <head><title>400 Bad Request</title></head> <body> <h1>400 Bad Request</h1> <p>Cannot serve request to on this server.</p> (...) </body> </html>
已知可创建自定义错误页,但需Servlet中的验证错误来生成有意义的响应。AEM版本:6.5
解决方案
可以通过以下两种方式实现直接返回自定义JSON错误响应:
方法一:使用setStatus替代sendError
sendError会触发Sling的错误处理机制,导致默认错误页被追加到响应中。改用setStatus设置错误状态码,同时直接写入自定义响应内容:
@Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { // 验证请求出错时 ErrorResponse errorResponse = new ErrorResponse(); errorResponse.setErrors(List.of("The provided value is incorrect")); Gson gson = new Gson(); response.setContentType(MediaType.JSON_UTF_8.toString()); // 设置400状态码但不触发错误处理 response.setStatus(HttpServletResponse.SC_BAD_REQUEST); gson.toJson(errorResponse, response.getWriter()); // 确保响应输出完成 response.getWriter().flush(); }
这种方式不会触发Sling的错误处理器,响应内容就是你生成的纯JSON。
方法二:自定义错误处理器并传递错误信息
如果必须使用sendError(比如需要触发某些全局错误逻辑),可以通过请求属性传递错误信息,再创建对应JSON格式的错误处理器:
- 在Servlet中设置错误属性并调用
sendError:
@Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { ErrorResponse errorResponse = new ErrorResponse(); errorResponse.setErrors(List.of("The provided value is incorrect")); // 将错误对象存入请求属性 request.setAttribute("customError", errorResponse); response.setContentType(MediaType.JSON_UTF_8.toString()); response.sendError(HttpServletResponse.SC_BAD_REQUEST); }
- 创建自定义Sling错误处理器Servlet,匹配JSON请求和400状态码:
@SlingServlet( methods = "*", resourceTypes = "sling/servlet/errorhandler", selectors = "400", extensions = "json", priority = 100) // 设置更高优先级覆盖默认处理器 public class Custom400JsonErrorHandler extends SlingAllMethodsServlet { @Override protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { ErrorResponse errorResponse = (ErrorResponse) request.getAttribute("customError"); if (errorResponse == null) { // 处理无自定义错误的情况 errorResponse = new ErrorResponse(); errorResponse.setErrors(List.of("Bad Request")); } Gson gson = new Gson(); response.setContentType(MediaType.JSON_UTF_8.toString()); response.setStatus(HttpServletResponse.SC_BAD_REQUEST); gson.toJson(errorResponse, response.getWriter()); } // 覆盖doPost方法处理POST请求的错误 @Override protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException { doGet(request, response); } }
注意要确保请求的Accept头为application/json,或者请求URL带有.json后缀,这样才会匹配到这个自定义错误处理器。
内容的提问来源于stack exchange,提问作者pkalinow
相关产品推荐
相关产品推荐

