【问题标题】:ModelAndView and byte[] within Spring MVC controllerSpring MVC 控制器中的 ModelAndView 和 byte[]
【发布时间】:2011-05-24 02:22:21
【问题描述】:

我有一个以下映射,它检索一些“场景”细节并将其显示在 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;
     }

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

<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[] 两次?

提前谢谢你。

【问题讨论】:

    标签: java hibernate servlets spring-mvc


    【解决方案1】:

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

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

    【讨论】:

    • 是的,谢谢。当然我可以使用 Session,但我正在考虑一种“Spring MVC”的方式来做到这一点:)
    • @danny:您可以使用@SessionAttributes 来执行此操作,但在我看来,这不值得 - 只需使用原始 Session 对象。
    • 使用会话可能会阻止您的应用程序很好地扩展(例如,如果您有两个 Web 服务器并且需要使会话在它们两者上都可用)。就像 skaffman 已经提到的那样,您需要注意会话的数量:如果您有这么多(和大)会话,它们将被持久化,那么与访问数据库相比,这种解决方案会使您的性能更加糟糕两次。因为当会话持续存在时,您必须写入数组并再次读取它。这比从数据库中读取要慢得多。
    【解决方案2】:

    Hibernate 为属性 http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-fetching-lazyproperties 提供延迟加载

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

    如果您担心性能,您可以为您的字节数组使用休眠属性延迟加载。所以当你只使用名称和其他东西(数组除外)时,不会加载数组。

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

    【讨论】:

      【解决方案3】:

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

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

      这样做的好处是:

      • 您可以通过将图像设置为在浏览器中缓存特定时间来提高应用程序的性能。这意味着加载图像的控制器不会一直被命中,从而减少服务器端的负载。但是,如果您将图像存储在会话中,它们将一直被加载,而与为它们设置的缓存设置无关。
      • 并非所有对 showScenes 的请求最终都会成功或需要显示图像。强制图像一直加载似乎很费力。
      • 这可能是个人喜好,但我希望会议尽可能保持干净和轻松。
      • 服务器端缓存是个好主意,但不要在会话中这样做。 Hibernate 的第二层缓存如何——所有用户共享的东西?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-06
        相关资源
        最近更新 更多