Spring Boot prints a Banner on the console by default when it starts, as shown below. Spring Boot allows us to customize this Banner freely to meet our personalized needs. This article will discuss several issues from a source code perspective.

  1. How to disable the Spring Boot Banner?
  2. How to customize text type Banner.
  3. How to customize image type Banner.

Banner Printing process

As you can see from Spring Boot’s Run method, the printBanner method comes after prepareEnvironment, because application.properties has some configuration items for the Banner. You need to parse the value of application.properties and bind it to the corresponding bean before you can proceed.

public ConfigurableApplicationContext run(String... args) {...try {
  ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
		ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
		configureIgnoreBeanInfo(environment);
  / / print the BannerBanner printedBanner = printBanner(environment); . }... }Copy the code

The specific process is as follows:

  1. Check the bannerMode. If it is OFF, it does not print. If it is LOG, it is printed to a file, otherwise it is printed to the console.
  2. Determine whether the Banner type is text or image based on whether there is a file at the specified location. The text type is ResourceBanner, and the image type is ImageBanner. If neither of the two types is used, the default Spring Bootbanner is used.
  3. Call the printBanner method of the Banner object. Different types of banners have different printBanner methods.

As can be seen, Spring Boot first obtains ImageBanner and then ResourceBanner. It should be noted that both of them can exist at the same time, and both of them will be printed at one time. If they are not satisfied, we will also get fallbackBanner, which is the bottom pocket Banner set by the user, but we rarely use it, because SpringBoot has a built-in bottom pocket scheme, namely Spring bootbanner.

private Banner getBanner(Environment environment) {
	Banners banners = new Banners();
	banners.addIfNotNull(getImageBanner(environment));
	banners.addIfNotNull(getTextBanner(environment));
	if (banners.hasAtLeastOneBanner()) {
		return banners;
	}
	if (this.fallbackBanner ! =null) {
		return this.fallbackBanner;
	}
	return DEFAULT_BANNER;
}
Copy the code

How do I disable the Spring Boot Banner

You can see this in the printBanner method. This method returns NULL when we set bannerMode to banner.mode. OFF. That is, the Banner will not be printed. Therefore, setting the bannerMode is the key to turning off the Banner function.

private Banner printBanner(ConfigurableEnvironment environment) {
  if (this.bannerMode == Banner.Mode.OFF) {
    return null; }... }Copy the code

BannerMode is a member variable of the SpringApplication. Spring Boot provides two options for setting bannerMode.

The first is set in the startup code. As shown below.

public static void main(String[] args) {
	SpringApplication app
			= new SpringApplication(XiangApplication.class);
	app.setBannerMode(Banner.Mode.OFF);
	app.run(args);
}
Copy the code

The second is to configure spring.main.banner-mode in application.properties

spring.main.banner-mode=off
Copy the code

Both methods can be used to turn off the Banner. Which one takes effect when they both exist? The SpringApplication object executes the Run method after calling setBannerMode in the startup code, changing the value of bannerMode, The value of application.properties is parsed in the run method and bound to the corresponding bean, which overrides the former, so the configuration in application.properties takes precedence.

In addition to setting off, bannerMode can also be set to off and log, which comes from banner.mode. Mode is an enumeration value, OFF means OFF, LOG means to print to a file, and CONSOLE means to print to the current CONSOLE using system. out. This article does not discuss the LOG mode, only the CONSOLE mode.

enum Mode {
	OFF,
	CONSOLE,
	LOG
}
Copy the code

Custom text type Banner

It is easy to customize the text type of Banner in Spring Boot. We just need to add a Banner. TXT under Resources. Let’s say I want my Banner to say ShenMAX. I can then add the following text to banner.txt.

_______. ____ _____ _____ _____ _____ _____ / | | __ ____ ____ / / / _ \ \ \ / / \ \ | _____ | \ _ / __ \ \ / \ \ / / / _ \ \ \ /  / \| Y \ ___/| | \ / Y \/ | \/ \ /_______ /|___| /\___ >___| / \____|__ /\____|__ /___/\ \ \/ \/ \/ \/ \/ \/ \_/Copy the code

