Spring-Data-JPA +Sharding-jdbc+druid数据库连接池 实现数据库读写分离

2023-11-03

关于Sharding-jdbc 简介

定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

  • 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。

官方文档地址:https://shardingsphere.apache.org/document/legacy/4.x/document/cn/overview/#sharding-jdbc

本文场景:

由于本地环境并没有使用Mysql主从复制,只是创建了二个库,其中database0作为主库,database1作为从库。主库进行增删改操作,从库进行查询操作,如下图为各个数据库的三张表。

主库:

丛库:

建表SQL

CREATE TABLE IF NOT EXISTS `author` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE IF NOT EXISTS `book` (
  `id` bigint(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

CREATE TABLE IF NOT EXISTS `book_author` (
  `book_id` bigint(10) NOT NULL,
  `author_id` bigint(10) NOT NULL,
  KEY `author_id` (`author_id`),
  KEY `book_id` (`book_id`),
  CONSTRAINT `author_id` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`),
  CONSTRAINT `book_id` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

Spring-Data-JPA源码:

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>
	<parent>
		<groupId>com.digipower</groupId>
		<artifactId>digipower-ureport</artifactId>
		<version>0.0.1-SNAPSHOT</version>
	</parent>
	<artifactId>digipower-oa</artifactId>

	<!-- 版本集中管理 -->
	<properties>
		<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
		<mybatis-spring-boot-starter.version>1.3.2</mybatis-spring-boot-starter.version>
		<mysql-connector-java.version>8.0.11</mysql-connector-java.version>
		<druid-spring-boot-starter.version>1.1.9</druid-spring-boot-starter.version>
		<commons-lang.version>2.6</commons-lang.version>
		<commons-codec.version>1.10</commons-codec.version>
		<commons-lang3.version>3.9</commons-lang3.version>
		<commons-net.version>3.6</commons-net.version>
		<commons-io.version>2.6</commons-io.version>
		<commons-collections.version>3.2.1</commons-collections.version>
		<commons-text.version>1.8</commons-text.version>
		<common-fileupload.version>1.3.1</common-fileupload.version>
	</properties>

	<dependencies>
		<!--springboot web 基础模块 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- springboot test 测试框架 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- springboot aop 基础模块 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<!--servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>${javax.servlet-api.version}</version>
		</dependency>
		<!--jpa orm 模块 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>${mysql-connector-java.version}</version>
			<scope>runtime</scope>
		</dependency>
		<!--数据库连接池druid 模块 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>${druid-spring-boot-starter.version}</version>
		</dependency>
		<!-- sharding-jdbc 实现读写分离 -->
	 	<dependency>
            <groupId>com.dangdang</groupId>
            <artifactId>sharding-jdbc-core</artifactId>
            <version>1.5.4</version>
        </dependency>
		<!-- Swagger2 -->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>2.7.0</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>2.7.0</version>
		</dependency>
		<!-- fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.48</version>
		</dependency>
		<!-- apache common 工具包 -->
		<!--common-lang 常用工具包 -->
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>${commons-lang.version}</version>
		</dependency>
		<!--commons-lang3 工具包 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>${commons-lang3.version}</version>
		</dependency>

		<!--commons-codec 加密工具包 -->
		<dependency>
			<groupId>commons-codec</groupId>
			<artifactId>commons-codec</artifactId>
			<version>${commons-codec.version}</version>
		</dependency>
		<!--commons-net 网络工具包 -->
		<dependency>
			<groupId>commons-net</groupId>
			<artifactId>commons-net</artifactId>
			<version>${commons-net.version}</version>
		</dependency>
		<!--common-io 工具包 -->
		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>${commons-io.version}</version>
		</dependency>
		<!--common-collection 工具包 -->
		<dependency>
			<groupId>commons-collections</groupId>
			<artifactId>commons-collections</artifactId>
			<version>${commons-collections.version}</version>
		</dependency>
		<!--common-fileupload 工具包 -->
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>${common-fileupload.version}</version>
		</dependency>
		<!-- common-text 工具包 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-text</artifactId>
			<version>${commons-text.version}</version>
		</dependency>
		<!-- lomback 工具包 -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.2</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
</project>

资源文件定义和程序入口

application.properties

# 指定服务端口
server.port=9098
# 指定服务 名称
# server.context-path=/ureport
#jpa配置
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
# MyBatis mysql8 主从配置
#spring.datasource.url=jdbc:mysql://127.0.0.1:3306/oasys?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
#spring.datasource.username=root
#spring.datasource.password=123456
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

##数据库配置
##数据库database0地址
database0.url=jdbc:mysql://127.0.0.1:3306/oasys?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
##数据库database0用户名
database0.username=root
##数据库database0密码
database0.password=123456
##数据库database0驱动
database0.driverClassName=com.mysql.cj.jdbc.Driver
##数据库database0名称
database0.databaseName=oasys

##数据库database1地址
database1.url=jdbc:mysql://127.0.0.1:3306/oasys_write?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
##数据库database1用户名
database1.username=root
##数据库database1密码
database1.password=123456
##数据库database1驱动
database1.driverClassName=com.mysql.cj.jdbc.Driver
##数据库database1名称
database1.databaseName=oasys_write
# Druid 配置
# 初始化时建立物理连接的个数
spring.datasource.druid.initial-size=5
# 最大连接池数量
spring.datasource.druid.max-active=30
# 最小连接池数量
spring.datasource.druid.min-idle=5
# 获取连接时最大等待时间,单位毫秒
spring.datasource.druid.max-wait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.druid.time-between-eviction-runs-millis=60000
# 连接保持空闲而不被驱逐的最小时间
spring.datasource.druid.min-evictable-idle-time-millis=300000
# 用来检测连接是否有效的sql,要求是一个查询语句
spring.datasource.druid.validation-query=SELECT 1 FROM DUAL
# 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
spring.datasource.druid.test-while-idle=true
# 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.druid.test-on-borrow=false
# 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
spring.datasource.druid.test-on-return=false
# 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。
spring.datasource.druid.pool-prepared-statements=true
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。
spring.datasource.druid.max-pool-prepared-statement-per-connection-size=50
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计
#spring.datasource.druid.filters=stat,wall
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
# 合并多个DruidDataSource的监控数据
spring.datasource.druid.use-global-data-source-stat=true
# 配置sql 注入方式
spring.datasource.druid.filters=stat,log4j

#日志文件配置
logging.config=classpath:logback.xml


package com.zzg;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableTransactionManagement(proxyTargetClass = true)
@EnableConfigurationProperties
@EnableJpaRepositories(basePackages = {"com.zzg.dao"})
public class Application {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SpringApplication.run(Application.class, args);
	}

}

 

实体层和dao层

package com.zzg.entity;

import java.io.Serializable;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name="author")
public class Author implements Serializable {
	@Id
    @GeneratedValue
    private Long id;

	@Column(name="name")
    private String name;

    @ManyToMany(mappedBy = "authors", fetch=FetchType.EAGER)
    private Set<Book> books;

    public Author() {
        super();
    }

    public Author(String name) {
        super();
        this.name = name;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Book> getBooks() {
        return books;
    }

    public void setBooks(Set<Book> books) {
        this.books = books;
    }

    @Override
    public String toString() {
    	 return "id is:" + id + "name is:" + name;
    }
}
package com.zzg.entity;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@SuppressWarnings("serial")
@Entity
@Table(name="book")
public class Book implements Serializable {
	@Id
    @GeneratedValue
    private Long id;
	
	@Column(name="name")
    private String name;

    @ManyToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinTable(name = "book_author", joinColumns = {
            @JoinColumn(name = "book_id", referencedColumnName = "id")}, inverseJoinColumns = {
            @JoinColumn(name = "author_id", referencedColumnName = "id")})
    private Set<Author> authors;

    public Book() {
        super();
    }

    public Book(String name) {
        super();
        this.name = name;
        this.authors = new HashSet<>();
    }

    public Book(String name, Set<Author> authors) {
        super();
        this.name = name;
        this.authors = authors;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Set<Author> getAuthors() {
        return authors;
    }

    public void setAuthors(Set<Author> authors) {
        this.authors = authors;
    }

    @Override
    public String toString() {
        return "id is:" + id + "name is:" + name;
    }
}
package com.zzg.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.zzg.entity.Author;

@Repository
public interface AuthorRepository extends JpaRepository<Author, Long> {

}
package com.zzg.dao;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.zzg.entity.Book;

@Repository
public interface BookRepository extends JpaRepository<Book, Long> {
	public Book findById(Long id);
}

Sharding-jdbc 读写分离核心配置:

package com.zzg.config;

import javax.sql.DataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;

/**
 * 主库(写库)
 * @author Administrator
 *
 */
@Data
@ConfigurationProperties(prefix = "database0")
@Component
public class Database0Config {
	private String url;
	private String username;
	private String password;
	private String driverClassName;
	private String databaseName;

	public DataSource createDataSource() {
		DruidDataSource result = new DruidDataSource();
		result.setDriverClassName(getDriverClassName());
		result.setUrl(getUrl());
		result.setUsername(getUsername());
		result.setPassword(getPassword());
		return result;
	}
}
package com.zzg.config;

import javax.sql.DataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import com.alibaba.druid.pool.DruidDataSource;
import lombok.Data;

/**
 * 丛库(读库)
 * @author Administrator
 *
 */
@Data
@ConfigurationProperties(prefix = "database1")
@Component
public class Database1Config {
	private String url;
	private String username;
	private String password;
	private String driverClassName;
	private String databaseName;

	public DataSource createDataSource() {
		DruidDataSource result = new DruidDataSource();
		result.setDriverClassName(getDriverClassName());
		result.setUrl(getUrl());
		result.setUsername(getUsername());
		result.setPassword(getPassword());
		return result;
	}
}
package com.zzg.config;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.alibaba.druid.pool.DruidDataSource;
import com.dangdang.ddframe.rdb.sharding.api.MasterSlaveDataSourceFactory;
import com.dangdang.ddframe.rdb.sharding.api.strategy.slave.MasterSlaveLoadBalanceStrategyType;

/**
 * sharding-jdbc 数据库读写分离
 * 
 * @author Administrator
 *
 */
@Configuration
public class ShardingJdbcConfig {

	@Autowired
	private Database0Config database0Config;

	@Autowired
	private Database1Config database1Config;

	@Bean
	public DataSource getDataSource() throws SQLException {
		return buildDataSource();
	}

	private DataSource buildDataSource() throws SQLException {
		// 设置从库数据源集合
		Map<String, DataSource> slaveDataSourceMap = new HashMap<>();
		slaveDataSourceMap.put(database1Config.getDatabaseName(), database1Config.createDataSource());


		// 获取数据源对象
		DataSource dataSource = MasterSlaveDataSourceFactory.createDataSource("masterSlave",
				database0Config.getDatabaseName(), database0Config.createDataSource(), slaveDataSourceMap,
				MasterSlaveLoadBalanceStrategyType.getDefaultStrategyType());
		return dataSource;
	}

}

功能测试(test)定义:

package com.zzg.test;

import java.util.Arrays;
import java.util.Set;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import com.zzg.annotation.TargetDateSource;
import com.zzg.config.DataSourceConfig;
import com.zzg.dao.AuthorRepository;
import com.zzg.dao.BookRepository;
import com.zzg.entity.Author;
import com.zzg.entity.Book;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ManyToManyTest {

	
	@Autowired
	private AuthorRepository authorRepository;
	
	@Autowired
	private BookRepository bookRepository;
	
    // 写库
	@Test
	public void insertManyToMany() {
		
		Author lewis = new Author("Lewis");
        Author mark = new Author("Mark");
        Author peter = new Author("Peter");

        Book spring = new Book("Spring in Action");
        spring.getAuthors().addAll(Arrays.asList(lewis, mark));

        Book springboot = new Book("Spring Boot in Action");
        springboot.getAuthors().addAll(Arrays.asList(lewis, peter));

        bookRepository.save(Arrays.asList(spring, springboot));
		
	}
	
    // 读库
	@Test
	public void selectManyToMany() {
		Book book = bookRepository.findOne(2L);
		System.out.println(book.toString());
		
		book.getAuthors().stream().forEach(item->{
			System.out.println(item.toString());
		});
		
		
	}
	

}

写库执行插入正常:

读库读取数据异常:

造成查询异常的原因是由于读写库的数据没有进行主从同步,导致查询指定数据提示空指针异常,这也进一步验证我们的读写分离的功能是OK 的 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring-Data-JPA +Sharding-jdbc+druid数据库连接池 实现数据库读写分离 的相关文章

随机推荐

  • 以太坊合并后,Layer2 何去何从?

    转载原文链接 http www btcwbo com 5671 html 在2022年以太坊开发者峰会上 联合创始人威尔基说 以太坊预计将信号标准链与主网络合并 通过8月份的TheMerge 合并 升级 这样以太坊就可以证明 POS 共识算
  • 英雄联盟-经验砖块

    作为一个LOL老玩家 如果说对游戏细节把握不到位 这是说不过去的 我们时常说道发育为重 那么发育包括等级和装备 我们是不是应该更精细的把我等级呢 今天我们来探究一下 赖线从小兵身上我们能获得多少经验等级 问题1 每个小兵有多少经验值呢 近战
  • 勒索软件攻击防护中的6个常见错误

    勒索软件攻击已经成为影响所有行业和组织的大问题 考虑到这些攻击可能对企业造成的影响 安全专业人员正在尝试以各种方式保护企业的网络 应用和数据 然而 但随着勒索攻击威胁形势的不断变化 很多错误的做法可能会阻碍企业勒索防护计划的有效执行 并使组
  • 最详细的Transformer讲解,Attention Is All You Need

    前言 Attention Is All You Need Google Brain 引用量 30255 1 3 ResNet 贡献 Transformer 是第一个完全依赖自注意力来计算其输入和输出表示而不是使用序列对齐的RNN和CNN 一
  • C++标准库头文件(工具库->csetjmp)

    参考网址 https zh cppreference com w cpp header https www runoob com cplusplus cpp standard library html 工具库 csetjmp 保存执行语境的
  • Android-Fragment详解

    Fragment是Android最常使用的控件之一 一般情况下 我们会在首页使用到 有的小伙伴也会单Activity和多Fragment的App 我总结了一下我了解的Fragment知识 希望对看这篇文章的小伙伴有所帮助 Fragment的
  • USB:Type-A、Type-B、Type-C、miniUSB、microUSB接口类型区分

    通用串行总线 universal serial bus USB 自推出以来 成功替代串口和并口 已经成为计算机和各种设备不可或缺的接口 USB的优点不用多说 网上有很多 今天主要小结一下USB的各种接口类型 避免被各种各样的USB名字搞晕
  • SQL调优案例1

    SQL语句的执行顺序 1 LIMIT 语句 分页查询是最常用的场景之一 但也通常也是最容易出问题的地方 比如对于下面简单的语句 一般 DBA 想到的办法是在 type name create time 字段上加组合索引 这样条件排序都能有效
  • 遥感影像识别-利用较大数据集训练

    回顾 经过前两次的思考 最终还是回到最初的想法上来 利用大量比较合理的电子地图进行模型的训练 看能否产生较好的效果 前两次的博文链接如下 遥感影像识别 制作数据集 遥感影像识别 训练策略 本次训练所使用的数据集 地域覆盖了全国几个主要的城市
  • Elasticsearch入门笔记

    ES入门笔记 1 概述 1 1 什么是全文检索 1 2 es的应用场景 1 3 参考资料 2 核心概念 3 进阶 3 1 集群 3 1 1 单节点 3 1 2 双节点 故障转移 3 1 3 三节点 水平扩容 3 1 4 应对故障 3 2 路
  • jdk1.8 Lambda 实战

    我们用常用的实例来感受 Lambda 带来的便利 替代匿名内部类 过去给方法传动态参数的唯一方法是使用内部类 比如 1 Runnable 接口 new Thread new Runnable Override public void run
  • 【HJ40】统计字符

    题目描述 输入一行字符 分别统计出包含英文字母 空格 数字和其它字符的个数 本题包含多组输入 数据范围 输入的字符串长度满足 1 1000 输入描述 输入一行字符串 可以有空格 输出描述 统计其中英文字符 空格字符 数字字符 其他字符的个数
  • CSS字体

    CSS字体属性定义文本中的字体 指定字体 font family属性 指定在文本中使用的字体系列 如 body font family sans serif 从sans serif字体系列中选择一个字体 并将其应用到body元素中 CSS字
  • 关于idea中提交svn时一直显示performing VCS refresh

    vue前端项目会自动生成node modules文件夹 在首次上传版本到svn的时候 不要提交node modules文件夹 否则node modules文件也会在版本控制中 那么在npm install之后 灾难就来了 Version C
  • 21年新版kali安装

    第一步 官网下载kali系统镜像文件 官网地址 www kali org 访问kali官网 点击上方GET KALI 然后点击Bare Metal 旁边的Virtual Machines是专门为虚拟机设计的 相比更为轻量 安装过程也比较简单
  • 配置Dot1q终结子接口实现跨设备VLAN间通信示例

    示例图 一 实验目的 1 配置Dot1q终结子接口实现跨设备VLAN间通信示例 二 注意事项 1 Dot1q终结子接口和QinQ终结子接口不支持透传不带VLAN Tag的报文 收到不带VLAN Tag的报文会直接丢弃 2 由于三层以太网子接
  • 前端传输数组条件查询,myslq使用in

    mysql语句使用in条件查询 从前端获取数组 1 post请求体中的json对象 Data public class UserSearchParam String userName NotNull Integer pageNum NotN
  • maomi

    我到家啦 你今天怎么样 需要我帮忙查资料么 转载于 https www cnblogs com loverain archive 2009 07 02 1515416 html
  • 每日一题:7. 分糖果(C++)

    每日一题 7 分糖果 C 题目 Alice 有 n 枚糖 其中第 i 枚糖的类型为 candyType i Alice 注意到她的体重正在增长 所以前去拜访了一位医生 医生建议 Alice 要少摄入糖分 只吃掉她所有糖的 n 2 即可 n
  • Spring-Data-JPA +Sharding-jdbc+druid数据库连接池 实现数据库读写分离

    关于Sharding jdbc 简介 定位为轻量级Java框架 在Java的JDBC层提供的额外服务 它使用客户端直连数据库 以jar包形式提供服务 无需额外部署和依赖 可理解为增强版的JDBC驱动 完全兼容JDBC和各种ORM框架 适用于