SpringBoot高级(自动配置 事件监听 监控)

2022-07-25 11:57:59

SpringBoot高级

SpringBoot自动配置

condition-1

Condition是Spring4.0后引入的条件化配置接口,通过实现Condition接口可以完成有条件的加载相应的Bean

@Conditional要配和Condition的实现类(ClassCondition)进行使用

  • ClassCondition
publicclassClassConditionimplementsCondition{/**
     *
     * @param context 上下文对象。用于获取环境,IOC容器,ClassLoader对象
     * @param metadata 注解元对象。 可以用于获取注解定义的属性值
     * @return
     */@Overridepublicbooleanmatches(ConditionContext context, AnnotatedTypeMetadata metadata){//1.需求: 导入Jedis坐标后创建Bean//思路:判断redis.clients.jedis.Jedis.class文件是否存在boolean flag=true;try{
            Class<?> cls= Class.forName("redis.clients.jedis.Jedis");}catch(ClassNotFoundException e){
            flag=false;}return flag;}}

UserConfig

@ConfigurationpublicclassUserConfig{@Bean@Conditional(ClassCondition.class)public Useruser(){returnnewUser();}}

测试

@SpringBootApplicationpublicclassSpringbootConditionApplication{publicstaticvoidmain(String[] args){//启动SpringBoot的应用,返回Spring的IOC容器
        ConfigurableApplicationContext context= SpringApplication.run(SpringbootConditionApplication.class, args);

        Object user= context.getBean("user");
        System.out.println(user);}}

依赖

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency>

这一段是判断jedis这个依赖要有没有来决定是否生成对应的bean对象,需要实现Condition接口,重写mathes方法,返回false则不创建对象,在这个user对象上加入注解@Conditioal(xxx.class)来实现判断。

condition-2

需求:将类的判断定义为动态的。判断哪个字节码文件存在可以动态指定。

自定义条件注解类

import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@Documented@Conditional(ClassCondition.class)public @interfaceConditionOnClass{
    String[]value();}

**注意:**此处@ConditionOnClass为自定义注解

