【问题标题】:Handling URLs in a Java Serlvet在 Java Servlet 中处理 URL
【发布时间】:2012-11-06 15:24:16
【问题描述】:

我对 servlet 相当陌生,如果 uri 匹配某个路径,我处理来自客户端的响应的方式是:

public class EntryServlet extends HttpServlet
{
  public void doGet (HttpServletRequest request, HttpServletResponse response) 
    throws IOException
  {
    String uri = request.getRequestURI ();

    if (uri.matches ("/1")) {
      do something....
    } else if (uri.matches ("/2")) {
      do something else.....    
    } else {
      throw error message...
    }
  }
}

这只有在我的网络服务有几个页面时才有效。但是假设我有 50 个 xml 文档,我想将 exmaple.com/1 映射到一个 xml ...到 example.com/50 到另一个 xml。现在如果有 50 个 if else 语句来处理每个资源,那将是一个糟糕的设计。有什么更好的方法来实现这一点?我试图在没有第三方应用程序/插件/框架的情况下纯粹在 java 中做到这一点

更新: 我只使用一个带有后台线程的 servlet。本质上是处理文件的客户端请求,后台线程处理处理并将 xml 文档存储在数据库中。我希望每个 xml 文档都成为 Web 服务上的资源。

【问题讨论】:

    标签: java http url servlets


    【解决方案1】:

    你给出的答案是“我想要地图”,所以让我们使用地图

    你有 2 个选项(我现在看到的)

    1:您将“/1”作为键并将字符串作为映射到您的 xyz.xml 的值

    2:你把“/1”作为一个键,然后把一个实现了“Executor”接口的对象放在...

    在这两种情况下,您都会查找键的值,然后使用值对象返回有用的东西。

    把它放在你的 Servlet 的 init 中并用你的对象填充它:

    Map<String,String> myActions = new HashMap<String,String>();
    myActions.put("/1","one.xml");
    .....
    

    现在你可以这样做了:

    String uri = request.getRequestURI ();
    
    if (myActions.containsKey(uri)) {
       String value = myActions.get(uri);
       do something with value
    } else {
       throw error message...
    }
    

    您可以通过使用实现此功能的对象轻松地将其更改为选项 2:

    public interface Action {
        String execute(HttpServletRequest req, HttpServletResponse res) throws ServletException,
                IOException;
    }
    

    【讨论】:

      【解决方案2】:

      答案可能取决于您要如何处理 URI 中的信息。在编写 REST 风格的应用程序时,URI 是将信息传递给应用程序的主要方式之一。因此,如果您可能想重新考虑您对其他软件包的反感,因为 REST API 非常受欢迎是有充分理由的。

      坚持使用普通的 Servlet,假设我们有 50 个 xml 文档,我们希望根据通过 URL 传递的 id 号来提供这些文档。 我们可以在数据库中存储一个表,指示 id 号和文档之间的对应关系。或者我们可以将这些数据存储到 CSV 文件中。无论哪种方式,对于这样一个相对较小的表,我都会在 Servlet 启动时将整个表加载到内存中。您可以将代码放在 init() 方法中以将数据加载到您的应用程序中。

      然后我们有这样的东西:

      static HashMap<Integer, String> fileMap;
      public void init() {
          fileMap = new HashMap<> ();
          fileMap.put(1,"thing1.xml");
          fileMap.put(2,"thing2.xml");
          fileMap.put(3,"Otherthingy.xml");
      }
      

      现在您可以在 doGet 方法中编写更简洁的代码。

      public void doGet (HttpServletRequest request, HttpServletResponse response) 
                                     throws IOException  {
              String uri = request.getRequestURI();
              int slash = uri.indexOf("/");
              if(slash+1 == uri.length())
                  //throw an error
      
              String idString = request.getRequestURI().substring(slash+1);
              int id = Integer.parseInt(idString);
              //should put this in a try catch block and throw an error if it is not a number.
              String requestedFile = fileMap.get(id);
              if(requestedFile == null)
                  //throw some error.
              // Do whatever you need to do with the file.
      }
      

      【讨论】:

        【解决方案3】:

        你应该

        1. 将每个 URI 特定逻辑移动到不同的 servlet。
        2. 使用 Java Servlet 规范中的 servlet 映射概念并在您的 web.xml 中定义以下内容

          <!- Define the servlets here, ofcourse you should use meaningful names -->
          <servlet>
              <servlet-name>servlet-1</servlet-name>
              <servlet-class>com.vikdor.webapps.ServletForURI1</servlet-class>
          </servlet>
          <servlet>
              <servlet-name>servlet-2</servlet-name>
              <servlet-class>com.vikdor.webapps.ServletForURI2</servlet-class>
          </servlet>
          ....
          
          
          <!- Map the servlet to the URL pattern -->
          <servlet-mapping>
              <servlet-name>servlet-1</servlet-name>
              <url-pattern>/1/</url-pattern>
          </servlet-mapping>
          <servlet-mapping>
              <servlet-name>servlet-2</servlet-name>
              <url-pattern>/2/</url-pattern>
          </servlet-mapping>
          ....
          

        这会将路由逻辑推送到 web.xml 并且每个 servlet 执行特定的工作。

        【讨论】:

          【解决方案4】:

          使用框架。这就是他们的目的。我偏爱Spring MVC,但对于像这样的基本用例,任何现代的东西都应该没问题。第一次设置它可能会让人感觉很痛苦,但一旦配置好了,开发速度会快得多并且更易于维护。

          编辑: 我刚刚注意到最初的问题说不要使用任何框架/库。我仍然坚持这个答案,尽管大多数时候这是一个坏主意。如果你真的需要,那么你可以按照其他人的建议创建地图,但从长远来看,它是不可维护的,所以尽可能避免它。

          【讨论】:

            【解决方案5】:

            您可以在您的 web.xml uri 模式中指定路由到特定的 servlet 类。原谅我糟糕的 servlet 名称。

            <servlet>
                <servlet-name>processUserXml</servlet-name>
                <servlet-class>com.example.server.ProcessUserXml</servlet-class>
            </servlet>
            <servlet-mapping>
                <servlet-name>processUserXml</servlet-name>
                <url-pattern>/processuser</url-pattern>
            </servlet-mapping>
            
            <servlet>
                <servlet-name>processItemXml</servlet-name>
                <servlet-class>com.example.server.ProcessItemXml</servlet-class>
            </servlet>
            <servlet-mapping>
                <servlet-name>processItemXml</servlet-name>
                <url-pattern>/processitem</url-pattern>
            </servlet-mapping>
            

            因此,当用户调用特定 uri 时,它不会接受来自单个网关的 uri 请求并通过 if 语句路由它们(就像您现在所做的那样),它会被路由到适合您的 servlet 类.因此,调用 uri /processuser 会将调用路由到 ProcessUserXml servlet 类 doGet 方法(或 doPost,如果它已定义并且这就是用户进行 HTTP 调用的方式)。

            【讨论】:

            • 我忘了指定,但我这里只处理一个 servlet。
            • 为什么它必须是一个 servlet?您希望执行的操作实质上可以成为它们自己的 servlet。
            猜你喜欢
            • 2018-02-11
            • 2016-06-10
            • 1970-01-01
            • 2011-11-24
            • 1970-01-01
            • 2015-10-06
            • 1970-01-01
            • 1970-01-01
            • 2014-07-22
            相关资源
            最近更新 更多