使用Spring MVC时的常见错误

spring_framework 当我大约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声明。

spring_component

上图显示了我们日常生活中遇到的种种现实问题。 大多数情况下,系统是由多个组件组成的,通常,一个组件可为多个产品提供服务。 每个应用程序和组件都有自己的bean。 在这种情况下,最好的声明方式是避免重复的bean声明?

这是我建议的策略:

  • 确保每个组件都必须以专用的软件包名称开头。 当我们需要进行组件扫描时,它使我们的工作变得更轻松。
  • 不要指示开发组件的团队采用在组件本身中声明Bean的方法(注释与xml声明)。 开发人员负责将组件打包到最终产品中,以确保没有重复的bean声明。
  • 如果组件中包含上下文定义文件,请给它一个包,而不是放在classpath的根目录中。 最好给它起一个特定的名字。 例如, src / main / resources / spring-core / spring-core-context.xmlsrc / main / resource / application-context.xml更好 想象一下,如果在相同的程序包中打包几个包含相同文件application-context.xml的组件,那该怎么办!
  • 如果您已经在一个上下文文件中声明了Bean,则不要为组件扫描提供任何注释( @ Component, @ Service@Repository )。
  • 将特定于环境的bean(例如data-sourceproperty-source)拆分到一个单独的文件中并重用。
  • 不要在常规包装上进行组件扫描。 例如,与扫描org.springframework包相比,如果我们扫描几个子包(例如org.springframework.coreorg.springframework.contextorg.springframework.ui ,…), 则更易于管理。

结论

希望以上技巧对日常使用很有帮助。 如有任何疑问或任何其他想法,请发送反馈以提供帮助。

翻译自: https://www.javacodegeeks.com/2014/07/common-mistakes-when-using-spring-mvc.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363039.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CopyOnWriteArrayList

CopyOnWriteArrayList,add,引用赋值是原子操作吗? 引用类型的读写均是原子操作,https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.7,https://www.v2ex.com/t/280788 转载于:https://www.cnblogs…

Statement与PreparedStatement区别

1.性能区别 Statement statement conn.createStatement(); PreparedStatement preStatement conn.prepareStatement(sql); 执行的时候: ResultSet rSet statement.executeQuery(sql); ResultSet pSet preStatement.executeQuery(); 由上可以看出,PreparedState…

C++ operator操作符重载(++,--,-,+,())

C中,--操作符重载需要说明是(--)在操作数前面,还是在操作数后面,区别如下: 代码经过测试无误(起码我这里没问题^_^)Code1#include <iostream> 2#include <cstdlib> 3using namespace std; 4template<typename T> class A 5{ 6public: 7 A(): m_(0){ 8 …

CSS3-2

倒圆角 <!DOCTYPE html><html lang"en"><head> <meta charset"UTF-8"> <title>Document</title></head><body> <h1>圆角边框 —— border-radius IE9</h1> <!-- border-radius 是复合属性…

JavaFX技巧9:请勿混用Swing / JavaFX

JavaFX团队非常努力地说服我们&#xff0c;因为可以将Swing内容嵌入JavaFX UI中&#xff0c;因此可以很容易地从Swing迁移到JavaFX。 我必须承认&#xff0c;我从来没有亲自尝试过&#xff0c;但是根据我从客户那里得到的反馈&#xff0c;我只能建议不要将Swing和JavaFX混合使用…

[ZJJOI2013]K大数查询 整体二分

[ZJJOI2013]K大数查询 链接 luogu 思路 整体二分。 代码 #include <bits/stdc.h> #define ll long long using namespace std; const ll _5e57; ll read() {ll x0,f1;char sgetchar();for(;s>9||s<0;sgetchar()) if(s-) f-1;for(;s>0&&s<9;sgetchar(…

javax.el.PropertyNotFoundException: Property [Xxxx] not found on type Xxx.xxx.xxxx.Xxxx]的解决办法...

当我将后台数据传递给jsp&#xff0c;用${requestScope.user.Id}取值时报错&#xff0c; 最后发现entity实体类的属性不能首字母大写然后再小写&#xff0c;例如 int Age&#xff1b;这个就不行&#xff0c;必须写成int age; 最后问题解决了 转载于:https://www.cnblogs.com/Th…

react学习目录

前面的话 React是如今热门的两大前端框架之一&#xff0c;它设计思路独特&#xff0c;性能卓越&#xff0c;逻辑简单&#xff0c;受到了大量开发者的喜爱。Vue的基本思路是基于HTML模板的扩展&#xff0c;而React的基本思路是基于JS语言的扩展。由于Vue的写法更接近于传统&…

