Microservice file upload practice

Business description

File upload based on Spring Cloud Alibaba solution, such as

Project creation and initialization

engineering structure

Refer to the following engineering structures for project creation, for example:

Create parent project

Create a project parent project to manage project dependencies

Create file service project

Create a project to handle file upload business, for example:

Create client service project

Create a client project in which some static pages are defined, such as file upload page


Parent project initialization

Open the pom.xml file of the parent project and add the following dependencies:

 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.3.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR9</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

File resource service implementation

Add project dependency

Add the following dependencies to the SCA resource project:

       <!--Spring Boot Web (service-built-in tomcat)-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--Nacos Discovery (Service registration discovery)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--Nacos Config (Configuration center)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!--Sentinel (Traffic guard-Current limiting and fusing)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <!--Spring Boot monitor-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
            <scope>provided</scope>
        </dependency>

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

Service initialization configuration

server:
  port: 8881
spring:
  application:
    name: sca-resource
  resources: #Define the path to the uploaded resource
    static-locations: file:d:/uploads  #Static resource path (resources originally stored in the resources/static directory can be stored in this directory)
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
      config:
        server-addr: localhost:8848
jt:
  resource:
      path: d:/uploads  #The root directory where the design upload file is stored (to be written to the configuration file later)
      host: http://localhost:8881 / # define the access server corresponding to the uploaded file

   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Build project startup class

package com.jt;

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

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Controller logic implementation

Define the Controller object that handles the upload request, for example:

package com.jt.resource.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("/resource/")
public class ResourceController {
//When @ Slf4J is added to the class, you don't have to create the following log objects yourself
// private static final Logger log=
// LoggerFactory.getLogger(ResourceController.class);

 <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">"${jt.resource.path}"</span><span class="token punctuation">)</span>
 <span class="token keyword">private</span> <span class="token class-name">String</span> resourcePath<span class="token punctuation">;</span><span class="token comment">//="d:/uploads/";</span>
 <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">"${jt.resource.host}"</span><span class="token punctuation">)</span>
 <span class="token keyword">private</span> <span class="token class-name">String</span> resourceHost<span class="token punctuation">;</span><span class="token comment">//="http://localhost:8881/";</span>

