这样做的好处是,易于开发和测试;也十分方便部署;当需要扩展时,只需要将war复制多份,然后放到多个服务器上,再做个负载均衡就可以了。
单体应用架构的缺点是,哪怕我要修改一个非常小的地方,我都需要停掉整个服务,重新打包、部署这个应用war包。特别是对于一个大型应用,我们不可能吧所有内容都放在一个应用里面,我们如何维护、如何分工合作都是问题。
官方提供了一个快速生成的网站,IDEA集成了这个网站。
https://start.spring.io/
在IDEA新建项目
选择对应选项
下一步,选择添加依赖
新建项目结构展示
项目结构一样太熟悉了,三部分分别是src目录下的"java"、“resources”、"test"文件夹。"java"文件夹中的类"HelloworldApplication"为程序的主入口,不能进行修改。可直接启动运行这个main方法。resources文件夹的"application.properties"为SpringBoot的配置文件,也会有yml结尾的文件,后续会说明。test文件夹中为单元测试部分。
访问80端口(默认访问的是个error接口),程序启动成功。
总结:
在使用springboot的过程中,我们既没有进行映射器的配置,也没有进行适配器的配置等操作。但是依然能够进行整个过程的开发。springboot中主打的就是一个自动装配。简单看一下注解"HelloworldApplication"类中的注解"@SpringBootApplication"
点击进去
可以看到"@Component"注解表示这也是一个组件,所以说明SpringBoot的启动类本身就是Spring的一个组件。
在线搜索 SpringBoot banner在线生成,随意找个网站,复制合适的图案等信息。在resource文件下新建文件banner.txt,把文件复制。
重新信息项目,控制台中打印的图案已经改变。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
启动器就是SpringBoot的启动场景。如果当你需要启动web,那么你就需要导入(-web)启动器
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
spring-boot-starter-web,就会帮我们自动导入web环境所有的依赖
springboot会将所有的功能场景,都变成一个一个的启动器
我们要使用什么功能,就只需要找到对应的启动器就可以了(可上官网查看)
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,就有对应的启动器了,有了启动器,我们自动装配就会生效,然后就配置成功。
@SpringBootApplication
public class HelloworldApplication {
public static void main(String[] args) {
//该方法返回一个ConfigurableApplicationContext对象
//参数一:应用入口的类 参数类:命令行参数
SpringApplication.run(HelloworldApplication.class, args);
}
}
SpringApplication.run分析
SpringApplication这个类主要做了以下几件事:
SpringBoot使用一个全局的配置文件,配置文件名称是固定的
配置文件的作用:修改SpringBoot自动配置的默认值,因为SpringBoot在底层都给我们自动配置好了
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>8081port>
server>
基础语法
k:(空格) v
以此来表示一对键值对(空格不能省略);以空格的缩进来控制层级关系,只要是左边对齐的一列数据都是同一个层级的。
注意:属性和值的大小写都是十分敏感的。
server:
port: 8081
path: /hello
值的写法
字面量:普通的值(数字、布尔值、字符串)
字面量直接写在后面就可以了,字符串默认不用加上双引号或者单引号;
双引号,不会转义字符串里面的特殊字符,特殊字符会作为本身想表示的意思;
比如:name: “wang \n wang”,输出:wang 换行 wang
可以同时存在两个配置文件,但是优先级不一样(application.properties文件和application.yaml)
properties和yaml文件使用对比。yaml中可以写对象、数组等数据。
结论:
在我们配置文件中能配置的东西,都存在一个固有的规律。XXXAutoConfiguration:默认值 xxxxProperties 和 配置文件绑定,我们就可以使用自定义的配置了。
举例:配置server
总结:
参考内容:源码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/ 使用之前的连接访问,访问不到。
在能够识别的目录(可查看代码中能识别的项目路径是哪些文件夹)下新建页面index.thml。直接访问localhost:8080即可访问首页
第一步:引入thymeleaf,对于SpringBoot来说,都不过是一个start的事情,我们需要在项目中引入一下。推荐三个网址:
在pom文件中导入对应版本的start启动器。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
<version>2.7.1version>
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>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div th:text="${msg}">div>
body>
html>
SpingBoot对SpringMVC做了哪些配置,如何扩展、如何定制。
源码查看
自定义视图解析器(扩展)
修改SpringBoot的默认配置
扩展使用SpringMVC
我们要做的就是编写一个@Configuration注解类,并且类型要为WebMvcConfigurer,还不能标注@EnableWebMvc注解。
新建一个包config,写一个类MyMvcConfig
如果使用了注解@EnableWebMvc,那么自动扩展的功能就会失效了。为什么会这样?
总结:在SpringBoot中,有非常多的xxxxConfiguration帮助我们进行扩展配置,只要看到了这个注解。就改变了原有的Sping的一些扩展,在原始的自动配置中看不到了。
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)
简介:
Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。
记住几个类:
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"));
}
http.csrf().disable();
http.rememberMe();
从外部来看Shiro,即从应用程序角度来观察如何使用Shiro完成工作:
查看官网文档:http://shiro.apache.org/tutorial.html
官方的quickstart:https://github.com/apache/shiro/tree/master/samples/quickstart/
官网:https://swagger.io/
在项目中使用swagger需要springbox
新建一个SpringBoot Web项目
导入相关的依赖(springfox-swagger2、springfox-swagger-ui)
配置Swagger Config
@Configuration
@EnableSwagger2 //开启Swagger2
public class SwaggerConfig{
}
测试运行:http://localhost:8080/swagger-ui.html
.groupName("xxx")
总结:
注意:在正式发布的时候,关闭Swagger,出于安全考虑,不能暴漏出公司的一些接口。而且节省内存。
使用在方法上使用注解@Async,告诉spring这是一个异步的方法。在spring中开启异步注解功能@EnableAsync
pom.xml文件中导入依赖"spring-boot-start-mail"
接口:TaskExecutor(任务执行者)、TaskScheduler(任务调度者)
注解:@EnableScheduling(开启定时功能的注解)、@Scheduled(什么时候执行)
pom.xml导入依赖spring-boot-start-data-redis
http协议
RPC协议,PRC的两个核心模块:通讯,序列化
Apache Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
ZooKeeper:注册中心
Dubbo-admin:是一个监控管理后台,查看我们注册了哪些服务,哪些服务被消费了
Dubbo:jar包
注册者/服务提供者:(进行一个服务的注册,提供一个向外的接口。在Dubbo-admin监控中可以进行查看)
服务消费者:
步骤:
前提是zookeeper服务已开启