首页 > 其他分享 >第四章 SpringBoot 底层机制

第四章 SpringBoot 底层机制

时间:2022-10-30 12:12:41浏览次数:50  
标签:java SpringBoot tomcat lzw context com public 第四章 底层

搭建 SpringBoot 底层机制开发环境

1、创建 Maven 项目 lzw-springboot

2、导入相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lzw</groupId>
    <artifactId>lzw-springboot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--导入springboot父工程-规定写法-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.5.3</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

</project>

创建 src/main/java/com/lzw/springboot/MainApp.java

package com.lzw.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author LiAng
 */
@SpringBootApplication
public class MainApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args);

    }
}

启动项目

@Configuration + @Bean 会发生什么

创建 src/main/java/com/lzw/springboot/bean/Dog.java

package com.lzw.springboot.bean;

/**
 * @author LiAng
 */
public class Dog {
}

创建 src/main/java/com/lzw/springboot/config/Config.java

package com.lzw.springboot.config;

import com.lzw.springboot.bean.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author LiAng
 * @Configuration :标识一个配置类, 充当Spring配置文件/容器
 * 该配置类,如果在springboot扫描的包/子包下,会被注入到Spring容器
 * 在该类中,可以通过@Bean 来注入其它的组件
 */
@Configuration
public class Config {

    /**
     * 1. 通过@Bean的方式, 将new出来的Bean对象, 放入到Spring容器
     * 2. 该bean在Spring容器的name/id 默认就是 方法名
     * 3. 通过方法名, 可以得到注入到spring容器中的dog对象
     */
    @Bean
    public Dog dog() {
        return new Dog();
    }
}

image-20220728105054888

底层机制分析:实现 Spring 容器那一套机制 IO/文件扫描+注解+反射+集合+映射

SpringBoot 是怎么启动 Tomcat的,并可以支持访问@Controller

创建 src/main/java/com/lzw/springboot/controller/HiController.java

package com.lzw.springboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author LiAng
 * 因为
 * 1. HiController 被 @RestController标注,就是一个控制器
 * 2. HiController 在扫描包/子包, 会被注入spring容器
 */
@RestController
public class HiController {
    @RequestMapping("/hi")
    public String hi(){
        return "hi lzw HiController";
    }
}

浏览器访问

SpringBoot 是怎么内嵌 Tomcat,并启动 Tomcat 的?

源码分析

Debug SpringApplication.run(MainApp.class, args) 看看 SpringBoot 是如何启动 Tomcat 的。

package com.lzw.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author LiAng
 */
