`
deepinmind
  • 浏览: 451467 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
1dc14e59-7bdf-33ab-841a-02d087aed982
Java函数式编程
浏览量:41622
社区版块
存档分类
最新评论

Spring MVC的常见错误

阅读更多
10年前我开始自己的职业生涯的时候,Struts还是市场上的主流标准。然而多年过后,我发现Spring MVC已经越来越流行了。对我而言这并不意外,因为它能和Spring容器无缝集成,同时它还提供了灵活性及扩展性。

从我迄今为止对Spring的经验来看,我发现有不少人在配置Spring的时候经常会犯一些常见的错误。跟使用Struts框架相比,这些错误要出现得更频繁一些。我猜想这可能是它在可用性和灵活性之间做出的权衡。不仅如此,Spring的文档中全是例子但缺少解释。为了填充这一空白,本文准备深入阐述三个大家常犯的错误。


在Servlet上下文定义文件中声明bean

我们都知道,Spring使用的是ContextLoaderListener来加载Spring的应用上下文(application context)。还有就是在声明 DispatcherServlet的时候,我们需要用"${servlet.name}-context.xml”的名字来创建servlet的上下文定义文件。你有想过为什么要这样吗?

应用上下文结构

并非所有的人都清楚,Spring应用上下文其实是分层的。我们看一下这个方法



org.springframework.context.ApplicationContext.getParent()






它告诉我们,Spring应用上下文,其实是有父context的。那么,它是用来干什么的?

如果你下载一下源码,搜索一下方法引用,你会发现 Spring Application Context把双亲作为它的扩展。如果你不想读源码的话,我来给你演示一下BeanFactoryUtils.beansOfTypeIncludingAncestors()方法的一个用法 :




if (lbf instanceof HierarchicalBeanFactory) {
    HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
    if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
 Map parentResult = 
              beansOfTypeIncludingAncestors((ListableBeanFactory) hbf.getParentBeanFactory(), type);
 ...
    }
}
return result;
}




如果你看完整个方法,你会发现 Spring Application Context 会先在内部的上下文中查找bean,然后再去搜索父context。通过这个策略,Spring可以进行高效的反向广度优先搜索。




ContextLoaderListener


每个开发人员都应该了解这个类。它能帮忙你从预定义的上下文定义文件中加载Spring应用上下文。由于它实现了ServletContextListener接口,因此一旦WEB应用加载完毕,就会立即加载Spring的上下文。毋庸置疑,当加载包含@PostContruct注解或者批处理任务的Spring容器时,这个会非常有用。

反过来,任何在servlet上下文定义文件中定义的bean在servlet初始化前都不会构造。那servlet在何时会被初始化呢?这个是不确定的。最坏的情况下,你可能得等到用户第一次点击对应的servlet所映射的URL的时候,才会加载Spring上下文。

知道了以上这些信息,你认为你的bean声明应该放在哪里好呢?我觉得最佳的位置就是ContextLoaderListener所加载的上下文定义中了,没有其它。这里有个技巧就是将ApplicationContext作为servlet的一个属性进行存储,




org.springframework.web.context.WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE   




然后,DispatcherServlet会从ServletContext中加载这个上下文,并把它赋值给上层的应用上下文。




protected WebApplicationContext initWebApplicationContext() {
   WebApplicationContext rootContext =
      WebApplicationContextUtils.getWebApplicationContext(getServletContext());
   ...
}




由于它的这个行为 ,我强烈建议你只创建一个空的servlet应用上下文定义文件,将你的bean定义在父context中。这能避免当WEB应用加载时bean的重复创建,并能保证批处理作业能立即执行。


理论上说,将bean定义在servlet应用上下文定义文件中会使得bean对该servlet是唯一可见的。然而,在我8年的Spring使用经验来看,我发现这个特性几乎没有什么用处,除了用来定义 WEB service端点。

在ContextLoaderListener后面声明Log4jConfigListener


这是一个小BUG,不过如果你不注意的话,它会让你栽跟头。Log4jConfigListener是我最喜欢的解决-Dlog4j.configuration问题的一个方案,这样我们可以控制log4j的加载而不用改变服务器启动的进程。

很明显,这应该是你在web.xml中声明的第一个监听器。否则,你所声明的所有日志配置都将不会生效。


重复的bean定义


在早期的Spring中,开发人员更多的时间是花在了配置XML文件上,而不是Java类。对每一个新的bean,我们都需要声明它,然后自己将依赖注入,尽管这个做法很干净,整洁,但却非常痛苦。所以后续版本的Spring在可用性上进行了很大的提升这也不足为奇了。现在来说,开发人员只需要声明事务管理器,数据源,属性源,WEB服务endpoint,剩下的工作就交给组件扫描与自动织入来完成吧。

我喜欢这些新特性,但是权利越大,责任越大,否则的话,事情很快就会变得一团糟。XML文件中的组件扫描与bean声明是完全独立的。因此,在同一个bean容器内,如果bean被注解为组件扫描并且是手动声明的,就很有可能会出现相同类的不同bean。所幸的是,这种错误一般只发生在新手身上。

当我们需要集成一些嵌入式组件的时候,事情就变得复杂了。这个时候我们就需要一种策略来避免重复的bean声明。



上图展示了我们在日常工作中可能面临的真实案例。大多数时候,系统是由多个组件组成 的,一个组件服务于多个产品。每个应用和组件都有自己的bean。在这个例子中,怎么做才能最好地避免bean的重复声明?

下面是我个人提出的一个策略:
  • 确保每个组件都以一个独特的包名开头。这样当我们需要组件扫描的时候会更容易一些。
  • 不要让开发组件的团队将bean声明在组件内部(注解 VS XML声明)。负责将组件打包成最终产品的开发人员,他应该得去确保bean声明是唯一的。
  • 如果在组件内部有上下文定义文件,最好将它放在某个包底下,而不是classpath的根目录下。如果能给它分配一个专门的名字则更好。比如说,src/main/resources/spring-core/spring-core-context.xml总比src/main/resource/application-context.xml要好。想像一下如果你打包组件的时候发现同一个包底下存在相同的application-context.xml你会是什么心情。
  • 如果你已经将bean声明在一个context文件中了,就不要提供任何组件扫描的注解(@Component, @Service or @Repository)。
  • 不要在通用包上进行组件扫描。比如说,不要扫描org.springframework,扫描子包的话会更容易管理,比如说org.springframework.core, org.springframework.context, org.springframework.ui。





  • 原创文章转载请注明出处:http://it.deepinmind.com

    英文原文链接
    2
    2
    分享到:
    评论

    相关推荐

      最全最经典spring-mvc教程

      错误处理和异常处理也是Spring MVC中的重要部分,通过@ControllerAdvice和@ExceptionHandler可以全局处理异常,提供统一的错误页面。 最后,测试是任何应用程序开发的重要环节。Spring MVC提供了MockMVC,可以在不...

      Spring MVC跟jQuery和Twitter Bootstrap的结合

      **Spring MVC 框架详解** Spring MVC 是 Spring 框架的一部分,它是一个用于构建 Web...这种组合充分利用了Spring MVC的后端处理能力,jQuery的前端交互性,以及Bootstrap的界面美化功能,是现代Web开发中的常见实践。

      spring mvc

      Spring MVC 是一个基于Java的轻量级Web应用框架,它属于Spring框架的一部分,主要用于构建控制器层,实现模型-视图-控制器(Model-View-Controller)架构。在Spring MVC中,开发者可以方便地处理HTTP请求,进行数据...

      Spring MVC 文件上传下载 后端 - Java.zip

      在Spring MVC框架中,文件上传和下载是常见的功能需求,特别是在构建Web应用程序时。这个压缩包文件"Spring MVC 文件上传下载 后端 - Java.zip"包含的文档可能详细阐述了如何在Java后端实现这些功能。以下是关于...

      Expert Spring MVC

      ### Expert Spring MVC 相关知识点概述 #### 一、Spring MVC 概述 Spring MVC 是 Spring Framework 的一个重要模块,主要用于构建基于 Java 的 Web 应用程序。它提供了一个清晰的模型-视图-控制器(Model-View-...

      基于Spring Mvc的JavaWeb项目

      在本项目中,我们探讨的是一个基于Spring MVC框架构建的JavaWeb应用。Spring MVC是Spring框架的一个模块,专为创建Web应用程序提供模型-视图-控制器(MVC)架构支持。这个项目涉及到的功能包括分页显示、单个或批量...

      四. Spring MVC 3 支持json及 常见错误解决

      本篇将深入探讨Spring MVC 3对JSON的支持以及解决常见错误的方法。 首先,让我们了解什么是JSON。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。在...

      Spring MVC资料

      Spring MVC 是一个基于Java的轻量级Web应用程序框架,它为构建模型-视图-控制器(MVC)架构的应用程序提供了强大的支持。Spring框架的核心组件之一,Spring MVC旨在简化开发,提供诸如数据验证、本地化、拦截器等...

      spring mvc + spring + hibernate 全注解整合开发视频教程 08

      6. **问题解决**:在教程的这一部分,可能会涵盖常见的错误和问题,例如事务管理不当导致的数据一致性问题,或者是注解配置不正确引起的运行时错误,帮助学习者了解如何调试和解决这些问题。 总的来说,这个"Spring...

      Spring MVC3。 最近研究

      这部分将讲解如何在Spring MVC中接收和处理用户提交的表单数据,包括数据验证和错误处理。 4. **Spring 3 MVC与Tiles插件的教程**:Tiles是一个布局管理工具,可以使页面设计更加模块化。这部分将教你如何在Spring ...

      spring mvc easyui grid 分页

      本项目聚焦于如何在Spring MVC中集成EasyUI的Grid组件实现分页功能,这是一个常见的Web开发场景,对于提高用户体验和减轻服务器压力至关重要。 **Spring MVC** 是一个强大的MVC(Model-View-Controller)框架,它由...

      spring mvc的例子

      Spring MVC 是 Spring 框架的一个模块,专为构建基于模型-视图-控制器(Model-View-Controller)架构的Web应用程序。这个框架提供了一种高效、灵活且强大的方式来组织和构建Web应用。在“spring mvc的例子”中,我们...

      spring mvc 项目错误,和一些配置

      ### Spring MVC 项目常见错误与配置 #### 1. Java.lang.reflect.InvocationTargetException - **原因**:通常这种异常是在执行一个方法时发生异常而导致的。在Spring MVC的场景下,可能是由于Bean初始化过程中的...

      spring in action mvc 第四版 中文版

      《Spring in Action: Spring MVC 第四版 中文版》是一本深入探讨Spring MVC框架的权威指南,适合Java开发者阅读。本书全面介绍了如何使用Spring MVC来构建健壮、高性能的Web应用程序。Spring MVC是Spring框架的核心...

      SpringMVC文档.zip_spring mvc

      - 这个文档可能提供了一个使用Spring MVC实现用户管理功能的实际案例,涉及到用户注册、登录、权限控制等常见功能。 5. **Spring MVC 3.x annotated controller的几点心得体会** - 作者可能分享了在实际开发中...

      Spring MVC教程.docx

      Spring MVC 是一个基于 Java 的轻量级 Web 应用框架,是 Spring 框架的一部分,主要用于构建 MVC(Model-View-Controller)架构的 Web 应用程序。它提供了丰富的功能,包括请求分发、视图解析、数据绑定以及异常处理...

      Spring MVC 到 Spring Boot 的简化之路.docx

      同时,Spring框架和其各个模块,如Spring MVC,通过依赖注入和抽象简化了常见的编程任务,提升了开发者的生产力。在这条简化之路上,Spring Boot成为了一种高效且现代化的开发工具,引领着开发者进入更加高效和便捷...

    Global site tag (gtag.js) - Google Analytics