《精通Spring4.x企业应用开发实战》第三章
这一章节主要介绍SpringBoot的使用,也是学习的重点内容,之后就打算用SpringBoot来写后台,所以提前看一下还是很有必要的。
3.SpringBoot概况
3.1.1SpringBoot发展背景
Spring Boot的出现。Spring Boot可让开发人员不再需要编写复杂的XML配置文件,仅通过几行代码就能实现一个可运行的Web应用。
Spring Boot革新Spring项目开发体验之道,其实是借助强大的Groovy 动态语言实现的,如借助Groovy强大的 MetaObject协议、可插拔的AST转换器及内置的依赖解决方案引擎等。在其核心的编译模型中,Spring Boot使用Groovy来构建工程文件,所以它可以轻松地利用导入模板及方法模板对类所生成的字节码进行改造,从而让开发者仅很简洁的代码就可以完成很复杂的操作。
从Spring Boot项目名称中的 Boot可以看出,Spring Boot的作用在于创建和启动新的基于Spring框架的项目,其目的是帮助开发人员快速构建出基于Spring 的应用。SpringBoot像一个“管家”,它会在后台“智能地”整合项目所需的第三方依赖类库或框架,因此大部分基于Spring Boot的应用仅需要很少的配置就可以运行起来。
Spring Boot包含如下特性:
为开发者提供Spring 快速入门体验
内嵌Tomcat和 Jetty容器,不需要部署WAR文件到Web容器就可独立运行应用。
提供许多基于Maven的pom配置模板来简化工程配置。提供实现自动化配置的基础设施。
提供可以直接在生产环境中使用的功能,如性能指标。
应用信息和应用健康检查开箱即用,没有代码生成,也无须XML配置文件,支持修改默认值来满足特定需求。
3.2快速配置。
我们以Maven方式快速创建一个 Spring Web应用,首先需要在pom.xml文件中引入 Spring Boot依赖。引用了一个spring-boot-starter-web启动器依赖,不像在第2章中的示例一样,需要引入很多Spring子模块依赖。其他的模块都已经封装好了。
@EnableAutoConfiguration注解是由Boot提供的,用于对Spring框架进行自动配置,减少了开发人员的工作量;@RestController和@RequestMapping注解是由SpringMVC提供的,用于创建Rest 服务。
虽然Spring Boot没有强制要求工程代码结构按某种方式进行组织,但为了编写代码的可读性,建议采用所示的包组织方式。
建议将应用的主类放在主包外层,将Application应用主类放在com.smart主包下。这个主类声明了main()方法,并在类级别上标注@Configuration、@ComponentScan,@EnableAutoConfiguration注解。在Spring Boot 1.2+中可以使用@SpringBootApplication注解代替上面3个注解。其他子包规划包括Web、Service、Domain、DAO等。一个典型的Application主类如代码所示。
3.4持久层
Spring框架提供了几种可选的操作数据库方式,可以直接使用Spring 内置轻量级的JdbcTemplate,也可以使用第三方持久化框架Hibernate或 MyBaits。Spring Boot为这两种操作数据库方式分别提供了相应的启动器spring-boot-starter-jdbc和 spring-boot-starter-jpa。应用Spring Boot启动器使数据库持久化操作变得更加简单,因为Spring Boot会自动配置访问数据库相关设施。只需在工程模块 pom.xml文件中添加spring-boot-starter-data-jdbc或spring-boot-starter-data-jpa依赖即可。下面将采用Boot 提供的JDBC启动器来实现第⒉章登录示例的持久层。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>chapter3</artifactId>
<name>Spring4.x第三章实例</name>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
...
导入依赖包之后,为了让Spring Boot能够自动装配数据源的连接,需要在资源根目录resources下创建一个application.properties,配置数据库的连接信息,如代码所示。
在Spring Boot 中,可以通过两种方式配置数据库连接。一种是通过自定义连接的方式,如在配置文件①-1处,通过配置spring.datasource.*选项设定数据源的链接地址、连接驱动器、用户名及密码。在默认情况下,Boot启动器自动创建tomcat-jdbc连接池。如果不想采用默认的连接池,则可以通过 spring.datasource.type属性手工指定项目所需的连接池(如DBCP、C3PO)。
另外一种是通过JNDI方式设置,在生产环境中通常会采用此种方式。如在示例②处,为spring.datasource.jndi-name属性指定一个JNDI连接名称即可。
在 Boot中提供了灵活的数据库初始化方式,可以设定DDL脚本,也可以设定DML脚本。如示例③处,spring.datasource.initialize 属性设置启动的时候是否进行初始化;spring.datasource.platform 属性设置当前数据库类型(如Oracle、MySQL、SQL Server等); spring.datasource.data属性设置DML 脚本文件名称,在启动的时候会从类根路径加载data-S{platform}.sql文件执行,其中$ {platform}为当前数据库类型,本示例配置会加载data-mysql.sql; spring.datasource.schema属性设置DDL脚本文件名称,在启动的时候会从类根路径加载schema-mysql.sql文件执行。
3.4.2UserDao
这里用@Repository定义了一个DAO Bean,用@Autowired将Spring容器中的 Bean注入进来。这个写法与第⒉章中的示例一致。细心的读者可能会有疑问:采用Boot方式与普通的方式不是一样的吗?
大家可以回顾一下第2章的持久层,写完了业务操作DAO之后,还有一个重要的步骤,就是要在Spring容器中装配DAO。
在Spring Boot中,这个步骤就不需要了,Boot 会自动帮我们装配好。这就是SpringBoot的强大之处,开发人员只需关注业务的实现,而无须关注Bean装配等配置,这也是Spring Boot设计的初衷。
3.5业务层
在编写业务层代码时有两个重要的步骤:一是编写正确的业务逻辑;二是对业务事务的管控。在 Spring Boot中,使用事务非常简单,首先在主类Application 上标注@EnableTransactionManagement注解(开启事务支持,相当于XML中的<tx:annotation-driven/>配置方式),然后在访问Service方法上标注@Transactional注解即可。如果将@Transactional注解标注在Service类级别上,那么当前Service类的所有方法都将被事务增强,建议不要在类级别上标注@Transactional注解。
通过@EnableTransactionManagement注解,Boot为应用自动装配了事务支持。这对用户并不透明,用户如果想自己定义事务管理器,则在Application类中添加一个即可,如代码所示。
在Application中添加自定义事务管理器方法txManager),并在方法上标注@Bean注解,此时Spring Boot 会加载自定义的事务管理器,不会重新实例化其他事务管理器。
如果在实际的项目中需要分布式事务支持,那么,Boot也提供了很好的支持,它集成了Atomikos和 Bitronix分布式事务处理框架,可以根据需要导入相应的启动器( spring-boot-starter-jta-atomikos或spring-boot-starter-jta-bitronix)。
3.6展现层
3.6.1配置pom.xml依赖
由于在示例中使用JSP作为视图,且用到了JSTL标签,因此需要再添加相关的依赖包,如代码所示。
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
3.6.2配置Spring MVC框架
在 Boot环境中配置MVC很简单,只要将上面的应用启动类Application稍作修改即可,如代码所示。
在①处继承了Spring Boot提供的Servlet初始化器SpringBootServletInitializer,在②处重写了SpringBootServletInitializer 的configure()方法。
3.6.3处理登录请求
首先需要编写的是LoginController,它负责处理登录请求,完成登录业务,并根据登录成功与否转向欢迎页面或失败页面。这与第2章示例LoginController一致,如代码所示。
@RestController
public class LoginController{
private UserService userService; @RequestMapping(value = {"/","/index.html"})
public ModelAndView loginPage(){
return new ModelAndView("login");
} @RequestMapping(value = "/loginCheck.html")
public ModelAndView loginCheck(HttpServletRequest request,LoginCommand loginCommand){
boolean isValidUser = userService.hasMatchUser(loginCommand.getUserName(),
loginCommand.getPassword());
if (!isValidUser) {
return new ModelAndView("login", "error", "用户名或密码错误。");
} else {
User user = userService.findUserByUserName(loginCommand
.getUserName());
user.setLastIp(request.getLocalAddr());
user.setLastVisit(new Date());
userService.loginSuccess(user);
request.getSession().setAttribute("user", user);
return new ModelAndView("main");
}
} @Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
编写好登录控制器LoginController 之后,接下来配置MVC视图映射。首先创建一个文件夹用于存放JSP文件。为了统一规范,在 src/main/webapp/WEB-INF目录下创建一个jsp文件夹,并将第﹖章示例中创建的两个页面(login.jsp 或main.jsp〉复制到此目录。
在默认情况下,Spring Boot对/static、/public、/resources或/META-INF/ resources目录下的静态文件提供支持,所以我们可以将应用中的静态文件(JS、CSS、Image等)放到这几个目录中。
规划好视图目录后,最后一步就是在 application.properties 中配置创建好的视图的路径。
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
通过spring.mvc.view.prefix 属性指定视图路径的前缀,通过 spring.mvc.view.suffix属性指定视图文件的后缀。至此,我们就完成了对第⒉章登录示例的改造工作。
最后,通过Spring Boot运行应用插件。双击spring-boot:run命令,即可启动应用。
基于Spring Boot应用,由于当前应用包含了一个可直接运行的Application类,所以在开发过程中,大家很容易在IDE(如 IDEA 工具)中单击鼠标右键运行当前类。虽然可以启动当前应用,在非 Web应用中可能不会有什么问题,但在 Web 应用中,如果采用上述方法直接运行应用,那么在访问有视图的页面时(如JSP),会一直报404错误。
因为直接运行当前启动类,Spring Boot无法找到当前页面资源。因此,基于SpringBoot 的应用在开发调试的时候,一定要基于Spring Boot提供的 spring-boot-maven-plugin插件命令来运行应用或通过Spring Boot命令行来运行应用。
基于Spring Boot应用,添加监控功能非常简单,只需在应用的pom.xml文件中添加spring-boot-starter-actuator依赖即可。
《精通Spring4.x企业应用开发实战》第三章的更多相关文章
- Linux内核设计与实现 第三章
1. 进程和线程 进程和线程是程序运行时状态,是动态变化的,进程和线程的管理操作都是由内核来实现的. Linux中的进程于Windows相比是很轻量级的,而且不严格区分进程和线程,线程不过是一种特殊的 ...
- linux及安全《Linux内核设计与实现》第一章——20135227黄晓妍
<linux内核设计与实现>第一章 第一章Linux内核简介: 1.3操作系统和内核简介 操作系统:系统包含了操作系统和所有运行在它之上的应用程序.操作系统是指整个在系统中负责完成最基本功 ...
- LINUX内核设计与实现第三周读书笔记
LINUX内核设计与实现第三周读书笔记 第一章 LINUX内核简介 1.1 Unix的历史 1969年的夏天,贝尔实验室的程序员们在一台PDR-7型机上实现了Unix这个全新的操作系统. 1973年, ...
- 《linux内核设计与实现》第一章
第一章Linux内核简介 一.unix 1.Unix的历史 Unix是现存操作系统中最强大和最优秀的系统. ——1969年由Ken Thompson和Dernis Ritchie的灵感点亮的产物. — ...
- linux及安全《Linux内核设计与实现》第二章——20135227黄晓妍
第二章:从内核出发 2.1获取源代码 2.1.1使用git Git:内核开发者们用来管理Linux内核源代码的控制系统. 我们使用git来下载和管理Linux源代码. 2.1.2安装内核源代码(如果使 ...
- Linux内核设计与实现 第十七章
1. 设备类型 linux中主要由3种类型的设备,分别是: 设备类型 代表设备 特点 访问方式 块设备 硬盘,光盘 随机访问设备中的内容 一般都是把设备挂载为文件系统后再访问 字符设备 键盘,打印机 ...
- Linux内核设计与实现 第五章
1. 什么是系统调用 系统调用就是用户程序和硬件设备之间的桥梁. 用户程序在需要的时候,通过系统调用来使用硬件设备. 系统调用的存在意义: 1)用户程序通过系统调用来使用硬件,而不用关心具体的硬件设备 ...
- 《linux内核设计与实现》第二章
第二章 从内核出发 一.获取内核源码 1.使用Git(linux创造的系统) 使用git来获取最新提交到linux版本树的一个副本: $ git clone git://git.kernel.org/ ...
- 《Linux内核分析》之第三章读书笔记
进程管理 进程是处于执行期的程序以及相关的资源的总称,也称作任务.执行线程,简称线程,是在进程中活动的对象. 可以两个或两个以上的进程执行同一个程序 也可以两个或两个以上并存的进程共享许多资源 内核调 ...
- Linux内核设计与实现 第四章
1. 什么是调度 现在的操作系统都是多任务的,为了能让更多的任务能同时在系统上更好的运行,需要一个管理程序来管理计算机上同时运行的各个任务(也就是进程). 这个管理程序就是调度程序,功能: 决定哪些进 ...
随机推荐
- npm包管理器报错-npm ERR! Response timeout while trying to fetch https://registry.npmjs.org/@XXX(over 30000ms)
由于这两天买的新电脑在短期内频频蓝屏.卡机,不得不把自己其他的本本拿出来换上,但是程序员换电脑是真的痛苦,其他不说就说一个配环境 真的折腾哈 我是一名前端菜鸟,现在自己的本本上使用的是npm包管理工具 ...
- CN1,CN2 GT和CN2 GIA的区别
用一句话来概括,CN1主要定位于承载普通质量的互联网业务,而CN2则定位于承载企业VPN业务.中国电信的自营业务及高质量的互联网业务,CN2 GIA又比GT要好一些. 顺序:CN2 GIA>CN ...
- npm npx cnpm yarn 的区别
npm npm 是 Node.js 官方提供的包管理工具.用于 Node.js 包的发布.传播.依赖控制.npm 提供了命令行工具,使你可以方便地下载.安装.升级.删除包,也可以让你作为开发者发布并维 ...
- git克隆指定分支到本地
我们每次使用命令 git clone https://xxx.com/android-app.git 默认 clone 的是这个仓库的 master 分支. 使用Git下载指定分支命令为:git cl ...
- 分布式锁结合SpringCache
1.高并发缓存失效问题: 缓存穿透: 指查询一个一定不存在的数据,由于缓存不命中导致去查询数据库,但数据库也无此记录,我们没有将此次查询的null写入缓存,导致这个不存在的数据每次请求都要到存储层进行 ...
- 集训DP复习整理
DP复习 集训%你赛2:测绘(审题DP) 经过2000+个小时的努力终于把这道题做出来的蒟蒻通 分析: 这道题我一直没做出来的原因就是因为我太蒟了题面看不懂,题面读懂了,其实不是特别难. 题目翻译: ...
- selenium-滚动
移动到指定的坐标(相对当前的坐标移动) driver.execute_script("window.scrollBy(0, 700)"); 移动到窗口绝对位置坐标,如下移动到纵坐标 ...
- Java 8 中的抽象类和接口到底有啥区别?
上一篇栈长发了这篇<Java 8 有多牛逼?打破一切你对接口的认知!>,帮助许多人解开了疑惑,还有读者留言说两者还有啥区别,故引发了此篇: 在我们面试时也会经常遇到面试官问抽象类和接口的区 ...
- Storm入门教程汇总
http://www.aboutyun.com/thread-8059-1-1.html
- ThreadLocal与Thread与Runable之间的关系
ThreadLocal继承Object,相当于没继承任何特殊的. ThreadLocal没有实现任何接口. ThreadLocal并不是一个Thread,而是Thread的局部变量