Savior for beginners - the simplest tutorial of SpringBoot 06:web development practice

Posted by wih on Thu, 07 Oct 2021 05:08:17 +0200

Complete static resources

First find this class: webmvcoautoconfiguration. In this jar package, it is still auto configuration

There is an addResourceHandlers method in webmvcoautoconfiguration, which is used to automatically configure the static resource directory.

public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    if (this.servletContext != null) {
                        ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
                        registration.addResourceLocations(new Resource[]{resource});
                    }

                });
            }
        }

Look at this first:

if (!this.resourceProperties.isAddMappings()) {
   logger.debug("Default resource handling disabled");
}

If isAddMappings is false, the print default resource mapping path is invalid. The isAddMappings method actually returns an addMappings variable (in web properties)

addMappings means running to access static resources. If you set it to false, you disable all static resource mappings.

When the webmaster wrote this tutorial, he used SpringBoot version 2.5.1, which is the latest version at present. It is found that compared with the previous version, the changes are still great. It's troublesome to turn the source code, so I'll just tell you the conclusion.

The default static resource directory is:

new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

This is the same as before. Test it

Which path can return public.js?

In WebMvcProperties, there is a staticPathPattern property.

The default is / * *, so whatever you access can be accepted by the static resource processor.

Start project, access http://localhost:8888/public.js

Successful access, now we manually add a static directory.

spring:
  profiles: test
  resources:
    static-locations: [classpath:/my/]

visit http://localhost:8888/my.txt , also succeeded.

Finally, you can turn off the static resource switch.

spring:
  profiles: test
  resources:
    static-locations: [classpath:/my/]
    add-mappings: false

In this way, you can't access any static resources, but generally speaking, you don't have to close it.

On static locations

Static locations indicates a custom static directory. If this property is configured, the default static resource directory will become invalid!

You can also use this configuration to access local resources

spring:
  profiles: test
  resources:
    static-locations: file:C:/upload/article/
    add-mappings: true

File: indicates access to a local file.

For example, I'm going to visit 1.jpg now

Restart project, access http://localhost:8888/20210415/1.jpg , can be accessed successfully.

However, other static resources cannot be accessed. Because we set static locations, which is an overwrite operation, the default directory is gone.

For accessing such local files, the directories for file upload and download are generally placed on the local disk and will not be bound to the project.

What if we want to get the original directory and access local files? At this time, do not configure static locations. We can configure an additional resource mapping.

Note that under normal circumstances, the default resource mapping is more than enough. Aren't so many folders enough for you to put resources...

(Note: the resources in the figure above should also be commented out, otherwise an error will be reported.)

Then, create a new configuration class.

