如何从 Liferay/Java 中的 doView 返回状态 404

问题描述

我们的一位开发人员编写了一个使用 doView 方法呈现相关内容的 portlet。但是,如果用户在没有有效记录的情况下转到该 portlet 的有效路径下的页面,我们会收到 NPE。

一个例子是:

/<location>/<postcode>/<propertyname>

/london/w1/10-downing-street - 有效

/london/w1/sdsd-downing-streetsss - 无效

slug 将从数据库提取记录,因为它是唯一的,但如果它无效,它会在 fillRenderRequestAttributes 上抛出 NPE,我们需要它抛出状态 404。

代码

public void doView(RenderRequest renderRequest,RenderResponse renderResponse) throws IOException,PortletException {

    fillRenderRequestAttributes(renderRequest,renderResponse);
    
    if(_log.isDebugEnabled())
    {
       _log.debug("DoView");
    }
    try
    {
       super.doView(renderRequest,renderResponse);
    }
    catch(Exception e)
    {
       _log.debug("broken");
       e.printstacktrace();
    }
    
}

我假设我们需要围绕 fillRenderRequestAttributes 进行 try/catch 并且在捕获中我们需要抛出 404?如何才能做到这一点?任何示例都会有所帮助。

解决方法

doView 正在呈现 portlet 的输出,不是整个页面。因此,它没有状态代码。该页面在其他地方呈现(例如,使用主题装饰,以及页面上可能仍显示相关内容的任意数量的其他 portlet)。

在 portlet 世界中,您处理的不是 HttpServletRequest/Response 对,而是 PortletRequest/Response 对(如 {{ 1}}/RenderRequest)。考虑 HTTP 返回码是错误的:您甚至不能保证在响应已经发送回浏览器之前呈现 portlet:一旦您确定您的 portlet 无法呈现适当的输出, 页面可能已经在运行中,状态码为 200。或者它可能被异步渲染并被注入到页面中。

如果 portlet 无法在 Response 中呈现适当的输出,您将需要捕获异常并在 portlet 中显示正确的错误消息

否则,请考虑实施 doView(您拥有更多控制权)或 REST 端点。但请注意:404 是一个技术错误,而您正在处理业务层错误 - 两者应该以不同的方式处理。