0

我尝试使用 Spring mvc 控制器以动态方式生成图像。

@Controller
@RequestMapping("/")
public String generateMik(final HttpServletResponse response){
...
BufferdImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
...

response.setContentType("image/png");
try {
    OutputStream os = response.getOutputStream();
    ImageIO.write(buffer, "png", os);
    os.flush();
    os.close();
...
}

我在 .jsp 中展示了这张图片:

<img src="picture" id="picture">

一切正常,图片显示在我的浏览器中,但我遇到了一个异常,我不知道正常解决这个问题的原因(我不想捕捉这个异常)。

org.apache.catalina.core.ApplicationDispatcher invoke
SEVERE: Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:626)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:215)
at org.apache.jasper.runtime.JspWriterImpl.initOut(JspWriterImpl.java:125)
at org.apache.jasper.runtime.JspWriterImpl.flushBuffer(JspWriterImpl.java:118)
at org.apache.jasper.runtime.PageContextImpl.release(PageContextImpl.java:190)
...

我的问题是:我如何以可能简单的方式生成动态图片?我不想临时保存图片。也许放在模型 outputStream 并在 jsp 中以某种神奇的方式显示?

4

3 回答 3

3

我认为这是由于您在控制器方法中有返回参数,该参数要求 spring 将请求转发到特定视图。

您应该将返回类型设为 void。

public void generateMik(final HttpServletResponse response)
于 2012-10-18T15:31:01.880 回答
3

您需要注释将@RequestMapping图像写入流的方法,@ResponseBody以告诉 Spring MVC 不要尝试查找用于呈现响应的视图。您可以@ResponseBody在自己处理写入输出流的任何方法上使用。

由于您的@RequestMapping方法返回 a String,因此 Spring 将您的方法的响应值解释为它应该在呈现响应时使用的视图的名称。

您看到异常是因为您正在写入(并关闭)响应流,然后 Spring MVC 尝试调用视图类以写入相同的响应流。

于 2012-10-18T16:06:51.797 回答
1

这对我来说很好用:

@RequestMapping(value = "/img", method = RequestMethod.GET)
public @ResponseBody void getImage(HttpServletResponse response)
{
    BufferedImage image = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);

    response.setContentType("image/png");
    OutputStream out;
    try
    {
        out = response.getOutputStream();
        ImageIO.write(image, "png", out);
        out.close();
    }
    catch (IOException ex)
    {
        Logger.getLogger(IndexController.class.getName()).log(Level.SEVERE, null, ex);
    }
}

但是,我 99.8% 肯定有更聪明的方法可以做到这一点。

于 2012-10-18T15:28:38.980 回答