志在指尖
用双手敲打未来

Spring 常犯的十大错误

1.错误一:太过关注底层
我们正在处理这个常见错误,是由于“非我所创”综合症在软件开发范畴很是常见。病症包括经常重写一些常见的代码,很多开发人员都有这种病症。
固然了解特定库的内部构造及其完成,在很大水平上是好的并且很有必要的(也能够是一个很好的学习过程),但作为软件工程师,不时地处置相同的底层完成细节对个人的开发作涯是有害的。
像Spring这种笼统框架的存在是有缘由的,它将你从反复地手工劳作中解放出来,并允许你专注于更高层次的细节——范畴对象和业务逻辑。
因而,承受笼统。下次面对特定问题时,首先停止快速搜索,肯定处理该问题的库能否已被集成到Spring中;如今,你可能找到一个适宜的现成处理计划。
比方,一个很有用的库,在本文的其他局部,我将在示例中运用ProjectLombok注解。Lombok被用作榜样代码生成器,希望懒散的开发人员在熟习这个库时不会遇到问题。举个例子,看看运用Lombok的“规范JavaBean”是什么样子的:
如你所想,上述代码被编译为:
但是,请留意,假如你打算在IDE中运用Lombok,很可能需求装置一个插件,可在此处找到IntellijIDEA版本的插件。java
2.错误二:内部构造“泄露”
公开你的内部构造,历来都不是一个好主见,由于它在效劳设计中形成了不灵敏性,从而促进了不好的编码理论。“泄露”的内部机制表现为使数据库构造能够从某些API端点访问。例如,下面的POJO(“PlainOldJavaObject”)类表示数据库中的一个表:
假定,存在一个端点,他需求访问TopTalentEntity数据。返回TopTalentEntity实例可能很诱人,但更灵敏的处理计划是创立一个新的类来表示API端点上的TopTalentEntity数据。
这样,对数据库后端停止更改将不需求在效劳层停止任何额外的更改。思索下,在TopTalentEntity中添加一个“password”字段来存储数据库中用户密码的Hash值——假如没有TopTalentData之类的衔接器,遗忘更改效劳前端,将会不测地暴露一些不用要的机密信息。
3.错误三:缺乏关注点别离
随着程序范围的增长,逐步地,代码组织成为一个越来越重要的问题。挖苦的是,大多数好的软件工程准绳开端在范围上解体——特别是在没有太多思索程序体系构造设计的状况下。开发人员最常犯的一个错误就是混杂代码关注点,这很容易做到!
通常,突破关注点别离的是将新功用简单地“倒”在现有类中。当然,这是一个很好的短期处理计划(关于初学者来说,它需求更少的输入),但它也不可防止地会在未来成为一个问题,无论是在测试期间、维护期间还是介于两者之间。思索下下面的控制器,它将从数据库返回TopTalentData。
起初,这段代码似乎没什么特别的问题;它提供了一个从TopTalentEntity实例检索出来的TopTalentData的List。
但是,认真察看下,我们能够看到TopTalentController实践上在此做了些事情;也就是说,它将恳求映射到特定端点,从数据库检索数据,并将从TopTalentRepository接纳的实体转换为另一种格式。一个“更洁净”的处理计划是将这些关注点别离到他们本人的类中。看起来可能是这个样子的:
这种层次构造的另一个优点是,它允许我们经过检查类名来肯定将功用驻留在何处。此外,在测试期间,假如需求,我们能够很容易地用模仿完成来交换任何类。
4.错误四:缺乏异常处置或处置不当
分歧性的主题并非是Spring(或Java)所独有的,但依然是处置Spring项目时需求思索的一个重要方面。固然编码作风可能存在争议(通常团队或整个公司内部已达成分歧),但具有一个共同的规范最终会极大地进步消费力。对多人团队尤为如此;分歧性允许交流发作,而不需求破费很多资源在手把手交接上,也不需求就不同类的职责提供冗长的解释。
思索一个包含各种配置文件、效劳和控制器的Spring项目。在命名时坚持语义上的分歧性,能够创立一个易于搜索的构造,任何新的开发人员都能够依照本人的方式管理代码;例如,将Config后缀添加到配置类,效劳层以Service结尾,以及控制器用Controller结尾。
与分歧性主题亲密相关,效劳器端的错误处置值得特别强调。假如你曾经不得不处置编写很差的API的异常响应,那你可能晓得缘由——正确解析异常会是一件痛苦的事情,而肯定这些异常最初发作的缘由则更为痛苦。
作为一名API开发者,理想状况下你希望掩盖一切面向用户的端点,并将他们转换为常见的错误格式。这通常意味着有一个通用的错误代码和描绘,而不是逃避处理问题:a)返回一个“500InternalServerError”信息。b)直接返回异常的堆栈信息给用户。(实践上,这些都应该不惜一切代价地去防止,由于除了客户端难以处置以外,它还暴露了你的内部信息)。
例如,常见错误响应格式可能长这样:
与此相似的事情在大多数盛行的API中也经常遇到,由于能够容易且系统地记载,效果常常很不错。将异常转换为这种格式能够经过向办法提供@ExceptionHandler注解来完成(注解案例可见于第六章)。
5.错误五:多线程处置不当
不论是桌面应用还是Web应用,无论是Spring还是NoSpring,多线程都是很难破解的。由并行执行程序所惹起的问题是令人毛骨悚然且难以捉摸的,而且常常难以调试——实践上,由于问题的实质,一旦你认识到你正在处置一个并行执行问题,你可能就不得不完整放弃调试器了,并“手动”检查代码,直到找到基本上的错误缘由。
不幸的是,这类问题并没有千篇一概的处理计划;依据详细场景来评价状况,然后从你以为最好的角度来处理问题。
当然,理想状况下,你也希望完整防止多线程错误。同样,不存在那种一刀切的办法,但这有一些调试和避免多线程错误的实践思索要素:
5.1.防止全局状态
首先,牢记“全局状态”问题。假如你正创立一个多线程应用,那么应该亲密关注任何可能全局修正的内容,假如可能的话,将他们全部删掉。假如某个全局变量有必需坚持可修正的缘由,请认真运用synchronization,并对程序性能停止跟踪,以肯定没有由于新引入的等候时间而招致系统性能降低。
5.2.防止可变性
这点直接来自于函数式编程,并且适用于OOP,声明应该防止类和状态的改动。简而言之,这意味着放弃setter办法,并在一切模型类上具有私有的final字段。它们的值独一发作变化的时间是在结构期间。这样,你能够肯定不会呈现争用问题,且访问对象属性将一直提供正确的值。
5.3.记载关键数据
评价你的程序可能会在何处发作异常,并预先记载一切关键数据。假如发作错误,你将很快乐能够得到信息阐明收到了哪些恳求,并可更好地理解你的应用程序为什么会呈现错误。需求再次留意的是,日志记载引入了额外的文件I/O,可能会严重影响应用的性能,因而请不要滥用日志。
5.4.复用现存完成
每当你需求创立本人的线程时(例如:向不同的效劳发出异步恳求),复用现有的平安完成来替代创立本人的处理计划。这在很大水平上意味着要运用ExecutorServices和Java8简约的函数式CompletableFutures来创立线程。Spring还允许经过DeferredResult类来停止异步恳求处置。
6.错误六:不运用基于注解的考证
假定我们之前的TopTalent效劳需求一个端点来添加新的TopTalent。此外,假定基于某些缘由,每个新名词都需求为10个字符长度。执行此操作的一种办法可能如下:
Spring常犯的十大错误,打死都不要犯
但是,上面的办法(除了结构很差以外)并不是一个真正“洁净”的处理方法。我们正检查不止一品种型的有效性(即TopTalentData不得为空,TopTalentData.name不得为空,且TopTalentData.name为10个字符长度),以及在数据无效时抛出异常。
经过在Spring中集成Hibernatevalidator,数据校验能够更洁净地停止。让我们首先重构addTopTalent办法来支持考证:
如今,Spring将在调用办法之前拦截其恳求并对参数停止考证——无需运用额外的手工测试。
另一种完成相同功用的办法是创立我们本人的注解。固然你通常只在需求超出Hibernate的内置约束集时才运用自定义注解,本例中,我们假定@Length不存在。你能够创立两个额外的类来考证字符串长度,一个用于考证,一个用于对属性停止注解:
请留意,这些状况下,关注点别离的最佳理论请求在属性为null时,将其标志为有效(isValid办法中的s==null),假如这是属性的附加请求,则运用@NotNull注解。
7.错误七:(照旧)运用基于xml的配置
固然之前版本的Spring需求XML,但往常大局部配置均可经过Java代码或注解来完成;XML配置只是作为附加的不用要的榜样代码。
本文(及其附带的GitHub仓库)均运用注解来配置Spring,Spring晓得应该衔接哪些Bean,由于待扫描的顶级包目录已在@SpringBootApplication复合注解中做了声明,如下所示:
Spring常犯的十大错误,打死都不要犯
复合注解(可经过Spring文档理解更多信息)只是向Spring提示应该扫描哪些包来检索Bean。在我们的案例中,这意味着这个顶级包(co.kukurin)将用于检索:
@Component(TopTalentConverter,MyAnnotationValidator)
@RestController(TopTalentController)
@Repository(TopTalentRepository)
@Service(TopTalentService)类
假如我们有任何额外的@Configuration注解类,它们也会检查基于Java的配置。
8.错误八:疏忽profile
在效劳端开发中,经常遇到的一个问题是辨别不同的配置类型,通常是消费配置和开发配置。在每次从测试切换到部署应用程序时,不要手动交换各种配置项,更有效的办法是运用profile。引荐阅读:SpringBootProfile不同环境配置。关注Java技术栈微信公众号,在后台回复关键字:boot,能够获取一份栈长整理的SpringBoot最新技术干货。
思索这么一种状况:你正在运用内存数据库停止本地开发,而在消费环境中运用MySQL数据库。实质上,这意味着你需求运用不同的URL和(希望如此)不同的凭证来访问这两者。让我们看看能够如何做到这两个不同的配置文件:
8.1.APPLICATION.YAML文件
假定你不希望在修正代码时不测地对消费数据库停止任何操作,因而将默许配置文件设为dev是很有意义的。
然后,在效劳器上,你能够经过提供-Dspring.profiles.active=prod参数给JVM来手动掩盖配置文件。另外,还可将操作系统的环境变量设置为所需的默许profile。
9.错误九:无法承受依赖项注入
正确运用Spring的依赖注入意味着允许其经过扫描一切必需的配置类来将一切对象衔接在一同;这关于解耦关系十分有用,也使测试变得更为容易,而不是经过类之间的紧耦合来做这样的事情:
我们让Spring为我们做衔接:
MiskoHevery的Googletalk深化解释了依赖注入的“为什么”,所以,让我们看看它在理论中是如何运用的。在关注点别离(常见错误#3)一节中,我们创立了一个效劳和控制器类。
假定我们想在TopTalentService行为正确的前提下测试控制器。我们能够经过提供一个单独的配置类来插入一个模仿对象来替代实践的效劳完成:
然后,我们能够经过通知Spring运用SampleUnitTestConfig作为它的配置类来注入模仿对象:
之后,我们就能够运用上下文配置将Bean注入到单元测试中。
10.错误十:缺乏测试,或测试不当
虽然单元测试的概念曾经存在很长时间了,但很多开发人员似乎要么“遗忘”做这件事(特别是假如它不是“必需”的时分),要么只是在事后把它添加进来。这显然是不可取的,由于测试不只应该考证代码的正确性,还应该作为程序在不同场景下应如何表现的文档。
在测试Web效劳时,很少只停止“纯”单元测试,由于经过HTTP停止通讯通常需求调用Spring的DispatcherServlet,并查看当收到一个实践的HttpServletRequest时会发作什么(使它成为一个“集成”测试,处置考证、序列化等)。
RESTAssured,一个用于简化测试REST效劳的JavaDSL,在MockMVC之上,曾经被证明提供了一个十分文雅的处理计划。思索以下带有依赖项注入的代码片段:
SampleUnitTestConfig类将TopTalentService的模仿完成衔接到TopTalentController中,而一切的其他类都是经过扫描应用类所在包的下级包目录来推断出的规范配置。RestAssuredMockMvc只是用来设置一个轻量级环境,并向/toptal/get端点发送一个GET恳求。

未经允许不得转载:IT技术网站 » Spring 常犯的十大错误
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

志在指尖 用双手敲打未来

登录/注册IT技术大全

热门IT技术

C#基础入门   SQL server数据库   系统SEO学习教程   WordPress小技巧   WordPress插件   脚本与源码下载