[SpringBoot] | Spring Boot overview and entry program analysis

Table of contents

One: Getting Started with Spring Boot

1. SpringBoot features

2. Create a Spring Boot project

3. SpringBoot core configuration file

4. Use JSP in SpringBoot (understand)

5. Using ApplicationContext in SpringBoot

6. CommandLineRunner interface & ApplicationRunner interface

Book recommendation: Collect all the "Four Great Masterpieces of Java" Summon the Dragon


One: Getting Started with Spring Boot

SpringBoot is a member of the Spring family, which can simplify the use of Spring and SpringMVC. Its core is still an IOC container!

1. SpringBoot features

The features are as follows:

①Create stand-alone Spring applications.

Explanation: Create a stand-alone spring application (using SpringBoot is actually using spring).

②Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files).

Explanation: Embed Tomcat, Jetty or Undertow server (no need to deploy WAR file).

③Provide opinionated 'starter' dependencies to simplify your build configuration.

Explanation: The starter dependency is provided to simplify the configuration of the application. For example: to use the MyBatis framework, you need to configure the MyBatis object SqlSessionFactory, Dao proxy object, etc. in the Spring project; now in the SpringBoot project, in the pom.xml, you only need to add a mybatis-spring-boot-starter dependency, then Indicates that the above two configurations have been configured.

④Automatically configure Spring and 3rd party libraries whenever possible.

Explanation: Automatically configure Spring and third-party libraries as much as possible. (It is to create objects in spring and third-party libraries in advance, put them in the container, and use them directly).

⑤Provide production-ready features such as metrics, health checks, and externalized configuration

Explanation: Provides production-ready features such as metrics, health checks, and externalized configuration.

⑥Absolutely no code generation and no requirement for XML configuration

Explanation: No need to generate code, no need to use xml for configuration.

2. Create a Spring Boot project

The first way: https://start.spring.io , using a foreign address, must be connected to the Internet

①New project

 ②Set basic information

③Select the dependent list

④ Project structure

⑤Generated pom.xml configuration

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--SpringBoot项目的父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.3</version>
        <relativePath/>
    </parent>
    <!--当前项目的gav坐标-->
    <groupId>com.zl</groupId>
    <artifactId>study-springboot-002</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>study-springboot-002</name>
    <description>study-springboot-002</description>
    <!--JDK的版本-->
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--web依赖,版本号就是父的版本号-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!--maven的插件-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

The second way: https://start.springboot.io , using a foreign address, must be connected to the Internet, and the steps to create a project are the same as above

① For other versions of the higher version of IDEA is the following interface

②You can also directly enter https://start.springboot.io on the browser  to set

③After selection, click GENERATE, and a compressed package will be downloaded

④ Unzip this compressed package, you can import the project into it

The third way: use the maven wizard to create a project

①Create an ordinary Maven project

②Manually add parent gav and web dependencies

<?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.zl</groupId>
    <artifactId>study-springboot-004</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <!--手动添加SpringBoot项目的父项目-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.3</version>
        <relativePath/>
    </parent>
    <!--手动添加依赖-->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>

③Manually add the directory where the project is missing

Getting Started Case:

Step 1: Create a SpringBoot web engineering project

Step 2: Create a Controller and make a request

Note: When using the springmvc framework, you need to use the spring framework-specific annotations @ResponseBody or @RestController annotations when processing json . These two annotations will handle the returned data format. After using this type of annotation, the return will no longer It is a view, it will not jump, but returns json or xml data format, and the output is on the page.

① @ResponseBody is generally used in a separate method, whichever method needs to return the json data format, it is used in that method, which is targeted.

②@RestController is generally used on classes. It means that it combines @Controller and @ResponseBody annotations. If all methods under a class need to return json data format, use it on that class The annotation is unified; it should be noted that after using the @RestController annotation, its essence is equivalent to uniformly using the @ResponseBody annotation on all methods of this class, so all methods under this class will return json data format, The output is on the page without ever returning to the view.

package com.zl.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller // 类要想当做controller使用,就添加这个注解
public class HelloSpringBoot {
    @RequestMapping("/hello")
    @ResponseBody // 把返回的String字符串当做数据来用,返回给浏览器
    public String helloSpringBoot(){
        return "欢迎使用SpringBoot!";
    }
}

