1、SpringBoot快速入门
1.1、什么是Spring
- Spring是一个开源框架,2003年兴起的一个轻量级的Java开发框架。
- Spring是为了解决企业级应用开发的复杂性而创建的,简化开发。
1.2、Spring是如何简化Java开发的
- 为了降低Java开发的复杂性,Spring采用了以下4种关键策略:
- 基于POJO的轻量级和最小侵入性编程;
- 通过IOC,依赖注入(DI)和面向接口实现松耦合;
- 基于切面(AOP)和惯例进行声明式编程;
- 通过切面和模板减少样式代码
1.3、什么是SpringBoot
- 学过javaweb的同学就知道,开发一个web应用,从最初开始接触Servlet结合Tomcat,跑出一个Hello Wolrld程序,是要经历特别多的步骤;后来就用了框架Struts,再后来是SpringMVC,到了现在的SpringBoot,过一两年又会有其他web框架出现;不知道你们有没经历过框架不断的演进,然后自己开发项目所有的技术也再不断的变化、改造。什么是SpringBoot呢,就是一个javaweb的开发框架,和SpringMVC类似,对比其他javaweb框架的好处,官方说是简化开发,约定大于配置, you can “just run”,能迅速的开发web应用,几行代码开发—个http接口。
- 所有的技术框架的发展似乎都遵循了一条主线规律:从一个复杂应用场景衍生一种规范框架,人们只需要进行各种配置而不需要自己去实现它,这时候强大的配置功能成了优点;发展到一定程度之后,人们根据实际生产应用情况,选取其中实用功能和设计精华,重构出一些轻量级的框架;之后为了提高开发效率,嫌弃原先的各类配置过于麻烦,于是开始提倡“约定大于配置”,进而衍生出一些一站式的解决方案。
- 这就是Java企业级应用——>J2EE——>Spring——>SpringBoot的过程。
- 随着Spring 不断的发展,涉及的领域越来越多,项目整合开发需要配合各种各样的文件,慢慢变得不那么易用简单,违背了最初的理念,甚至人称配置地狱。Spring Boot 正是在这样的一个背景下被抽象出来的开发框架,目的为了让大家更容易的使用Spring、更容易的集成各种常用的中间件、开源软件。
- Spring Boot基于Spring 开发,Spirng Boot本身并不提供Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于Spring 框架的应用程序。也就是说,它并不是用来替代Spring 的解决方案,而是和Spring框架紧密结合用于提升Spring 开发者体验的工具。SpringBoot以约定大于配置的核心思想,默认帮我们进行了很多设置,多数Spring Boot应用只需要很少的Spring 配置。同时它集成了大量常用的第三方库配置(例如Redis、MongoDB、Jpa、RabbitMQ、Quartz等等),SpringBoot整合了所有的框架。
- 简单来说就是SpringBoot其实不是什么新的框架,它默认配置了很多框架的使用方式,就像maven整合了所有的jar包,spring boot整合了所有的框架。
- Spring Boot出生名门,从一开始就站在一个比较高的起点,又经过这几年的发展,生态足够完善,Spring Boot已经当之无愧成为Java领域最热门的技术。
- SpringBoot的主要优点:
- 为所有Spring开发者更快的入门
- 开箱即用,提供各种默认配置来简化项目配置
- 内嵌式容器简化Web项目
- 没有冗余代码生成和xml配置的要求
2、微服务
2.1、什么是微服务
- 微服务是一种架构风格,它要求我们在开发一个应用的时候,这个应用必须构建成一系列小服务的组合;可以通过http的方式进行互通。要说微服务架构,先得说说过去我们的单体应用架构。
2.2、单体应用架构
- 所谓单体应用架构(all in one)是指,我们将一个应用的中的所有应用服务都封装在一个应用中。
- 无论是ERP、CRM或是其他什么系统,你都把数据库访问,web访问,等等各个功能放到一个war包内。
这样做的好处是,易于开发和测试;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
单体应用架构的缺点是,哪怕我要修改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,我们不可能吧所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题。
2.3、微服务架构
- all in one的架构方式,我们把所有的功能单元放在一个应用里面。然后我们把整个应用部署到服务器上。如果负载能力不行,我们将整个应用进行水平复制,进行扩展,然后在负载均衡。
- 所谓微服务架构,就是打破之前all in one的架构方式,把每个功能元素独立出来。把独立出来的功能元素的动态组合,需要的功能元素才去拿来组合,需要多一些时可以整合多个功能元素。所以微服务架构是对功能元素进行复制,而没有对整个应用进行复制。
- 这样做的好处是:
- 节省了调用资源
- 每个功能元素的服务都是一个可替换的、可独立升级的软件代码
- Martin Flower于2014年3月25日写的《Microservices》,详细的阐述了什么是微服务。
- 原文地址: http://martinfowler.com/articles/microservices.html
- 翻译: https: //www.cnblogs.com/liuning8023/p/4493156.html
2.4、如何构建微服务
- 一个大型系统的微服务架构,就像一个复杂交织的神经网络,每一个神经元就是一个功能元素,它们各自完成自己的功能,然后通过http相互请求调用。比如一个电商系统,查缓存、连数据库、浏览页面、结账、支付等服务都是一个个独立的功能服务,都被微化了,它们作为一个个微服务共同构建了一个庞大的系统。如果修改其中的一个功能,只需要更新升级其中一个功能服务单元即可。
- 但是这种庞大的系统架构给部署和运维带来很大的难度。于是,spring为我们带来了构建大型分布式微服务的全套、全程产品:
- 构建一个个功能独立的微服务应用单元,可以使用springboot,可以帮我们快速构建一个应用;
- 大型分布式网络服务的调用,这部分由spring cloud来完成,实现分布式;
- 在分布式中间,进行流式数据计算、批处理,我们有spring cloud data flow。
- spring为我们想清楚了整个从开始构建应用到大型分布式应用全流程方案。
3、第一个SpringBoot程序
官方提供了一个快速生成的网站,IDEA集成了这个网站。
https://start.spring.io/
- 可以在官网直接下载后,导入idea开发。
- 直接使用idea创建一个SpringBoot项目。
在IDEA新建项目
选择对应选项
下一步,选择添加依赖
新建项目结构展示
项目结构一样太熟悉了,三部分分别是src目录下的"java"、“resources”、"test"文件夹。"java"文件夹中的类"HelloworldApplication"为程序的主入口,不能进行修改。可直接启动运行这个main方法。resources文件夹的"application.properties"为SpringBoot的配置文件,也会有yml结尾的文件,后续会说明。test文件夹中为单元测试部分。
访问80端口(默认访问的是个error接口),程序启动成功。
- 新建我们自己需要的结构目录,注意目录的层级结构。需要与"HelloworldApplication"类在同级目录,因为在扫描的时候扫描不到其他的目录,如果写的层级有问题,会扫描不到。
- 新建测试controller类
- 访问接口
-
总结:
在使用springboot的过程中,我们既没有进行映射器的配置,也没有进行适配器的配置等操作。但是依然能够进行整个过程的开发。springboot中主打的就是一个自动装配。简单看一下注解"HelloworldApplication"类中的注解"@SpringBootApplication"
点击进去
可以看到"@Component"注解表示这也是一个组件,所以说明SpringBoot的启动类本身就是Spring的一个组件。
- 重点关注pom.xml文件中的描述信息
- 项目元数据信息:创建时候输入的Project Metadata部分,也就是Maven项目的基本元素,包括:groupld、artifactld、version、name、description等
- parent:继承spring-boot-starter-parent的依赖管理,控制版本与打包等内容
- dependencies:项目具体依赖,这里包含了spring-boot-starter-web用于实现HTTP接口(该依赖中包含了Spring MVC),官网对它的描述是:使用Spring MVC构建Web(包括RESTful)应用程序的入门者,使用Tomcat作为默认嵌入式容器。 spring-boot-starter-test用于编写单元测试的依赖包。
- build:构建配置部分。默认使用了 spring-boot-maven-plugin,配合spring-boot-starter-parent就可以把Spring Boot应用打包成JAR来直接运行。
- 更改项目的端口号(直接在application文件中修改)
- 访问效果
- 自定义banner(既控制台打印输出的图案信息)
在线搜索 SpringBoot banner在线生成,随意找个网站,复制合适的图案等信息。在resource文件下新建文件banner.txt,把文件复制。
重新信息项目,控制台中打印的图案已经改变。
4、自动装配原理
4.1、pom.xml
- spring-boot-dependencies:核心依赖在父工程中
- 我们在写或者引入一些SpringBoot依赖的时候,不需要指定版本,就是因为有这些版本仓库
4.2、启动器
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
-
启动器就是SpringBoot的启动场景。如果当你需要启动web,那么你就需要导入(-web)启动器
-
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
-
spring-boot-starter-web,就会帮我们自动导入web环境所有的依赖
-
springboot会将所有的功能场景,都变成一个一个的启动器
-
我们要使用什么功能,就只需要找到对应的启动器就可以了(可上官网查看)
4.3、主程序
package com.wang.helloworld;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//@SpringBootApplication:标注这个类是一个springboot的应用
@SpringBootApplication
public class HelloworldApplication {
public static void main(String[] args) {
//将springboot应用启动
SpringApplication.run(HelloworldApplication.class, args);
}
}
-
注解
-
@SpringBootConfiguration //SpringBoot的配置 @Configuration //spring配置类 @Component //说明这也是一个spring的组件 @EnableAutoConfiguration //自动配置 @AutoConfigurationPackage //自动配置包 @Import({Registrar.class}) //自动配置"包注册" @Import({AutoConfigurationImportSelector.class}) //自动配置导入选择 List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes); //获取所有的配置
-
接着点进去方法"getCandidateConfigurations"——获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader())); ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you are using a custom packaging, make sure that file is correct."); return configurations; }
-
兜兜转转到最后是为了告诉我们"启动类下的所有资源被导入"
-
META-INF/spring.factories:自动配置的核心文件
-
打开文件,会看到这里有许多资源文件的配置,加载时会根据这里的配置进行加载读取。所有的自动配置类都在这里了 。
-
这么多自动配置为什么有的有效,有的没有生效?需要导入对应的start才能有作用。
-
核心注解:@ConditionalOnxxxx:如果这里面的条件都满足,才会生效。
-
回到上一级方法,一路点击进入这个方法。这个方法中从路径"META-INF/spring.factories"获取配置资源。从这些资源中遍历了所有的nextElement(自动配置),遍历完成之后,封装为Properties供我们使用
-
Properties properties = PropertiesLoaderUtils.loadProperties(resource); 所有资源加载到配置类中
-
结论:SpringBoot所有自动配置都是在启动的时候扫描并加载:spring.factories所有的自动配置类都在这里面,但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功。
- springboot在启动的时候,从类路径下"/META-INF/spring.factories"获取指定的值
- 将这些自动配置的类导入容器,自动配置就会生效,帮我们进行自动配置
- 以前我们需要自动配置的东西,现在springboot帮我们做了
- 整个javaEE,解决方案和自动配置的东西都在spring-boot-autoconfigure这个包下
- 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器(org.springframework.boot.autoconfigure.xxx)
- 容器中也会存在非常多的xxAutoConfiguration的文件(@Bean),就是这些类给容器中导入了这个场景需要的所有组件,并自动配置(@Configuration )
- 有了自动配置类,免去了我们手动编写配置文件的工作
4.4、SpringApplication.run
- 你以为就只是运行了一个main方法,但是却开启了一个服务
@SpringBootApplication
public class HelloworldApplication {
public static void main(String[] args) {
//该方法返回一个ConfigurableApplicationContext对象
//参数一:应用入口的类 参数类:命令行参数
SpringApplication.run(HelloworldApplication.class, args);
}
}
-
SpringApplication.run分析
- SpringApplication的实例化
- run方法的执行
-
SpringApplication这个类主要做了以下几件事:
- 推断应用的类型是普通的项目还是Web项目
- 查找并加载所有可用初始化器,设置到initializers属性中
- 找出所有的应用程序监听器,设置到listeners属性中
- 推断并设置main方法的定义类,找到运行的主类
5、yaml语法
- 在文件"application.properties"中,官方已经罗列出了所有的配置信息。从debugger、log日志等。可去官网连接查找。
5.1、配置文件
SpringBoot使用一个全局的配置文件,配置文件名称是固定的
- application.properties
- 语法结构:key = value
- application.yml
- 语法结构:key:空格 value
配置文件的作用:修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了
5.2、YAML
-
YAML是"YAML Ain’t a Markup Language"(YAML不是一种置标语言)的递归缩写。在开发的这种语言时,YAML的意思其实是:“Yet Another Markup Language”(仍是一种置标语言)
-
YAML A Markup Language:是一个标记语言
-
YAML isnot Markup Language:不是一个标记语言
标记语言
以前的配置文件,大多数都是使用xml来配置;比如一个简单的端口配置,我们来对比yaml和xml
-
yaml配置
server: port: 8081
-
xml配置:
<server> <port>8081</port> </server>
5.2.1、yaml语法
-
基础语法
k:(空格) v
-
以此来表示一对键值对(空格不能省略);以空格的缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
-
注意:属性和值的大小写都是十分敏感的。
server: port: 8081 path: /hello
-
值的写法
-
字面量:普通的值(数字、布尔值、字符串)
-
字面量直接写在后面就可以了,字符串默认不用加上双引号或者单引号;
-
双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思;
-
比如:name: “wang \n wang”,输出:wang 换行 wang
-
-
可以同时存在两个配置文件,但是优先级不一样(application.properties文件和application.yaml)
-
properties和yaml文件使用对比。yaml中可以写对象、数组等数据。
5.3、使用yaml可以给实体类赋值
- @configurationProperties作用:
- 将配置文件中配置的每一个属性的值,映射到这个组件中;
- 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
- 参数 prefix = “person”:将配置文件中的person下面的所有属性——对应
- 只有这个组件是容器中的组件,才能使用容器提供的@configurationProperties功能
- 测试输出结果:
- 如果说你头铁,非要使用properties文件,加载指定的配置文件。那么就是使用javaConfig绑定我们配置文件的值。
- yaml文件中还可以更加灵活的使用,例如:随机数、随机的uuid、判断的三元运算
- name:${person.hello:hello}_旺财(如果person对象有hello属性则取对应的属性值然后拼接"_旺财",否则就是"hello_旺财")
- value则需要每个字段都添加
- 松散绑定:这个什么意思呢?比如我的yml中写的last-name,这个和lastName是一样的,"-"后面跟着的字母默认是大写的。这就是松散绑定
- JSR303数据校验,这个就是我们可以在字段是增加一层过滤器验证,可以保证数据的合法性
- 复杂类型封装,yml中可以封装对象,使用@value就不支持
结论:
- 配置yml和配置properties都可以获取到值,强烈推荐yml
- 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下@value
- 如果说,我们专门编写了一个JavaBean来和配置文件进行映射,就直接使用@configurationProperties,不要犹豫
6、JSR303数据校验
- spring-boot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统—处理。
7、多环境配置以及配置文件位置
7.1、配置文件位置以及优先级
- 配置文件可以存在多个,并且可以出现的位置如图所示。在读取文件时候会存在优先级的选项。
- file:./config/ (项目路径下的config文件夹配置文件)
- file:./ (项目路径下配置文件)
- classpath:/config/ (资源路径下的config文件夹配置文件)
- classpath:/ (资源路径下配置文件)
7.2、多环境切换
- 多环境配置,当配置了多个数据库的地址。举例:开发环境、测试环境等等。可以在默认环境中进行修改切换。
- 使用yaml文件可以避免出现多个文件的情况,可以都写在一个文件中。如图
8、自动配置原理再理解
- Conditional注解判断是否满足条件
- 每一个XXXAutoConfiguration类都是容器中的一个组件,最后都加入到容器中,用他们来做自动配置
- 每一个自动配置类可以进行自动配置功能。
- 总结:根据当前不同的条件判断,决定这个配置类是否生效。
- 一但这个配置类生效,这个配置类就会给容器中添加各种组件,这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的
- 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着,配置文件能配置什么就可以参照某个功能对应的这个属性类。
在我们配置文件中能配置的东西,都存在一个固有的规律。XXXAutoConfiguration:默认值 xxxxProperties 和 配置文件绑定,我们就可以使用自定义的配置了。
举例:配置server
- 点击进去查看源码,发现都是通过注解@ConfigurationProperties把类绑定到配置文件
- 每一个可配置的类都对应着这个配置类,可配置的选项存在的属性都可以配置
总结:
- SpringBoot启动会加载大量的自动配置类
- 我们看我们需要的功能有没有在SpringBoot默认写好的自动配置类当中
- 我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件存在在其中,我们就不需要再手动配置了)
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们只需要在配置文件中指定这些属性的值即可
- xxxxAutoConfigurartion:自动配置类;给容器中添加组件
- xxxxProperties:封装配置文件中相关属性
- 可以通过 debug = true来查看,哪些自动配置类生效,哪些没有生效;在application.yml文件中。
9、SpringBoot Web开发
9.1、静态资源导入
参考内容:源码WebMvcAutoConfiguration中的方法
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
registration.addResourceLocations(new Resource[]{resource});
}
});
}
}
-
在SpringBoot中,我们可以使用以下方式处理静态资源
-
webjars (访问:localhost:8080/webjars/)
-
classpath:/META-INF/resources/ classpath:/resources/ classpath:/static/ classpath:/public/
-
访问(localhost:8080/)
-
优先级:resources > static > public
-
如果配置了自定义的路径,那么方法就会在这里返回不往下走了。(resourceProperties.isAddMappings())
-
测试在配置文件中配置:spring.mvc.static-path-pattern = /hello/,classpath:/wang/ 使用之前的连接访问,访问不到。
-
9.2、首页和图标定制
9.2.1、首页定制
- 查看源码与首页相关的方法如图(返回index.html页面)
在能够识别的目录(可查看代码中能识别的项目路径是哪些文件夹)下新建页面index.thml。直接访问localhost:8080即可访问首页
- 如果尝试使用mvc模式的视图跳转形式,那么在templates目录下的文件需要使用Controller才能访问得到。同时需要模板引擎的支持
9.2.2、图标
- 有些新版本可能已经不支持修改,修改的操作同样是在配置文件中设置绑定类的属性。
9.3、Thymeleaf模板引擎
- 前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面。jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。jsp支持非常强大的功能,包括能写Java代码,但是呢,我们现在的这种情况,SpringBoot这个项目首先是以jar的方式,不是war,第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的。
- 那不支持jsp,如果我们直接用纯静态页面的方式,那给我们开发会带来非常大的麻烦,那怎么办呢,SpringBoot推荐你可以来使用模板引擎。
- 那么这模板引擎,我们其实大家听到很多,其实jsp就是一个模板引擎,还有以用的比较多的freemarker,包括SpringBoot给我们推荐的Thymeleaf,模板引擎有非常多,但再多的模板引擎,他们的思想都是一样的,什么样一个思想呢我们来看一下这张图。
- 模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的,我们写一些表达式。而这些值,从哪来呢,我们来组装一些数据,我们把这些数据找到。然后把这个模板和这个数据交给我们模板引擎,模板引擎按照我们这个数据帮你把这表达式解析、填充到我们指定的位置,然后把这个数据最终生成一个我们想要的内容给我们写出去。
- 这就是我们这个模板引擎,不管是jsp还是其他模板引擎,都是这个思想。只不过呢,就是说不同模板引擎之间,他们可能这个语法有点不一样。主要来介绍一下SpringBoot给我们推荐的Thymeleaf模板引擎,这模板引擎呢,是一个高级语言的模板引擎,他的这个语法更简单。而且呢,功能更强大。
第一步:引入thymeleaf,对于SpringBoot来说,都不过是一个start的事情,我们需要在项目中引入一下。推荐三个网址:
- Thymeleaf官网: https://www.thymeleaf.org/
- Thymeleaf在Github的主页:https://github.com/thymeleaf/thymeleaf
- Spring官方文档:“https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/htmlsingle/#using-boot-starter",找到我们对应的版本
在pom文件中导入对应版本的start启动器。
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.7.1</version>
</dependency>
如之前所讲,每个导入的类都会有一个对应的Properties类,所以可想而知,Thymeleaf的对应配置类为ThymeleafProperties。查看源码得知,在这里会有一个类似视图解析器一样拼接前缀与后缀的操作。页面在这个路径下就会生效。
实例:
-
导入pom文件对应的start
-
在对应的项目文件目录下新建页面
public static final String DEFAULT_PREFIX = "classpath:/templates/"; public static final String DEFAULT_SUFFIX = ".html";
-
编写Controller
@Controller public class HelloController { @RequestMapping("/hello") public String hello(Model model){ model.addAttribute("msg","hello,SpringBott"); return "test"; } }
-
编写对应的页面
<!DOCTYPE html> <!--导入命名空间 xmlns:th="http://www.thymeleaf.org"--> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--所有的html元素都可以被thymeleaf替换接管。th:元素名--> <div th:text="${msg}"></div> </body> </html>
9.4、Thymeleaf语法
10、MVC配置原理
-
SpingBoot对SpringMVC做了哪些配置,如何扩展、如何定制。
- 源码分析
- 官方文档:https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-developing-web-applications.html
-
源码查看
-
自定义视图解析器(扩展)
-
修改SpringBoot的默认配置
- SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(如果用户自己配置@bean),如果有就用用户配置的,如果没有就用自动配置的。如果有些组件可以存在多个,比如我们的视图解析器,就将用户配置的和自己默认的组合起来。
-
扩展使用SpringMVC
-
我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解。
-
新建一个包config,写一个类MyMvcConfig
-
-
如果使用了注解@EnableWebMvc,那么自动扩展的功能就会失效了。为什么会这样?
- 查看源码得知这个注解会自动帮我们导入一个类:@Import({DelegatingWebMvcConfiguration.class})
- 进入WebMvc自动装配的类查看有注解说明,当这个类不在容器中时,自动配置才会生效。@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
-
扩展SpringMVC
总结:在SpringBoot中,有非常多的xxxxConfiguration帮助我们进行扩展配置,只要看到了这个注解。就改变了原有的Sping的一些扩展,在原始的自动配置中看不到了。
11、整合数据库
11.1、整合JDBC使用
- 对于数据访问层,无论是SQL(关系型数据库)还是NOSQL(非关系型数据库),Spring Boot底层都是采用Spring Data的方式进行统一处理。
- Spring Boot底层都是采用Spring Data的方式进行统一处理各种数据库,Spring Data也是Spring 中与Spring Boot、Spring Cloud等齐名的知名项目。
- Sping Data官网:https://spring.io/projects/spring-data
- 数据库相关的启动器:可以参考官方文档:https://docs.spring.io/spring-boot/docs/2.1.7.RELEASE/reference/htmlsingle/#using-boot-starter
- 首先需要在配置文件中配置数据库连接那些参数,数据源会被封装成jdbcTemplate,使用CRUD时直接jdbcTemplate.方法即可。
11.2、整合Druid数据源
DRUID简介:
Druid是阿里巴巴开源平台上一个数据库连接池实现,结合了C3PO、DBCP、PROXOOL等DB池的优点,同时加入了日志监控。
Druid可以很好的监控DB池连接和SQL的执行情况,天生就是针对监控而生的 DB连接池。
Spring Boot 2.0以上默认使用Hikari数据源,可以说Hikari与 Driud都是当前Java Web上最优秀的数据源,下面介绍Spring Boot如何集成Druid数据源,如何实现数据库监控。
引入数据源:
需要在应用的pom.xml文件中添加上 Druid数据源依赖,而这个依赖可以从 Maven 仓库官网Maven Repository中获取。
配置参数:(使用log4j需要导入log4j的jar)
11.3、整合Mybatis
- 使用前在pom文件中导入相关的启动器 mybatis-spring-boot-start。冷知识:SpringBoot官方定义的启动器都是"spring-boot-starter"开头的。很明显这个不是SpringBoot官方。
- 配置依赖
- 写对应的查询语句
- 继续在配置文件中整合mybatis
12、SpringSecurity
简介:
Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。
记住几个类:
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
Spring Security的两个主要目标是“认证"和“授权”(访问控制)。
“认证”(Authentication)
“授权”(Authorization)
这个概念是通用的,而不是只在Spring Security中存在。
参考官网:https://spring.io/projects/spring-security
查看我们自己项目中的版本,找到对应的帮助文档:
https://docs.spring.io/spring-security/site/docs/5.2.0.RELEASE/reference/htmlsingle
- 默认的架子
@EnableWebSecurity
public class Config extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
super().configure(http);
}
}
- 代码实例:
认证代码实例:由于框架要求,进行了用户密码的加密操作。这里使用的是数据是内存中读取使用的,一般来说认证的用户数据是需要从数据库中读取的。可以修改auth.后面的方法(jdbc)
数据库认证:
@Autowired
private DataSource dataSource;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// ensure the passwords are encoded properly
UserBuilder users = User.withDefaultPasswordEncoder();
auth
.jdbcAuthentication()
.dataSource(dataSource)
.withDefaultSchema()
.withUser(users.username("user").password("password").roles("USER"))
.withUser(users.username("admin").password("password").roles("USER","ADMIN"));
}
- thymeleaf和security整合。(在thymeleaf中可以写一些security的操作)
- 导入对应的maven文件
- 导入命名空间:xmlns:sec=“http: //www.thymeleaf.org/thymeleaf-extras-springsecurity4”
- 根据用户角色实现动态菜单的效果
- 防止网站攻击,造成登录失败的原因。关闭csrf功能
http.csrf().disable();
- 开启记住我功能 cookie,默认保存两周
http.rememberMe();
13、Shiro
13.1、什么是Shiro
- Apache Shiro是一个Java的安全(权限)框架。
- Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。
- Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等。
- 下载地址:http://shiro.apache.org/
13.2、有哪些功能
- Authentication:身份认证、登录,验证用户是不是拥有相应的身份
- Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限,即判断用户能否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限
- Session Manager:会话管理,即用户登录后就是第一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通的JavaSE环境,也可以是Web环境
- Cryptography:加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;
- Web Support:Web支持,可以非常容易的集成到Web环境;
- Caching:缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率
- Concurrency:Shiro支持多线程应用的并发验证,即,如在一个线程中开启另一个线程,能把权限自动的传播过去
- Testing:提供测试支持
- Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问
- Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了
13.3、Shiro架构(外部)
从外部来看Shiro,即从应用程序角度来观察如何使用Shiro完成工作:
- subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject,Subject代表了当前的用户,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager; Subject其实是一个门面,SecurityManageer才是实际的执行者
- SecurityManager:安全管理器,即所有与安全有关的操作都会与SercurityManager交互,并且它管理着所有的Subject,可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC的DispatcherServlet的角色
- Realm:Shiro从Realm获取安全数据(如用户,角色,权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法;也需要从Realm得到用户相应的角色、权限,进行验证用户的操作是否能够进行,可以把Realm看成DataSource;
13.4、Shiro架构(内部)
- Subject:任何可以与应用交互的"用户";
- Security Manager:相当于SpringMVC中的DispatcherServlet;是Shiro的心脏,所有具体的交互都通过Security Manager进行控制,它管理者所有的Subject,且负责进行认证,授权,会话,及缓存的管理
- Authenticator:负责Subject认证,是一个扩展点,可以自定义实现;可以使用认证策略(AuthenticationStrategy),即什么情况下算用户认证通过了
- Authorizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的那些功能
- Realm:可以有一个或者多个的realm,可以认为是安全实体数据源,即用于获取安全实体的,可以用JDBC实现,也可以是内存实现等等,由用户提供;所以一般在应用中都需要实现自己的realm
- SessionManager:管理Session生命周期的组件,而Shiro并不仅仅可以用在Web环境,也可以用在普通的JavaSE环境中
- CacheManager:缓存控制器,来管理如用户,角色,权限等缓存的;因为这些数据基本上很少改变,放到缓存中后可以提高访问的性能
- Cryptography:密码模块,Shiro提高了一些常见的加密组件用于密码加密,解密等
13.5、HelloWorld
13.5.1、快速实践
查看官网文档:http://shiro.apache.org/tutorial.html
官方的quickstart:https://github.com/apache/shiro/tree/master/samples/quickstart/
14、Shiro整合Mybatis
- 导入对应的pom文件
- 修改配置文件
14.1、Shiro请求授权实现
14.2、Shiro整合Thymeleaf
15、Swagger介绍及集成
- API框架
- RestFul API文档在线自动生成工具(API文档与API定义同步更新)
- 直接运行,可以在线测试API接口
- 支持多种语言
官网:https://swagger.io/
在项目中使用swagger需要springbox
- swagger2
- ui
15.1、SpringBoot 集成Swagger
-
新建一个SpringBoot Web项目
-
导入相关的依赖(springfox-swagger2、springfox-swagger-ui)
-
配置Swagger Config
@Configuration @EnableSwagger2 //开启Swagger2 public class SwaggerConfig{ }
-
测试运行:http://localhost:8080/swagger-ui.html
15.2、配置Swagger
15.3、Swagger配置扫描接口
- Docket.select()
- 配置是否启动Swagger()
- 问题:只希望Swagger在生产环境中使用,在发布的时候不使用?
- 判断是不是生产环境 flag = false
- 注入 enable(flag)
- 配置API文档的分组
.groupName("xxx")
- 如何配置多个分组,多个Docket实例即可
总结:
- 我们可以通过Swagger给一些比较难理解的属性或者接口,增加注释信息
- 接口文档实时更新
- 可以在线测试
注意:在正式发布的时候,关闭Swagger,出于安全考虑,不能暴漏出公司的一些接口。而且节省内存。
16、异步任务
使用在方法上使用注解@Async,告诉spring这是一个异步的方法。在spring中开启异步注解功能@EnableAsync
17、邮件任务
pom.xml文件中导入依赖"spring-boot-start-mail"
18、定时任务
接口:TaskExecutor(任务执行者)、TaskScheduler(任务调度者)
注解:@EnableScheduling(开启定时功能的注解)、@Scheduled(什么时候执行)
19、SpringBoot集成Redis
pom.xml导入依赖spring-boot-start-data-redis
20、分布式 Dubbo + Zookeeper + SpringBoot
-
http协议
-
RPC协议,PRC的两个核心模块:通讯,序列化
-
Apache Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
-
ZooKeeper:注册中心
-
Dubbo-admin:是一个监控管理后台,查看我们注册了哪些服务,哪些服务被消费了
-
Dubbo:jar包
整合项目
注册者/服务提供者:(进行一个服务的注册,提供一个向外的接口。在Dubbo-admin监控中可以进行查看)
- 导入jar
- 在配置文件中进行服务的配置
- 编写好代码之后,启动zookeeper服务,启动dubbo-admin监控平台(网页)查看,启动项目。
服务消费者:
- 编写配置文件,在文件中配置需要从哪里获取服务、从注册中心(配置注册中心的地址)、
- 编写调用服务代码(在消费者调用时,需要使用到我们注册服务时候的接口类型TicketService,但是在消费者的服务中并没有定义这个接口的服务代码,所以没有这个类型存在。这里的解决方法是:1.pom坐标解决;2.可以定义路径相同的接口名,其目的就是为了存在这个类型的类。)
- 测试调用
步骤:
前提是zookeeper服务已开启
- 提供者提供服务
- 导入依赖
- 配置注册中心的地址,以及服务器发现名和要扫描的包
- 在想要被注册的服务上面加上注解@Service(注意导包的地址)
- 消费者如何消费
- 导入依赖
- 配置注册中心的地址,配置自己的服务名
- 从远程注入服务(@Reference)