“This is the sixth day of my participation in the First Gwen Challenge 2022.First challenge in 2022”

Used by SpringBoot2 applications

Integrate MyBatis in SpringBoot

This article will describe how to use SpringBoot to integrate MyBatis with MySQL database

Idea creates a normal Maven projectSpringBootYYBJApplication note

Import POM dependencies

pom.xml

 
      
 <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>org.example</groupId>
     <artifactId>SpringBootYYBJ</artifactId>
     <version>1.0 the SNAPSHOT</version>
 ​
     <! -- Integrate a parent project -->
     <parent>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
         <version>2.1.6. RELEASE</version>
     </parent>
 ​
     <dependencies>
         <! -- SpringBoot starter -- web dependency -->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-web</artifactId>
         </dependency>
 ​
         <! -- mysql database -->
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
             <version>5.1.48</version>
         </dependency>
         <! -- FastJSON -->
         <dependency>
             <groupId>com.alibaba</groupId>
             <artifactId>fastjson</artifactId>
             <version>1.2.31</version>
         </dependency>
         <! MyBatis integration required -->
         <dependency>
             <groupId>org.mybatis.spring.boot</groupId>
             <artifactId>mybatis-spring-boot-starter</artifactId>
             <version>1.1.1</version>
         </dependency>
     </dependencies>
 ​
 </project>
Copy the code

Configuration yml

