深入浅析 Spring Boot Starter
spring boot 简介
spring框架功能很强大,但是就算是一个很简单的项目,我们也要配置很多东西。因此就有了spring boot框架,它的作用很简单,就是帮我们自动配置。spring boot框架的核心就是自动配置,只要存在相应的jar包,spring就帮我们自动配置。如果默认配置不能满足需求,我们还可以替换掉自动配置类,使用我们自己的配置。另外,spring boot还集成了嵌入式的web服务器,系统监控等很多有用的功,让我们快速构建企业及应用程序。
依赖管理是任何复杂项目的关键部分。以手动的方式来实现依赖管理不太现实,你得花更多时间,同时你在项目的其他重要方面能付出的时间就会变得越少。
spring boot starter 就是为了解决这个问题而诞生的。starter pom 是一组方便的依赖描述符,您可以将其包含在应用程序中。您可以获得所需的所有 spring 和相关技术的一站式服务,无需通过示例代码搜索和复制粘贴依赖。
我们有超过 30 个 boot starter — 下文将提到其中一部分。
2、web starter
首先,让我们来看看 rest 服务开发。我们可以使用像 spring mvc、tomcat 和 jackson 这样的库,这对于单个应用程序来说是还是存在许多依赖。
spring boot starter 通过添加一个依赖来帮助减少手动添加依赖的数量。 因此,不要手动指定依赖,您只需要添加一个 starter 即可,如下所示:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency>
现在我们可以创建一个 rest 控制器。为了简单起见,我们不会使用数据库,只专注于 rest 控制器:
@restcontroller public class genericentitycontroller{ private list<genericentity> entitylist = new arraylist<>(); @requestmapping("/entity/all") public list<genericentity> findall(){ return entitylist; } @requestmapping(value = "/entity", method = requestmethod.post) public genericentity addentity(genericentity entity){ entitylist.add(entity); return entity; } @requestmapping("/entity/findby/{id}") public genericentity findbyid(@pathvariable long id){ return entitylist.stream(). filter(entity -> entity.getid().equals(id)). findfirst().get(); } }
genericentity是一个简单的 bean, id 的类型为 long , value 为 string 类型。
就是这样,应用程序可以开始运行了,您可以访问 并检查控制器是否正常工作。
我们已经创建了一个配置非常少的 rest 应用程序。
3、test starter
对于测试,我们通常使用以下组合:spring test、junit、hamcrest 和 mockito。我们可以手动包含所有这些库,但使用以下 spring boot starter 方式可以自动包含这些库:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-test</artifactid> <scope>test</scope> </dependency>
请注意,您不需要指定工件的版本号。spring boot 会自动选择合适的版本 — 您仅需要指定 spring-boot-starter-parent-artifact 的版本。 如果之后您想要升级 boot 库和依赖,只需在一个地方升级 boot 版本即可,它将会处理其余部分。
让我们来测试一下之前创建的控制器。
测试控制器有两种方法:
- 使用 mock 环境
- 使用嵌入式 servlet 容器(如 tomcat 或 jetty)
在本例中,我们将使用一个 mock 环境:
@runwith(springjunit4classrunner.class) @springapplicationconfiguration(classes = application.class) @webappconfiguration public class springbootapplicationtest{ @autowired private webapplicationcontext webapplicationcontext; private mockmvc mockmvc; @before public void setupmockmvc(){ mockmvc = mockmvcbuilders.webappcontextsetup(webapplicationcontext).build(); } @test public void givenrequesthasbeenmade_whenmeetsallofgivenconditions_thencorrect() throws exception { mediatype contenttype = new mediatype(mediatype.application_json.gettype(), mediatype.application_json.getsubtype(), charset.forname("utf8")); mockmvc.perform(mockmvcrequestbuilders.get("/entity/all")). andexpect(mockmvcresultmatchers.status().isok()). andexpect(mockmvcresultmatchers.content().contenttype(contenttype)). andexpect(jsonpath("$", hassize(4))); } }
这里重要的是 @webappconfiguration 注解和 mockmvc 是 spring-test 模块的一部分, hassize 是一个 hamcrest matcher, @before 是一个 junit 注解。这些都可以通过导入这一个这样的 starter 依赖来引入。
4、data jpa starter
大多数 web 应用程序都存在某些持久化 — 常见的是 jpa。
让我们使用 starter 来开始,而不是手动定义所有关联的依赖:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-data-jpa</artifactid> </dependency> <dependency> <groupid>com.h2database</groupid> <artifactid>h2</artifactid> <scope>runtime</scope> </dependency>
请注意,我们对这些数据库已经有了开箱即用的自动支持:h2、derby 和 hsqldb。在我们的示例中,我们将使用 h2。
现在让我们为实体创建仓储(repository):
public interface genericentityrepositoryextends jparepository<genericentity,long>{}
现在是测试代码的时候了。这是 junit 测试:
@runwith(springjunit4classrunner.class) @springapplicationconfiguration(classes = application.class) public class springbootjpatest{ @autowired private genericentityrepository genericentityrepository; @test public void givengenericentityrepository_whensaveandretreiveentity_thenok(){ genericentity genericentity = genericentityrepository.save(new genericentity("test")); genericentity foundedentity = genericentityrepository.findone(genericentity.getid()); assertnotnull(foundedentity); assertequals(genericentity.getvalue(), foundedentity.getvalue()); } }
我们没有花时间指定数据库厂商、url 连接和凭据。没有额外所需的配置,这些都受益于 boot 的默认支持。 但是,如果您需要,可以进行详细配置。
5、mail starter
企业开发中一个非常常见的任务就是发送电子邮件,直接使用 java mail api 来处理通常很困难。
spring boot starter 屏蔽了这些复杂性 — mail 依赖可以通过以下方式指定:
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-mail</artifactid> </dependency>
现在我们可以直接使用 javamailsender 。让我们开始编写一些测试。
为了测试,我们需要一个简单的 smtp 服务器。在此例中,我们将使用 wiser。将其包含到我们的 pom 中:
<dependency> <groupid>org.subethamail</groupid> <artifactid>subethasmtp</artifactid> <version>3.1.7</version> <scope>test</scope> </dependency>
最新版本的 wiser 可以在 maven *仓库 ( http://search.maven.org/#search%7cga%7c1%7csubethasmtp)中找到。
以下是测试源码:
@runwith(springjunit4classrunner.class) @springapplicationconfiguration(classes = application.class) public class springbootmailtest{ @autowired private javamailsender javamailsender; private wiser wiser; private string userto = "user2@localhost"; private string userfrom = "user1@localhost"; private string subject = "test subject"; private string textmail = "text subject mail"; @before public void setup()throws exception { final int test_port = 25; wiser = new wiser(test_port); wiser.start(); } @after public void teardown()throws exception { wiser.stop(); } @test public void givenmail_whensendandreceived_thencorrect()throws exception { simplemailmessage message = composeemailmessage(); javamailsender.send(message); list<wisermessage> messages = wiser.getmessages(); assertthat(messages, hassize(1)); wisermessage wisermessage = messages.get(0); assertequals(userfrom, wisermessage.getenvelopesender()); assertequals(userto, wisermessage.getenvelopereceiver()); assertequals(subject, getsubject(wisermessage)); assertequals(textmail, getmessage(wisermessage)); } private string getmessage(wisermessage wisermessage) throws messagingexception, ioexception { return wisermessage.getmimemessage().getcontent().tostring().trim(); } private string getsubject(wisermessage wisermessage)throws messagingexception { return wisermessage.getmimemessage().getsubject(); } private simplemailmessage composeemailmessage(){ simplemailmessage mailmessage = new simplemailmessage(); mailmessage.setto(userto); mailmessage.setreplyto(userfrom); mailmessage.setfrom(userfrom); mailmessage.setsubject(subject); mailmessage.settext(textmail); return mailmessage; } }
在测试中, @before 和 @after 方法负责启动和停止邮件服务器。
请注意,我们装配了 javamailsender bean — 该 bean 是 由 spring boot 自动创建 。
与 boot 中的其他默认值一样, javamailsender 的 email 设置可以在 application.properties 中自定义:
spring.mail.host=localhost spring.mail.port=25 spring.mail.properties.mail.smtp.auth=false
我们在 localhost:25 上配置了邮件服务器,不需要身份验证。
6、结论
在本文中,我们介绍了 starter,解释了为什么我们需要它们,并提供了如何在项目中使用它们的示例。
让我们回顾一下使用 spring boot starter 的好处:
- 增加 pom 可管理性
- 生产就绪、测试与依赖配置支持
- 减少项目的整体配置时间
总结
以上所述是小编给大家介绍的spring boot starter的相关知识,希望对大家有所帮助