SpringBoot高级
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中用法:
- 导入Bean
- 导入配置类
- 导入ImportSelector的实现类。
- 导入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流程分析
初始化
配置启动引导类(判断是否有启动主类)
判断是否是Web环境
获取初始化类、监听器类
run
启动计时器
执行监听器
准备环境
打印banner:可以resource下粘贴自定义的banner
创建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}