使用Spring MVC时的常见错误
当我大约10年前开始我的职业生涯时,Struts MVC就是市场上的常态。 但是,多年来,我观察到Spring MVC逐渐流行起来。 鉴于Spring MVC与Spring容器的无缝集成以及它提供的灵活性和可扩展性,这对我来说并不奇怪。
从到目前为止的Spring旅程中,我通常会看到人们在配置Spring框架时犯了一些常见的错误。 与人们仍然使用Struts框架的时间相比,这种情况发生的频率更高。 我想这是灵活性和可用性之间的权衡。 另外,Spring文档中有很多示例,但缺乏解释。 为了填补这一空白,本文将尝试阐述和解释我经常看到的3个常见问题。
在Servlet上下文定义文件中声明bean
因此,我们每个人都知道Spring使用ContextLoaderListener加载Spring应用程序上下文。 不过,当宣布
DispatcherServlet ,我们需要创建名称为“ $ {servlet.name} -context.xml”的servlet上下文定义文件。 有没有想过为什么?
应用程序上下文层次结构
并非所有开发人员都知道Spring应用程序上下文具有层次结构。 让我们看一下这种方法:
org.springframework.context.ApplicationContext.getParent()
它告诉我们Spring Application Context具有父级。 那么,这个父母干什么呢?
如果下载源代码并进行快速引用搜索,则应该发现Spring Application Context将parent作为其扩展名。 如果您不介意阅读代码,请让我向您展示方法BeanFactoryUtils.beansOfTypeIn includedAncestors()中的用法示例:
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。 通过这种策略,Spring Application Context将有效地进行反向广度优先搜索以查找bean。
ContextLoaderListener
这是每个开发人员都应该知道的众所周知的类。 它有助于从预定义的上下文定义文件中加载Spring应用程序上下文。 由于实现了ServletContextListener ,因此将在加载Web应用程序后立即加载Spring应用程序上下文。 当加载包含带有@PostContruct批注或批处理作业的bean的Spring容器时,这带来了无可争议的好处。
相反,在初始化servlet之前,不会构造servlet上下文定义文件中的任何bean定义。 何时初始化Servlet? 这是不确定的。 在最坏的情况下,您可能需要等到用户对servlet映射URL进行第一次点击才能加载spring上下文。
根据以上信息,您应该在哪里声明所有珍贵的豆子? 我觉得这样做的最佳位置是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。 这将有助于避免在加载Web应用程序时重复创建Bean,并确保立即执行批处理作业。
从理论上讲,在servlet应用程序上下文定义文件中定义bean会使该bean唯一且仅对该servlet可见。 但是,在使用Spring的8年中,除了定义Web Service端点之外,我几乎没有发现此功能的任何用途。
在
这是一个小错误,但是如果您不注意它,它将引起您的注意。 Log4jConfigListener是我在-Dlog4j.configuration首选的解决方案,我们可以控制的log4j加载不改变服务器的引导过程。
显然,这应该是在web.xml中声明的第一个侦听器。 否则,您浪费所有的时间来声明正确的日志记录配置。
由于对Bean的探索管理不善而复制了Bean
在Spring的早期,开发人员在xml文件上打字的时间比Java类花费的时间更多。 对于每个新bean,我们需要自己声明和连接依赖项,这是干净,整洁但非常痛苦的。 毫无疑问,Spring框架的更高版本向更高的可用性发展。 如今,开发人员可能只需要声明事务管理器,数据源,属性源,Web服务端点,其余的就可以进行组件扫描和自动装配。
我喜欢这些新功能,但是这种强大的力量需要承担巨大的责任。 否则,事情会很快变得混乱。 XML文件中的组件扫描和bean声明是完全独立的。 因此,如果对bean进行注释以进行组件扫描并手动进行声明,则在bean容器中完全可能具有相同类的相同bean。 幸运的是,这种错误应该只发生在初学者身上。
当我们需要将一些嵌入式组件集成到最终产品中时,情况变得更加复杂。 然后,我们确实需要一种策略来避免重复的bean声明。
上图显示了我们日常生活中遇到的种种现实问题。 大多数情况下,系统是由多个组件组成的,通常,一个组件可为多个产品提供服务。 每个应用程序和组件都有自己的bean。 在这种情况下,最好的声明方式是避免重复的bean声明?
这是我建议的策略:
- 确保每个组件都必须以专用的软件包名称开头。 当我们需要进行组件扫描时,它使我们的工作变得更轻松。
- 不要指示开发组件的团队采用在组件本身中声明Bean的方法(注释与xml声明)。 开发人员负责将组件打包到最终产品中,以确保没有重复的bean声明。
- 如果组件中包含上下文定义文件,请给它一个包,而不是放在classpath的根目录中。 最好给它起一个特定的名字。 例如, src / main / resources / spring-core / spring-core-context.xml比src / main / resource / application-context.xml更好。 想象一下,如果在相同的程序包中打包几个包含相同文件application-context.xml的组件,那该怎么办!
- 如果您已经在一个上下文文件中声明了Bean,则不要为组件扫描提供任何注释( @ Component, @ Service或@Repository )。
- 将特定于环境的bean(例如data-source , property-source)拆分到一个单独的文件中并重用。
- 不要在常规包装上进行组件扫描。 例如,与扫描org.springframework包相比,如果我们扫描几个子包(例如org.springframework.core , org.springframework.context , org.springframework.ui ,…), 则更易于管理。
结论
希望以上技巧对日常使用很有帮助。 如有任何疑问或任何其他想法,请发送反馈以提供帮助。
翻译自: https://www.javacodegeeks.com/2014/07/common-mistakes-when-using-spring-mvc.html
使用Spring MVC时的常见错误相关推荐
- Python运行的17个时新手常见错误小结
Python运行的17个时新手常见错误小结 1 发布时间:『 2017-11-04 11:20 』 帖子类别:『人工智能』 阅读次数:8803 (本文『Python运行的17个时新手常见错误 ...
- VS编译时一些常见错误积累LNK,比如LNK2019、LNK2001(实时更新)
1. lnk2019 LNK2019错误一般是 compile 能找到 header(.h)文件,但是在链接时找不到需要的 lib 库文件或者是 dll 文件. 一般认为在编译 OSG 简单示例的时候 ...
- python编辑elif显示错误_Python运行的17个时新手常见错误小结
1)忘记在 if , elif , else , for , while , class ,def 声明末尾添加 :(导致 "SyntaxError :invalid syntax" ...
- [转]在SSIS中,使用“包配置”时的常见错误与解析
本文转自:http://www.cnblogs.com/invinboy/archive/2008/05/26/1034312.html 在以前的DTS中,在包的开发.测试.发布迁移过程中你必须手动的 ...
- 使用 ESP-Prog _ Jlink 进行 JTAG 调试时的常见错误及解决办法
此篇博客用来记录使用 ESP-PROG / Jlink 来对 ESP32-Lyrat 进行 JTAG 调试时遇到的一些问题以及解决办法.如果对进行 JTAG 相关操作有疑惑,请参考以下资料: 使用 E ...
- java ajax 404_java – 在jQuery AJAX中调用Spring控制器时发现404错误
我是春天的新手.我生成如下的JSON: [ { "customer" : "16", "project" : "19", ...
- SQL 数据库还原备份时的常见错误
1.还原sql数据库时提示"集中备份的数据库与现有数据库不同" 原因:备份的数据库是sqlserver2005,现有数据库是sql2008 解决:通过执行sql语句还原数据库,可以 ...
- Spring MVC集成测试:断言给定的模型属性有全局错误
为了使用Bean验证报告Spring MVC中的全局错误,我们可以创建一个自定义的类级别约束注释. 全局错误与已验证Bean中的任何特定字段都不相关. 在本文中,我将展示如何使用Spring Test ...
- Spring MVC错误处理示例
这篇文章描述了在Spring MVC 3中执行错误处理的不同技术.该代码在GitHub上的Spring-MVC-Error-Handling目录中可用. 它基于带有注释的Spring MVC示例. 在 ...
最新文章
- TinyML-TVM是如何驯服Tiny的(上)
- Java过滤特殊字符的正则表达式
- php xml 增删改查,PHP实现对xml进行简单的增删改查(CRUD)操作示例
- 读取CRM 产品主数据所有属性的API
- Mysql高级之主从复制
- SQL注入漏洞与参数化查询
- readlink()不能读取硬链接的目标
- 解决谷歌浏览器添加插件时显示程序包无效:“CRX_HEADER_INVALID“
- Java提取视频中的音频(JavaCV)
- oracle便携智能投影,洁牙设备又添一将!OraCleen S 智能便携牙刷
- docker安装和基本命令
- 工作十年的程序员,却拿着毕业三年的工资……
- XLNet 详解(看不懂你来骂我)
- C4D中使用Redshift渲染器翻转贴图
- 【P1516】青蛙的约会
- java计算机毕业设计在线影视系统源码+数据库+lw文档+系统+部署
- 天眼探空经济发展_前沿|“天眼”探空惊艳全球
- jQuery实现表单验证
- 限量版 情感智能机器人Pepper今天发售了!
- 青龙面板-简单获取京东CK
热门文章
- JS重写toString(),打印想要的值
- php移动代码,移动专区周级收录如何提交 复制这段php代码即可
- java泛型程序设计——泛型类的静态上下文中类型变量无效+不能抛出或捕获泛型类的实例
- leetcode初级算法4.两个数组的交集 II
- drools6.5_Drools 6.5.0.Final可用
- gradle入门_Gradle入门:集成测试
- 在邮件标头中找到无效的字符_在实践中重试HTTP标头
- java 登陆验证失败_使用Java 8流进行快速失败的验证
- spring 组件扫描_避免不必要的Spring配置组件扫描
- angular java_带有Angular JS的Java EE 7 –第1部分