“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 projectSpringBootYYBJ
Application 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 class
Constructor without arguments
andConstructor that contains all parameters
- The second annotation uses all the tags in the class
@ NonNull annotations
orA member variable with a final modifier
Generate 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…