@SpringBootApplication
public class MainApp {
    public static void main(String[] args) {
        ConfigurableApplicationContext ioc = SpringApplication.run(MainApp.class, args);

        /**
         *  这里我们开始Debug SpringApplication.run()
         *  1. SpringApplication.java
         *  public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
         * 		return run(new Class<?>[] { primarySource }, args);
         *   }
         *
         *  2.SpringApplication.java : 创建返回 ConfigurableApplicationContext对象
         *  public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
         * 		return new SpringApplication(primarySources).run(args);
         *        }
         *
         *  3. SpringApplication.java
         *
         *  public ConfigurableApplicationContext run(String... args) {
         * 		StopWatch stopWatch = new StopWatch();
         * 		stopWatch.start();
         * 		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
         * 		ConfigurableApplicationContext context = null;
         * 		configureHeadlessProperty();
         * 		SpringApplicationRunListeners listeners = getRunListeners(args);
         * 		listeners.starting(bootstrapContext, this.mainApplicationClass);
         * 		try {
         * 			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
         * 			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
         * 			configureIgnoreBeanInfo(environment);
         * 			Banner printedBanner = printBanner(environment);
         * 			context = createApplicationContext(); //严重分析: 创建容器
         * 			context.setApplicationStartup(this.applicationStartup);
         * 			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
         * 			refreshContext(context); //严重分析: 刷新应用程序上下文,比如 初始化默认设置/注入相关Bean/启动tomcat
         * 			afterRefresh(context, applicationArguments);
         * 			stopWatch.stop();
         * 			if (this.logStartupInfo) {
         * 				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
         *                        }
         * 			listeners.started(context);
         * 			callRunners(context, applicationArguments);* 		}
         * 		catch (Throwable ex) {
         * 			handleRunFailure(context, ex, listeners);
         * 			throw new IllegalStateException(ex);
         * 		}
         *
         * 		try {
         * 			listeners.running(context);
         * 		}
         * 		catch (Throwable ex) {
         * 			handleRunFailure(context, ex, null);
         * 			throw new IllegalStateException(ex);
         * 		}
         * 		return context;
         * 	}
         *
         * 	4. SpringApplication.java : 容器类型很多,会根据你的this.webApplicationType创建对应的容器
         * 	默认 this.webApplicationType 是 SERVLET 也就是web容器/可以处理servlet
         * 	protected ConfigurableApplicationContext createApplicationContext() {
         * 		return this.applicationContextFactory.create(this.webApplicationType);
         *        }
         *
         *  5. ApplicationContextFactory.java
         *
         *  ApplicationContextFactory DEFAULT = (webApplicationType) -> {
         * 		try {
         * 			switch (webApplicationType) {
         * 			case SERVLET://默认是进入到这个分支 ,返回AnnotationConfigServletWebServerApplicationContext容器
         * 				return new AnnotationConfigServletWebServerApplicationContext();
         * 			case REACTIVE:
         * 				return new AnnotationConfigReactiveWebServerApplicationContext();
         * 			default:
         * 				return new AnnotationConfigApplicationContext();
         *                        }* 		}
         * 		catch (Exception ex) {
         * 			throw new IllegalStateException("Unable create a default ApplicationContext instance, "
         * 					+ "you may need a custom ApplicationContextFactory", ex);
         * 		}
         * 	};
         *
         * 	6. SpringApplication.java
         * 	private void refreshContext(ConfigurableApplicationContext context) {
         * 		if (this.registerShutdownHook) {
         * 			shutdownHook.registerApplicationContext(context);
         *                }
         * 		refresh(context); //严重分析,真正执行相关任务
         *  }
         *
         *  7. SpringApplication.java
         *  protected void refresh(ConfigurableApplicationContext applicationContext) {
         * 		applicationContext.refresh();
         *    }
         *
         *
         *  8. ServletWebServerApplicationContext.java
         *  @Override
         *        public final void refresh() throws BeansException, IllegalStateException {
         * 		try {
         * 			super.refresh();//分析这个方法
         *        }
         * 		catch (RuntimeException ex) {
         * 			WebServer webServer = this.webServer;
         * 			if (webServer != null) {
         * 				webServer.stop();
         *            }
         * 			throw ex;
         *        }
         *    }
         *
         * 9. AbstractApplicationContext.java
         *
         * @Override
         *        public void refresh() throws BeansException, IllegalStateException {
         * 		synchronized (this.startupShutdownMonitor) {
         * 			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
         *
         * 			// Prepare this context for refreshing.
         * 			prepareRefresh();
         *
         * 			// Tell the subclass to refresh the internal bean factory.
         * 			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
         *
         * 			// Prepare the bean factory for use in this context.
         * 			prepareBeanFactory(beanFactory);
         *
         * 			try {
         * 				// Allows post-processing of the bean factory in context subclasses.
         * 				postProcessBeanFactory(beanFactory);
         *
         * 				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
         * 				// Invoke factory processors registered as beans in the context.
         * 				invokeBeanFactoryPostProcessors(beanFactory);
         *
         * 				// Register bean processors that intercept bean creation.
         * 				registerBeanPostProcessors(beanFactory);
         * 				beanPostProcess.end();
         *
         * 				// Initialize message source for this context.
         * 				initMessageSource();
         *
         * 				// Initialize event multicaster for this context.
         * 				initApplicationEventMulticaster();
         *
         * 				// Initialize other special beans in specific context subclasses.
         * 				onRefresh(); //严重分析,当父类完成通用的工作后,再重新动态绑定机制回到子类
         *
         * 				// Check for listener beans and register them.
         * 				registerListeners();
         *
         * 				// Instantiate all remaining (non-lazy-init) singletons.
         * 				finishBeanFactoryInitialization(beanFactory);
         *
         * 				// Last step: publish corresponding event.
         * 				finishRefresh();
         *            }
         *
         * 			catch (BeansException ex) {
         * 				if (logger.isWarnEnabled()) {
         * 					logger.warn("Exception encountered during context initialization - " +
         * 							"cancelling refresh attempt: " + ex);
         *                }
         *
         * 				// Destroy already created singletons to avoid dangling resources.
         * 				destroyBeans();
         *
         * 				// Reset 'active' flag.
         * 				cancelRefresh(ex);
         *
         * 				// Propagate exception to caller.
         * 				throw ex;
         *            }
         *
         * 			finally {
         * 				// Reset common introspection caches in Spring's core, since we
         * 				// might not ever need metadata for singleton beans anymore...
         * 				resetCommonCaches();
         * 				contextRefresh.end();
         *            }
         *        }
         *    }
         *  10. ServletWebServerApplicationContext.java
         *  @Override
         * 	protected void onRefresh() {
         * 		super.onRefresh();
         * 		try {
         * 			createWebServer();//看到胜利的曙光,创建webserver 可以理解成会创建指定web服务-Tomcat
         *                }
         * 		catch (Throwable ex) {
         * 			throw new ApplicationContextException("Unable to start web server", ex);
         *        }    * 	}
         *   11. ServletWebServerApplicationContext.java
         *
         *   private void createWebServer() {
         * 		WebServer webServer = this.webServer;
         * 		ServletContext servletContext = getServletContext();
         * 		if (webServer == null && servletContext == null) {
         * 			StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
         * 			ServletWebServerFactory factory = getWebServerFactory();
         * 			createWebServer.tag("factory", factory.getClass().toString());
         * 			this.webServer = factory.getWebServer(getSelfInitializer());//严重分析,使用TomcatServletWebServerFactory 创建一个TomcatWebServer
         * 			createWebServer.end();
         * 			getBeanFactory().registerSingleton("webServerGracefulShutdown",
         * 					new WebServerGracefulShutdownLifecycle(this.webServer));
         * 			getBeanFactory().registerSingleton("webServerStartStop",
         * 					new WebServerStartStopLifecycle(this, this.webServer));
         *                }
         * 		else if (servletContext != null) {
         * 			try {
         * 				getSelfInitializer().onStartup(servletContext);
         *            }
         * 			catch (ServletException ex) {
         * 				throw new ApplicationContextException("Cannot initialize servlet context", ex);
         *            }
         *        }
         * 		initPropertySources();    * 	}
         *
         * 	12. TomcatServletWebServerFactory.java 会创建Tomcat 并启动Tomcat
         *
         *        @Override
         *    public WebServer getWebServer(ServletContextInitializer... initializers) {
         * 		if (this.disableMBeanRegistry) {
         * 			Registry.disableRegistry();
         *        }
         * 		Tomcat tomcat = new Tomcat();//创建了Tomcat对象
         * 		File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
         * 	    //做了一系列的设置
         * 		tomcat.setBaseDir(baseDir.getAbsolutePath());
         *
         * 		Connector connector = new Connector(this.protocol);
         * 		connector.setThrowOnFailure(true);
         * 		tomcat.getService().addConnector(connector);
         * 		customizeConnector(connector);
         * 		tomcat.setConnector(connector);
         * 		tomcat.getHost().setAutoDeploy(false);
         * 		configureEngine(tomcat.getEngine());
         * 		for (Connector additionalConnector : this.additionalTomcatConnectors) {
         * 			tomcat.getService().addConnector(additionalConnector);
         *        }
         * 		prepareContext(tomcat.getHost(), initializers);
         * 		return getTomcatWebServer(tomcat); //严重分析该方法.
         *    }
         *
         *    13. TomcatServletWebServerFactory.java , 这里做了校验创建 TomcatWebServer
         *    protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
         * 		return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
         *        }
         *    14. TomcatWebServer.java
         *    public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
         * 		Assert.notNull(tomcat, "Tomcat Server must not be null");
         * 		this.tomcat = tomcat;
         * 		this.autoStart = autoStart;
         * 		this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
         * 		initialize();//分析这个方法.
         *        }
         *    15.TomcatWebServer.java
         *
         *    private void initialize() throws WebServerException {
         * 		logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
         * 		synchronized (this.monitor) {
         * 			try {
         * 				addInstanceIdToEngineName();
         *
         * 				Context context = findContext();
         * 				context.addLifecycleListener((event) -> {
         * 					if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
         * 						// Remove service connectors so that protocol binding doesn't
         * 						// happen when the service is started.
         * 						removeServiceConnectors();
         *                                        }                * 				});
         *
         * 				// Start the server to trigger initialization listeners
         * 				this.tomcat.start(); //启动Tomcat
         *
         * 				// We can re-throw failure exception directly in the main thread
         * 				rethrowDeferredStartupExceptions();
         *
         * 				try {
         * 					ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader());
         *                }
         * 				catch (NamingException ex) {
         * 					// Naming is not enabled. Continue
         *                }
         *
         * 				// Unlike Jetty, all Tomcat threads are daemon threads. We create a
         * 				// blocking non-daemon to stop immediate shutdown
         * 				startDaemonAwaitThread();
         *            }
         * 			catch (Exception ex) {
         * 				stopSilently();
         * 				destroySilently();
         * 				throw new WebServerException("Unable to start embedded Tomcat", ex);
         *            }
         *        }
         *    }
         */
        System.out.println("hello ioc");
    }
}

