2010-12-11 152 views
1

我有一个下面的映射,它检索一些“场景”细节并在jsp页面中显示它。Spring MVC控制器中的ModelAndView和byte []

@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; 
    } 

我的问题是,场景对象中的一个字段是PNG图像作为字节[],我需要显示它。我知道我可以创建另一个控制器来处理所有的.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事务。是否有任何解决办法可以保存此事务,而不是两次检索byte []?

预先感谢您。

回答

1

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

然后,您将有权在您确实需要它们时才加载图像。如前所述,执行showScene的控制器不需要加载图像,它们可以由不同的控制器来处理。

这样做的好处是:

  • 可以改善图像设置您的应用程序的性能被缓存的时间在浏览器中一个特定的金额。这意味着您的控制器加载图像不会一直点击,从而减少服务器端的负载。但是,如果您将图像存储在会话中,则无论为其设置了哪些缓存设置,它们都会一直加载。
  • 并非所有showScenes的请求最终都会成功或者需要显示图片。强制图像加载所有的时间似乎很费力。
  • 这可能是个人偏好,但我喜欢将会话保持干净和尽可能轻。
  • 服务器端缓存是一个好主意,但不要在会话中这样做。 Hibernate的第二层缓存如何 - 所有用户都可以共享?
2

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

您必须小心,不要在会话中放置太多图像,以便在检索完成后删除它们,或者一次只允许一个会话。

+0

是的,谢谢你。我可以使用会话,但我正在考虑一种“Spring MVC”方式来做到这一点:) – 2010-12-11 23:17:11

+0

@danny:你可以使用'@ SessionAttributes'来做到这一点,但在我的意见,这是不值得的 - 只使用原始的Session对象。 – skaffman 2010-12-11 23:24:46

+0

使用会话可能会阻止您的应用程序扩展(例如,如果您有两个Web服务器并且需要使会话在两个Web服务器上都可用)。就像已经提到的skaffman一样,你需要关心会话的数量:如果你有很多(和大的)会话,他们将会被持续,那么这种结果会使你的性能变得更糟,那么如果你访问数据库两次。因为当会话持续时,你必须写数组并再次读取它。这会比从数据库中读取要慢得多。 – Ralph 2010-12-12 09:30:13

1

Hibernate提供惰性加载包含的页面像你这样的属性http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-fetching-lazyproperties

我相信春天的方法是使用两个控制器方法,一个和第二个只返回图像。

如果您对性能很害怕,可以使用hibernate属性lazyloading来存储字节数组。所以当你只使用名称和其他东西(数组除外)时,数组将不会被加载。

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