【问题标题】:FreeMarker : Displaying a custom 404 page without redirectionFreeMarker:显示自定义 404 页面而不重定向
【发布时间】:2015-07-02 07:18:56
【问题描述】:

我有一个静态 404 页面,里面有很多花哨的东西。 如果用户输入了一个不存在的页面的错误 url,我希望他看到那个 404 页面,但也希望保持 url 原样,以便用户查看他/她输入了什么错误网址。

进入的页面不存在: http://localhost:10039/my.website/my/halp.html

404 页面: http://localhost:10039/my.website/my/notfound.html

简而言之,我不会在这里使用“sendRedirect”,而是“获取 pageNotFoundUrl 的内容”并在 url 仍为 http://localhost:10039/my.website/my/halp.html 时显示它

我还尝试按照 Kayaman 的建议“转发”而不是重定向,但在这种情况下,我得到 “无法转发。响应已提交。”

TestServlet 定义在 web.xml 中,并且这个类扩展了 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;
    }

}

【问题讨论】:

  • 您可以使用 javascript 更改页面内容...并使用您从用户那里获取数据的同一页面...
  • @CoderNeji,不确定是否要将 JS 放入我的项目中。这可以在服务器端处理它们吗?
  • 您可以在服务器端执行所有这些操作,但 url 会随着 404 页面的存在而改变,并且您已将 404 页面设置为错误页面,并且它有一些获取路径。
  • @shamaleyte 使用转发而不是重定向来保留 URL,但显示 404 页面的内容。
  • CoderNeji,那么如果不更改服务器端的 url 就不可能? @Kayaman,我该如何转发?由 RequestDispatcher ?

标签: java servlets freemarker


【解决方案1】:

执行转发而不是重定向到所需资源,URL 将保持不变。

RequestDispatcher rd = request.getRequestDispatcher("my_404.html");
rd.forward(request, response);

【讨论】:

  • 我收到以下错误“无法转发。响应已提交。”。在提交响应之前有什么办法吗?
  • 您需要尽快执行此操作,然后再对响应对象执行任何操作。编辑问题并显示您的代码。
【解决方案2】:

RequestDispatcher 在我的情况下没有用,因为响应总是被提交。这是我最终为 Freemarker Servlets 提供的解决方案;

为了我的目的,我重写了几个 Freemarker servlet 方法,例如 service() 和 requestUrlToTemplatePath()。通过这种方式,我可以在响应提交之前进行干预。

  1. First Override 用于服务方法。我的目的是检查请求的 url 页面是否存在。

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {         
        checkIfPageExists(req);
        super.service(req, resp);                       
    }
    
  2. 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);
    }
    
  3. 项目符号 1 中的最后一行用于 super.service() 方法。这将触发 requestUrlToTemplatePath() 方法,该方法实际上是您可以指定要显示的 url 页面而不更改 url 的方法。 我只是在检查请求是否具有 NOT_FOUND_PAGE 属性。如果是这样,只需覆盖路径本身并继续流程中的下一步。否则,只需使用超类的路径。

    @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;
     }
    

【讨论】:

    猜你喜欢
    • 2018-01-05
    • 2019-09-14
    • 1970-01-01
    • 1970-01-01
    • 2012-10-01
    • 1970-01-01
    • 2014-12-23
    • 1970-01-01
    • 2011-11-17
    相关资源
    最近更新 更多