 <span class="token annotation punctuation">@PostMapping</span><span class="token punctuation">(</span><span class="token string">"/upload/"</span><span class="token punctuation">)</span>
 <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">uploadFile</span><span class="token punctuation">(</span><span class="token class-name">MultipartFile</span> uploadFile<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">IOException</span> <span class="token punctuation">{<!-- --></span>
     <span class="token comment">//1. Create file storage directory (create by time - yyyy / mm / DD)</span>
     <span class="token comment">//1.1 get a directory of the current time</span>
     <span class="token class-name">String</span> dateDir <span class="token operator">=</span> <span class="token class-name">DateTimeFormatter</span><span class="token punctuation">.</span><span class="token function">ofPattern</span><span class="token punctuation">(</span><span class="token string">"yyyy/MM/dd"</span><span class="token punctuation">)</span>
             <span class="token punctuation">.</span><span class="token function">format</span><span class="token punctuation">(</span><span class="token class-name">LocalDate</span><span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token comment">//1.2 build directory file object</span>
     <span class="token class-name">File</span> uploadFileDir<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">File</span><span class="token punctuation">(</span>resourcePath<span class="token punctuation">,</span>dateDir<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>uploadFileDir<span class="token punctuation">.</span><span class="token function">exists</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>uploadFileDir<span class="token punctuation">.</span><span class="token function">mkdirs</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token comment">//2. Name the document (try not to repeat it)</span>
     <span class="token comment">//2.1 obtain the suffix of the original document</span>
     <span class="token class-name">String</span> originalFilename<span class="token operator">=</span>uploadFile<span class="token punctuation">.</span><span class="token function">getOriginalFilename</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token class-name">String</span> ext <span class="token operator">=</span> originalFilename<span class="token punctuation">.</span><span class="token function">substring</span><span class="token punctuation">(</span>
             originalFilename<span class="token punctuation">.</span><span class="token function">lastIndexOf</span><span class="token punctuation">(</span><span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token comment">//2.2 build a new file name</span>
     <span class="token class-name">String</span> newFilePrefix<span class="token operator">=</span>UUID<span class="token punctuation">.</span><span class="token function">randomUUID</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token class-name">String</span> newFileName<span class="token operator">=</span>newFilePrefix<span class="token operator">+</span>ext<span class="token punctuation">;</span>
     <span class="token comment">//3. Start file upload</span>
     <span class="token comment">//3.1 build a new file object and point to the final address of the actually uploaded file</span>
     <span class="token class-name">File</span> file<span class="token operator">=</span><span class="token keyword">new</span> <span class="token class-name">File</span><span class="token punctuation">(</span>uploadFileDir<span class="token punctuation">,</span>newFileName<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token comment">//3.2 upload files (write file data to the designated service location)</span>
     uploadFile<span class="token punctuation">.</span><span class="token function">transferTo</span><span class="token punctuation">(</span>file<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token class-name">String</span> fileRealPath<span class="token operator">=</span>resourceHost<span class="token operator">+</span>dateDir<span class="token operator">+</span><span class="token string">"/"</span><span class="token operator">+</span>newFileName<span class="token punctuation">;</span>
     log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"fileRealPath {}"</span><span class="token punctuation">,</span>fileRealPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
     <span class="token comment">//Can I write the uploaded file information to the database later</ span>
     <span class="token keyword">return</span> fileRealPath<span class="token punctuation">;</span>
 <span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

Cross domain configuration implementation

When accessing the file upload service through the client project, we need to conduct cross domain configuration, such as:

package com.jt.files.config;

/**

  • Cross domain configuration (configure based on filter mode, and set the filter priority higher)
    /
    @Configuration
    public class CorsFilterConfig {
    @Bean
    public FilterRegistrationBean<CorsFilter> filterFilterRegistrationBean(){
    //1. Configure this filter (cross domain settings - url,method)
    UrlBasedCorsConfigurationSource configSource=new UrlBasedCorsConfigurationSource();
    CorsConfiguration config=new CorsConfiguration();
    //Which request headers are allowed to cross domains
    config.addAllowedHeader("");
    //Which method types are allowed to cross domain get post delete put
    config.addAllowedMethod("");
    //Which request sources (IP: ports) are allowed to cross domains
    config.addAllowedOrigin("");
    //Whether to allow carrying cookie s across domains
    config.setAllowCredentials(true);
    //2. Register the filter and set its priority
    configSource.registerCorsConfiguration("/**", config);
    FilterRegistrationBean<CorsFilter> fBean= new FilterRegistrationBean(new CorsFilter(configSource));
    fBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
    return fBean;
    }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

Client engineering logic implementation

Add dependency

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

 
  • 1
  • 2
  • 3
  • 4

Build project startup class

package com.jt;

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

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Create file upload page

Define the file upload page fileupload.html, for example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>File upload demo</title>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<form id="fileForm" method="post" enctype="multipart/form-data" onsubmit="return doUpload()">
    <div>
        <label>Upload file
            <input id="uploadFile" type="file" name="uploadFile">
        </label>
    </div>
    <button type="submit">Upload file</button>
</form>
</body>
<script>
    //Form submission event for jquery code
    function doUpload(){
        //Get all pictures selected by the user (get array)
        let files=document.getElementById("uploadFile").files;
        if(files.length>0){
            //Get the unique picture selected by the user (take it out of the array)
            let file=files[0];
            //Start uploading this picture
            //Since there are many uploaded codes, you do not want to interfere with other codes here, so define a method call
            upload(file);
        }
        //Block form submission effect
        return false;
    };
    // Method of uploading file to server
    function upload(file){
        //Define a form
        let form=new FormData();
        //Add file to form
        form.append("uploadFile",file);
        //Asynchronous commit
        let url="http://localhost:8881/resource/upload/";
        axios.post(url,form)
             .then(function (response){
                 alert("upload ok")
                 console.log(response.data);
             })
             .catch(function (e){//Execute catch code block on failure
                 console.log(e);
         })
    }
</script>
</html>

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

Start service access test

Step 1: start nacos
Step 2: start the SCA resource service
Step 3: start the SCA resource UI service
Step 4: open the browser for access test, for example:

Engineering practice of API gateway

summary

API gateway is the entrance for external resources to access the internal resources of the service, so the file upload request should first request the gateway service, and then be forwarded by the gateway service to the specific resource service.

Service invocation architecture

Project structure design

Create Gateway project and initialization

Step 1: create an SCA resource Gateway project, for example:


Step 2: add project dependencies, for example:

 <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Step 3: create the configuration file bootstrap.xml, and then perform the initial configuration, for example:

server:
  port: 9000
spring:
  application:
    name: sca-resource-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
      config:
        server-addr: localhost:8848
        file-extension: yml
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: router01
          uri: lb://sca-resource
          predicates:
            - Path=/sca/resource/upload/**
          filters:
            - StripPrefix=1

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

Step 4: build the project startup class and start the service to check whether it is correct, for example:

package com.jt;

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

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Gateway cross domain configuration

When we access the gateway based on Ajax technology, we need to conduct cross domain design at the gateway level, for example:

package com.jt.config;

import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

//@Configuration
public class CorsFilterConfig {
@Bean
public CorsWebFilter corsWebFilter(){
//1. Build a cross domain configuration based on url
UrlBasedCorsConfigurationSource source= new UrlBasedCorsConfigurationSource();
//2. Cross domain configuration
CorsConfiguration config=new CorsConfiguration();
//2.1 allow all IP: ports to cross domain
config.addAllowedOrigin("");
//2.2 allow all request headers to cross domains
config.addAllowedHeader("");
//2.3 allow all request methods to cross domains: get,post
config.addAllowedMethod("*");
//2.4 it is allowed to carry valid cookie s across domains
config.setAllowCredentials(true);
source.registerCorsConfiguration("/**",config);
return new CorsWebFilter(source);
}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

The cross domain design in the Spring Gateway project can not only configure the cross domain filter in java code in the gateway project, but also directly configure the cross domain in the configuration file, for example:

spring:
  cloud:
    gateway:
      globalcors: #Cross domain configuration
        corsConfigurations:
          '[/**]':
            allowedOrigins: "*"
            allowedHeaders: "*"
            allowedMethods: "*"
            allowCredentials: true

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

Start the project for service access

First open the gateway, the resource server, and the client engineering service (UI), and then modify the url to access the resource server in the fileupload.html file, such as

 let url="http://localhost:9999/nacos/resource/upload/";

 
  • 1

Next, perform an access test, for example:

AOP mode operation logging

Add project dependency

Add AOP dependency in SCA resource project, for example:

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

 
  • 1
  • 2
  • 3
  • 4

Create pointcut annotations

Our project aims to enhance the function of the target business, but the system should specify who is the target business. Here we define an annotation, which will be used to describe the target business later.

package com.jt.resource.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RequiredLog {
String value() default "";
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Define pointcut methods

Describe the resource controller file upload method in the SCA resources project through the annotation RequiredLog defined above, for example:

@RequiredLog("upload file")
@PostMapping("/upload/")
public String uploadFile(MultipartFile uploadFile) throws IOException {...}

 
  • 1
  • 2
  • 3

Note: the method described by @ RequiredLog annotation can be regarded as "Brocade" with icing on the cake, and the subsequent adding of flowers can be placed in the aspect notification method.

Define log operation facet

In AOP programming, we will encapsulate the definitions of Pointcut and extended business logic (Around,...) through aspects, such as:

package com.jt.resource.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Slf4j
@Aspect
@Component
public class LogAspect {
//Define pointcuts
@Pointcut("@annotation(com.jt.resource.annotation.RequiredLog)")
public void doLog(){ }//Icing on the cake (annotation description method)

<span class="token comment">//Define extended business logic</span>
<span class="token annotation punctuation">@Around</span><span class="token punctuation">(</span><span class="token string">"doLog()"</span><span class="token punctuation">)</span>
<span class="token comment">//@Around("@annotation(com.jt.resource.annotation.RequiredLog)")</span>
<span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">doAround</span><span class="token punctuation">(</span><span class="token class-name">ProceedingJoinPoint</span> joinPoint<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span> <span class="token punctuation">{<!-- --></span>
    log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"Before {}"</span><span class="token punctuation">,</span><span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token class-name">Object</span> result<span class="token operator">=</span>joinPoint<span class="token punctuation">.</span><span class="token function">proceed</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//Execution chain (other aspects, target method - Jin)</span>
    log<span class="token punctuation">.</span><span class="token function">debug</span><span class="token punctuation">(</span><span class="token string">"After {}"</span><span class="token punctuation">,</span><span class="token class-name">System</span><span class="token punctuation">.</span><span class="token function">currentTimeMillis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> result<span class="token punctuation">;</span><span class="token comment">//Execution result of target method (pointcut method)</span>
<span class="token punctuation">}</span>

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

Analysis of AOP logging principle

When we record user operation logs based on AOP, the underlying workflow is as follows:

Note: after defining the AOP Aspect in the project, when the system starts, it will load and analyze the classes described by the @ Aspect annotation, create a proxy object based on the description of the pointcut as the target type object, and create an execution chain inside the proxy object, which contains interceptors (encapsulating the pointcut information), notifications (Around,...), When we request the target object resources, we will directly call the resources in the order of the execution chain.

Summary

This chapter has taken file upload as an example to review and strengthen the mastery and practice of basic knowledge of microservice.

Tags: Java Spring Spring Boot

Posted on Tue, 21 Sep 2021 20:03:27 -0400 by DontheCat