写点什么

使用 Spring Boot 快速构建应用

  • 2014-01-20
  • 本文字数:3794 字

    阅读完需:约 12 分钟

随着 Spring 4 新版本的发布 Spring Boot 这个新的子项目得到了广泛的关注,因为不管是 Spring 4 官方发布的新闻稿还是针对首席架构师Adrian Colyer 的专访,都对这个子项目所带来的生产率提升赞誉有加。

Spring Boot 充分利用了 JavaConfig 的配置模式以及“约定优于配置”的理念,能够极大的简化基于 Spring MVC 的 Web 应用和 REST 服务开发。

Spring 4 倡导微服务的架构,针对这一理念,近来在微博上也有一些有价值的讨论,如这里这里。微服务架构倡导将功能拆分到离散的服务中,独立地进行部署,Spring Boot 能够很方便地将应用打包成独立可运行的 JAR 包,因此在开发模式上很契合这一理念。目前,Spring Boot 依然是 0.5.0 的里程碑版本,因此相关的文档尚不完善,本文将会以一个简单的样例来介绍基于这个项目的开发过程。

要 Spring Boot 进行功能开发,需要使用 Gradle 或者 Maven 作为构建工具。在本例中,我们会使用 Eclipse 和 Maven 插件进行开发。要使用 Spring Boot,首先创建一个 Maven 工程,并修改 Maven 主要的配置文件 pom.xml,如下所示:

复制代码
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>0.5.0.M7</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring3</artifactId>
</dependency>
</dependencies>
<properties>
<start-class>com.levin.Application</start-class>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestone</id>
<url>http://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-milestone</id>
<url>http://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>

在上面的配置中,需要将工程的 parent 设置为 spring-boot-starter-parent,并添加对 spring-boot-starter-web 的依赖,这样我们就无需设置各个依赖项及其版本信息了。并且在构建中要声明使用 spring-boot-maven-plugin 这个插件,它会对 Maven 打包形成的 JAR 进行二次修改,最终产生符合我们要求的内容结构。

在我们的应用中将要发布一个 REST 服务,显示一个基本的用户信息,首先定义一个简单的模型类:

