step04day07 file upload case and comprehensive test

Posted by raahatazim on Sat, 18 Dec 2021 20:17:56 +0100

1. Parent child project creation and aggregation project

1.1 engineering structure

Function: simulate the connection test of front and rear ends through parent-child projects

Note: SCA resource project stores back-end files, and SCA resource UI project stores front-end files

1.2 parent child aggregation project

1.2. 1. Create parent project

 

1.2. 2. Configuration dependency

 <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. Create sub project

Front end analog Ui

Back end simulation SSM

 

1.2. 4. Configuration dependency

Front end (client) configuration dependency

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

Backend (resource side) configuration dependency

       <!--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>

version control

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

Note: after adding this annotation, the compiled version of idea becomes jdk8

1.2. 5. Write resource file

1. Service initialization configuration (backend configuration, configuration file upload path)

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

2. Startup class

Back end file upload

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

Front end startup resources

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

1.3 knowledge points related to aggregation Engineering

1.3. 1. Concept of aggregation

It is generally used for sub module development, and finally packaged and released as a whole
Maven Project runs independently
Maven Module cannot run independently
 


1.3. 2. Polymerization engineering development steps

  1. The root project is a pom project.
    2. Sub module: Maven Module
    3. The corresponding resources are written in the sub module, such as the three-tier architecture of web pages in ui resources and back-end resources
 

Note: when aggregating and packaging (install), select the parent project for aggregation
Publish to the Tomcat runtime (tomcat7:run), and select the web project to publish and run
   
1.3. 3. Difference between engineering aggregation and inheritance

Aggregation is to facilitate rapid component projects. For the aggregation module, it knows which modules are aggregated, but those modules do not know the existence of the aggregation module
Inheritance is to eliminate duplicate configurations. For the parent POM of inheritance relationship, it does not know which sub modules inherit from it, but the sub module must know what its parent POM is
   

2. Resource items and configuration files

2.1 front end resources

<!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>

2.2 back end resources

 2.2. 1. Control layer

@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);

     @Value("${jt.resource.path}")
     private String resourcePath;//="d:/uploads/";
     @Value("${jt.resource.host}")
     private String resourceHost;//="http://localhost:8881/";

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

Note: the control layer writes the file upload business, specifies the file upload path, and constructs a new file name

2.2. 2 cross domain configuration implementation

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

@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;
    }

Note: this item can also be configured in yml

3. Document item test

3.1 specific process

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:

3.2 possible errors in file upload

3.3 process call summary

4.API gateway engineering practice

4.1 General

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.

4.2 service invocation architecture

 

4.3 project structure design

4.4. Create Gateway project and initialize

Step 1: create an SCA resource Gateway project,

Step 2: add project dependencies,

 <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>

Step 3: create the configuration file bootstrap XML, and then initial configuration

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

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

4.5 gateway cross domain configuration

1.java file implementation

//@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);
    }
}

2. Configuration file implementation

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

4.6 start the project for service access

First open the gateway, resource server, client engineering service (UI), and then modify fileUpload The url to access the resource server in the HTML file, for example

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

Next, perform an access test, for example:

 

Topics: html5 Vue.js html