Of course, if we have to edit this string of text ourselves, obviously too much trouble, we can use some tools to do this, such as patorjk.com/software/ta… Support for converting various texts to text graphs. www.degraeve.com/img2txt.php support convert all kinds of pictures to text.

Placeholders can be added to this text, which will be replaced before printing. For example, if we want to print the current version, we can add the following code.

Spring Boot Version: ${spring-boot.version}
Copy the code

In addition to some placeholders that come with the system, we can also use environment variables configured in application.properties as placeholders. For example, if app.placeholder=no code,no kill is configured in application.properties, we can use ${app.placeholder} to refer to this statement in banner. TXT.

System.out.println() allows you to control the color of the text, including the background color and whether the text is bold or not. For example, if we want the text output to be red, we can use the following code.

System.out.println("\033[31m" + "The font is red.");
Copy the code

Spring Boot encapsulates this capability as AnsiColor, and we can use AnsiColor to specify the color of subsequent text in banner.txt.

${AnsiColor.BRIGHT_YELLOW}
  _________.__                       _____      _____  ____  ___
 /   _____/|  |__   ____   ____     /     \    /  _  \ \   \/  /
 \_____  \ |  |  \_/ __ \ /    \   /  \ /  \  /  /_\  \ \     /
 /        \|   Y  \  ___/|   |  \ /    Y    \/    |    \/     \
/_______  /|___|  /\___  >___|  / \____|__  /\____|__  /___/\  \
        \/      \/     \/     \/          \/         \/      \_/
${AnsiColor.BLUE}
Spring Boot Version: ${spring-boot.version}
Copy the code

Here is the final result

How does Spring Boot automatically load this resource file? Before printing the default Banner, Spring Boot calls the getTextBanner method to try to read the value of the environment variable spring.banner. Location, If we do not configure this value in application.properties, the default is banner.txt. Load the resource file with resourceLoader, and if loaded, use the loaded resource file as the Banner.

static final String BANNER_LOCATION_PROPERTY = "spring.banner.location";

static final String DEFAULT_BANNER_LOCATION = "banner.txt";

private Banner getTextBanner(Environment environment) {
	String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);
	Resource resource = this.resourceLoader.getResource(location);
	try {
		if(resource.exists() && ! resource.getURL().toExternalForm().contains("liquibase-core")) {
			return newResourceBanner(resource); }}catch (IOException ex) {
		// Ignore
	}
	return null;
}
Copy the code

ResourceBanner Converts the read text stream to a String. Instead of printing the text directly, you replace placeholders in the text.

@Override
public void printBanner(Environment environment, Class
        sourceClass, PrintStream out) {
    try {
        String banner = StreamUtils.copyToString(this.resource.getInputStream(),
            environment.getProperty("spring.banner.charset", Charset.class, StandardCharsets.UTF_8));

        for (PropertyResolver resolver : getPropertyResolvers(environment, sourceClass)) {
          banner = resolver.resolvePlaceholders(banner);
        }
        out.println(banner);
    }
  catch (Exception ex) {
    logger.warn(LogMessage.format("Banner not printable: %s (%s: '%s')".this.resource, ex.getClass(), ex.getMessage()), ex); }}Copy the code

To resolve placeholders in the Banner, four parsers are used, environment corresponding to the configuration in application.properties; VersionResolver resolves the Spring Boot version, AnsiResolver resolves style configurations such as colors or fonts, and TitleResolver resolves the current application version, name, and so on.

protected List<PropertyResolver> getPropertyResolvers(Environment environment, Class
        sourceClass) {
    List<PropertyResolver> resolvers = new ArrayList<>();
    resolvers.add(environment);
    resolvers.add(getVersionResolver(sourceClass));
    resolvers.add(getAnsiResolver());
    resolvers.add(getTitleResolver(sourceClass));
    return resolvers;
}
Copy the code

