【问题标题】:How do I output content to a HttpServletResponse buffer?如何将内容输出到 HttpServletResponse 缓冲区?
【发布时间】:2017-12-08 20:32:32
【问题描述】:

我正在使用 Spring 4.3.8.RELEASE。我想为特定的 Forbidden 错误设置错误消息。我的控制器中有这个。 “响应”的类型为“javax.servlet.HttpServletResponse”。

        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
        response.setContentLength(errorMsg.length());
        byte[] buffer = new byte[10240];
        final OutputStream output = response.getOutputStream();
        output.write(buffer, 0, errorMsg.length());
        output.flush();

但是,内容似乎没有被返回,至少我在单元测试中看不到它......

    final MvcResult result = mockMvc.perform(get(contextPath + "/myurl") 
                    .contextPath(contextPath)
                    .principal(auth)
                    .param("param1", param1)
                    .param("param2", param2))
        .andExpect(status().isForbidden())
        .andReturn();
    // Verify the error message is correct
    final String msgKey = "error.code";
    final String errorMsg = MessageFormat.format(resourceBundle.getString(msgKey), new Object[] {});
    Assert.assertEquals("Failed to return proper error message.", errorMsg, result.getResponse().getContentAsString()); 

断言失败,表示响应字符串为空。将响应写回 HttpServletResponse 缓冲区的正确方法是什么?

【问题讨论】:

    标签: spring servlets junit httpresponse mockmvc


    【解决方案1】:

    您永远不会将errorMsg 写入outputbuffer

    类似

    response.getWriter().write(errorMsg)
    

    应该解决问题

    【讨论】:

    • 是的,我愿意。见这一行——“output.write(buffer, 0, errorMsg.length());”
    • 否,将errorMsg.length() 字节从buffer 开始写入到输出。但是 buffer 全部为 0,因为您从未将 errorMsg 复制到它。
    【解决方案2】:

    你可以使用响应实体

    @RequestMapping("/handle")
    public ResponseEntity<String> handle() {
    
       HttpHeaders responseHeaders = new HttpHeaders();
       responseHeaders.setLocation(location);
       responseHeaders.set("MyResponseHeader", "MyValue");
       return new ResponseEntity<String>("Hello World", responseHeaders, HttpStatus.FORBIDDEN);
     }
    

    Spring Response Entity

    【讨论】:

    • 也许我应该更清楚。如何在给定 HttpSERvletResponse 的情况下生成输出字符串。你的回答没有解决这个问题。谢谢,-
    【解决方案3】:

    一件好事是throw 一个自定义异常将HttpServletResponse 作为参数传递或使用一个已经存在的异常(如果它服务于您的用例),这样错误就可以在控制器方法之外处理(单独的关注点,被认为是一种好的做法)。

    如果没有,您可以直接在控制器方法中设置响应。

    所以在这两种情况下你都可以使用HttpServletResponses sendError 方法,像这样:

    // your controller (or exception) method
        try {
            response.sendError(HttpStatus.FORBIDEN.value(), "My custom error message")
            } catch (IOException e) {
        // handle if error could not be sent
            }
        }
    

    这将打印出一个字符串作为所需HttpStatus 的响应。

    另外,这里有一些关于 Spring 异常处理 here 的“oldie-but-goldie”信息

    【讨论】:

    • 谢谢。如何在我的 JUnit 测试代码中验证这一点?我输入了您的代码,虽然我可以看到它在调试过程中运行,但行“Assert.assertEquals("Failed to return proper error message.", errorMsg, result.getResponse().getContentAsString());"无法抱怨“result.getResponse().getContentAsString()”为空。
    • @Dave 如果您使用的是@RestController,您会从 JSON 响应中读取。所以使用mockMvc.perform(.....) .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.error.message").value("My custom error message"));可以通过Postman之类的调用看到json结构
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多