实现 SpringBoot底层机制

阶段1-创建 Tomcat 并启动

修改pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.lzw</groupId>
    <artifactId>lzw-springboot</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!--导入springboot父工程-规定写法-->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.5.3</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!--因为我们自己要创建Tomcat对象,并启动,
            因此我们先排除 内嵌的 spring-boot-starter-tomcat-->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--
            我们指定tomcat版本,引入tomcat依赖/库
            1. 使用指定的tomcat 8.5.75
            2. 如果我们引入自己指定的tomcat,一定要记住把前面spring-boot-starter-tomcat排除
            3. 如果你不排除,会出现 GenericServlet Not Found错误提示
        -->
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>8.5.75</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-jasper</artifactId>
            <version>8.5.75</version>
        </dependency>
    </dependencies>
</project>

创建 src/main/java/com/lzw/lzwspringboot/LzwSpringApplication.java

package com.lzw.lzwspringboot;

import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;

/**
 * @author LiAng
 */
public class LzwSpringApplication {

    //这里会创建tomcat对象,并关联Spring容器, 并启动
    public static void run(){
        try {
            //创建Tomcat对象
            Tomcat tomcat = new Tomcat();
            //设置9090
            tomcat.setPort(9090);
            //启动
            tomcat.start();
            //等待请求接入
            System.out.println("======9090====等待请求=====");
            tomcat.getServer().await();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

创建 src/main/java/com/lzw/lzwspringboot/LzwMainApp.java

package com.lzw.lzwspringboot;

/**
 * @author LiAng
 * 主程序
 */
public class LzwMainApp {
    public static void main(String[] args) {
        //启动LzwSpringBoot项目/程序
        LzwSpringApplication.run();
    }
}

阶段2-创建Spring容器

创建 src/main/java/com/lzw/lzwspringboot/bean/Monster.java

package com.lzw.lzwspringboot.bean;

/**
 * @author LiAng
 */
public class Monster {
}

创建 src/main/java/com/lzw/lzwspringboot/controller/LzwHiController.java

package com.lzw.lzwspringboot.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author LiAng
 */
@RestController
public class LzwHiController {

    @RequestMapping("/lzwhi")
    public String hi(){
        return "hi,lzw LzwHiController";
    }
}

创建 src/main/java/com/lzw/lzwspringboot/config/LzwConfig.java

package com.lzw.lzwspringboot.config;

import com.lzw.lzwspringboot.bean.Monster;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @author LiAng
 * 配置类-作为Spring的配置文件
 * 容器怎么知道要扫描哪些包呢?
 * 在配置类可以指定要扫描的包  @ComponentScan("com.lzw.lzwspringboot")
 */
@Configuration
@ComponentScan("com.lzw.lzwspringboot")
public class LzwConfig {
    //注入Bean-monster 对象到Spring容器
    @Bean
    public Monster monster(){
        return new Monster();
    }
}

创建 src/main/java/com/lzw/lzwspringboot/LzwWebApplicationInitializer.java

package com.lzw.lzwspringboot;

import com.lzw.lzwspringboot.config.LzwConfig;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

/**
 * @author LiAng
 * 1. 创建我们的Spring 容器
 * 2. 加载/关联Spring容器的配置-按照注解的方式
 * 3. 完成Spring容器配置的bean的创建, 依赖注入
 * 4. 创建前端控制器 DispatcherServlet , 并让其持有Spring容器
 * 5. 当DispatcherServlet 持有容器, 就可以进行分发映射 (SpringMVC底层机制)
 * 6. 这里onStartup 是Tomcat调用, 并把ServletContext 对象传入
 */
public class LzwWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        System.out.println("startup...");
        //加载Spring web application configuration => 容器
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        //在ac中注册 HspConfig.class 配置类
        ac.register(LzwConfig.class);
        ac.refresh();//完成bean的创建和配置

        //1. 创建注册非常重要的前端控制器 DispatcherServlet
        //2. 让DispatcherServlet 持有容器
        //3. 这样就可以进行映射分发, 回忆一下SpringMvc机制[自己实现过]
        DispatcherServlet dispatcherServlet = new DispatcherServlet(ac);
        //返回了ServletRegistration.Dynamic对象
        ServletRegistration.Dynamic registration = servletContext.addServlet("app", dispatcherServlet);
        //当tomcat启动时,加载 dispatcherServlet
        registration.setLoadOnStartup(1);
        //拦截请求,并进行分发处理
        //提示 / 和 /* 的区别 =>  java web 中
        registration.addMapping("/");

    }
}

阶段3-将 Tomcat 和 Spring 容器关联,并启动 Spring 容器

修改 LzwSpringApplication

