FreeMarker:显示自定义 404 页面而不重定向
FreeMarker : Displaying a custom 404 page without redirection
我有一个静态的 404 页面,里面有花哨的东西。
如果用户输入错误的 url 不存在的页面,我希望他看到那个 404 页面,但也希望保持 url 不变,以便用户看到s/he 输入 url 有什么错误。
进入的页面不存在:
http://localhost:10039/my.website/my/halp.html
404页面:
http://localhost:10039/my.website/my/notfound.html
简而言之,我不会在这里使用 "sendRedirect",而是 "get content" 的 pageNotFoundUrl 并在 url 仍然是 http://localhost:10039/my.website/my/halp.html
时显示它
我还按照 Kayaman 的建议尝试了 "forward" 而不是重定向,但在这种情况下我得到 " 无法转发。响应已提交。"
TestServlet 在 web.xml 中定义,而这个 class 扩展了 UtilFreemarkerServlet,它扩展了 FreemarkerServlet。
UtilFreemarkerServlet
public abstract class UtilFreemarkerServlet extends FreemarkerServlet {
private static final long serialVersionUID = 1L;
public static final String REQUEST_OBJECT_NAME = "RequestObject";
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void init() throws ServletException {
logger.info("init started");
super.init();
Configuration cfg = getConfiguration();
cfg.setLocalizedLookup(false);
}
@Override
protected ObjectWrapper createObjectWrapper() {
return ObjectWrapper.BEANS_WRAPPER;
}
@Override
protected HttpRequestParametersHashModel createRequestParametersHashModel(HttpServletRequest request) {
request.setAttribute(REQUEST_OBJECT_NAME, request);
return super.createRequestParametersHashModel(request);
}
}
TestServlet
public class TestServlet extends UtilFreemarkerServlet{
private static final long serialVersionUID = 1L;
private String website;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
boolean handleResult = handlerForRequest(req, resp);
}
protected boolean handlerForRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (resp.getStatus() == 404) {
String pageNotFoundUrl = "http://localhost:10039/my.website/my/notfound.html";
RequestDispatcher rd = req.getRequestDispatcher(url);
rd.forward(req, resp);
// resp.sendRedirect(url);
}
return true;
}
}
转发而不是重定向到所需资源,URL 将保持不变。
RequestDispatcher rd = request.getRequestDispatcher("my_404.html");
rd.forward(request, response);
RequestDispatcher 在我的例子中没有用,因为响应一直被提交。这是我最终为 Freemarker Servlet 提供的解决方案;
出于我的目的,我正在覆盖 Freemarker servlet 的几个方法,例如 service() 和 requestUrlToTemplatePath()。通过这种方式,我可以在响应提交之前进行干预。
首先覆盖服务方法。我的目的是检查请求的 url 页面是否存在。
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
checkIfPageExists(req);
super.service(req, resp);
}
checkIfPageTemplateExists 检查页面模板是否为空。如果为 null,则表示它不可用。在这种情况下,我设置了一个请求属性。否则说明存在
protected void checkIfPageExists(HttpServletRequest req)
throws ServletException {
String relativeUrl = requestUrlToTemplatePath(req);
try {
getConfiguration().getTemplate(relativeUrl); //throws exception if the template cannot be accessed
} catch (TemplateNotFoundException e) {
logger.debug("TemplateNotFoundException for " + relativeUrl);
pageNotFound = "/customNotFoundPage.html";
} catch (IOException e) {
logger.debug("IOException for " + relativeUrl);
pageNotFound = "/customNotFoundPage.html";
}
req.setAttribute(NOT_FOUND_PAGE, pageNotFoundPage);
}
项目符号 1 中的最后一行是针对 super.service() 方法的。这将触发 requestUrlToTemplatePath() 方法,该方法实际上是您可以在不更改 url 的情况下指定要显示的 url 页面的方法。
我只是检查请求是否具有 NOT_FOUND_PAGE 属性。如果是这样,只需覆盖路径本身并继续流程中的下一步。否则,直接使用superclass的路径即可。
@Override
protected String requestUrlToTemplatePath(HttpServletRequest request)
throws ServletException {
String path = super.requestUrlToTemplatePath(request);
//Check if NOT_FOUND_PAGE is requested
if(request.getAttribute(NOT_FOUND_PAGE) != null) {
path = (String) request.getAttribute(NOT_FOUND_PAGE);
}
return path;
}
我有一个静态的 404 页面,里面有花哨的东西。 如果用户输入错误的 url 不存在的页面,我希望他看到那个 404 页面,但也希望保持 url 不变,以便用户看到s/he 输入 url 有什么错误。
进入的页面不存在: http://localhost:10039/my.website/my/halp.html
404页面: http://localhost:10039/my.website/my/notfound.html
简而言之,我不会在这里使用 "sendRedirect",而是 "get content" 的 pageNotFoundUrl 并在 url 仍然是 http://localhost:10039/my.website/my/halp.html
时显示它我还按照 Kayaman 的建议尝试了 "forward" 而不是重定向,但在这种情况下我得到 " 无法转发。响应已提交。"
TestServlet 在 web.xml 中定义,而这个 class 扩展了 UtilFreemarkerServlet,它扩展了 FreemarkerServlet。
UtilFreemarkerServlet
public abstract class UtilFreemarkerServlet extends FreemarkerServlet {
private static final long serialVersionUID = 1L;
public static final String REQUEST_OBJECT_NAME = "RequestObject";
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void init() throws ServletException {
logger.info("init started");
super.init();
Configuration cfg = getConfiguration();
cfg.setLocalizedLookup(false);
}
@Override
protected ObjectWrapper createObjectWrapper() {
return ObjectWrapper.BEANS_WRAPPER;
}
@Override
protected HttpRequestParametersHashModel createRequestParametersHashModel(HttpServletRequest request) {
request.setAttribute(REQUEST_OBJECT_NAME, request);
return super.createRequestParametersHashModel(request);
}
}
TestServlet
public class TestServlet extends UtilFreemarkerServlet{
private static final long serialVersionUID = 1L;
private String website;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.service(req, resp);
boolean handleResult = handlerForRequest(req, resp);
}
protected boolean handlerForRequest(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if (resp.getStatus() == 404) {
String pageNotFoundUrl = "http://localhost:10039/my.website/my/notfound.html";
RequestDispatcher rd = req.getRequestDispatcher(url);
rd.forward(req, resp);
// resp.sendRedirect(url);
}
return true;
}
}
转发而不是重定向到所需资源,URL 将保持不变。
RequestDispatcher rd = request.getRequestDispatcher("my_404.html");
rd.forward(request, response);
RequestDispatcher 在我的例子中没有用,因为响应一直被提交。这是我最终为 Freemarker Servlet 提供的解决方案;
出于我的目的,我正在覆盖 Freemarker servlet 的几个方法,例如 service() 和 requestUrlToTemplatePath()。通过这种方式,我可以在响应提交之前进行干预。
首先覆盖服务方法。我的目的是检查请求的 url 页面是否存在。
@Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { checkIfPageExists(req); super.service(req, resp); }
checkIfPageTemplateExists 检查页面模板是否为空。如果为 null,则表示它不可用。在这种情况下,我设置了一个请求属性。否则说明存在
protected void checkIfPageExists(HttpServletRequest req) throws ServletException { String relativeUrl = requestUrlToTemplatePath(req); try { getConfiguration().getTemplate(relativeUrl); //throws exception if the template cannot be accessed } catch (TemplateNotFoundException e) { logger.debug("TemplateNotFoundException for " + relativeUrl); pageNotFound = "/customNotFoundPage.html"; } catch (IOException e) { logger.debug("IOException for " + relativeUrl); pageNotFound = "/customNotFoundPage.html"; } req.setAttribute(NOT_FOUND_PAGE, pageNotFoundPage); }
项目符号 1 中的最后一行是针对 super.service() 方法的。这将触发 requestUrlToTemplatePath() 方法,该方法实际上是您可以在不更改 url 的情况下指定要显示的 url 页面的方法。 我只是检查请求是否具有 NOT_FOUND_PAGE 属性。如果是这样,只需覆盖路径本身并继续流程中的下一步。否则,直接使用superclass的路径即可。
@Override protected String requestUrlToTemplatePath(HttpServletRequest request) throws ServletException { String path = super.requestUrlToTemplatePath(request); //Check if NOT_FOUND_PAGE is requested if(request.getAttribute(NOT_FOUND_PAGE) != null) { path = (String) request.getAttribute(NOT_FOUND_PAGE); } return path; }