The first actual combat project of springboot+vue music website in winter vacation

Posted by scooterlibby on Tue, 22 Feb 2022 17:13:16 +0100

preface

Front end usage: vue/cli "^ 4.5.15"
Back end usage: springboot2 6.2, mybatis-plus3. 5.9,mybatis-plus-generator3. five point one
Deployment: nginx,tomcat,webpack
Summary Although the project is colorful, it is not difficult The biggest gains are:
1. Technical selection and task requirements Once determined, late changes are costly
2. Pay attention to backup
3. Database form design
4.bug solution
5. More in-depth experience is MVVM architecture development mode, which creates entities in a pipeline and realizes business logic:
domain/pojo/bean → dao/mapper → mapper.xml → service → serviceimpl → controller
6. Remember to give priority to data verification on the front end

Thanks to the elder Wang Hanyuan of station b and the people who helped me in the development Due to copyright reasons, the open source project does not publish any songs
Due to the wrong selection at that time, there was no api development As a result, the songs are uploaded one by one... So the technology selection is the biggest pit I stepped on

I Achievement display

Front desk overview

Background overview

II Back end process

2.1 database table design

In this single user project, you can basically hold a java development manual and abide by its regulations (but how can I say this? At this stage, it feels like chicken ribs. So I'm going to take a look at mysql advanced)
Single user project development is basically a common example, but we should still consider the actual needs of our own project

2.2. Back end construction

2.2.1 simplified development of code generated by mybatis plus reverse engineering

In order to facilitate development, we should first establish a database Then use mybatis plus reverse engineering, code generator! It is not recommended to use lombok to omit entity constructors and get and set methods (I've seen a saying that if java is full of plug-ins that can modify the source code like lmobok, it's like rootless duckweed. Without its own core competitiveness, java will be replaced sooner or later!) But we can't deny that it's also very convenient. I usually use lombok, mainly his @slf4j log

This method can help us generate automatically
Domain / POJO / bean (full generation) → dao/mapper (generation model and general crud method) → mapper XML (generation model and general crud method) → service (generation model and general crud method) → serviceimpl (generation model and general crud method) → controller (generation model and general crud method) if we are not satisfied with its own crud method, we can write it ourselves. We suggest writing it ourselves!
Note that mybatis-plus-generator3 Version 5.1 is a transformation code generation See here for details

2.2.2 configuration data, cross domain and static resource release

Since the basic configuration can be reused, I pasted it below
The configuration class and yaml configuration file are combined
1.druid class configuration file

package com.vector.music.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.Arrays;

/**
 * @author WangYuanJie
 * @description: about jdbcDruidConfig
 * @ClassName MyDataSourceConfig
 * @date 2022/1/21 16:17
 */
@Configuration
public class MyDataSourceConfig {
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource dataSource() throws SQLException {
        DruidDataSource druidDataSource = new DruidDataSource();
        //Add monitoring function
//        druidDataSource.setFilters("stat,wall");

        return druidDataSource;
    }
    /*
     * Solve the druid log error: discard long time none received connection:xxx
     * */
    @PostConstruct
    public void setProperties(){
        System.setProperty("druid.mysql.usePingMethod","false");
    }
    /**
     * Configure the monitoring page of druid
     * @return
     */
    @Bean
    public ServletRegistrationBean statViewServlet(){
        StatViewServlet statViewServlet = new StatViewServlet();
        ServletRegistrationBean<StatViewServlet> registrationBean = new ServletRegistrationBean<>(statViewServlet, "/druid/*");
        registrationBean.addInitParameter("loginUsername","admin");
        registrationBean.addInitParameter("loginPassword","123456");
        return registrationBean;
    }
    /**
     * WebStatFilter It is used to collect the data of Web JDBC Association monitoring
     */
    @Bean
    public FilterRegistrationBean webStatFilter(){
        WebStatFilter webStatFilter = new WebStatFilter();
        FilterRegistrationBean<WebStatFilter> filterRegistrationBean = new FilterRegistrationBean<>(webStatFilter);
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/*"));
        filterRegistrationBean.addInitParameter("exclusions","*.js,*.gif,*.jpg,*.ico,/druid/*");
        return filterRegistrationBean;
    }
}

2. Solve cross domain problems at the back end

/**
 * Solve cross domain problems
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowCredentials(true)
                .allowedMethods("*");
    }

3. Solve the problem of static resource release

You can put static resources where you want, but try not to put them in the project, because the project will only run in memory later Don't increase the memory load, and you will have a strange problem with springboot image echo See here for details

    /**
     * By default, Spring Boot uses various properties configured in webmvcoautoconfiguration.
     * The default mapped folders are:
     * classpath:/META-INF/resources
     * classpath:/resources
     * classpath:/static
     * classpath:/public
     * The above are the mapping paths of static resources. The priority order is: meta-inf / Resources > Resources > static > public
     * Principle: static mapping / * *.
     * Request to come in and find the Controller first to see if it can be handled. All requests that cannot be processed are handed over to the static resource processor. If the static resource cannot be found, the 404 page will be responded
     * Static resource access prefix
     * Default no prefix
     * spring:
     * mvc:
     * static-path-pattern: /res/**
     * Current project + static path pattern + static resource name = find under static resource folder
     */
    // The following is a custom static resource access
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        /**
         * spring boot Echo problem of uploaded pictures in
         * Locate singer avatar address
         * Absolute path mapping, which can be echoed without redeployment, because it maps your local path
         */
        registry.addResourceHandler("static/**").addResourceLocations(
                System.getProperty("user.dir") + File.separator + "static" + File.separator);

    }

4.yaml configuration file

# Declare that the current service port number is 8083
server:
  port: 8083
#spring configuration
spring:
# Solve the problem that the path matching update and mvc path matching pattern do not match after using swagger high version update, resulting in an error in druid
  mvc:
    pathmatch:
      matching-strategy: ANT_PATH_MATCHER
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/music?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
    username: music
    password: 123456
    # Configure some functions of Druid UI
    druid:
      filters: stat,wall,slf4j
      max-active: 12
      stat-view-servlet:
        enabled: true
        login-username: admin
        login-password: 123456
        reset-enable: false
      web-stat-filter:
        enabled: true
        url-pattern: /*
        exclusions: '*.js,*.gif,*.jpg,*.ico,/druid/*'
      aop-patterns: com.vector.admin.*
      filter:
        stat:
          slow-sql-millis: 1000
          log-slow-sql: true
          enabled: true
        wall:
          enabled: true
  # json object parsing processing
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
  # Declare the size and total size received by our backend each time
  servlet:
    multipart:
      max-file-size: 10MB
      max-request-size: 20000MB


# Configure mybatis related content
mybatis:
  #  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mapper/*.xml
  configuration: #Specify the relevant configuration items in the mybatis global configuration file
    map-underscore-to-camel-case: true
mybatis-plus:
  type-aliases-package: com.vector.music.pojo

2.3. Pipeline development mode

domain/pojo/bean → dao/mapper→ mapper.xml → service → serviceimpl → controller
It is worth mentioning that

Don't use localdatetime for the time attribute of general entity classes. You can't control it! Although it is thread safe, you must use HttpRequestServlet to obtain the string method passed in from the front end, then convert it through datetime, and then splice it into the necessary format:
Yyyy MM DD HH: mm: SS assigned to localdatetime

1. File upload function: See here for details The database generally stores the url, and the previously configured static resource path stores the uploaded actual file We don't need to be afraid that uuid or timestamp will make us unable to understand. We don't need to understand these. At the same time, we can also determine what is uploaded through other fields
2. Cooperate with the front-end requirements and pay attention to the verification of front-end data
The controller layer pays attention to whether the request mode of @ RequestMapping is consistent with the front end; Note whether @ ResponseBody. Is written Stop using HttpRequestServlet to get the object from the front end Because his code is too repetitive, it is troublesome to modify it It is recommended to use @ RequestBody annotation entity class to obtain the value of the front end (note that the name of the value passed from the front end should correspond to the attribute of the entity class)`

mapper.xml I think try to take this parameter

III Front end vue construction

Statement: the front-end technology feels very good

3.1 construction of front-end basic environment

3.1.1 scaffold construction and errors that are easy to occur

webstorm is similar to idea, so it is very convenient to build Vue cli See here for details
It should be noted that if there is a blank page when npm run build is packaged in the later stage Just look at config / index JS
assetsPublicPath in build method: '. /'
Whether history mode is used in route navigation

3.1.2 interaction between Axios and backend

Since axios code is also reusable, paste it as follows

import axios from 'axios'
import router from '../router'

axios.defaults.timeout = 5000 // The supermarket time is 5 seconds
axios.defaults.withCredentials = true // Allow cross domain
// Content type response header
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'
// Base url
// Port number corresponding to the backend yaml file
axios.defaults.baseURL = 'http://127.0.0.1:8083'

// Response interceptor
axios.interceptors.response.use(
  response => {
    // If the status in reponse is 200, it indicates that the interface has been accessed, otherwise an error occurs
    if (response.status === 200) {
      return Promise.resolve(response)
    } else {
      return Promise.reject(response)
    }
  },
  error => {
    if (error.response.status) {
      switch (error.response.status) {
        case 401: // Not logged in
          router.replace({
            path: '/',
            query: {
              redirect: router.currentRoute.fullPath
            }
          })
          break
        case 404: // Can't find
          break
      }
      return Promise.reject(error.response)
    }
  }
)

/**
 * Encapsulate get method
 */
export function get(url, params = {}) {
  return new Promise((resolve, reject) => {
    axios.get(url, {params: params})
      .then(response => {
        resolve(response.data)
      })
      .catch(err => {
        reject(err)
      })
  })
}

/**
 * Encapsulate post method
 */
export function post(url, data = {}) {
  return new Promise((resolve, reject) => {
    axios.post(url, data)
      .then(response => {
        resolve(response.data)
      })
      .catch(err => {
        reject(err)
      })
  })
}

3.2 basic writing process

It is basically divided into axios request, assets static resource storage, router routing and navigation, vuex, i.e. store global method, view component, componentsc specific functional component and reusable component
components are divided in detail to understand coupling These are the basic development processes But the thought of css makes my head swell Too hard, too hard

3.3 the front end emphasizes the attention again

1. Pay attention to the blank page when npm run build is packaged in the later stage Just look at config / index JS
assetsPublicPath in build method: '. /'
Whether history mode is used in route navigation
2. Pay attention to the separation of reusable components to facilitate the direct use of other projects in the future
3. Note that methods in vue objects cannot be named randomly, and they must strictly abide by the official vue documents All you can play at will are those in data(),methods(),computed(),watch() You should know what I mean mixins mixing
4. Note that if the webpack installation fails, delete the node_modules file and package lock JSON file
To execute the webpack command, you must first download node

IV Project deployment steps

1. Modify the access address in the project to the address of the server (127.0.0.1 or localhost or 0.0.0.0 to the target server), and pay attention to the release of firewall port You can use tomcat
2. Pay attention to the back-end port and front-end port, and all access the same back-end port
3. Front end npm run build packages foreground and background dist
4. The backend uses the idea maven version control function to generate jar s

5. Note that the developed jdk matches the jdk version of linux, and then put the jar package anywhere and execute it there

nohup java -jar upload jar Package full name >temp.txt &

6. The foreground and background of Vue development can be placed in webapps of tomcat or html of nginx, and then

#Start tomcat and execute it under the bin path of tomcat 
sh start.sh
#Nginx starts sbin entering nginx
nginx

Default port
MySQL 3306
nginx/http 80
https 443
tomcat 8080
Castle tower 8888
Project port customization recommendations after 1024

Note the port release of tomcat, nginx and project access path and the release of security policy group firewall
There's another flash of light. I forgot

summary

For the first time, I felt great about project separation and development. What I gained most was that I was familiar with the development process and learned a lot of convenient development skills But it's easy to forget But these things just like the food we eat have inadvertently transformed into our nutrients
Goal of the next stage: Advanced Learning of mysql: the main contents include in-depth b + tree structure, index optimization, data migration, disaster recovery backup, blocking and deadlock
Then write a boot project I started learning redis As for the later learning of basic jvm,jmm or cloud, I think it's jvm,jmm

Reiterate that the server address will not be published due to copyright reasons. Of course, I'm afraid of being beaten
github address

Sometimes I am confused about the basic jvm,jmm, algorithm, compilation principle, database and network planning; Advanced mq message queue, kafka,cloud,zookeeper,k8s... I feel so far away that I have to learn, but the time is far from enough. I can't be sure whether I take the postgraduate entrance examination or not. Sometimes I really feel very tired... I only have the joy of making achievements after learning, but before long, how much I feel is completed by myself? A sense of loss permeates me again
Share a song But Taylor Swift's songs can always rekindle my confidence!

Topics: Java Linux Spring Boot Vue.js