JavaFX技巧13:学习Modena CSS文件

到目前为止&#xff0c;这是最简单&#xff0c;最短的提示。 如果要执行以下任何操作&#xff1a; 了解如何使用CSS 使您的自定义控件看起来像标准控件 重用标准控件使用的SVG路径图形&#xff08;例如&#xff0c;滚动条箭头&#xff09; 弄清楚如何浏览标准控件的结构 确…

委托之异步

在 使用BackgroundWorker组件 一文中&#xff0c;阐述了在Winform编程中&#xff0c;使用BackgroundWorker组件实现异步调用&#xff0c;本文主要讲述利用委托实现异步。 以下描述摘抄于MSDN: 异步委托提供以异步方式调用同步方法的能力。 当同步调用委托时&#xff0c;Invoke(…

[NOI2010]超级钢琴 主席树

[NOI2010]超级钢琴 链接 luogu 思路 和12省联考的异或粽子一样。 堆维护n个左端点&#xff0c;每次取出来再放回去次 代码 #include <bits/stdc.h> #define ll long long using namespace std; const int _5e57,INF0x3f3f3f3f; int read() {int x0,f1;char sgetchar();fo…

【MSP430单片机】IIC 篇

一、转载于:https://www.cnblogs.com/wangsure/p/10734745.html

纹理文本

前面的话 本文将通过多种方式实现纹理文本的效果 背景裁切 对于实现纹理文本的效果&#xff0c;脑海中最直接能想到的办法可能是背景裁切background-clip 使用线性渐变来填充文本背景 <style>.box-with-text { background-image: linear-gradient(135deg,hsl(50, 100%, 7…

ORACLE EXP/IMP 说明

Oracle 的导出导入是一个很常用的迁移工具。 在Oracle 10g中&#xff0c;Oracle 推出了数据泵(expdp/impdp). 它可以通过使用并行&#xff0c;从而在效率上要比exp/imp 要高。 在Oracle 10g和11g的官方文档里没有搜到有关exp/imp 的说明&#xff0c; 在9i里找到了相关的使用说…

JAXB –新手的观点,第1部分

我知道你们很多人已经在想什么了&#xff0c;所以让我们摆脱它&#xff1a;“ JAXB&#xff1f; 如XML&#xff1f; 来吧&#xff0c;所有很棒的孩子都在使用JSON。” 关于XML与JSON的争论以及许多促成它的论据都已被很好地记录在案。 我不会花很多时间在这里重新整理它们。 我…

初识C语言(五)

自定义函数 C语言提供了大量的库函数&#xff08;右侧资料下载中有&#xff09;&#xff0c;比如stdio.h提供输出函数&#xff0c;但是还是满足不了我们开发中的一些逻辑&#xff0c;所以这个时候需要自己定义函数&#xff0c;自定义函数的一般形式&#xff1a; 注意&#xff1…

bzoj2916: [Poi1997]Monochromatic Triangles 思路

bzoj2916: [Poi1997]Monochromatic Triangles 链接 bzoj 思路 总方案\(C_{n}^{3}-异色三角形\) 异色三角形有个特点。 会出现两个点有两条不同色的边。 然后统计就行了。 代码 #include <bits/stdc.h> #define ll long long using namespace std; const int _5e37; int n…

nodeJS实现简单网页爬虫功能

前面的话 本文将使用nodeJS实现一个简单的网页爬虫功能 网页源码 使用http.get()方法获取网页源码&#xff0c;以hao123网站的头条页面为例 http://tuijian.hao123.com/hotrank var http require(http);http.get(http://tuijian.hao123.com/hotrank,function(res){var data ;…

不能上网原因(查)

实验室不能上网原因记录&#xff1a;如果不是你电脑原因&#xff0c;很可能就是路由器和dns设置的问题。。把dns设置为寝室校园网专用dns试试可能就好了。。 网页打不开&#xff0c;浏览器打不开&#xff0c;这是上网时候广大网友经常碰见的问题&#xff0c;本文将针对网页打不…

JavaFX技巧6:使用透明颜色

为用户界面元素选择正确的颜色始终是一个很大的挑战&#xff0c;但是当您开发可重用的框架控件时&#xff0c;开发人员就无法控制使用它们的应用程序的外观和感觉&#xff0c;这甚至更具挑战性。 尽管您可能总是将元素添加到默认的灰色背景之上&#xff0c;但是嵌入控件的开发人…