SpringBoot2学习笔记
SpringBoot2
SpringBoot2基础入门
Spring与SpringBoot
SpringBoot优点
Create stand-alone Spring application
- 创建独立Spring应用
Embed Tomcat, Jetty or Undertow directly(no need to deploy WAR files)
- 内嵌Web服务器
Provide opinionated ‘starter’ dependencies to simplify your build configuration
- 自动starter依赖,简化构建配置
Automatically configure Spring and 3rd party libraries whenever possible
- 自动配置Spring以及第三方功能
Provide production-ready features such as metrics, health checks, and externalized configuration
- 提供生产级别的监控、健康检查及外部化配置
Absolutely no code generation and no requirement for XML configuration
- 无代码生成、无需编写XML
SpringBoot是整合Spring技术栈的一站式框架、是简化Spring技术栈的快速开发
SpringBoot缺点
- 版本迭代快
- 封装深,內部原理复杂,不易精通
SpringBoot使用基础示例
maven依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.2</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.4.2</version>
</dependency>
@SpringBootApplication
open class MainApplicationfun main(args: Array<String>) {//返回IOC容器val runApplication = runApplication<MainApplication>(*args)//查看容器中的组件val names = runApplication.beanDefinitionNamesfor (name in names) {println(name)}
}//@ResponseBody //直接返回字符串,而非跳转页面
//@Controller
//@RestController = @ResponseBody + @Controller
@RestController
class HelloController {@RequestMapping("/hello")fun helloHandler(): String = "hello spring boot"
}
@SpringBootApplication
public class MainApplication {public static void main(String[] args) {SpringApplication.run(MainApplicationJava.class, args);}
}
得到:Tomcat started on port(s): 8080 (http) with context path ‘’
可直接访问localhost:8080/hello显示hello spring boot
简化配置
所有属性配置均放入application.properties中
简化部署
<plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.4.2</version></plugin>
</plugins>
把项目打成jar包,直接在目标服务器执行
注意点
- 取消cmd的快速编辑模式
自动配置原理
SpringBoot特点
依赖管理
- 父项目做依赖管理
依赖管理
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.2</version><relativePath/>
</parent>其父项目
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.4.2</version>
</parent>
几乎声明了所有开发中常用的依赖的版本号,即为自动版本仲裁机制
- 开发导入starter场景启动器
1.见到很多spring-boot-starter-*,*就是某种场景
2.只要引入starter,这个场景的所有常规需要的依赖都会自动引入
3.见到的*-spring-boot-starter是第三方提供的场景启动器
4.所有场景启动器最底层的依赖:<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>xxx</version><scope>compile</scope></dependency>
- 无需关注版本号,自动版本仲裁
1.引入依赖默认都可以不写版本号
2.引入非版本仲裁的jar需写版本号
- 可以修改版本号
1.查看spring-boot-dependencies里面规定当前依赖的版本用的key。
2.在当前项目中重写配置<properties><mysql.version>xxx</mysql.version></properties>
自动配置
自动配置Tomcat
引入Tomcat依赖
配置Tomcat
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId><version>xxx</version><scope>compile</scope> </dependency>
自动配置SpringMVC
- 引入SpringMVC全套组件
- 自动配置SpringMVC常用组件(功能)
自动配置Web常见功能,如字符编码问题
- SpringBoot配置好所有web开发的常见场景
默认包结构
主程序所在包及其下所有子包中的组件都会被默认扫描进来
使用@SpringBootApplication(scanBasePackages = ["cn.kazunto"])将扫描范围放大 或@ComponentScan指定扫描路径@SpringBootApplication等同于@SpringBootConfiguration、@EnableAutoConfiguration和ComponentScan("cn.kazunto")
各种配置拥有默认值
- 默认配置最终都是映射到MultipartProperties
- 配置文件的值最终会绑定到每个类上,类会在容器中创建对象
按需加载所有自动配置项
- 场景的自动配置只要被引入后才会开启
- SpringBoot所有的自动配置功能都在spring-boot-autoconfigure包里
…
a
容器功能
组件添加
@Configuration
基本使用
//1.这是一个配置类,等同于配置文件; //2.自身也是组件 //3.proxyBeanMethods:代理Bean的方法,默认为true // Full(proxyBeanMethods=true) 保持单实例 // Lite(proxyBeanMethods=false) // 组件依赖 @Configuration class Config {//给容器中添加组件,以方法名作为组件id;返回类型就是组件类型;返回的值就是组件在容器中的实例@Bean("自定义名字")fun user(): User = User("kazunto", "24") }//从容器中获取组件val kazunto1 = runApplication.getBean("user", User::class.java)val kazunto2 = runApplication.getBean("user", User::class.java)println(kazunto1)println(kazunto2)//User(id=null, name=kazunto, gender=24) //User(id=null, name=kazunto, gender=24)
Full模式与Lite模式
- 示例
- 实战
- 配置类组件之间无依赖管理用Lite模式加速容器启动过程,减少判断
- 配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
@Bean、@Component、@Controller、@Service和@Repository
@ComponentScan和@Import
@Import({User.class, Config.class}) //java
@Import(User::class, Config::class) //kotlin
给容器中自动创建出指定类型的组件,默认组件的名字是全类名
@Conditional
条件装配:满足Conditional指定的条件,则进行组件注入
原生配置文件引入
@ImportResource
@ImportResource(“classpath:beans.xml”)导入Spring的配置文件
配置绑定
@ConfigurationProperties
application.properties配置文件
mycar.brand=HONDA
mycar.price=10000
bean类
//只要在容器中的组件,才有SpirngBoot提供的功能
@Component
@ConfigurationProperties(prefix="mycar")
class Car() {var brand: String? = nullvar price: Int? = null
}config类
@EnableConfigurationProperties(Car::class.java)
//1.开启Car配置绑定功能
//2.把Car组件自动注册到容器中
//3.此时Car类上不需要@Component
class MyConfig {}
@EnableConfigurationProperties + @ConfigurationProperties
@Component + @ConfigurationProperties
自动配置原理入门
引导加载自动配置类
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponenetScan(excludeFilters = {@Filter(type=FilterType.CUSTOM, classes=TypeExculdFilter.class), @Filter(type=FilterType.CUSTOM, classes=AutoConfigurationExcludeFilter.class)})
public @interface SpringBootApplication {}
@SpringBootConfiguration
@Configuration代表当前是一个配置类
@ComponentScan
指定扫描,Spring注解
@EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.java)
public @interface EnableAutoConfiguration {}
@AutoConfigurationPackage
自动配置包,指定了默认的包规则
@Import(AutoConfigurationPackages.Registrar.class) //给容器中导入组件
@public @interface AutoConfigurationPackage {}
//利用Registrar给容器中导入一系列组件
@Import(AutoConfigurationImportSelector.class)
1.利用getAutoConfigurationEntry(annotationMetadata);给容器中批量导入一些组件
2.调用List<String> configuration = getCandidateConfigurations(annotationMetadata, attributes)获取所有需要导入到容器中的配置类
3.利用工厂加载Map<string, List<string>> loadStringFactories(@Nullable ClassLoader classLoader);得到所有的组件
4.从META-INF/spring.factories位置来加载一个文件。默认扫描当前系统里所有META-INF/spring.factoories位置的文件spring-boot-autoconfigure-x.x.x.jar里也有META-INF/spring.factooriesspirng-boot中规定了给容器加载的所有配置类:#Auto Configureorg.springframework.boot.autoconfigure.EnableAutofiguration=\org.springframework.boot.autoconfigure.***Autofiguration=\......
按需开启自动配置项
按照条件装配规则(@Conditional),最终会按需配置
修改默认配置
@Bean
@ConditionalOnBean(MultipartResolver.class) //容器中有该组件
@ConditionalOnMissingBean(name=DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) //容器中无该multipartResolver名字的组件
//给@Bean标注的方法传入对象参数,该参数值会从容器中寻找
//SpringMVC multipartResolver防止用户配置的文件上传解析器不符合规范
public MultipartResolver multipartResolver(MultipartReslver resolver) {// Defect if the user has created a MultipartResolver but named it incorrectlyreturn resolver;
}
给容器中加入文件上传解析器
SpringBoot默认会在底层配置所有组件,如果用户进行配置,则以用户配置为准
总结:
SpringBoot先加载所有的自动配置类 xxxAutoConfiguration
每个自动配置类按照条件进行生效,默认绑定配置文件指定的值;从xxxProeprties中获取;xxxProperties和配置文件进行绑定
生效的配置类给容器中装配组件
容器中存在组件后,组件的功能生效
定制配置:
直接@Bean替换底层的组件
@Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() {}
在配置文件中修改组件获取的参数值
application.properties server.servlet.encoding.charset=utf-8
xxxAutoConfiguration–>组件–>xxxProperties–>application.properties
最佳实践
引入场景依赖
- https://docs.spring.io/spring-boot/docs/current/reference/html/using-spring-boot.html#using-boot-starter
查看自动配置哪些(选做)
- 配置文件中添加debug=true开启自动配置报告;Negative,不生效;Positive,生效
是否需要定制化
参照文档修改配置项
- https://docs.spring.io/spring-boot/docs/current/refence/html/appendix-application-properties.html#common-application-properrties
- 手动分析在xxxProperties绑定了哪些配置
自定义加入或替换组件
- @Bean、@Component…
自定义器 XxxCustomizer
…
开发小技巧
Lombok
简化JavaBean开发。自动生成get和set方法
配置依赖
pom.xml <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId> </dependency>
安装插件
Settings–>Plugins–>Lombok
使用
@Data //Getter & Setter @ToString //ToString @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode public class Pet {private String name; }@Slf4j public class Log {public String write() {log.info("...log message...");} }
dev-tools
配置依赖
pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><optional>true</optional> </dependency>
使用
Ctrl+F9,热更新,自动重启
Spring Initalizier
项目初始化向导
SpringBoot2核心技术-核心功能
配置文件、Web开发、数据访问、单元测试、指标监控、原理解析
配置文件
properties
yaml
简介
YAML是“YAML Ain’t Markup Language”(YAML不是一种标记语言)的递归缩写;在开发的这种语言时,意思是“Yet Another Markup Language”(仍是一种标记语言)。
非常适合用来做以数据为中心的配置文件。
基本语法
- key: value;key和value间有空格
- 大小写敏感
- 使用缩进表示层级关系
- 缩进不允许使用tab,只允许空格
- 所需的空格数不重要,只要相同层级的元素左对齐即可
- '#'表示注释
- ''与""表示字符串内容,会被转义/不转义
数据类型
字面量:单个的、不可再分的值。date、boolean、string、number、null
k: v
对象:键值对的集合。map、hash、set、object
#行内写法: k: {k1:v1,k2:v2,k3:v3} #或 k:k1: v1k2: v2k3: v3
数组:一组按次序排列的值。array、list、queue
#行内写法: k: [v1,v2,v3] #或 k:- v1- v2- v3
示例
class Person() {var userName: String? = nullvar boss: Boolean? = nullvar birth: Date? = nullvar age: Int? = nullvar per: Pet? = nullvar interests: Array<String>? = nullvar animal: List<String>? = nullvar score: Map<String, Any>? = nullvar salarys: Set<Double>? = nullvar allPets: Map<String, List<Pet>>? = null
}class Pet() {var name: String? = nullvar weight: Double? = null
}
xxx.yaml || xxx.ymlperson:userName: kazuntoboss: truebirth: 1997/3/11age: 24#interests: [日语,那西隆语]interests:- 日语- 那西隆语animal: [ 中华田园猫,缅因猫 ]# score:# English: 70# Math: 100score: { English:70,Math:100 }salarys:- 2000- 1968pet:name: mimiweight: 20allPets:sick:- { name: xie, weight: 10 }- name: mimiweight: 20- name: jiweight: 5health:- { name: hana, weight: 10 }- { name: won, weight: 10 }
Web开发
深入Web原理
- SpringMVC自动配置概览
- 简单功能分析
- 请求参数处理
- 数据响应与内容协商
- 视图解析与模板引擎
- 拦截器
- 跨域
- 异常处理
- 原生Servlet组件
- 嵌入式Web容器
- 定制化原理
SpringMVC自动配置概览
Spring Boot provides auto-configuration for Spring MVC that works well with most applications.(大多场景我们都无需自定义配置)
The auto-configuration adds the following features on top of Spring`s defaults:
- Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
- 内容协商视图解析器和BeanName视图解析器。
- Support for serving static resources, including support for WebJars(coverd later in this document).
- 静态资源(包括webjars)
- Automatic registration or Converter, GenericConverter, and Formatter beans.
- 自动注册Converter,GenericConverter,Formatter
- Support for HttpMessageConverters(converd later in this document)
- 支持HttpMessageConverters(后来我们配合内容协商理解原则)
- Automatic registration of MessageCodesResolver (converd later in this document)
- 自动注册MessageCodesResolver (国际化用)
- Static index.html support
- 静态index.html页支持
- Custom Favicon support (converd later in this document)
- 自定义Favicon
- Automatic use of a ConfigurableWebBindingInitializer bean (converd later in this document)
- 自动使用ConfigurableWebBindingInitializer ,(DataBinder负责将请求数据绑定到JavaBean上)
If you want to keep those Spring Boot MVC customizations and make more MVC customizations (interceptors, formatters, view controllers, and other features), you can add your own @Configuration class of type WebMvcconfigurer but without @EnableWebMVC.
不用@EnableWebMvc注解。使用@Configuration + WebMvcConfiguration 自定义规则
If you want to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter, or ExceptionHandlerExceptionResolver, and still keep this Spring Boot MVC customizations, you can declare a bean of type WebMvcRegistrations and use it to provide custom instanes of those components.
声明 WebMvcRegistrations 改变默认底层
简单功能分析
静态资源访问
静态资源目录
只要静态资源放在类路径:/static or /public or /resources or /META-INF/resources
访问:当前目录根路径/ + 静态资源名
原理:静态映射/**;请求先在Controller中处理,无法处理的请求交给静态资源处理器。
改变默认的静态资源路径:
spring:web:resources:static-locations: [classpath:/file_path/,...] #src/main/resources/file_path/file_name.xx
静态资源访问前缀
默认无前缀
spring:mvc:static-path-pattern: /res/**
当前项目 + static-path-pattern + 静态资源名 = 静态资源文件下寻找
webjars
将JQuery等打包
<dependency><groupId>org.webjars</groupId><artifactId>jquery</artifactId><version>3.5.1</version>
</dependency>
访问地址:http://localhost:8080/webjars/jquery/3.5.1/jquery.js
欢迎页支持
静态资源路径下index.html
- 可以配置静态资源路径
- 不可以配置静态资源的访问前缀,否则导致indx.html不能被默认访问
spring: # mvc: # static-path-pattern: /res/** # 会导致welcome page功能失效web:resources:static-locations: [classpath:/file_path/,...]
controller能处理/index
自定义Favicon
网页图标,将favicon.ico放入static即可。
配置静态资源的访问前缀也会使该功能失效。
请求参数处理
- SpringBoot启动默认加载,xxxAutoConfiguration类(自动配置类)
- SpringMVC功能的自动配置类WebMVCAutoConfiguration,生效
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PERCEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {}
- 配置文件的相关属性和xxx进行了绑定。WebMvcProperties == spring.mvc,ResourceProperties == spring.resources
配置类只要一个有参构造器
org.springframework.boot:spring-boot-autoconfigure/web/servlet/WebMvcAutoConfiguration //有参构造器所有参数的值都会从容器中确定 //ResourceProperties resourceProperties:获取和spring.resources绑定的所有的值的对象 //WebMvcProperties mvcProperties:获取和spring.mvc绑定的所有的值的对象 //ListableBeanFactory beanFactory:Spring的BeanFactory //HttpMessageConverters:找到所有的HttpMessageConverters //ResourceHandlerRegistrationCustomizer:找到资源处理器的自定义器 //DispatcherServletPath //ServletRegistrationBean:给应用注册Servlet、Filter public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {this.mvcProperties = mvcProperties;this.beanFactory = beanFactory;this.messageConvertersProvider = messageConvertersProvider;this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();this.dispatcherServletPath = dispatcherServletPath;this.servletRegistrations = servletRegistrations;this.mvcProperties.checkConfiguration(); }
资源处理的默认规则
org.springframework.boot:spring-boot-autoconfigure/web/servlet/WebMvcAutoConfigurationprotected void addResourceHandlers(ResourceHandlerRegistry registry) {super.addResourceHandlers(registry);if (!this.resourceProperties.isAddMappings()) {logger.debug("Default resource handling disabled");} else {ServletContext servletContext = this.getServletContext();this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {registration.addResourceLocations(this.resourceProperties.getStaticLocations());if (servletContext != null) {registration.addResourceLocations(new Resource[]{new ServletContextResource(servletContext, "/")});}});} }
org.springframework.boot:spring-boot-autoconfigure/web/WebProperties/Resourcesprivate static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"}; private String[] staticLocations;
请求映射
@xxxMapping;
Rest风格支持(使用HTTP请求方式动词来表示对资源的操作)
- 以前:/getUser 获取用户 /deleteUser 删除用户 /editUser 修改用户 /saveUser 保存用户
- 现在:/user GET-获取用户 DELETE-删除用户 PUT-修改用户 POST-保存用户
- 核心Filter:HiddenHttpMethodFilter
- 用法:表单method=post,隐藏域_method=put
- SpringBoot中手动开启
//@RequestMapping(value=["/user"], method=[RequestMethod.GET]) @GetMapping("/user") fun getUser(): String = "GET-Kazunto"//@RequestMapping(value=["/user"], method=[RequestMethod.POST]) @PostMapping("/user") fun saveUser(): String = "POST-Kazunto"//@RequestMapping(value=["/user"], method=[RequestMethod.PUT]) @PutMapping("/user") fun putUser(): String = "PUT-Kazunto"//@RequestMapping(value=["/user"], method=[RequestMethod.DELETE]) @DeleteMapping("/user") fun deleteUser(): String = "DELETE-Kazunto"
<form action="/user" method="get"><input value="GET" type="submit"/> </form> <form action="/user" method="post"><input value="POST" type="submit"/> </form> <form action="/user" method="post"><input name="_method" type="hidden" value="PUT"/><input value="PUT" type="submit"/> </form> <form action="/user" method="post"><input name="_method" type="hidden" value="DELETE"/><input value="DELETE" type="submit"/> </form>
spring:mvc:hiddenmethod:filter:enabled: true
Rest原理(表单提交要使用RESST的时候)
- 表单提交会带上**_method=PUT**
- 请求被HiddenHttpMethodFilter拦截
- 请求是否正常,且是POST
- 获取到_method的值
- 兼容以下请求:PUT、DELETE、PATCH
- 原生request(post),包装模式requestWrapper重写了getMethod方法,返回的是传入的值
- 过滤器链放行时用wrapper,以后的方法调用getMethod是调用requestWrapper的方法
- 请求是否正常,且是POST
Rest使用客户端工具
- 如PostMain直接发送PUT、DELETE等方式请求,无需Filter
请求映射原理
普通参数与基本注解
注解:
@PathVariable(路径变量)、@RequestHeader(获取请求头)、@ModeAttribute、@RequestParam获取请求参数)、@MatrixVariable(矩阵变量)、@CookieValue(获取cookie值)、@RequestBody(获取请求头[POST])
@GetMapping("/car/{id}/owner/{username}") fun get(@PathVariable("id") id: Int,@PathVariable("username") name: String,@PathVariable pv: Map<String, String>,@RequestHeader("User-Agent") userAgent: String,@RequestHeader header: Map<String, String>,@RequestParam("age") age: Int,@RequestParam("inters") inters: List<String>,@RequestParam params: Map<String, String>,@CookieValue("Idea-a2c17425") _ga: String,@CookieValue("Idea-a2c17425") cookie:Cookie): Map<String, Any>? {val map = HashMap<String, Any>() // map.put("id", id) // map.put("name", name) // map.put("pv", pv) // map.put("userAgent", userAgent) // map.put("headers", header)map.put("age", age)map.put("inters", inters)map.put("params", params)map.put("Idea-a2c17425", _ga)println(cookie.name)println(cookie.value)return map }<a href="car/0/owner/Kazunto?age=24&lan=Здравствыйте&inters=game">car</a>
@PostMapping("/save") fun postMethod(@RequestBody content: String): Map<Any, Any>? {val map = HashMap<Any, Any>()map.put("content", content)return map }<form action="/save" method="post">用户名:<input name="username"/>备注:<input name="other"/><input type="submit" value="提交"/> </form>
@Controller class RequestController {@GetMapping("/goto")fun goToPage(request: HttpServletRequest): String {request.setAttribute("msg", "Здравствыйте")request.setAttribute("code", 1024)//转发到 /success请求return "forward:/success"}@ResponseBody@GetMapping("/success")fun success(@RequestAttribute("msg") msg: String, @RequestAttribute("code") code: Int, request: HttpServletRequest): Map<Any, Any>? {val map = HashMap<Any, Any>()map.put("msg1", request.getAttribute("msg"))map.put("msg", msg)return map}}
矩阵变量需要在SpringBoot中手动开启,根据RFC3986规范,矩阵变量应当绑定在路径变量中。若有多个矩阵变量,应使用英文符号;进行分割;若一个矩阵变量有多个值,应使用英文符号,进行分割,或命名多个重复的key即可。
如:/cars/sell;low=34;brand=byd,audi,auto
session.set()–>jsessionid–>cookie–>每次发请求携带
url重写:/abc;jsessionid=xxxx 把cookie的值使用矩阵变量的方式进行传递
手动开启矩阵变量原理:对于路径的处理:UrlPathHelper进行解析。removeSemicolonContent(移除分号内容)支持矩阵变量
@Configuration(proxyBeanMethods = false) class WebConfig : WebMvcConfigurer {override fun configurePathMatch(configurer: PathMatchConfigurer) {val urlPathHelper = UrlPathHelper();urlPathHelper.setRemoveSemicolonContent(false)configurer.setUrlPathHelper(urlPathHelper);}}
<a href="cars/sell;low=34;brand=honda,toyota,das auto">Matrix Variable First</a> <br/> <a href="cars/sell;low=34;brand=honda;brand=toyota;brand=das auto">Matrix Variable Second</a> <br/> <a href="boss/1;age=20/2;age=10">Matrix Variable Thirdly/boss/{bossId}/{empId}</a>
//cars/sell;low=34;brand=honda,toyota,das auto @GetMapping("/cars/{path}") fun carsSell(@MatrixVariable("low") low: Int,@MatrixVariable("brand") brand: List<String>,@PathVariable("path") path: String): Map<Any, Any>? {val map = HashMap<Any, Any>()map.put("low", low)map.put("brand", brand)map.put("path", path)return map }//boss/1;age=20/2;age=10 @GetMapping("/boss/{bossId}/{empId}") fun boss(@MatrixVariable(value = "age", pathVar = "bossId") bossAge: Int,@MatrixVariable(value = "age", pathVar = "empId") empAge: Int): Map<Any, Any>? {val map = HashMap<Any, Any>()map.put("bossAge", bossAge)map.put("empAge", empAge)return map }
Servlet API:
WebRequest、ServletRequest、MultipartRequest、HttpSession、Javax,servlet.http.PushBuilder、Principal、InputStrean、Reader、HttpMethod、Locale、TimeZone、ZoneId
复杂参数:
Map、Errors/BindingResult、Model、RedirectAttributes、ServletResponse、SessionStatus、UriComponentsBuilder、ServletUriComponentsBuilder
自定义对象参数:
可以自动类型转换与格式化,可以级联封装
/* <input name="username"/><br/> <input name="age"/><br/> <input name="birthday"/><br/> <input name="pet.name"/><br/> <input name="pet.age"/><br/> */@Date class Person() {var userName: String? = nullvar age: Int? = nullvar birth: Date? = nullvar pet: Pet? = null }@Date class Pet() {var name: String? = nullvar age: String? = null }
POJO封装过程
<form action="/saveuser" method="post">姓名:<input name="userName"/><br/>年龄:<input name="age"/><br/>生日:<input name="birth"/><br/>
<!-- 宠物姓名:<input name="pet.name"/><br/>-->
<!-- 宠物年龄:<input name="pet.age"/><br/>--><input name="pet" value="neko,7"/><br/><input type="submit" value="提交"/></form>
WebConfig.kt @Beanfun webMvcConfigurer(): WebMvcConfigurer {return object : WebMvcConfigurer {override fun configurePathMatch(configurer: PathMatchConfigurer) {val urlPathHelper = UrlPathHelper();urlPathHelper.setRemoveSemicolonContent(false)configurer.setUrlPathHelper(urlPathHelper);}override fun addFormatters(registry: FormatterRegistry) {registry.addConverter(Converter<String, Pet?> { source ->if (!source.isEmpty()) {val pet = Pet()pet.name = source.split(",").toTypedArray()[0]pet.age = source.split(",").toTypedArray()[1].toInt()return@Converter pet}null})}}}
参数处理原理
HandlerMapping中找到能处理请求的Handler(Controller.method)
为当前Handler找一个适配器HandlerAdapter
HandlerAdapter:
RequestMappingHandlerAdapter
支持方法上标注@RequestMapping
HandkerFunctionAdapter
支持函数式编程
HttpRequestHandlerAdapter
SimpleControllerHandlelrAdapter
执行目标方法
//Actually invoke the handler //DispatcherServlet -- doDispatch mv = ha.handler(processedRequest, responese, mappedHandler.getHandler());
参数解析器
确定将要执行的目标方法每一个参数的值是什么
SpringMVC目标方法能写多少种参数类型,取决于参数解析器
HandlerMethodArgumentResolver
- resolveArgument
- supportsParameter
当前解析器是否支持该参数,如支持则调用resolveArgument
返回值处理器
解析该参数值:resolveArgument
自定义类型参数 封装POJO
ServletModelAttributeMethodProcessor
目标方法执行完成
将所有的数据都放在ModelAndViewContainer中,包含目的页面地址View、Model数据
处理派发结果
响应数据与内容协商
数据响应
- 响应页面
- 响应数据
- JSON
- XML
- xls
- 图片、视频
- 自定义协议数据
响应JSON
jackson.jar + @ResponseBody
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
web场景自动引入JSON场景
<dependecncy><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-json</artifactId><version>xxx</version><scope>compile</scope>
</dependecncy>
给前端自动返回JSON数据
HTTPMessageConverter原理
内容协商
根据客户端接收能力不同,返回不同媒体类型的数据
引入XML依赖
<dependency><groupId>org.springframework.dataformat</groupId><artifactId>jackson-dataformat-xml</artifactId> </dependency>
postman分别测试返回JSON和XML
只需要改变请求头Accept字段。Http协议中规定的,告诉服务器可以接收的数据类型
开启浏览器参数方式内容协商功能
为方便内容协商,开启基于请求参数的内容协商功能。
spring:mvc:contentnegotiation:favor-parameter: true
http://localhost:8080/text/person?format=json
http://localhost:8080/text/person?format=xml
内容协商原理
- 判断当前响应头中我是否已有确定的媒体类型。MediaType
- 获取客户端(PostMan、浏览器)支持接收的内容类型(获取客户端Accept请求头字段)[application/xml]
- contentNegotiationManager内容协商管理器,默认使用基于请求头的策略
- HeaderContentNegotiationStrategy确定客户端可以接收的内容类型
- 遍历循环所有当前系统的MessageConverter
- 获得所有支持指定类型的Converter
- 客户端需要[application/xml],服务器能力
- 进行内容协商的最佳匹配
- 用 支持 将对象转为最佳匹配媒体类型的Converter,调用进行转化
自定义MessageConverter
实现多协议数据兼容。json、xml、x-xxx
@ReponseBody响应数据调用RequestResponseBodyMethodProcessor处理
- Processor处理方法返回值,通过MessageConverter处理
- 所有MessageConverter整体可以支持各种媒体类型数据的操作(读、写)
- 内容协商找到最终的messageConverter
自定义Converter
class KazuntoMessageConverter : HttpMessageConverter<Person> {override fun canRead(clazz: Class<*>, mediaType: MediaType?): Boolean {TODO("Not yet implemented")}override fun canWrite(clazz: Class<*>, mediaType: MediaType?): Boolean {return clazz.isAssignableFrom(Person::class.java)}override fun getSupportedMediaTypes(): MutableList<MediaType> {return MediaType.parseMediaTypes("application/x-kazunto")}override fun read(clazz: Class<out Person>, inputMessage: HttpInputMessage): Person {TODO("Not yet implemented")}override fun write(t: Person, contentType: MediaType?, outputMessage: HttpOutputMessage) {val data = "${t.userName};${t.age};${t.birth}"val body = outputMessage.bodybody.write(data.toByteArray())}
}
自定义内容协商策略
@Bean
public WebMvcConfigurer webMvcConfigurer() {return new WebMvcConfigurer() {@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {converters.add(new KazuntoMessageConverter());}@Overridepublic void configureContentNegotiation(ContentNegotiationConfigurer configurer) {Map<String, MediaType> mediaType = new HashMap<>();mediaType.put("json", MediaType.APPLICATION_JSON);mediaType.put("xml", MediaType.APPLICATION_XML);mediaType.put("kzt", MediaType.parseMediaType("application/x-kazunto"));ParameterContentNegotiationStrategy parameterStrategy = new ParameterContentNegotiationStrategy(mediaType);HeaderContentNegotiationStrategy headerStategy = new HeaderContentNegotiationStrategy();configurer.strategies(Arrays.asList(parameterStrategy, headerStategy));}@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {UrlPathHelper urlPathHelper = new UrlPathHelper();urlPathHelper.setRemoveSemicolonContent(false);configurer.setUrlPathHelper(urlPathHelper);}};
}
@Bean
fun webMvcConfigurer(): WebMvcConfigurer {return object : WebMvcConfigurer {override fun configurePathMatch(configurer: PathMatchConfigurer) {val urlPathHelper = UrlPathHelper();urlPathHelper.setRemoveSemicolonContent(false)configurer.setUrlPathHelper(urlPathHelper);}override fun addFormatters(registry: FormatterRegistry) {registry.addConverter(Converter<String, Pet?> { source ->if (!source.isEmpty()) {val pet = Pet()pet.name = source.split(",").toTypedArray()[0]pet.age = source.split(",").toTypedArray()[1].toInt()return@Converter pet}null})}override fun extendMessageConverters(converters: MutableList<HttpMessageConverter<*>?>) {converters.add(KazuntoMessageConverter())}override fun configureContentNegotiation(configurer: ContentNegotiationConfigurer){val mediaType = HashMap<String, MediaType>()mediaType["json"] = MediaType.APPLICATION_JSONmediaType["xml"] = MediaType.APPLICATION_XMLmediaType["kzt"] = MediaType.parseMediaType("application/x-kazunto")val parameterStrategy = ParameterContentNegotiationStrategy(mediaType)val headerStategy = HeaderContentNegotiationStrategy()configurer.strategies(listOf(parameterStrategy, headerStategy))}}
}
视图解析与模板引擎
视图解析:SpringBoot默认不支持JSP,需引入第三方模板引擎技术实现页面渲染。
视图解析
模板引擎-Thymeleaf
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
thymeleaf简介
Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text.
现代化、服务端Java模板引擎
页面须放在/templates/下,且为.html
基本语法
表达式名字 语法 用途 变量取值 ${…} 获取请求域、session域、对象等 选择变量 *{…} 获取上下文对象值 消息 #{…} 获取国际化等值 链接 @{…} 生成链接 片段表达式 ~{…} jsp:include作用,引入公共页面 字面量
文本值:’…’
数字
布尔值:true, false
空值:null
变量:one, …变量不能有空格
文本操作
字符串拼接:+
变量替换:|The name is ${name}|
数学运算
运算符:+ - * / %
布尔运算
运算符:and or
一元运算:!, not
比较运算
比较:> < >= <= (gt lt ge le)
等式:== != (eq ne)
条件运算
If-then:(if) ? (then) : (false)
If-then-else:(if) ? (then) : (else)
Default:(value) ?: (defaultValue)
特殊操作
无操作: _
设置属性值-th:attr
设置单个值
<form><fieldset><input type="text" name="email"/><input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/></fieldset> </form>
设置多个值
<img src="../../images/qwe.png" th:attr="src=@{/images/qwe.png},title=#{logo}"/>
以上代替写法th:xxx
<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/> <form action="subscribe.html" th:action="@{/subscribe}"></form>
迭代
<tr class="gradeX" th:each="user,status:${userList}"><td th:text="${status.count}">0</td><td th:text="${user.username}">null</td><td th:text="${user.password}">null</td> </tr>
@GetMapping("/dynamic_table") public String dynamicTable(Model model) {List<User> userList = Arrays.asList(new User("ka", "123456"),new User("ka2", "123456"),new User("ka3", "123456"),new User("ka4", "123456"));model.addAttribute("userList", userList);return "table/dynamic_table"; }
拦截器
HandlerInterceptor接口
preHandler 目标方法完成以前、postHandler 目标方法完成以后、afterCompletion 页面渲染以后
配置拦截器
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {HttpSession session = request.getSession();Object loginUser = session.getAttribute("loginUser");if (loginUser != null)return true;request.setAttribute("msg", "请先登录");
// response.sendRedirect("/");request.getRequestDispatcher("/").forward(request, response);return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}
@Configuration
public class AdminWebConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/", "/login", "/css/**", "/fonts/**", "/images/**", "/js/**");}
}
验证拦截器
文件上传
页面表单
<div class="form-group"><label for="exampleInputFile">头像</label><input type="file" name="headImage" id="exampleInputFile">
</div>
<div class="form-group"><label for="exampleInputFile">生活照</label><input type="file" name="photos" multiple>
</div>
上传代码
@PostMapping("/upload")
public String upload(@RequestParam("email") String email,@RequestParam("username") String username,@RequestPart("headImage") MultipartFile headImage,@RequestPart("photos") MultipartFile[] photos) throws IOException {//默认单文件不超过1MB,总大小不超过10MB,可在配置文件中修改if (!headImage.isEmpty()) {headImage.transferTo(new File("D:\\" + headImage.getOriginalFilename()));}if (photos.length > 0) {for (MultipartFile photo : photos) {if (!photo.isEmpty()) {photo.transferTo(new File("D:\\" + photo.getOriginalFilename()));}}}return "index";
}
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB
异常处理
错误处理
1、默认规则
- 默认情况下,SpringBoot提供/error处理所以的错误的映射
- 对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,响应一个"whitelabel"错误视图,以HTML格式呈现相同的数据
- 进行自定义:添加view解析为error
- 完全替换默认行为:实现ErrorController并注册该类型的Bean定义,或添加ErrorAttributes类型的组件以使用现有机制但替换其内容。
- templates/error/下的4xx,5xx页面会被自动解析
2、定制错误处理逻辑
- 自定义错误页
- error/404.html error/5xx.html
- @ControllerAdvice + @ExceptionHandler处理异常
- 实现HandlerExceptionResolver处理异常
3、异常处理原理
Web原生组件注入(Servlet、Filter、Listener)
1、使用Servlet API
//直接响应,不经过Spring拦截器
@WebServlet(urlPatterns = "/my")
public class MyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.getWriter().write("6666666666");}
}@WebFilter(urlPatterns = {"/css/*", "/images/*"})
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}
}@Slf4j
@WebListener
public class MyServletContextListener implements ServletContextListener {@Overridepublic void contextInitialized(ServletContextEvent sce) {log.info("监听到项目初始化完成");}@Overridepublic void contextDestroyed(ServletContextEvent sce) {log.info("监听到项目销毁");}
}//主配置类
@ServletComponentScan(basePackages = "cn.kazunto.admin")
@SpringBootApplication
public class Boot05WebAdminApplication {public static void main(String[] args) {SpringApplication.run(Boot05WebAdminApplication.class, args);}}
2、使用RegistrationBean
ServletRegistrationBean、FilterRegistrationBean 和 ServletListenerRegistrationBean
@Configuration
public class MyRegistConfig {@Beanpublic ServletRegistrationBean myServlet() {MyServlet myServlet = new MyServlet();return new ServletRegistrationBean(myServlet, "/my", "/my02");}@Beanpublic FilterRegistrationBean myFilter() {MyFilter myFilter = new MyFilter();//只拦截myServlet中的路径,my my02//return new FilterRegistrationBean(myFilter, myServlet());FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(myFilter);filterRegistrationBean.setUrlPatterns(Arrays.asList("/my", "/css/*"));return filterRegistrationBean;}@Beanpublic ServletListenerRegistrationBean myListener() {MyServletContextListener myServletContextListener = new MyServletContextListener();return new ServletListenerRegistrationBean(myServletContextListener);}
}
定制化原理
1、定制化的常见方式
@Bean替换、增加容器中默认组件;视图解析器
修改配置文件
xxxCustomizer
编写自定义的配置类 xxxConfiguration
web应用实现WebMvcConfigurer即可定制化Web功能
@EnableWebMvc + WebMvcConfigurer —— @Bean 可以全面接管SpringMVC,所以规则全部自己重新部署;实现定制和扩展功能
2、原理分析套路
场景starter - xxxAutoConfiguration - 导入xxx组件 - 绑定xxxProperties
数据访问
1、SQL
1、数据源的自动配置
导入JDBC场景
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency>默认版本8.0.22,SpringBoot已完成版本仲裁,无需手写版本信息。数据库版本应与驱动版本对应<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
分析自动配置
- 自动配置的类
- DataSourceAutoConfiguration:数据源的自动配置
- 修改数据源相关的配置:spring.datasource
- 数据库连接池的配置,当容器中没有DataSource才自动配置
- 底层配置好的连接池是:HikariDataSource
- DataSourceTransactionManagerAutoConfiguration:事务管理的自动配置
- JdbcTemplateAutoConfiguration:JdbcTemplate的自动配置,可以对数据库进行crud(增删改查)
- 可以修改配置项@ConfigurationProperties(prefix=“spring.jdbc”)来修改JdbcTemplate
- @Bean @Primary JdbcTemplate;容器中该组件
- JndiDataSourceAutoConfiguration:jndi的自动配置
- XADataSourceAutoConfiguration:分布式事务相关的
- DataSourceAutoConfiguration:数据源的自动配置
- 自动配置的类
修改配置项
spring:datasource:url: jdbc:mysql://localhost:3306/tk?serverTimezone=Asia/Shanghai&userUnicode=true&characterEncoding=utf8&userSSL=trueusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverjdbc:template:query-timeout: 3
2、使用Druid数据源
http://localhost:8080/druid/login.html
Druid官方github地址:https://github.com/alibaba/druid
整合第三方技术的两种方式:自定义、starter
自定义方式
- 创建数据源
starter
引入starter
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.17</version></dependency>
分析自动配置
- 扩展配置项spring.datasource.druid
- DruidSpringAopConfiguration.class,监控SpringBoot的配置项:spring.datasource.druid.aop-patterns
- DruidStatViewServletConfiguration.class,监控页的配置:spring.datasource.druid.stat-view-servlet;默认开启
- DruidWebStatFilterConfiguration.class,Web监控配置:spring.datasource.druid.web-stat-filter;默认开启
- DruidFilterConfiguration.class,所有Druid自己的filter配置
配置示例
spring:datasource:url: jdbc:mysql://localhost:3306/tk?serverTimezone=Asia/Shanghai&userUnicode=true&characterEncoding=utf8&userSSL=trueusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Driverdruid:filters: start,wall,slf4j #底层开启功能:stat(sql监控),wall(防火墙)aop-patterns: cn.kazunto.admin.* #监控SpringBeanstat-view-servlet: #配置监控页功能 http://localhost:8080/druid/login.htmlenabled: truelogin-username: adminlogin-password: adminresetEnable: falseweb-stat-filter: #监控webenabled: trueurl-pattern: /*exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'filter:stat:slow-sql-millis: 1000logSlowSql: trueenabled: truewall:enabled: trueconfig:drop-table-allow: false #禁止删表jdbc:template:query-timeout: 3
3、整合MyBatis操作
https://github.com/mybatis
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.4</version></dependency>
配置模式
全局配置文件
SqlSessionFactory:自动配置好
SqlSession:自动配置了SqlSessionTemplate组合了SqlSession
@Import(AutoConfiguredMapperScannerRegister.class)
Mapper:只要写的操作MyBatis的接口标注了@Mapper就会被自动扫描进来
@EnalbeConfigurationProperties(MyBatisProperties.class) //MyBatis配置项绑定类 @AutoConfigureAfter({DataSourceAutoConfiguration.class, MyBatisLanguageDriverAutoConfiguration.class}) public class MyBatisAutoConfiguration{}@ConfigurationProperties(prefix="mybatis") public class MyBatisProperties//通过修改配置文件中mybatis开头的
mybatis:config-location: classpath:mybatis/mybatis-config.xmlmapper-locations: classpath:mybatis/mapper/*.xml
- 导入mybatis官方starter
- 编写mapper接口,标注@Mapper
- 编写sql映射文件并绑定mapper接口
- 在yml中指定mapper配置文件位置,和配置文件信息
注解模式
混合模式
4、整合MyBatis-Plus完成CRUD
需安装MyBatisX插件
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-jdbc</artifactId>-->
<!-- </dependency>--><!-- <dependency>-->
<!-- <groupId>org.mybatis.spring.boot</groupId>-->
<!-- <artifactId>mybatis-spring-boot-starter</artifactId>-->
<!-- <version>2.1.4</version>-->
<!-- </dependency>--><!--引入该内容后,不需要引入jdbc和mybatis--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version></dependency>
自动配置:
- MybatisPlusAutoConfiguration配置类,MybatisPlusProperties配置项绑定。mybatis-plus(yaml)。
- SqlSessionFactory:自动配置好
- mapperLoactions:自动配置好。默认为classpath*:/mapper/**/*.xml;任意包的类路径下所有mapper文件夹下任意路径下的所有xml。
- 自动配置了SqlSessionTemplate
- @Mapper标注的接口被自动扫描
- 只需要Mapper继承BaseMapper就拥有CRUD能力
2、NoSQL
Redis是开源的,内存中的数据结构存储系统,可以用作数据库、缓存和消息中间件。支持多种类型的数据结构:strings、hashes、lists、sets、sorted sets与范围查询、bitmaps、hyperloglogs和地理空间(geospatial)索引半径查询。Redis内置了复制(replication)、LUA脚本(Lua scripting)、LRU驱动事件(LRU eviction)、事务(transactions)和不同级别的磁盘持久化(persistence),并通过Redis哨兵(Sentinel)和自动分区(Cluster)提供高可用性。
1.Redis自动配置
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- RedisAutoConfiguration自动配置类。RedisProperties属性类–>spring.redis.xxx是对redis的配置
- 连接工厂是准备好的。LettuceConnectionConfiguration、JedisConnectionConfiguration
- 自动注入RedisTemplate<Object, Object>和StringRedisTemplate,前者key和value是Object类型,后者都是String类型
- 底层只要使用RedisTemplate和StringRedisTemplate就可以操作Redis
指标监控
1.SpringBoot Actuator
1.简介
每一个微服务在云上部署以后,都需要对其进行监控、追踪、审计和控制等。SpringBoot抽取了Actuator场景,使得每个微服务快速引用即可获得生产级别的应用监控和审计等功能。
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2. 1.x和2.x的不同
SpringBoot Actuator 1.x | SpringBoot Actuator 2.x |
---|---|
支持SpringMVC | 支持SpringMVC、JAX-RS以及Webflux |
基于继承方式进行拓展 | 注解驱动进行拓展 |
层级Metrics配置 | 层级&名称空间Metrics |
自定义Metrics收集 | 底层使用MicroMeter,强大、便捷 |
默认较少的安全策略 | 默认丰富的安全策略 |
3.如何使用
- 引入场景
- 访问http://localhost:8080/actuator/health
- 暴露所有监控行为HTTP
#management是所有actuator的配置
management:endpoints:enabled-by-default: true #默认开启所有监控端点web:exposure:include: '*' #以web方式暴露所有端点endpoint:health:show-details: always
最常用的Endpoint:
- Health:健康状况
- Metrics:运行时指标
- Loggers:日志记录
2.Health Endpoint
健康检查端点,一般在使用云平台时会定期检查应用的健康状况,就通过Health Endpoint返回健康状况的集合。
- Health Endpoint返回的结果,是一系列健康检查后的汇总报告。
- 很多健康检查默认配置完毕,例如数据库和Redis等。
- 简单地添加自定义的健康检查机制。
3.Metrics Endpoint
提供详细的、层级的、空间指标信息,该信息可以被pull(主动推送)或push(被动获取)方式得到。
- 通过Metrics对接多种监控系统
- 简化核心Metrics开发
- 添加自定义Metrics或者扩展已有Metrics
4.管理Endpoints
1.开启与禁用Endpoints
- 默认所有的Endpoints除过shutdown都是开启的
2.定制info信息
编写配置文件
info:appName: KazuntomavenProjectName: @project.artifactId@ #使用@@可以获取maven的pom文本值
编写Controller
@Controller public class KazuntoInfoContributor implements InfoContributor {@Overridepublic void contribute(Info.Builder builder) {builder.withDetail(...);} }
5.定制Metrics信息
class KazuntoService {Counter counter;public KazuntoService(MeterRegistry meterRegistry) {counter = meterRegistry.counter("kazuntoService.method.running.counter");}public void hello() {counter.increment();}
}//或下面方式
@Bean
MeterBinder queueSize(Queue queue) {return (registry) -> Gauge.builder("queueSize", queue::size).register(registry);
}
6.定制Endpoint
@Component
@Endpoint(id="container")
public class KazuntoEndpoint {@ReadOperationpublic Map getInfo() {return Collection.singletonMap("", "");}@WriteOperationprivate void restart() {}
}
场景:开发ReadinessEndpoint管理程序是否就绪,或LivenessEndpoint管理程序是否存活;也可以直接使用:https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#produciton-ready-kubernetes-probes
7.可视化
https://github.com/codecentric/spring-boot-admin
新建项目(服务器):用于记录数据
<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.3.1</version> </dependency>
@Configuration @EnableAutoConfiguration @EnableAdminServer public class SpringBootAdminApplication {public static void main(String[] args) {SpringApplication.run(SpringBootAdminApplication.class, args);} }
server.port=8888
客户端:被记录数据
<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-client</artifactId><version>2.3.1</version> </dependency> <dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-security</artifactId> </dependency>
spring.boot.admin.client.url=http://localhost:8080 management.endpoints.web.exposure.include=*
或
spring:boot:admin:client:url: http://localhost:8888instance:prefer-ip: trueapplication:name: Kazunto management:endpoints:enabled-by-default: trueweb:exposure:include: '*'
Profile功能
为方便多环境适配,springboot简化了profile功能。
1. applicaiton-profile功能
默认配置文件 application.yaml 任何时候都会加载
指定环境配置文件 application-{env}.yaml
application.properties spring.profiles.active=prod #激活application-prod.properties或application-prod.yml
激活指定环境
配置文件激活
命令行激活
java -jar PROJECTNAME.jar --spring.profiles.active=prod2 --server.port=1234
- 修改配置文件的任意值,命令行优先
默认配置与环境配置同时生效
同名配置项,profile配置优先
2. @Profile条件装配功能
@Profile(“prod”)
className or functionName
决定类或方法在什么配置文件生效时启用
3、Profile分组
application.properties
spring.profiles.active=name
spring.profiles.group.name[0]=yaml1
spring.profiles.group.name[1]=yaml2
SpringBoot2学习笔记相关推荐
- springboot2 war页面放在那_成为微服务架构师--SpringBoot2学习笔记
<"爱读书"--给你讲技术>,我来看书,你来进步,让我们开始吧! 本书简介 书名为<SpringBoot2企业应用实战>,这是一本简单易懂的SpringBo ...
- 【黑马程序员】SpringBoot2学习笔记
1.SpringBoot的前菜 1.1 发展沿革 2013年,Pivotal团队开始研发SpringBoot. 2014年4月,发布全新开源的轻量级框架的第一个SpringBoot版本. 1.2 特点 ...
- springboot2学习笔记:mvnw相关文件生成
在学习springboot2的时候,我们会发现,可以用 命令 mvnw spring-boot:run 来启动项目. 使用这个命令,依赖于项目中的 mvnw,mvnw.bat,mvnw文件夹 那么怎么 ...
- SpringBoot2学习笔记01-基础
非常推荐直接看教程,老师讲的真的很好,虽然很多原理部分很糊但是如果用过一段时间再来看原理的解析会非常透彻,力荐:这里是教程 这里是教程的1-20P,内容其实不多,主要是一些基础的注解和怎么用,接下来才 ...
- 学习笔记之-Activiti7工作流引擎,概述,环境搭建,类关系图,使用Activiti BPMN visualizer,流程变量,组任务 网关,Activiti整合Spring SpringBoot
本篇学习笔记是观看黑马程序员Activiti7视频而得 Activiti7 一.工作流介绍 1.1 概念 工作流(Workflow),就是通过计算机对业务流程自动化执行管理.它主要解决的是" ...
- 8. SpringBoot基础学习笔记
SpringBoot基础学习笔记 课程前置知识说明 1 SpringBoot基础篇 1.1 快速上手SpringBoot SpringBoot入门程序制作 1.2 SpringBoot简介 1.2.1 ...
- 尚硅谷SpringBoot学习笔记
目录 简介编辑 快速搭建一个SpringBoot的网页 自动配置原理 容器功能 组件添加 原生配置文件引入 配置绑定 自动配置原理 1.引导加载自动配置类 2.按需配置开启自动配置项 开发小技巧 1 ...
- Redis学习笔记(B站狂神说)(自己总结方便复习)
Redis学习笔记B站狂神说 redis: 非关系型数据库 一.NoSQL概述 1.为什么要用Nosql 1.单机Mysql的年代 思考一下,这种情况下:整个网站的瓶颈是什么? 1.数据量如果太大,一 ...
- SpringBoot(学习笔记)
SpringBoot学习笔记 从今天开始就进入微服务阶段 一些小问题 1.HelloWorld 1.1回顾什么是Spring 1.2什么是SpringBoot 1.3微服务架构 2.第一个Spring ...
最新文章
- wps 项目进度_平安科技软件+金山WPS测试面试题
- 关于Cloud各种组件的停更/升级/替换
- OpenGL屏幕空间环境光遮挡
- Spring_AOP架构介绍与源码分析(含事务深度分析)
- MySQL中GTID的几个限制和解决方案(r13笔记第21天)
- 积分图像追踪目标 (一)
- C++中的STL和MFC
- B00015 平方矩阵问题
- CSS设置居屏幕中间的弹出块
- IP地址是如何分配的
- html怎么让鼠标自动移动位置,手把手教你编作弊软件之 鼠标自动移动/点击
- Oxyplot实时绘图学习笔记(下)
- 从零开始学习大数据系列之Linux-02Vim与Shell script
- 深度学习之 DCGAN 及TensorFlow 实现
- nginx重启报找不到nginx.pid的解决方法
- ROS path [0]=/opt/ros/melodic/share/rosROS path [1]=/home/huanyu-pc/robot_ws/srcROS path [2]=/opt/
- 2022疫情缩水,啃透这份399页Java架构知识点笔记,已从13K涨到25K
- ITEYE手机阅读器更新
- 软件测试工程师的介绍
- STM32CubeIDE设置