Custom image type Banner

Spring Boot support direct configuration a picture as a Banner, Banner and text type configuration is the same, choose a picture (suffix is JPG | PNG | GIF). Change the name to banner, put it in the resource directory, and you’re done.

I found a picture of the cloud disk, and the effect after transformation is as shown in the picture below.

The original:

Print:

For an image Banner, Spring Boot installs it in printable text format and prints it out. So we can kind of look at the logic of this.

Resource for the image of style and way of resource loading text is consistent, first of all determine whether a spring configuration. Banner. Image. The location variables, default is resources directory. In that directory in order to find the banner GIF, banner. JPG, banner. PNG. You only need to find one to count as an image Banner.

static final String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";

static final String[] IMAGE_EXTENSION = { "gif"."jpg"."png" };
private Banner getImageBanner(Environment environment) {
	String location = environment.getProperty(BANNER_IMAGE_LOCATION_PROPERTY);
	if (StringUtils.hasLength(location)) {
		Resource resource = this.resourceLoader.getResource(location);
		return resource.exists() ? new ImageBanner(resource) : null;
	}
	for (String ext : IMAGE_EXTENSION) {
		Resource resource = this.resourceLoader.getResource("banner." + ext);
		if (resource.exists()) {
			return newImageBanner(resource); }}return null;
}
Copy the code

The printing process of picture type Banner is rather tedious. The idea is as follows: the program will compress the original image first according to the length and width information configured by us, and then traverse every pixel of the original image, parse the color of the point, and find the printable color closest to the color of the point (AnsiColor). Here involves more configuration, such as spring. The banner. Image. Image width, width configuration. Spring. The banner image. Bitdepth ANSI colour bit depth. Supported values are 4 (16 colors) or 8 (256 colors).

private void printBanner(Environment environment, PrintStream out) throws IOException {
    int width = getProperty(environment, "width", Integer.class, 76);
    int height = getProperty(environment, "height", Integer.class, 0);
    int margin = getProperty(environment, "margin", Integer.class, 2);
    boolean invert = getProperty(environment, "invert", Boolean.class, false);
    BitDepth bitDepth = getBitDepthProperty(environment);
    PixelMode pixelMode = getPixelModeProperty(environment);
    Frame[] frames = readFrames(width, height);
    for (int i = 0; i < frames.length; i++) {
    	if (i > 0) {
    		resetCursor(frames[i - 1].getImage(), out); } printBanner(frames[i].getImage(), margin, invert, bitDepth, pixelMode, out); sleep(frames[i].getDelayTime()); }}Copy the code

If you want a better display of pictures, these configurations must be adjusted. The default configuration can only output some simple pictures, and the display effect of complex pictures is very poor, which is one of the reasons WHY I do not recommend using pictures as banners.

Since the process of converting images to characters needs to go through image compression, traversing pixels and other operations, it will slow down the startup speed when printing large images, which is not worth the loss. In addition, we can’t use placeholders to output configuration information in the image. If we just want to look good, we can turn the image into text in advance. There is no need for Spring Boot to do this work.

Another interesting point is that Spring Boot supports setting GIF to Banner. Originally thought to be a black technology, the result is to separate GIF into a picture, and then output in order, but for a long time or simple image output, the function is a bit weak.

The last

Spring Boot has a lot of interesting details, and Banner is one of them. When we look at the Banner printing logic, we should not only know how to customize a text Banner or picture Banner, how to configure a custom Banner, but also to understand some of the underlying implementation principles. For example, system.out.println () can output colored text, which is also the secret of Spring Boot Boot log with color. For example, while learning about picture Banner, take a look at how Java implements picture to text. Function points and knowledge points, need to pay equal attention to, this is the correct way to read the source code.

If you think you’ve learned something, please give it a thumbs up!