Step 3: Start the entry class, which is automatically generated

Note: The execution of this class will start the built-in Tomcat server!

package com.zl;

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

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

Step Four: Make a Visit

Several important annotations in SpringBoot

①@SpringBootApplication annotation: @SpringBootApplication annotation is actually a composite annotation, which iscomposed of @SpringBootConfiguration annotation , @EnableAutoConfiguration annotation , and @ComponentScan ; it can be seen from the source code:

②@SpringBootConfiguration annotation:  This annotation is the function of the @Configuration annotation. The class using the @SpringBootConfiguration annotation is used as a configuration file , as can be seen from the source code:

Note: Since there is a @Configuration function, combined with the @Bean annotation, an object can be placed in the Spring container 

package com.zl;

import com.zl.controller.Student;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    // 声明对象,把这个对象注入到Spring容器当中
    @Bean
    public Student myStudent(){
        return new Student();
    }

}

③@EnableAutoConfiguration annotation: Enable automatic configuration, configure the java object, and inject it into the spring container. For example: the object of mybatis can be created and put into the container

④@ComponentScan annotation: component scanner, scanning annotations , creating java beans, assigning values ​​to attributes, etc. according to the functions of annotations. The package scanned by the component scanner by default is the class where the @ComponentScan annotation is located, the package and sub-package where the class is located. So it is recommended to put the entry class Application with @SpringBootApplication annotation under the main package!

3. SpringBoot core configuration file

The name of the configuration file is: application , and the extensions are: properties, yml ; for example: application.properties or application.yml.

Note: The configuration using the properties extension is in the format of key=value , and the configuration using the yml extension is in the format of key:value

Step 1: Create a controller

package com.zl.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SpringController {
    @RequestMapping("/spring")
    @ResponseBody
    public String doSome(){
        return "hello SpringBoot";
    }
}

Step 2: Create a startup class. For the startup class, we can delete the automatically generated ones and write one by ourselves.

①The class name is arbitrary, and there is a main method in it. In the main method, the run method of SpringApplication is called . One parameter is this class.class , and the other parameter is the parameter args of the main method above .

②Add the @SpringBootApplication annotation to this class.

package com.zl;

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

@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class,args);
    }
}

Step 3: Use the application.properties/yml configuration file to configure the port number, context path, etc.

① Use the default

② Configure application.properties by yourself, # stands for comments

#设置端口号
server.port=8082
#设置访问应用上下文路径,contextpath
server.servlet.context-path=/myboot

 ③ Use the configuration method of yml, application.yml

yml is a configuration file in yaml format, which mainly uses certain spaces, line breaks and other formats for configuration. yaml is an intuitive data serialization format that can be recognized by computers and is easy to be read by humans. yaml is similar to xml, but its syntax is much simpler than xml. There must be a space between the value and the preceding colon configuration item, and the yml suffix is ​​also A yaml suffix can be used.

server:
  port: 8082
  servlet:
    context-path: /myboot

Note: When two formats of configuration files exist at the same time, properties is used by default . Starting from SpringBoot2.4, yml configuration files are used. It is recommended to use yml format configuration files .

【Multi-environment test】

In the actual development process, our project will go through many stages (development->test->online), and the configuration of each stage will be different, such as: port, context root, database, etc., so this time for convenience in To switch between different environments, SpringBoot provides multi-environment configuration, the specific steps are as follows:

Note: Create a configuration file for each environment, and the name must be identified by application-environment.properties or yml

Development environment application-dev.properties:

#配置端口号
server.port=8081
#配置应用根路径
server.servlet.context-path=/mydev

Test environment application-test.properties:

#配置端口号
server.port=8082
#配置应用根路径
server.servlet.context-path=/mytest

Online environment application-onlion.properties:

#配置端口号
server.port=8083
#配置应用根路径
server.servlet.context-path=/myonlion

Specify the configuration file to use in application.properties

#激活使用哪个配置文件
spring.profiles.active=dev
spring.profiles.active=test
spring.profiles.active=onlion