@ConfigurationpublicclassUserConfig{@Bean//@Conditional(ClassCondition.class)@ConditionOnClass("com.alibaba.fastjson.JSON")public Useruser(){returnnewUser();}@Bean@ConditionalOnProperty(name="itcast",havingValue="ii")public Useruser2(){returnnewUser();}}

测试User对象的创建

@SpringBootApplicationpublicclassSpringbootConditionApplication{publicstaticvoidmain(String[] args){//启动SpringBoot的应用,返回Spring的IOC容器
        ConfigurableApplicationContext context= SpringApplication.run(SpringbootConditionApplication.class, args);

        Object user= context.getBean("user");
        System.out.println(user);}}
  • 自定义注解其实是对原来注解的封装
  • @ConditionalOnProperty是看配置文件中是否存在一个这样的键值对,如果有则创建、
    -执行顺序:
    @ConditionOnClass的value值,找到依赖和自定义注解类,通过自定义注解类上的class找到具体要执行的代码,决定是否生成bean对象。

查看条件注解源码
在这里插入图片描述
SpringBoot 提供的常用条件注解:

ConditionalOnProperty:判断配置文件中是否有对应属性和值才初始化Bean

ConditionalOnClass:判断环境中是否有对应字节码文件才初始化Bean

ConditionalOnMissingBean:判断环境中没有对应Bean才初始化Bean

SpringBoot自动配置-切换内置web服务器

查看继承关系图
在这里插入图片描述
在这里插入图片描述

排除Tomcat
在这里插入图片描述
pom文件中的排除依赖效果

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><!--排除tomcat依赖--><exclusions><exclusion><artifactId>spring-boot-starter-tomcat</artifactId><groupId>org.springframework.boot</groupId></exclusion></exclusions></dependency><!--引入jetty的依赖--><dependency><artifactId>spring-boot-starter-jetty</artifactId><groupId>org.springframework.boot</groupId></dependency>

SpringBoot配置拦截器

创建拦截器类

package com.*.*.interceptor;import java.io.IOException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import com.*.*.*.User;/**
 * 
 * 
 * @Package: com.*.*.interceptor 
 * @ClassName: AdminInterceptor 
 * @Description:拦截器
 * @author: zk
 * @date: 2019年9月19日 下午2:20:57
 */publicclassAdminInterceptorimplementsHandlerInterceptor{/**
     * 在请求处理之前进行调用(Controller方法调用之前)
     */@OverridepublicbooleanpreHandle(HttpServletRequest request, HttpServletResponse response, Object handler){//        System.out.println("执行了TestInterceptor的preHandle方法");try{//统一拦截(查询当前session是否存在user)(这里user会在每次登陆成功后,写入session)
            User user=(User)request.getSession().getAttribute("USER");if(user!=null){returntrue;}
            response.sendRedirect(request.getContextPath()+"你的登陆页地址");}catch(IOException e){
            e.printStackTrace();}returnfalse;//如果设置为false时,被请求时,拦截器执行到此处将不会继续操作//如果设置为true时,请求将会继续执行后面的操作}/**
     * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后)
     */@OverridepublicvoidpostHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView){//         System.out.println("执行了TestInterceptor的postHandle方法");}/**
     * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作)
     */@OverridepublicvoidafterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex){//        System.out.println("执行了TestInterceptor的afterCompletion方法");}}

配置拦截器

package com.*.*.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import com.*.*.interceptor.AdminInterceptor;/**
 * 
 * 
 * @Package: com.*.*.config 
 * @ClassName: LoginConfig 
 * @Description:拦截器配置
 * @author: zk
 * @date: 2019年9月19日 下午2:18:35
 */@ConfigurationpublicclassLoginConfigimplementsWebMvcConfigurer{@OverridepublicvoidaddInterceptors(InterceptorRegistry registry){//注册TestInterceptor拦截器
        InterceptorRegistration registration= registry.addInterceptor(newAdminInterceptor());
        registration.addPathPatterns("/**");//所有路径都被拦截
        registration.excludePathPatterns(//添加不拦截路径"你的登陆路径",//登录"/**/*.html",//html静态资源"/**/*.js",//js静态资源"/**/*.css",//css静态资源"/**/*.woff","/**/*.ttf");}}

SpringBoot应用监控

SpringBoot自动配置-Enable注解原理

SpringBoot不能直接获取在其他工程中定义的Bean

演示代码:

springboot-enable工程

/**
 * @ComponentScan 扫描范围:当前引导类所在包及其子包
 *
 * com.itheima.springbootenable
 * com.itheima.config
 * //1.使用@ComponentScan扫描com.itheima.config包
 * //2.可以使用@Import注解,加载类。这些类都会被Spring创建,并放入IOC容器
 * //3.可以对Import注解进行封装。
 *///@ComponentScan("com.itheima.config")//@Import(UserConfig.class)@EnableUser@SpringBootApplicationpublicclassSpringbootEnableApplication{publicstaticvoidmain(String[] args){
        ConfigurableApplicationContext context= SpringApplication.run(SpringbootEnableApplication.class, args);//获取Bean
        Object user= context.getBean("user");
        System.out.println(user);}}

pom中引入springboot-enable-other

<dependency><groupId>com.itheima</groupId><artifactId>springboot-enable-other</artifactId><version>0.0.1-SNAPSHOT</version></dependency>

springboot-enable-other工程

UserConfig

@ConfigurationpublicclassUserConfig{@Beanpublic Useruser(){returnnewUser();}}

EnableUser注解类

import org.springframework.context.annotation.Import;import java.lang.annotation.*;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(UserConfig.class)public @interfaceEnableUser{

在这里插入图片描述

myImportSelector

publicclassMyImportSelectorimplementsImportSelector{@Overridepublic String[]selectImports(AnnotationMetadata importingClassMetadata){returnnewString[]{"com.itheima.domain.User","com.itheima.domain.Role"};}}

ImportBeanDefinitionRegistrar 实现类

publicclassMyImportBeanDefinitionRegistrarimplementsImportBeanDefinitionRegistrar{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
        AbstractBeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        registry.registerBeanDefinition("user", beanDefinition);}}

在这里插入图片描述
Import4中用法:

    1. 导入Bean
    1. 导入配置类
    1. 导入ImportSelector的实现类。
    1. 导入ImportBeanDefinitionRegistrar实现类

自定义依赖

在这里插入图片描述

SpringBoot事件监听

Java中的事件监听机制定义了以下几个角色:

①事件:Event,继承 java.util.EventObject 类的对象

②事件源:Source ,任意对象Object

③监听器:Listener,实现 java.util.EventListener 接口 的对象

SpringBoot 在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成一些操作。

  • ApplicationContextInitializer、

  • SpringApplicationRunListener、

  • CommandLineRunner、

  • ApplicationRunner

    自定义监听器的启动时机:MyApplicationRunner和MyCommandLineRunner都是当项目启动后执行,使用@Component放入容器即可使用

MyApplicationRunner

/**
 * 当项目启动后执行run方法。
 */@ComponentpublicclassMyApplicationRunnerimplementsApplicationRunner{@Overridepublicvoidrun(ApplicationArguments args)throws Exception{
        System.out.println("ApplicationRunner...run");
        System.out.println(Arrays.asList(args.getSourceArgs()));}}

MyCommandLineRunner

@ComponentpublicclassMyCommandLineRunnerimplementsCommandLineRunner{@Overridepublicvoidrun(String... args)throws Exception{
        System.out.println("CommandLineRunner...run");
        System.out.println(Arrays.asList(args));}}

MyApplicationContextInitializer的使用要在resource文件夹下添加META-INF/spring.factories

org.springframework.context.ApplicationContextInitializer=com.itheima.springbootlistener.listener.MyApplicationContextInitializer
@ComponentpublicclassMyApplicationContextInitializerimplementsApplicationContextInitializer{@Overridepublicvoidinitialize(ConfigurableApplicationContext applicationContext){
        System.out.println("ApplicationContextInitializer....initialize");}}

MySpringApplicationRunListener的使用要添加构造器(最屌)

publicclassMySpringApplicationRunListenerimplementsSpringApplicationRunListener{publicMySpringApplicationRunListener(SpringApplication application, String[] args){}@Overridepublicvoidstarting(){
        System.out.println("starting...项目启动中");}@OverridepublicvoidenvironmentPrepared(ConfigurableEnvironment environment){
        System.out.println("environmentPrepared...环境对象开始准备");}@OverridepublicvoidcontextPrepared(ConfigurableApplicationContext context){
        System.out.println("contextPrepared...上下文对象开始准备");}@OverridepublicvoidcontextLoaded(ConfigurableApplicationContext context){
        System.out.println("contextLoaded...上下文对象开始加载");}@Overridepublicvoidstarted(ConfigurableApplicationContext context){
        System.out.println("started...上下文对象加载完成");}@Overridepublicvoidrunning(ConfigurableApplicationContext context){
        System.out.println("running...项目启动完成,开始运行");}@Overridepublicvoidfailed(ConfigurableApplicationContext context, Throwable exception){
        System.out.println("failed...项目启动失败");}}

在这里插入图片描述

Springboot Admin图形化管理平台

SpringBoot Admin 有两个角色,客户端(Client)和服务端(Server)。

把要被监控的服务作为客户端。提供图形化界面的服务作为服务端

admin-server 模块

导入依赖坐标 admin-starter-server

<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-server</artifactId><version>2.2.1</version></dependency>

在引导类上启用监控功能@EnableAdminServer

@EnableAdminServer@SpringBootApplicationpublicclassSpringbootAdminServerApplication{publicstaticvoidmain(String[] args){
        SpringApplication.run(SpringbootAdminServerApplication.class, args);}}

admin-client 模块

<dependency><groupId>de.codecentric</groupId><artifactId>spring-boot-admin-starter-client</artifactId><version>2.2.1</version></dependency>
# 执行admin.server地址
spring.boot.admin.client.url=http://localhost:9000

management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=*
spring:boot:admin:client:url: http://localhost:8888# 服务端的地址management:endpoint:health:show-details: alwaysendpoints:web:exposure:include:"*"

注意:要求必须是web项目才会注册到服务端

④启动server和client服务,访问server

http://localhost:8888/

以后可以server打成jar包,然后其他服务通过端口去绑定注册

Springboot 部署

部署有两个方式
1.通过maven或者命令直接打成jar包,通过cmd,直接运行jar包即可
2.通过war包启动,pom.xml里加入war,主文件继承SpringBootServletInitializer,重写方法,即可

在这里插入图片描述

SpringBoot流程分析

初始化

  1. 配置启动引导类(判断是否有启动主类)

  2. 判断是否是Web环境

  3. 获取初始化类、监听器类

在这里插入图片描述
run

  1. 启动计时器

  2. 执行监听器

  3. 准备环境

  4. 打印banner:可以resource下粘贴自定义的banner

  5. 创建context

    refreshContext(context);

    执行refreshContext方法后才真正创建Bean

在这里插入图片描述

最后给个banner

1

${AnsiColor.BRIGHT_GREEN}$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$${AnsiColor.BRIGHT_YELLOW}$$                                _.ooOoo._                               $$${AnsiColor.BRIGHT_RED}$$                               o888888888o                              $$${AnsiColor.BRIGHT_CYAN}$$                               88"  .  "88                              $$${AnsiColor.BRIGHT_MAGENTA}$$(|  ^_^|)                              $$${AnsiColor.BRIGHT_GREEN}$$                               O\=   /O                              $$${AnsiColor.BRIGHT_RED}$$                            ____/`-----'\____                           $$${AnsiColor.BRIGHT_CYAN}$$                          .'  \\||$$`.                         $$${AnsiColor.BRIGHT_MAGENTA}$$                         /  \\|||:|||$$  \                        $$${AnsiColor.BRIGHT_GREEN}$$                        /  _|||||  -:-|||||-  \                       $$${AnsiColor.BRIGHT_YELLOW}$$|| \\\   -   $$/||                       $$${AnsiColor.BRIGHT_GREEN}$$| \_|''\-----/''||                       $$${AnsiColor.BRIGHT_YELLOW}$$                        \  .-\___`-`  ____/-. /                       $$${AnsiColor.BRIGHT_CYAN}
  • 作者:Ybb_studyRecord
  • 原文链接:https://blog.csdn.net/m0_46690280/article/details/108567548
    更新时间:2022-07-25 11:57:59