【问题标题】:How do I catch or raise exceptions inside a Viewable object in a restful service如何在 Restful 服务中捕获或引发 Viewable 对象内的异常
【发布时间】:2012-06-01 17:28:14
【问题描述】:

如果页面名称为 PathParam,我希望能够从 restful 服务返回特定的 jsp 页面。部署应用程序后,这些页面将由不同的人添加和删除。

我相信使用Viewable 对象是一种不错的方式(我愿意接受更好/正确的方式。)

@GET
@Produces(MediaType.TEXT_HTML)
@Path("{page}") 
public Response showJSP(@PathParam("page") String page) {
    Viewable loadPage = null;

    try {
      loadPage = new Viewable("/" + page, null);
    } catch (Exception e) {
        return Response.status(404).build();
    }

  Response ret = Response.ok(loadPage).build();

//    if (ret.getStatus() == 500){
//          ret = Response.status(404).build();
//      }

 return ret;
}

以上是我的实验代码,包含我处理错误的尝试。

只要页面名称是有效的 jsp 页面,它就可以正常工作。如果我传入一个无效页面,我会得到

500 Internal Server Error

java.io.IOException: The template name, /someWrongFileName, could not be resolved to a fully qualified template name.....

我发现这个错误是在 Viewable 对象内部生成的,因此它不会引发异常,而且响应当然是一个有效页面,因此检查 500 状态不起作用。

我可以破解一些我很确定是错误的事情,例如,我真的不想将生成的页面和正则表达式字符串化为错误文本。

我希望能够检测到页面无效并简单地返回 404。

我是在正确的道路上还是有更好的方法?

如果我在正确的路径上,如何检测错误的页面名称?