[custom configuration]

(1) @Value annotation

Note: Add custom configuration items in application.properties, and then use the @Value(${variable name}) annotation to introduce them when needed in the class.

application.properties configuration

#配置端口号
server.port=8082
#context-path
server.servlet.context-path=/myboot

#自定义key=value
school.name=大连大学
school.website=www.baidu.com
school.address=辽宁省大连市

site=www.sina.com.cn

Combine @Value annotation in controller to get data

package com.zl.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class DataController {

    // 定义变量接收赋值
    @Value("${server.port}")
    private Integer port;
    @Value("${server.servlet.context-path}")
    private String contextPath;
    // 自定义的
    @Value("${school.name}")
    private String name;
    @Value("${site}")
    private String site;


    @RequestMapping("/data")
    @ResponseBody
    public String queryData(){
        return name+","+site+",项目访问的地址"+contextPath+",使用的端口"+port;
    }
}

Results of the:

(2) @ConfigurationProperties annotation

We took out the values ​​one by one before, now we map the entire file into a Java object, which is used when there are many custom configuration items! 

Working principle: define a class using @ConfigurationProperties annotation, and specify the prefix prefix, it will find the properties starting with this prefix in the configuration according to this prefix; if the following properties starting with this prefix are the same as the properties of the Java object we defined Just assign value!

Define a School class

Key point: How do the data in the configuration file correspond to the attributes in the School class?

Use the @ConfigurationProperties annotation to specify a prefix!

package com.zl.vo;


import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component // 创建对象
@ConfigurationProperties(prefix = "school") // 把school开头的配置项找出来
public class School {
    private String name;
    private String website;
    private String address;

    public School() {
    }
    public School(String name, String website, String address) {
        this.name = name;
        this.website = website;
        this.address = address;
    }

    @Override
    public String toString() {
        return "School{" +
                "name='" + name + '\'' +
                ", website='" + website + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

carry out testing:

package com.zl.controller;

import com.zl.vo.School;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;

@Controller
public class DataController {

    @Resource // 赋值
    private School school;

    @RequestMapping("/school")
    @ResponseBody
    public School querySchool(){
        return school;
    }
}

Results of the:

In fact, there is an error message, let us add a dependency, of course, do not add or affect the normal operation of the project

 Add the following dependencies

<!--处理ConfigurationProperties注解有关的元数据-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

4. Use JSP in SpringBoot (understand)

SpringBoot does not recommend using jsp, but uses template technology instead of jsp, and uses it as a view!

Using jsp requires configuration:

①Add a dependency for processing jsp, which is responsible for compiling jsp files

<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>

② If you need to use servlet, jsp, jstl functions, you need to add corresponding dependencies

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
</dependency>

<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>javax.servlet-api</artifactId>
</dependency>

<dependency>
<groupId>javax.servlet.jsp</groupId>
	<artifactId>javax.servlet.jsp-api</artifactId>
	<version>2.3.1</version>
</dependency>

③Create a directory to store jsp, generally called webapp, this directory cannot create jsp files by default, we need to manually change the properties of the webapp directory

Write index.jsp page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>index.jsp</title>
</head>
<body>
<h1>使用jsp显示Controller中的数据${data}</h1>
</body>
</html>

④ It is necessary to specify the storage directory of the compiled jsp file in pom.xml; META-INF/resources (fixed)

    <build>
        <!--指定jsp编译后的存放目录-->
        <resources>
            <resource>
                <!--jsp原来的目录-->
                <directory>src/main/webapp</directory>
                <!--指定编译后的存放目录-->
                <targetPath>META-INF/resources</targetPath>
                <!--指定处理的目录和文件-->
                <includes>
                    <!--表示webapp下任意目录的任意文件-->
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

⑤Create Controller, access jsp

package com.zl.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;


@Controller
public class JspController {
    // 方法一:使用HttpServletRequest对象
    /*public String doJsp(HttpServletRequest request){
        request.setAttribute("data","SpringBoot使用JSP进行显示");
        // 返回视图的逻辑名称
        return  "index";
    }*/
    // 方法二:使用Model对象
    @RequestMapping("/myjsp")
    public String doJsp(Model model){
        model.addAttribute("data","SpringBoot使用JSP进行显示");
        // 返回视图的逻辑名称
        return  "index";
    }
}

⑥ Configure the view resolver in the application.propertis file

#配置端口号
server.port=9090
#配置context-path
server.servlet.context-path=/myboot
#配置视图解析器
# / 就是src/main/webapp
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp

5. Using ApplicationContext in SpringBoot

How to use the container object? To get the object from the container, get the container through SpringApplication.run(Application.class, args); return value, what is the return value type? Through source code analysis:

First locate the run method of SpringApplication

The return value of the run method is the ConfigurableApplicationContext interface

ConfigurableApplicationContext interface inherits ApplicationContext interface

 So the return value of the run method is actually an ApplicationContext container ( when the ClassPathXmlApplicationContext object is created in the Spring container, the returned result is the ApplicationContext [is the parent class of ClassPathXmlApplicationContext], and then the getBean method can be called to obtain the object ) !

Case: Use the SpringApplication.run() method in the main method to get the returned Spring container object, and then get the business bean to call!

Create a UserService interface:

package com.zl.service;

public interface UserService {
    void sayHello(String name);
}

Write the implementation class of the UserService interface:

package com.zl.service.impl;

import com.zl.service.UserService;
import org.springframework.stereotype.Service;

@Service("userService") // 交给Spring容器管理
public class UserServiceImpl implements UserService {
    @Override
    public void sayHello(String name) {
        System.out.println("对"+name+"说sayHello");
    }
}

Take out the UserServiceImpl class managed by the Spring container in the entry method:

package com.zl;

import com.zl.service.UserService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        // 返回一个ConfigurableApplicationContext接口容器或者父接口的
        // ConfigurableApplicationContext cac = SpringApplication.run(Application.class, args);
        ApplicationContext cac = SpringApplication.run(Application.class, args);
        // 调用getBean方法,获取交给Spring容器管理的对象
        UserService userService = cac.getBean("userService", UserService.class);
        // 方法的调用
        userService.sayHello("张三");
    }
}