复制代码
package com.levin;
public class Person {
private String name;
private String email;
public Person(String name, String email) {
this.name = name;
this.email = email;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

接下来,我们需要声明一个 Spring MVC 的 Controller,响应对实体的请求:

复制代码
@Controller
public class ShowPersonController {
@RequestMapping("/showPerson")
public @ResponseBody Person showPerson() {
return new Person("levinzhang","levinzhang1981@gmail.com");
}
}

这个类与我们在使用 Spring MVC 定义 Controller 时并无任何差别。接下来,我们需要声明一个主类启动这个应用程序:

复制代码
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

这个类的 main 方法中使用了 SpringApplication 帮助类,并以 Application 这个类作为配置来启动 Spring 的应用上下文。在这个类中使用了 ComponentScan 以及 EnableAutoConfiguration 注解,其中 ComponentScan 注解会告知 Spring 扫描指定的包来初始化 Spring Bean,这能够确保我们声明的 Bean 能够被发现。EnableAutoConfiguration 将会启动自动配置模式,在我们的配置中会将对 Tomcat 的依赖级联进来,因此在应用启动时将会自动启动一个嵌入式的 Tomcat,因为在样例中使用了 Spring MVC,所以也会自动注册所需的 DispatcherServlet,这都不需要类似 web.xml 这样的配置。

在 Eclipse 中要运行这个应用的话,可以直接以 Java Application 的形式来运行这个 main 函数,此时会启动应用,我们在浏览器中可以看到如下的运行效果,这就是我们想要的 REST 服务:

在开发调试完成之后,可以将应用打成 JAR 包的形式,在 Eclipse 中可以直接使用 Maven 插件的 package 命令,最终会形成一个可运行的 JAR 包。我们使用 java –jar 命令就可以运行这个 JAR 包了。所呈现出的效果与在调试期是一样的。现在看一下这个 JAR 包解压后的目录结构:

这个 JAR 包与传统 JAR 包的不同之处在于里面有一个名为 lib 的目录,在这个目录中包含了这个简单应用所依赖的其他 JAR 包,其中也包含内置的嵌入式 Tomcat,正是使用它,才能发布服务和访问 Web 资源。除了我们编写的源码所编译形成的 CLASS 以外,在 org 目录下还有许多 Spring 所提供的 CLASS,正是依赖这些 CLASS,才能够加载位于 lib 目录下 JAR 中的类。这样的加载机制与在 OSGi bundle 中声明 Bundle-Classpath 很类似,不过在 OSGi 中会由容器来负责加载指定路径下的类。这大致阐述了这样一个 JAR 包能够发布服务的原因。

如果我们想要使用 HTML、JSP 等 Web 资源的话,在 Controller 中直接返回对应的视图就可以了。

如果我们想要将这个 JAR 包转换成可以在 Servlet 容器中部署的 WAR 的话,就不能依赖于 Application 的 main 函数了,而是要以类似于 web.xml 文件配置的方式来启动 Spring 应用上下文,此时我们需要声明这样一个类:

复制代码
public class HelloWebXml extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
}

这个类的作用与在 web.xml 中配置负责初始化 Spring 应用上下文的监听器作用类似,只不过在这里不需要编写额外的 XML 文件了。

如果要将最终的打包形式改为 WAR 的话,还需要对 pom.xml 文件进行修改,除了需要将 packaging 的值修改为 war 以外,还需要对依赖进行适当的配置(这一部分在 Spring Boot 的样例和文档中均未提及,提醒大家注意):

复制代码
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>

在这里需要移除对嵌入式 Tomcat 的依赖,这样打出的 WAR 包中,在 lib 目录下才不会包含 Tomcat 相关的 JAR 包,否则将会出现启动错误。另外,在移除对 Tomcat 的依赖后,为了保证编译正确,还需要添加对 servlet-api 的依赖,因此添加如下的配置:

复制代码
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
<version>7.0.42</version>
<scope>provided</scope>
</dependency>

在这里将 scope 属性设置为 provided,这样在最终形成的 WAR 中不会包含这个 JAR 包,因为 Tomcat 或 Jetty 等服务器在运行时将会提供相关的 API 类。此时,执行 mvn package 命令就会得到一个 WAR 文件,我们可以直接将其放到 Tomcat 下运行(需要 7.0.42 版本以上)。

以上介绍了基于 Spring Boot 开发应用的过程,目前它的文档尚不完善,但是在 GitHub 上有不少的样例,包括与 Spring Data 集成访问数据库(关系型以及非关系型)、安全、WebSocket 等,读者感兴趣可以下载运行,需要注意的是有些样例中使用的是 0.5.0.M6 版本,这个版本有问题,运行时会出错,建议手动修改为 0.5.0.M7 或快照版本。

基于以上的介绍,希望读者能够对 Spring Boot 这个新项目有所了解。它简化了 JAR 包管理和相关基础设施环境的配置,能够帮助我们快速开发 Web 应用或构建 REST 服务,希望它能够尽快完善成熟,更多地用于实践,提升开发效率。

参考资料

http://projects.spring.io/spring-boot/

http://projects.spring.io/spring-boot/docs/README.html

http://spring.io/guides/gs/spring-boot/

http://spring.io/guides/gs/actuator-service/

http://spring.io/guides/gs/convert-jar-to-war/

2014-01-20 23:2340226

评论

发布
暂无评论
发现更多内容

Required request parameter ‘XXX‘ for method parameter type String is not present

源字节1号

开源 软件开发 前端开发 后端开发 小程序开发

科普:基于FMU模型的TSN交换机仿真

DevOps和数字孪生

FMU模型 TSN

嵌入式Linux的学习误区

芯动大师

Linux 嵌入式 处理器

巧用 TiCDC Syncpiont 构建银行实时交易和准实时计算一体化架构

PingCAP

数据库 TiDB

Linux设备驱动系列(九)——procfs文件系统

Linux内核拾遗

文件系统 linux开发 Linux内核 设备驱动 procfs

当「软件研发」遇上 AI 大模型

阿里巴巴云原生

阿里云 云原生 通义灵码

视觉语言模型详解

不在线第一只蜗牛

自然语言 语言模型

架构实战营 - 模块六作业

满心

Rust vs Go:如何选择最适合你的编程语言

伤感汤姆布利柏

ACK One x OpenKruiseGame 全球游戏服多地域一致性交付最佳实践

阿里巴巴云原生

阿里云 开源 容器 云原生

30 秒出服装设计稿,森马用函数计算+AIGC 整“新活”!

阿里巴巴云原生

阿里云 Serverless 云原生 函数计算

银行核心背后的落地工程体系丨Oracle - TiDB 数据迁移详解

PingCAP

数据库 TiDB

TiDB Vector 太香啦:以图搜图初体验!

PingCAP

数据库 TiDB

这届黑客马拉松,和效率“杠上了” | StartDT Hackathon

奇点云

黑客马拉松 数据技术 奇点云

事业-最佳实践-编码-声明规范

南山

为什么公共事业机构会偏爱 TiDB :TiDB 数据库在某省妇幼健康管理系统的应用

PingCAP

数据库 TiDB

PPT软件Gamma平替!这款AI生成PPT工具千万别错过!

彭宏豪95

PPT 在线白板 PPT模板 办公软件 AI生成PPT

在线音频,没有新故事

自象限

前端面试题 - 如何实现promise?

Geek_fed966

null是原始类型,但为什么typeof null的结果是object?

Geek_fed966

当「软件研发」遇上 AI 大模型

阿里云云效

阿里云 AI 云原生 通义灵码

使用Spring Boot快速构建应用_Java_张卫滨_InfoQ精选文章