【问题讨论】:

    标签: java rest jersey


    【解决方案1】:

    我已经尝试像您一样捕捉错误,但似乎很难。我想这个类从来没有打算以这种方式使用。

    Viewable 接口允许您使用 JSP 作为一种可视化应用程序资源表示的方法。通常,资源由您序列化为 JSON、XML 或传递给 Viewable 构造函数的 POJO 表示。

    据我了解,您在此处尝试执行的操作有些不同。您的资源是 JSP 本身,并且您似乎只想使页面对客户端可用,而不将任何对象传递给 Viewable 构造函数。

    HTTP 404 错误意味着找不到资源。在您的情况下(将 JSP 视为资源),当 JSP 的路径不正确时,这正是发生的情况,所以我理解您为什么要使用状态码。

    但是,我认为您尝试使用的界面的创建者对此事有不同的看法。他们没有将 JSP 视为资源,而是将其视为代表它们的工具。视图的构建在这里被视为完全不同的事情。服务器内部的事情,应该对客户端隐藏的事情。客户端必须接收包含 HTML 字符串的响应。它如何发生根本不重要。在这种情况下,HTTP 500 是完全可以理解的。

    如果您只想使用 GET 请求来获取 JSP 的内容,您可以忽略 Viewable 接口甚至 Jersey 本身。如果您的 web.xml 设置得当,那么这些页面无论如何都应该可以访问。您不必将 JSP 名称传递给带注释的方法。只需使用文档本身的路径即可。自定义 404 也可以在 web.xml 中处理。

    假设您有一个名为 MyApp 的项目并部署到路径 <host>:<port>/MyApp

    其网页目录结构如下。

    -Web pages
    |-META-INF
    |-WEB-INF
    |-error
    |\-error404.jsp
    |-package1
    ||-ResourceClass
    ||\-page1.jsp
    |-pages
    ||-plainpage1.jsp
    |\-plainpage2.jsp
    \-index.jsp
    

    现在,让我们假设 web.xml 看起来像这样:

    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <servlet>
        <servlet-name>ServletAdaptor</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServletAdaptor</servlet-name>
        <url-pattern>/resources/ *</url-pattern>
    </servlet-mapping>
    <error-page>
        <error-code>404</error-code>
        <location>/err/err404.jsp</location>
    </error-page>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    

    您可以使用 Viewable 界面为您的实际资源显示一个页面。这就是应该如何使用接口的方式。作为一种显示资源的 html 表示形式的方法,而不是资源本身

    package package1;
    
    @Path("/")
    public class ResourceClass {    
    
    @Path("/POJO/{id}")
    @GET
    public Response tryToGetBadView(@PathParam("id") String id) {
        MyPOJOClass entity = null;
        //fetch your POJO from database/file/whatever          
        return Response.ok().entity(new Viewable("page1",entity)).build();        
    }
    }
    

    您可以使用如下路径获得适当的视图:

    <host>:<port>/MyApp/resources/POJO/1
    

    同时能够在没有 Jersey Servlet Container 帮助的情况下获得普通的 JSP。这些文件就在那里,它们不需要任何其他的表示,而不是它们自己。您的 Jersey Servlet 容器的路径指定为

    <host>:<port>/resources/*
    

    因此,您可以省略容器并从您的 Web Apps 文件夹中访问普通文件。图像、css 和 JSP。 像这样:

    <host>:<port>/MyApp/pages/plainpage1.jsp
    

    你得到同样的方式

    <host>:<port>/MyApp/index.jsp
    

    甚至是你通常用来构造 Viewable 对象的页面(不保证它在不传递 POJO 的情况下可以正常工作)

    <host>:<port>/MyApp/package1/ResourceClass/page1.jsp
    

    对于这些“静态”文件,每次选择不存在页面的名称时都会收到 404。显示的错误页面将是 web.xml 中指定的页面

    我就是这样做的。使用 Jersey 来提供普通的 JSP 似乎有点过头了,而且会带来不必要的复杂性。如果不是你的意思,我建议重新考虑设计。

    请注意,虽然没有使用 Jersey,但仍然可以通过您认为 RESTful 的方式访问页面。

    如果你真的想坚持你的实验代码,你也可以尝试使用 IO API 访问你的网页文件夹中的目录并手动检查请求的文件是否存在。这会很丑陋,但它可能会起作用。

    【讨论】:

    • 我的问题是显示的 500 错误是作为从可视对象返回的内容生成的。在将状态传递给响应对象之前,我没有抛出异常,也没有办法检查状态。所以我没有要解析的错误代码。
    • @Driver 好吧,我没有明白问题的要点。检查我编辑的答案。
    • 我还有其他方法可以处理除此之外的宁静调用,因此我需要保留球衣。这个方法的目的是提供一个普通的jsp页面作为对@GET请求的响应,接受html给定一个有效的@PathParam("page")。给定我上面的代码,整个事情(包括 jsp 页面和其他服务)都可以工作,除非页面不存在并且我从可查看的内容中收到 500 错误。基本上我试图保持网址简短。如果我收到了一个 restful 方法可以处理的请求,让它,如果没有尝试提供静态/jsp 页面,则返回 404。
    • @Driver 我不是要你放弃泽西岛。只需放弃这种单一方法,将这些 JSP 作为静态资源提供服务。其余的可以保持几乎相同。这只是一种解决方法,但在这种情况下我真的想不出更好的解决方案。
    • 感谢您的帮助,我从您的示例中挑选了一些有用的信息。
    【解决方案2】:

    我在another post 中找到了我要查找的内容,并在下面修改了我的方法。

    @GET
    @Produces("text/html")
    @Path("{page}") 
    public void showJSP(@Context HttpServletResponse response,
                        @Context HttpServletRequest request,
                        @PathParam("orderId") String orderId) throws ServletException, IOException {
        request.getRequestDispatcher(page + ".jsp").forward(request, response);
    }
    

    这给了我我正在寻找的 404,我的所有服务仍然有效。

    如果这是执行此操作的“错误”方式,我仍然愿意接受想法,但现在它有效。

    【讨论】:

      猜你喜欢
      • 2014-01-20
      • 1970-01-01
      • 2012-03-14
      • 1970-01-01
      • 2013-06-30
      • 2017-07-03
      • 2022-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多