package com.java18.vipmgr.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyWebResourcesHandler implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/upload/**")
                .addResourceLocations("file:C:/upload/article/");
    }
}

Restart, access http://localhost:8888/upload/20210415/1.jpg You can see the picture, and it will not affect the original resource directory. This is the recommended practice in the project.

Spring boot integrates JDBC

Add jdbc dependency:

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

mysql dependencies are inherently:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

Modify yml configuration:

spring:
  profiles: test
  #resources:
    #static-locations: file:C:/upload/article/
    #add-mappings: true

  #Configure data sources
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/idea?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password:

By default, the driver package of mysql8.x is used. Pay attention to adding the time zone to the url, otherwise an error will be reported.

Test whether the data source is loaded successfully:

@SpringBootTest
class DataTests {

    @Autowired
    DataSource dataSource;

    @Test
    void dataSource() {
        System.out.println(dataSource.getClass());
    }

}

Print: class com.zaxxer.hikari.HikariDataSource

This is the default data source for springboot.

Test sql statement query

@Test
void dataSource() {
    //System.out.println(dataSource.getClass());
    List<Map<String, Object>> users = jdbcTemplate.queryForList("select * from users");
    System.out.println(users);
}

Result: [{id=1, username=zhangsan, password=123, points=1000}]

Database:

infer other things from one fact:

1. Why can JDBC template be used directly?

Because SpringBoot has automatic configuration, the conditions are:

@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
@ConditionalOnSingleCandidate(DataSource.class)

The DataSource has been configured, and the JdbcTemplate must also have spring boot starter JDBC. So it is configured automatically.

Take another look at the JdbcTemplateConfiguration:

Consolidate Druid data sources

First of all, help you clarify several concepts. What is a data source?

A data source is a connection pool. What is a connection pool?

We write jdbc code normally. Don't we want to get the connection and close the connection after using it. One on and one off, does it affect the performance!

In that case, why don't we generate 20 jdbc connections at the beginning? If you want to use it, I'll give you one. Isn't it beautiful for you to return it after you use it!

druid is a set of connection pool code encapsulated by Alibaba for jdbc. To put it bluntly, it is a jar package with some classes.

So:

**Druid data source**

=A jar package

=A dependency

Well, after understanding these concepts, we begin to integrate Druid data sources.

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.18</version>
</dependency>

Note that each time you import a new dependency, you must right-click the project, maven, reload, and some idea s are reimport.

Then, modify the default data source configuration in the application.yml configuration file.

#Configure data sources
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/idea?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password:
    type: com.alibaba.druid.pool.DruidDataSource

Is to add a type attribute. If not, the default data source is used.

druid also has some other configurations, which are directly pasted on it. It is the same level as type.

initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
#   Configure the filters for monitoring statistics interception. After removal, the sql in the monitoring interface cannot be counted, 'wall' is used for firewall
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500

Key: write configuration classes and enable sql monitoring

package com.java18.vipmgr.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.sql.DataSource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DruidConfig {

    /**
     * Assemble the Druid object in the way of ConfigurationProperties
     * @return
     */
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druid(){
        return  new DruidDataSource();
    }

    //Configure Druid monitoring
    //In fact, it is equivalent to configuring a Servlet to manage the background in web.xml
    //After this Servlet is enabled, you can access the background page, and the mapping address is / druid/*
    @Bean
    public ServletRegistrationBean statViewServlet(){
        /**
         * Druid The built-in provides a StatViewServlet to display Druid statistics.
         * The purposes of this StatViewServlet include:
         * Provide html page for monitoring information display
         * JSON API that provides monitoring information
         */
        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        Map<String,String> initParams = new HashMap<>();
        //Here is the account and password of the configuration administrator. Just write it dead
        initParams.put("loginUsername","admin");
        initParams.put("loginPassword","123456");
        initParams.put("allow","");//The default is to allow all access
        initParams.put("deny","192.168.x.x"); //This is the default to disable access to an IP

        bean.setInitParameters(initParams);
        return bean;
    }

    //2. Configure a web monitoring filter
    @Bean
    public FilterRegistrationBean webStatFilter(){
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new WebStatFilter());

        Map<String,String> initParams = new HashMap<>();
        initParams.put("exclusions","*.js,*.css,/druid/*");

        bean.setInitParameters(initParams);

        bean.setUrlPatterns(Arrays.asList("/*"));

        return  bean;
    }
}

To facilitate testing, we add a Controller

package com.java18.vipmgr.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("user")
public class UserController {
    @Autowired
    JdbcTemplate jdbcTemplate;

    @GetMapping("getAll")
    public List<Map<String,Object>> getAll(){
        return jdbcTemplate.queryForList("select * from users");
    }
}

Note that there is a small pit here. Because we use the druid monitoring function, the log will be printed by default, so log4j needs to be introduced.

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

Start project, access http://localhost:8888/user/getAll , you can query data. Then visit http://localhost:8888/druid

Enter the account and password to enter the monitoring page

You can view the operation of each sql, which is why Druid is used.

I am Xiaobai, a salted fish with a dream. If you have any questions, please leave a message in the comment area and I will reply.

Topics: Java Spring Boot RESTful