Spring MVC控制器中的ModelAndView和byte []

时间:2010-12-11 23:08:11

标签: java hibernate servlets spring-mvc

我有一个以下映射,它检索一些“场景”细节并在jsp页面中显示它。

 @RequestMapping(value="/{id}",method = RequestMethod.GET)
     public ModelAndView showScene(@PathVariable String id){
         ModelAndView mv = new ModelAndView("/Scene/scene");
                 //retrieving Scene using Hibernate                 
                 Scene scene = service.getScene(Long.parseLong(id));
         mv.addObject("name", scene.getName());
                 mv.addObject("desc", scene.getDescription());
                 //etc....
         return mv;
     }

我的问题是,scene对象中的一个字段是png图像为byte [],我需要显示它。我知道我可以创建另一个控制器来处理所有.png扩展请求并返回byte []。类似的东西:

<servlet-mapping>
    <servlet-name>PNGHandler</servlet-name>
    <url-pattern>*.png</url-pattern>
  </servlet-mapping>   

并将对图像的引用发送为:

mv.add("image", "image/"+scene.getId()+".png");

但是我需要在png控制器中再次检索byte [],这将花费额外的Hibernate Transaction。有什么工作可以保存这个事务而不是两次检索byte []吗?

提前谢谢。

3 个答案:

答案 0 :(得分:2)

最简单的解决方案是第一个请求在会话中存储byte[](或整个Scene对象),第二个请求是从会话中获取它并将其流回客户端。您可以在固定密钥下将数据存储在会话中,或者您可以每次生成一个新密钥,将其存储在该密钥下的会话中,然后在呈现时将密钥编码为<img> URL页。

您必须注意不要在会话中放置太多图像,因此您可以在检索后删除它们,或者一次只允许会话中的一个。

答案 1 :(得分:1)

Hibernate为属性http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-fetching-lazyproperties

提供延迟加载

我相信春天的方式是使用两个控制器方法,一个包含像你一样的页面,第二个只返回图像。

如果你害怕性能,你可以使用hibernate属性lazyloading为你的字节数组。因此,当您仅使用名称和其他内容(数组除外)时,将不会加载数组。

但据我所知,属性延迟加载需要某种字节码增强。因此,如果这是一个巨大的问题,您可以考虑直接使用查询加载属性,而不是通过映射类加载它。

答案 2 :(得分:1)

我会说 - 将字节分隔给不同的Hibernate映射实体(可能是Image?),并让Scene通过延迟加载的关系引用它。

然后,只有在您真正需要时才能加载图像。如前所述,执行showScene的Controller不需要加载图像,它们可以由不同的Controller处理。

这样做的好处是:

  • 您可以通过将图片设置为在浏览器中缓存一段特定时间来提高应用性能。这意味着加载图像的控制器不会一直被击中,从而减少了服务器端的负载。但是,如果您在会话中存储图像,它们将一直加载,而不管为它们设置的缓存设置。
  • 并非所有showScenes请求都会成功或需要显示图像。强制图像一直加载似乎很费力。
  • 这可能是个人偏好,但我希望会议尽可能保持清洁和轻松。
  • 服务器端缓存是一个好主意,但不要在会话中执行此操作。 Hibernate的第二层缓存怎么样 - 所有用户都可以共享?