【问题标题】:Java Servlet send form data to REST APIJava Servlet 将表单数据发送到 REST API
【发布时间】:2021-09-02 17:58:40
【问题描述】:

我有一个简单的 HTML 表单来向 REST API 发送请求。效果很好,当我提交时,它会将表单数据发送到 API 并在浏览器中显示响应。

<form name="theForm" action="localhost:8080/App/rest/consumeForm" method="post">
    <input name="userName" value="Bob Smith" /><br/>
    <input type="submit" value="submit"/>
</form>

浏览器显示:

{"address": "12 First St.", "city": "Toronto"}

我想捕获响应。有任何想法吗? (没有 ajax 或 javascript,请使用普通的旧 Servlet 或 JSP)

第 2 部分: 我现在将表单发布到我创建的 servlet,它处理来自 REST API 的请求和响应。它工作得很好,但它需要表单数据 URLEncoded。谁知道有没有办法将表单数据转换成这样的字符串,甚至直接将表单数据转换成JSON?

String charset = java.nio.charset.StandardCharsets.UTF_8.name();
String userName = "Bob Smith";
String country = "Canada";

String queryString = String.format("userName=%s&country=%s" 
        ,URLEncoder.encode(userName, charset) 
        ,URLEncoder.encode(country, charset)            
        );

我可以动态构建上面的 queryString 吗?

//// send request
URLConnection connection = new URL("localhost:8080/App/rest/consumeForm").openConnection();
connection.setDoOutput(true); // Triggers POST.
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
try (OutputStream output = connection.getOutputStream()) {
    output.write(queryString.getBytes(charset));
}       

//// get response
BufferedReader apiResponse = new BufferedReader(new InputStreamReader((connection.getInputStream())));
String output;
System.out.println("\n\n\nrecieved....");
while ((output = apiResponse.readLine()) != null) {
    System.out.println(output);
}

【问题讨论】:

    标签: java rest post servlets


    【解决方案1】:

    我想捕获响应。有什么想法吗?

    安装处理此问题的 servlet Filter。当它收到对 REST API 端点的请求时,它可以将HttpServletResponse 提供给链中配备了您想要的任何工具的下一个元素。您可能会发现 HttpServletResponseWrapper 是您自定义工具响应类的有用基类。

    Filter 的实现可能是这样的:

    public class ResponseCapturingFilter implements Filter {
        private static final String SERVLET_TO_FILTER = "...";
    
        @Override
        public void init(ServletConfig config) {
            // ...
        }
    
        @Override
        public void destroy() {
            // ...
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response,
                FilterChain chain) throws IOException, ServletException {
            if (((HttpServletRequest) request).getServletPath().equals(SERVLET_TO_FILTER)) {
                response = new MyCapturingResponseWrapper(response);
            }
            chain.doFilter(request, response);
        }
    }
    

    要捕获响应文本,您可能希望包装器至少适当地覆盖 getOutputStream()getWriter()

    【讨论】:

    • 谢谢约翰。我在过滤器方面的经验不是很好,我希望这个过程尽可能简单。你有一个很好的例子,但由于我的知识有限,我无法实施。
    • 好吧,@Jakev1,如果用户直接向 REST API 发出请求,那么捕获飞行中的响应的唯一方法就是在响应路径中插入一个组件。如果您想在 Web 应用程序中执行此操作,那么 Filter 是唯一适合该角色的组件。我看到的替代方法是修改 REST 端点以直接向您提供响应数据(所以不是“在飞行中”),或者在 web 应用程序的前面和外部站起来。
    【解决方案2】:

    事实证明,使用 POST 提交到 servlet 并使用 servlet 与 REST API 通信对我有用。可能有更好的方法,但这对于初级开发人员来说似乎比较干净,可以遵循和维护。 (我仍然愿意接受其他选择)。

    我用表单数据构建了一个查询字符串(req 是 HttpServletRequest)

    String theQueryString="domainId=1";
    for(Entry<String, String[]> qsParm:req.getParameterMap().entrySet()) {
      theQueryString+="&"+qsParm.getKey()+"="+URLEncoder.encode(req.getParameter(qsParm.getKey()), charset);   
    }
    
    // set up connection to use as API interaction
    URLConnection connection = new URL("localhost:8080/App/rest/consumeForm").openConnection();
    connection.setDoOutput(true); // Triggers POST apparently
    connection.setRequestProperty("Accept-Charset", java.nio.charset.StandardCharsets.UTF_8.name());
    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=" + java.nio.charset.StandardCharsets.UTF_8.name());
            
    // send request to API via connection OutputStream
    try (OutputStream output = connection.getOutputStream()) {
      output.write(theQueryString.getBytes(java.nio.charset.StandardCharsets.UTF_8.name()));  // this sends the request to the API url
    }       
    
    // get response from connection InputStream and read as JSON
    ObjectMapper mapper = new ObjectMapper();
    JsonNode jsonMap = mapper.readTree(connection.getInputStream());
    
    // now the response can be worked with in at least two ways that I have tried
    String user1 = jsonMap.get("userName").asText();
    String user2 = jsonMap.at("user").getValueAsText();
    
    

    【讨论】:

      猜你喜欢
      • 2019-08-26
      • 2013-05-27
      • 2014-07-21
      • 2012-07-31
      • 1970-01-01
      • 1970-01-01
      • 2019-08-14
      • 2020-06-22
      • 1970-01-01
      相关资源
      最近更新 更多