Results of the:

6. CommandLineRunner interface & ApplicationRunner interface

(1) There may be such a situation in development: some content needs to be executed after the container is started; for example: reading configuration files, database connections, etc.; SpringBoot provides us with two interfaces to help us realize this requirement, These two interfaces are CommandLineRunner and ApplicationRunner respectively , and their execution timing is when the container is started (after the container object is created, the run method is automatically executed) .

(2) There is a run() method in these two interfaces , we only need to implement this method .

(3) The difference between these two interfaces is: the parameter of the run() method in ApplicationRunner is ApplicationArguments , while the parameter of the run method in the CommandLineRunner interface is a String array .

ApplicationRunner interface

package org.springframework.boot;

@FunctionalInterface
public interface ApplicationRunner {
    void run(ApplicationArguments args) throws Exception;
}

CommandLineRunner interface

package org.springframework.boot;

@FunctionalInterface
public interface CommandLineRunner {
    void run(String... args) throws Exception;
}

case:

Write SomeService interface

package com.zl.service;

public interface SomeService {
    String doSome(String name);
}

Write the implementation class SomeServiceImpl of the SomeService interface 

package com.zl.service.impl;

import com.zl.service.SomeService;
import org.springframework.stereotype.Service;

@Service("someService") // 交给Spring容器管理
public class SomeServiceImpl implements SomeService {
    @Override
    public String doSome(String name) {
        return  name+"----》去打篮球了!";
    }
}

Let the startup class Application implement the CommandLineRunner interface, and rewrite the run() method

package com.zl;

import com.zl.service.SomeService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Resource // 下面容器创建好以后就会给属性赋值
    private SomeService someService;

    public static void main(String[] args) {
        System.out.println("准备创建容器对象"); // 1

        // 创建容器对象
        SpringApplication.run(Application.class, args);

        System.out.println("容器对象创建好之后"); // 3
    }

    @Override
    public void run(String... args) throws Exception {
        // 在这个run方法里做自定义的操作
        System.out.println("容器对象创建好,马上执行的!"); // 2

        // 调用容器中对象的方法
        // 在这里执行,已经保证1的容器对象创建好了
        String str = someService.doSome("张大傻");
        System.out.println(str);
    }
}