	public static void run(){
        try {
            //创建Tomcat对象
            Tomcat tomcat = new Tomcat();
            //1. 让tomcat可以将请求转发到spring web容器,因此需要进行关联
            //2. "/lzwboot" 就是我们的项目的 application context , 就是我们原来配置tomcat时,指定的application context
            //3. "D:\Study\VIP\AllDemo\SpringBoot\lzw-springboot" 指定项目的目录
            tomcat.addWebapp("/lzwboot","D:\\Study\\VIP\\AllDemo\\SpringBoot\\lzw-springboot");
            
            //设置9090
            tomcat.setPort(9090);
            //启动
            tomcat.start();
            //等待请求接入
            System.out.println("======9090====等待请求=====");
            tomcat.getServer().await();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

image-20220730090821292

标签:java,SpringBoot,tomcat,lzw,context,com,public,第四章,底层
From: https://www.cnblogs.com/liangnice/p/16840904.html

相关文章

  • Springboot centos7 启动
     1、java-jardemo.jar说明:用这种方法启动后,不能继续执行其它命令了,如果想要继续执行其它命令,就都打断,打断一般用ctrl+c。2、java-jardemo.jar&第2种在第1种方式的基础......
  • SpringBoot3.x原生镜像-Native Image尝鲜
    前提Spring团队致力于为Spring应用程序提供原生映像支持已经有一段时间了。在SpringBoo2.x的SpringNative实验项目中酝酿了3年多之后,随着SpringFramework6和SpringBoo......
  • SpringBoot(三) - Ribbon客户端负载均衡,Zuul网关,Config配置中心
    1、Ribbon客户端负载均衡1.1依赖1.2配置信息#feign默认加载了ribbon负载均衡,默认负载均衡机制是:轮询#负载均衡机制是添加在消费端(客户端)的,如果改为随机,指定服务名......
  • 代码大全第四章
    第四章主要讲的是一些细节问题,比如使用什么编程语言来编程、编程过程中的一些约定等等。编程约束还是很重要的,这方面很重要,尤其是在与人合作的时候。如果编程约束设定的好......
  • springBoot
    入门案例:直接开发控制器的类: 4.运行自带的带有main方法的类  SpringBoot能运行的原因是,在pom里面继承了一个依赖,父类里面有很多依赖,还有一个启动依赖,里......
  • JAVA___HashSet底层原理
    HashCode和equalsHashSet通过hashCode确定元素存储的位置,如果该位置没有元素就直接放入,有元素的话需要利用equals方法比较两个元素是否相同,如果不相同利用链表将两个元素......
  • 十三,SpringBoot-全局异常处理器
     springboot自定义拦截器,需要继承WebMvcConfigurerAdapter并重写addInterceptors。======以下仅为示例,代码沿用上一章=====具体实现如下:①创建MyInterceptor.java文件@Conf......
  • 解决SpringBoot测试提示Failed to resolve org.junit.platform:junit-platform-launch
    解决SpringBoot测试提示Failedtoresolveorg.junit.platform:junit-platform-launcher:1.5.2解决方案:只需要添加:junit-platform-launcher依赖即可<dependency>......
  • Springboot项目启动报错Failed to configure a DataSource: ‘url‘ attribute is not
    ***************************APPLICATIONFAILEDTOSTART***************************Description:FailedtoconfigureaDataSource:'url'attributeisnotspecified......
  • 《程序员修炼之道——从小工到专家》第四章
      “YouCan'tWritePerfectSoftware.”。这是第四章的开篇语,直接了当的告诉了我们,在程序设计中写出一份十全十美的程序是不可能的。一名有时效的程序员连自己都“不......