SpringBoot has default values for some configurations but you can also modify application.yml directly via application.properties or application.yml

 server:
   port: 9090    # SpringBoot port
 
 spring:
   datasource:   Data source configuration: driver, URL, user, password (note that the database name is changed according to your needs!)
     driver-class-name: com.mysql.jdbc.Driver
     url: jdbc:mysql://localhost:3306/shipms? useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
     username: root
     password: ok
 /*.xml load package under all..
 mybatis:
   mapper-locations: classpath:mapper/*.xml
 logging:
   level:
     com.zb.mapper: DEBUG  # SQL execution outputs SQL statements
Copy the code

Entity Service Mapper Controller: Entity Service mapper Controller: Util Config At this point, the basic configuration is complete:

  • Write as needed, not too different from previous SpringMVC applications!
  • And you don’t need to write the front end, you just need to write the Controller, return the front end JSON…
  • Below I realize a check all operation..

Database shipms

Create entity entity

Create Mapper

UserMapper.Java

Dao = session.getMapper(Dao interface.class); Public interface UserMapper {// query all ~ public List<Users> selall(); }Copy the code

Write MybstaisSQL mapping

UserMapper.xml

 
      
 <! DOCTYPEmapper PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
 <mapper namespace="com.wsm.mapper.UserMapper">
     <! -->
     <select id="selall" resultType="com.wsm.entity.Users"  >
         SELECT * FROM `users`
     </select>
 </mapper>
Copy the code

Create a service

UserService.Java

 @Service     // Classes are handled by the Spring container and represent business logic
 public class UserService {
 ​
     @Autowired  // or @autowired (required = false) sometimes idea tool will check for errors (Spring context has no classes), use it, do not check;
     private UserMapper um;
 ​
     // Query all ~
     public List<Users> selall(a){
         returnum.selall(); }}Copy the code

Create a controller bag

UserController.Java

 @CrossOrigin        // Indicates support for cross-domain operations: since SpringBoot is pre-and-post-separated, cross-server operations are designed (access between two projects).. Plus;
 @RestController     // All methods in this class return values as JSON.
 public class UserController {
     @Autowired
     private UserService us;
 ​
     @GetMapping("/selall")   // This is equivalent to @requestMapping GET of SpringMVC
     public List<Users> selall(a){
         returnus.selall(); }}Copy the code

Don’t forget the main program class:

SpringBootRun.Java

 @SpringBootApplication
 public class SpringBootRun {
     public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class, args); }}Copy the code

Cross domain:

Write a front-end project: through: http://cross-domain… index.html

 <! DOCTYPEhtml>
 <html lang="en">
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
     <title>Document</title>
     <script src=".. / jquery - 1.12.4. Js. ""></script>
     <script type="text/javascript" >
         // page loading event:
         $(function(){
             page();
         })// Page loading event completed!
         
         function page(){
         
             // Perform asynchrony!
             $.ajax({
                 url:'http://localhost:9090/selall'.type:'get'.success:function(result){
                     var html=' ';    // Define a variable to save, later to concatenate!
                     for(var i=0; i<result.length; i++){JSON is a Page object. Its data property. Length traverses its property.
                         var r = result[i];                  
                         html+="<tr>"+
                                 "<td>"+r.id+"</td>"+
                                 "<td>"+r.name+"</td>"+
                                 "<td>"+r.status+"</td>"+
                                 "<td>"+r.typeid+"</td>"+
                                 "<td>"+r.lastModifyTime+"</td>"+
                                 
                             "</tr>";
                     }
                     $("tbody").html(html); }})}</script>
 </head>
 <body>
     <! -- table displays data -->
     <div>
     
     <table width="100%"  border="1" >
         <thead>
             <tr>
                 <td>Serial number</td>
                 <td>The user name</td>
                 <td>The user types</td>
                 <td>User state</td>
                 <td>Last Modified time</td>
             </tr>
         </thead>
         <tbody>
             <! -- Content from Ajax -->
         </tbody>
     </table>
     </div>
 </body>
 </html>
Copy the code

Integrate Redis with SpringBoot

Follow up on the last project…

Import Redis dependencies

pom.xml

 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-redis</artifactId>
      <version>1.4.5. RELEASE</version>
 </dependency>
Copy the code

Added based on configuring YML

application.yml

 spring:
   datasource:
     driver-class-name: com.mysql.jdbc.Driver
     url: jdbc:mysql://localhost:3306/shipms? useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
     username: root
     password: ok
 #redis configuration is in the Spring directory.. And my redis does not have a password, according to your own situation ~ (I do not have a password)
 #Spring
   redis:      
     host: 127.0. 01.
     port: 6379
Copy the code

Yml files are distinguished by tree structure…

Create RestConfig

Add a package com.wsm.config config class package redisconfig.java

package com.wsm.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/** * Redis configuration class *@program: springbootdemo
 * @Description: * /
@Configuration
@EnableCaching // Open annotations
public class RedisConfig extends CachingConfigurerSupport {

    /** * retemplate configuration *@param factory
     * @return* /
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // Configure the connection factory
        template.setConnectionFactory(factory);

        / / use Jackson2JsonRedisSerializer to serialization and deserialization of redis value value (the default serialization way of using JDK)
        Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);

        ObjectMapper om = new ObjectMapper();
        // Specify the serialized field, field,get, and set, and the modifier range. ANY is both private and public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        Classes must be non-final. Final classes, such as String,Integer, etc., run exceptions
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jacksonSeial.setObjectMapper(om);

        // Values are json serialized
        template.setValueSerializer(jacksonSeial);
        // Use StringRedisSerializer to serialize and deserialize the redis key
        template.setKeySerializer(new StringRedisSerializer());

        // Set hash key and value serialization mode
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();

        return template;
    }

    /** * to operate on hash data **@param redisTemplate
     * @return* /
    @Bean
    public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForHash();
    }

    /** * Operates on redis string data **@param redisTemplate
     * @return* /
    @Bean
    public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForValue();
    }

    /** ** to operate on list type data **@param redisTemplate
     * @return* /
    @Bean
    public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForList();
    }

    /** * Operates on unordered collection type data **@param redisTemplate
     * @return* /
    @Bean
    public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
        return redisTemplate.opsForSet();
    }

    /** * Operates on data of ordered collection type **@param redisTemplate
     * @return* /
    @Bean
    public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
        returnredisTemplate.opsForZSet(); }}Copy the code

Used in the Service layer

Make sure the entity class is serialized first. Implement the Serializable interfaceSerialization is not required using the above Config

Make sure the Redis service is started at…. before using Reids

UserService.Java

 @Service     // Classes are handled by the Spring container and represent business logic
 public class UserService {
 ​
     @Autowired  // or @autowired (required = false) sometimes idea tool will check for errors (Spring context has no classes), use it, do not check;
     private UserMapper um;
 ​
     @Autowired
     private RedisTemplate<String, Object> redisTemplate;
 ​
     // Query all ~
     //redis: database access is not from the redis next access, reduce database access connection...
     public List<Users> selall(a){
         System.out.println("Access to business Inquiry Method");
         List<Users> usersList = null;
         String key = "Users";               // Redis stores the key
         if (redisTemplate.hasKey(key)) {    // Whether there is a key
             System.out.println("Redis query");
             String val = redisTemplate.boundValueOps(key).get().toString();
             usersList = JSON.parseArray(val, Users.class);
         } else {
             System.out.println("Db database query");
             usersList = um.selall();
             redisTemplate.boundValueOps(key).set(JSON.toJSONString(usersList));
         }
         System.out.println("Exit business Enquiry Method");
         returnusersList; }}Copy the code

The main program performs the refresh twice ~

SpringBoot uses Reids roughly like this… Deep Redis still need to study hard…

Redis utility class:

  • The basic use of Redis has been described above, but it is a little uncomfortable to use the RedisTemplate internal-encapsulation method
  • Tool class can be more convenient to improve the efficiency of development!, the RedisTemplate is repackaged internally!Try it!
  • It is generally recommended that this utility class be stored in a specified util package for easy management!

RedisUtil.Java

package com.zb.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/** * redisTemplate encapsulates ** /
@Component
public class RedisUtil {
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /** * specifies the cache expiration time *@paramThe key key *@paramTime Time (seconds) *@return* /
    public boolean expire(String key,long time){
        try {
            if(time>0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Get expiration time by key *@paramThe key key cannot be NULL *@returnTime (s) returns 0 for permanently valid */
    public long getExpire(String key){
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }

    /** * Check whether the key exists *@paramThe key key *@returnTrue Exists false Does not exist */
    public boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * delete cache *@paramKey can pass one value or more */
    @SuppressWarnings("unchecked")
    public void del(String ... key){
        if(key! =null&&key.length>0) {if(key.length==1){
                redisTemplate.delete(key[0]);
            }else{ redisTemplate.delete(CollectionUtils.arrayToList(key)); }}}//============================String=============================
    /** * Common cache fetch *@paramThe key key *@returnValue * /
    public Object get(String key){
        return key==null?null:redisTemplate.opsForValue().get(key);
    }

    /** * Normal cache into *@paramThe key key *@paramThe value value *@returnTrue Successful false failed */
    public boolean set(String key,Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Normal cache is placed and set time *@paramThe key key *@paramThe value value *@paramTime Time (s) Time must be greater than 0. If time is less than or equal to 0, the value is set indefinitely *@returnTrue Successful false failed */
    public boolean set(String key,Object value,long time){
        try {
            if(time>0){
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            }else{
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * increment *@paramThe key key *@paramDelta is incremented by a number (greater than 0) *@return* /
    public long incr(String key, long delta){
        if(delta<0) {throw new RuntimeException("The increasing factor must be greater than zero.");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /** * decrements *@paramThe key key *@paramDelta is reduced by a number (less than 0) *@return* /
    public long decr(String key, long delta){
        if(delta<0) {throw new RuntimeException("The decrement factor must be greater than zero.");
        }
        return redisTemplate.opsForValue().increment(key, -delta);
    }
    
    //================================Map=================================
    /**
     * HashGet
     * @paramThe key key cannot be NULL *@paramItem items cannot be null *@returnValue * /
    public Object hget(String key,String item){
        return redisTemplate.opsForHash().get(key, item);
    }

    /** * get all keys * corresponding to the hashKey@paramThe key key *@returnCorresponding multiple key values */
    public Map<Object,Object> hmget(String key){
        return redisTemplate.opsForHash().entries(key);
    }

    /**
     * HashSet
     * @paramThe key key *@paramMap corresponds to multiple key values *@returnTrue Successful false failed */
    public boolean hmset(String key, Map<String,Object> map){
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * HashSet and set the time *@paramThe key key *@paramMap corresponds to multiple key values *@paramTime Time (seconds) *@returnTrue Successful false failed */
    public boolean hmset(String key, Map<String,Object> map, long time){
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if(time>0){
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * puts data into a hash table, or creates * if none exists@paramThe key key *@paramItem item *@paramThe value value *@returnTrue Successful false failed */
    public boolean hset(String key,String item,Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * puts data into a hash table, or creates * if none exists@paramThe key key *@paramItem item *@paramThe value value *@paramTime Time (s) Note: If the existing hash table has time, the original time * will be replaced@returnTrue Successful false failed */
    public boolean hset(String key,String item,Object value,long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if(time>0){
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Delete the value * from the hash table@paramThe key key cannot be NULL *@paramItem items can be more than null */
    public void hdel(String key, Object... item){
        redisTemplate.opsForHash().delete(key,item);
    }

    /** * Determines whether the value of the item * exists in the hash table@paramThe key key cannot be NULL *@paramItem items cannot be null *@returnTrue Exists false Does not exist */
    public boolean hHasKey(String key, String item){
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /** * hash increments that do not exist create one and return the new value *@paramThe key key *@paramItem item *@paramBy is going to be increased by how much (greater than 0) star@return* /
    public double hincr(String key, String item,double by){
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /** * hash decrement *@paramThe key key *@paramItem item *@paramI'm going to subtract by (less than 0) star@return* /
    public double hdecr(String key, String item,double by){
        return redisTemplate.opsForHash().increment(key, item,-by);
    }

    //============================set=============================
    /** * Get all values in the Set based on key *@paramThe key key *@return* /
    public Set<Object> sGet(String key){
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
            return null; }}/** * select * from a set based on value@paramThe key key *@paramThe value value *@returnTrue Exists false Does not exist */
    public boolean sHasKey(String key,Object value){
        try {
            return redisTemplate.opsForSet().isMember(key, value);
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Put the data into the set cache *@paramThe key key *@paramValues can be multiple *@returnNumber of successes */
    public long sSet(String key, Object... values) {
        try {
            return redisTemplate.opsForSet().add(key, values);
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * Put set data into cache *@paramThe key key *@paramTime Time (seconds) *@paramValues can be multiple *@returnNumber of successes */
    public long sSetAndTime(String key,longtime,Object... values) {
        try {
            Long count = redisTemplate.opsForSet().add(key, values);
            if(time>0) {
                expire(key, time);
            }
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * Get the length of the set cache *@paramThe key key *@return* /
    public long sGetSetSize(String key){
        try {
            return redisTemplate.opsForSet().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * removes * from value@paramThe key key *@paramValues can be multiple *@returnNumber of removals */
    public long setRemove(String key, Object ... values) {
        try {
            Long count = redisTemplate.opsForSet().remove(key, values);
            return count;
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}//===============================list=================================

    /** * retrieve the contents of the list cache *@paramThe key key *@paramStart to *@paramEnd End 0 to -1 represent all values *@return* /
    public List<Object> lGet(String key, long start, long end){
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null; }}/** * Get the length of the list cache *@paramThe key key *@return* /
    public long lGetListSize(String key){
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * Get the value * from the list by index@paramThe key key *@paramIndex index>=0, 0, 1, second element, and so on; When index<0, -1, the end of the table, the next-to-last element of -2, and so on@return* /
    public Object lGetIndex(String key,long index){
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null; }}/** * put the list in the cache *@paramThe key key *@paramThe value value *@return* /
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * put the list in the cache *@paramThe key key *@paramThe value value *@paramTime Time (seconds) *@return* /
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * put the list in the cache *@paramThe key key *@paramThe value value *@return* /
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * put the list in the cache *@paramThe key key *@paramThe value value *@paramTime Time (seconds) *@return* /
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * Modify a list of data according to the index *@paramThe key key *@paramThe index index *@paramThe value value *@return* /
    public boolean lUpdateIndex(String key, long index,Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false; }}/** * remove N values to value *@paramThe key key *@paramCount removes how many *@paramThe value value *@returnNumber of removals */
    public long lRemove(String key,long count,Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0; }}/** * Fuzzy query to obtain the key value *@param pattern
     * @return* /
    public Set keys(String pattern){
        return redisTemplate.keys(pattern);
    }

    /** * Use Redis message queue *@param channel
     * @paramMessage Message content */
    public void convertAndSend(String channel, Object message){
        redisTemplate.convertAndSend(channel,message);
    }
    
    / / = = = = = = = = = BoundListOperations usage start = = = = = = = = = = = =

    /** * Add data to Redis's list (from the right) *@param listKey
     * @paramExpireEnum Enumeration class of the validity period *@paramValues Data to be added */
    public void addToListRight(String listKey, Status.ExpireEnum expireEnum, Object... values) {
        // Bind operation
        BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
        // Insert data
        boundValueOperations.rightPushAll(values);
        // Set the expiration time
        boundValueOperations.expire(expireEnum.getTime(),expireEnum.getTimeUnit());
    }
    /** * iterates through list * in Redis according to the start and end sequence@param listKey
     * @paramStart Indicates the start number *@paramEnd Indicates the end number *@return* /
    public List<Object> rangeList(String listKey, long start, long end) {
        // Bind operation
        BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
        // Query data
        return boundValueOperations.range(start, end);
    }
    /** * pop up the value on the right - and remove the value *@param listKey
     */
    public Object rifhtPop(String listKey){
        // Bind operation
        BoundListOperations<String, Object> boundValueOperations = redisTemplate.boundListOps(listKey);
        return boundValueOperations.rightPop();
    }
    / / = = = = = = = = = BoundListOperations usage End = = = = = = = = = = = =
}
Copy the code

SpringBoot multithreading

When processing big data or real-time data, if a large number of objects are frequently created in the main thread, these objects will become free objects after being used up and will not be immediately GC (garbage collection ~). When the creation speed is greater than the destruction speed, memory may continue to grow, and eventually overflow memory. You can open multithreading to process, the object in the thread will be destroyed as soon as possible after the execution, evenly divide the burden of memory accumulation, ensure the stability of memory occupation.

Configuration @ EnableAsync

The Config class is defined to implement the AsyncConfigurer interface. The following two methods to implement it CustomMultiThreadingConfig. Java

 /** * Thread configuration class */
 @Configuration
 @EnableAsync(proxyTargetClass = true)// Enable asynchronous task support with @enableAsync annotation
 @ComponentScan("cn.hello")           / / scan packages
 public class CustomMultiThreadingConfig implements AsyncConfigurer {
     @Override
     public Executor getAsyncExecutor(a) {
         ThreadPoolTaskExecutor taskExecutort = new ThreadPoolTaskExecutor();
         taskExecutort.setCorePoolSize(10);          // Initial thread pool size
         taskExecutort.setMaxPoolSize(50);           // The maximum number of connections in the thread pool
         taskExecutort.setQueueCapacity(500);        // Message queue
         taskExecutort.setWaitForTasksToCompleteOnShutdown(true);// Sleep while waiting
         taskExecutort.setBeanName("my-thrad:");     / / thread
         taskExecutort.initialize();                 / / initialization
         return taskExecutort;
     }
 ​
     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler(a) {
         return newSimpleAsyncUncaughtExceptionHandler(); }}Copy the code

When the number of submitted tasks is greater than QueueCapacity, you need to set this parameter. However, none of the tasks provided by Spring is suitable for business scenarios. You can customize one or ensure that the number of submitted tasks is not greater than QueueCapacity

Configuration @ Asyn

First create a listener package to facilitate management

  • The @asyn declaration modifies a class on a method/class to indicate that all methods in the class are executed asynchronously by multiple threads..
  • After the main thread calls a method, SpringBoot starts a thread underneath by default to execute itMethods.. Is very strong!!!!!

Here is a scenario defined:

  • Query all methods, 10 seconds later, multithreading delete Redis key..MyAsynclmp.java
 @Component      // a class is managed by Spring;
 public class MyAsynclmp {
 ​
     @Autowired // Get a Redis object
     private RedisTemplate<String, Object> redisTemplate;
 ​
     @Async     // indicates that the method is multithreaded...
     public void clearData(String key) {
         System.out.println("Enter asynchronous method ready to wipe data");
         try {
             Thread.sleep(10000);
             redisTemplate.delete(key);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
         System.out.println("Asynchronous method completed!"); }}Copy the code

The Service implementation

UserService.Java

 @Service     // Classes are handled by the Spring container and represent business logic
 public class UserService {
 ​
     @Autowired  // or @autowired (required = false) sometimes idea tool will check for errors (Spring context has no classes), use it, do not check;
     private UserMapper um;
     @Autowired
     private RedisTemplate<String, Object> redisTemplate;
     @Autowired
     private MyAsynclmp myAsynclmp;
 ​
     // Query all ~
     //redis: database access is not from the redis next access, reduce database access connection...
     public List<Users> selall(a){
         System.out.println("Access to business Inquiry Method");
         List<Users> usersList = null;
         String key = "Users";               // Redis stores the key
         if (redisTemplate.hasKey(key)) {    // Whether there is a key
             System.out.println("Redis query");
             String val = redisTemplate.boundValueOps(key).get().toString();
             usersList = JSON.parseArray(val, Users.class);
         } else {
             System.out.println("Db database query");
             usersList = um.selall();
             redisTemplate.boundValueOps(key).set(JSON.toJSONString(usersList));
         }
         
         // Execute multithreading
         myAsynclmp.clearData("Users");
         
         System.out.println("Exit business Enquiry Method");
         returnusersList; }}Copy the code

Main program execution:

Note: Calling methods cannot be in the same class as asynchronous methods

SpringBoot uses the JVM cache @ehCache

Usually when obtaining data, in order to be efficient, we often extract common data from the database and store it in redIS cache, so that common data stored in Redis can not need to visit the database frequently. If that’s not enough, we can store our data in a Java virtual machine more efficiently.

  • EhCache is a pure Java in-process cache framework, which is fast and lean.
  • The default Cache in Hibernate is the EhCache used.

Using EhCache as the cache, we first introduce dependencies.

pom.xml

 <! - ehcache dependence - >
 <dependency>
   <groupId>net.sf.ehcache</groupId>
   <artifactId>ehcache</artifactId>
 </dependency>
 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-cache</artifactId>
 </dependency>
Copy the code

Then create the EhCache configuration fileehcache.xml

ehcache.xml

 
      
 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd" updateCheck="false">
      
     <! - Disk storage: Moves the objects that are not used in the cache to disks, similar to the virtual memory in Windows. Path: Specifies the path for storing objects on disks. User.home (user's home directory) user.dir (user's current working directory) java.io. Tmpdir (default temporary directory) Ehcache.disk.store. dir (Ehcache configuration directory) Absolute path (e.g. String tmpDir = system.getProperty ("java.io.tmpdir"); -->
       
     <diskStore path="java.io.tmpdir"/>
     <! MaxElementsInMemory: Sets the maximum number of recorded objects to store in the cache. Eternal: indicates whether the object will never expire TimeToLiveSeconds: maximum retention time/second overflowToDisk: Specifies whether to allow the object to be written to the disk. The following configuration is valid 600 seconds (10 minutes) after the cache is established. If the cache is not accessed for 120 consecutive seconds (2 minutes) within the valid 600 seconds (10 minutes), the cache is invalidated. If there is access, it only lasts 600 seconds. -->
       
     <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="600"
                   timeToLiveSeconds="600" overflowToDisk="true"/>
      
       
     <cache name="mycache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120"
            timeToLiveSeconds="600" overflowToDisk="true"/>
      <! Custom cache configuration: the above configuration takes effect 600 seconds (10 minutes) after the cache is created. If the cache is not accessed for 120 consecutive seconds (2 minutes) within the valid 600 seconds (10 minutes), the cache is invalidated. If there is access, it only lasts 600 seconds. --> 
 </ehcache>
Copy the code

The SpringBoot configuration file then specifies the cache type and declares the location of the Ehcache configuration file.

application.yml

 Data source configuration: driver, URL, user, password (note that the database name is changed according to your needs!)
 spring:
   datasource:
     driver-class-name: com.mysql.jdbc.Driver
     url: jdbc:mysql://localhost:3306/shipms? useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
     username: root
     password: ok
 #redis configuration is in the Spring directory.. And my redis has no password, according to your own situation to ~
 #Spring
   redis:
     host: 127.0. 01.
     port: 6379
 Declare the location of the Ehcache configuration file
 #Spring
   cache:
     type: ehcache
     ehcache:
       config: classpath:ehcache.xml
Copy the code

Annotations on the Service

Added a new feature to query a user by ID, usermapper.java, for illustration purposes

 @Mapper
 // Indicates that the Mapper(formerly Dao) is managed by Spring,
 // Compared to previous Spring: Dao interface Dao = session.getmapper (Dao interface.class);
 public interface UserMapper {
     // Query all ~
     public List<Users> selall(a);
     // View users by ID
     public Users selid(int id);
 }
Copy the code

UserMapper. XML increase

 <select id="selid"  resultType="com.wsm.entity.Users"  parameterType="int" >
     SELECT * FROM `users` where id=#{id}
 </select>
Copy the code

UserService. Java is increased

 /* select user by id; @cacheable declares that the return values of all methods on or under a method/class are added to the JVM memory. Value: Used to specify the collection name of the cache store. Key: optional. The default value is the combination of all parameters of the function. When the method is called, it will look for the corresponding data in memory according to the key. If not, it will execute the method and add the method return value to the memory. If there is a key directly from the memory!! Select * from 'user 'where key=' user1 'and key=' user2 ' Access 2 to get 1's data!! * * /
 @Cacheable(value = "mycache", key = "'user:'+#id")
 public Users selid(int id){
     String key = "user";
     Users user = null;
     if(redisTemplate.hasKey(key)){
         System.out.println("Look it up in Redis");
         user = (Users) redisTemplate.opsForHash().get(key, key+":"+id);
         if(user==null){
             user = this.seluser(key, id); }}else {
         System.out.println("Find in DB");
         user = this.seluser(key, id);
     }
     return user;
 }
​
 // Redis uses the map structure to store keys.
 public Users seluser(String key,int id){
     Users  user = um.selid(id);
     HashMap<String, Users> map = new HashMap<String, Users>();
     map.put(key+":"+id, user);
     redisTemplate.opsForHash().putAll(key, map);
     redisTemplate.expire(key, 1000, TimeUnit.SECONDS);
     return user;
 }
 ​
Copy the code

Usercontroller.java add control method ();

     @GetMapping("/selid")
     public Users selid(int id){
         return us.selid(id);
     };
Copy the code

Main program @enablecaching Enables the Spring Cache caching function.

SpringBootRun.Java

 @EnableCaching
 @SpringBootApplication
 public class SpringBootRun {
     public static void main(String[] args) { ConfigurableApplicationContext run = SpringApplication.run(SpringBootRun.class, args); }}Copy the code

The program performs the first callback from the database and adds to reIDS memory; Next time if you view the same data directly according to the key from the memory can be obtained!!If the program is closed! Memory data disappeared… The next startup execution will get data from redis local! In memory for next access…

Cache comment details

  • @cacheconfig: Used to configure common cache configurations that will be used in this class. @cacheconfig (cacheNames = “Users “) : The content returned from this data access object is configured to be stored in a cache object named Users. We can also omit this annotation and define the name of the cache set by @cacheable ourselves.
  • @cacheable: Declares that the return values of all methods/methods under a class on a method/class are added to JVM memory. Value, cacheNames: Two equivalent parameters cacheNames is new to Spring 4 and used as the alias of value to specify the cache storage collection name. With the addition of @Cacheconfig in Spring 4, the value attribute is not required in Spring 3. Key: The key value of the cache object stored in the Map collection is not required. By default, all parameters of the function are used as the key value. SpEL @cacheable (key = “# parameter name “) condition: SpEL expressions are only cached if the expression conditions are met, for example: @cacheable (key = “#p0”, condition = “#p0.length() < 3”) indicates that AAA users will not be cached if the first parameter is less than 3 in length. Readers can experiment on their own. .
  • @cachePUT: It takes arguments similar to @cacheable except that it actually calls a function every time, so it’s used for adding and modifying data. The database calls methods to modify the data, of course, the data in memory also need to change! Don’t forget to update Redsi
  • @cacheevict is configured for functions and is usually used in delete methods to remove data from the cache. Database call delete method, there is no data in the database, there is no need to keep it in memory, according to the key delete memory cache ~

Springboot uses SLF4J for logging

Environment to prepare

Logging is a must in project development. When we use the Springboot framework, logging becomes extremely simple. Springboot has the SLF4J logging framework built in, so we just need to add dependencies and do some simple configuration.

  • It is important to note that the Lombok dependency requires a plug-in to be installed, which we can install online:
  • The idea of tools: Open File -- setting -- Plugins
  • Then search Lombok directly to install.
  • There are many other features of LombokSuch as the use@ Data annotations Getters, setters, and toString methods can be generated automatically for a bean

Rely on

Pom.xml introduces Lombok’s dependencies

 <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
 </dependency>
Copy the code

Set the log level to info in the YML file

 Set the log level to info
 logging:
   level:
     root: info
Copy the code

Or configure log display level Debug in application.properties

 logging.level.root=debug
Copy the code

test

Modify the controller UserController. Java

 @Slf4j              // Lombok annotation allows logging!!
 @CrossOrigin        // Indicates support for cross-domain operations: since SpringBoot is pre-and-post-separated, cross-server operations are designed (access between two projects).. Plus;
 @RestController     // All methods in this class return values as JSON.
 public class UserController {
     @Autowired
     private UserService us;
 ​
     @GetMapping("/selall")   // This is equivalent to @requestMapping GET of SpringMVC
     public List<Users> selall(a){
         return us.selall();
     }
 ​
     @GetMapping("/selid")
     public Users selid(int id){
         // Then you can use log...
         log.info("######### info #########");
         log.debug("######### debug #########");
         log.error("######### error #########");
 ​
         return us.selid(id);
     };
 }
 ​
Copy the code

Add an annotation for @slf4j. At this point, you’ll notice that you can use a log object directly in this class. This proves that your plug-ins and dependencies work.

Lombok includes many other annotations as well..

@NonNull

This annotation can be used in front of arguments to member methods or constructors and will automatically generate a non-null check for the argument and throw a null-pointer exception if the argument is null

 // Member method arguments annotated with @nonnull
 public String getName(@NonNull Person p){
     return p.getName();
 }
Copy the code

The practical effect is equivalent to:

 public String getName(@NonNull Person p){
     if(p==null) {throw new NullPointerException("person");
     }
     return p.getName();
 }
Copy the code

This works similarly with constructor parameters, so I won't give you any more examples.

@Getter/@Setter

This pair of annotations is used in front of a member variable to generate the corresponding get and set methods for the member variable. It is also possible to specify access modifiers for the generated method. The default is public.

 public class Programmer{
     @Getter
     @Setter
     private String name;
     @Setter(AccessLevel.PROTECTED)
     private int age;
     @Getter(AccessLevel.PUBLIC)
     private String language;
 }
Copy the code

The practical effect is equivalent to:

 public class Programmer{
     private String name;
     private int age;
     private String language;
 ​
     public void setName(String name){
         this.name = name;
     }
 ​
     public String getName(a){
         return name;
     }
 ​
     protected void setAge(int age){
         this.age = age;
     }
 ​
     public String getLanguage(a){
         returnlanguage; }}Copy the code

These two annotations can also be used directly on a class to generate corresponding GET and set methods for all non-static member variables in the class.

@ToString/@EqualsAndHashCode

These two annotations are also easier to understand, generating the toString, equals, and HashCode methods along with a canEqual method that determines whether an object is an instance of the current class. Only non-static and non-transient member variables of the class are used when generating the method

@NoArgsConstructor/@RequiredArgsConstructor /@AllArgsConstructor

All three of these annotations apply to classes

  • The first one and the third one are well understood and are generated for this classConstructor without argumentsandConstructor that contains all parameters
  • The second annotation uses all the tags in the class@ NonNull annotationsorA member variable with a final modifierGenerate the corresponding constructor
  • Of course, as with the previous annotations, member variables are non-static, and the @noargsconstructor annotation cannot be used if a class has a final modified member variable.

Each of the three annotations can specify access to the generated constructor, while the second annotation can also be used

  • @ RequiredArgsConstructor (staticName = “methodName”)
  • Returns an object generated by calling the corresponding constructor

@Data/@Value

@Data

  • The @data annotation is synthesized
  • @ Getter / @ Setter @ ToString @ EqualsAndHashCode @ RequiredArgsConstructor annotation
  • Where @requiredargsconstructor uses a member variable of the class with the @nonNULL annotation or final modifier
  • It can use @data (staticConstructor= “methodName”) to generate a static method that returns an object generated by calling the corresponding constructor.

@Value

  • The @value annotation is similar to @data
  • The difference is that it defines all member variables as private final by default and does not generate set methods.

@… More…