Execution sequence results:

Book recommendation: Collect all the "Four Great Masterpieces of Java" Summon the Dragon

Java is 28 years old, and it will be played for many years. For you who are about to or are using Java, I recommend the Java "It's a pity if you miss it in this life" series of books. See which one you still lack? Please complete. The discount book link is in the article, take it and thank you!

1. Java Core Technology 12th Edition Development Basics + Advanced Features

The latest edition of Core Java, one of the " Four Great Masterpieces of Java ", packs a full set of 2 volumes with one click! It is recommended for beginners and developers who plan to upgrade to Java17 to purchase. This book is fully upgraded according to the new features of Java17! Give the author personally taught video lessons + massive code sets.

Time-limited flash kill link: click to buy

2. Java core technology 11th edition basic knowledge + advanced features

One of the " Four Great Masterpieces of Java " , the newest edition of Core Java, packs a full set of 2 volumes with one click! It is recommended that developers whose actual production environment is still using Java8 and Java11 to develop and have no plans to upgrade the version to purchase. This book is written based on Java9-11, and the author gives video lessons + massive code sets as a gift.

Time-limited flash kill link: click to buy

3. Java programming thought [Thinking in Java]

One of the " Four Great Masterpieces of Java " , people with a certain programming foundation are required to read it. Even if a lot of content is still incomprehensible, it will definitely gain something after reading it every time. The "Java Core Technology" recommended at the top of the book list focuses on technology, while "Java Programming Thoughts" focuses on "ideas". This book analyzes the design concepts of various contents in Java for you. This is a good book that accompanies our technological growth. Buy one and put it next to it, and you will feel confident when you touch it.

Time-limited flash kill link: click to buy

4. Effective Java Chinese Edition (the third edition of the original book)

 One of the " Four Great Masterpieces of Java " , it is suitable for programmers who have mastered the core technology of Java and developers who want to have a deeper understanding of the Java programming language. Provides the most practical and authoritative guidelines on how to write efficient and well-designed programs, explores new design patterns and language idioms through 90 short, independent rules of thumb, and helps you use the Java programming language and Its basic class library guides you to avoid detours. These rules of thumb cover solutions to problems that most developers face every day. It is an indispensable reference book on the desk of Java developers.

Time-limited flash kill link: click to buy

5. Java Language Programming Basics + Advanced

This set of books is more basic than " Java Core Technology". If you are struggling to read " Java Core Technology", it is recommended to start from this book. The "Book of the Great Wall", which has been best-selling for more than 20 years, is packed with one click! Selected as a textbook by universities around the world, updated to Java9, 10 and 11. This book explains problem-solving skills through examples, provides a large number of program lists, and each chapter is equipped with rich review questions and programming exercises to help readers master programming techniques and solve problems encountered in actual development.

Time-limited flash kill link: click to buy

6. Java concurrent programming practice

Let you who focus on actual combat quickly understand the essentials of Java concurrent programming, and quickly build large-scale concurrent applications. Joshua Bloch, the author of "Effective Java", one of the "Four Great Masterpieces of Java", participated in the writing . This book is a milestone work in the field of Java concurrent programming! Starting with the basic theory of concurrent programming, it gradually introduces various important design principles, design patterns and thinking patterns when designing Java concurrent programs. Another book "The Art of Java Concurrent Programming" written by Mr. Fang Tengfei of Ant Financial is also suitable for reading together.

Time-limited flash kill link: click to buy

7.  Software Architecture Practice

A guide for advanced architects to avoid detours! Book Oscar Jolt Awards Double Crown Works! Published in more than 10 countries around the world. Carnegie Mellon and other famous school textbooks, top 10 books in IEEE magazine, de facto standards for software architecture books.

 

Time-limited flash kill link: click to buy

All the above books are sold in seconds on Dangdang.com, and the more you buy, the more discounts you will get! For more good books, click: Core Java Fully Upgraded!

Guess you like

Origin blog.csdn.net/m0_61933976/article/details/129307706