00.springboot 操作数据库的封装
参考https://gitee.com/owenwangwen/open-capacity-platform项目
springboot springcloud中需要经常使用到关系型数据库或者非关系型数据库,这里做了一个maven的基本模块,别人需要使用关系型或非关系数据库redis时,加入maven依赖即可,代码如下:
<!-- 关系型和非关系型数据库配置 --><dependency><groupId>com.open.capacity</groupId><artifactId>open-db-core</artifactId><version>${unieap.platform.version}</version></dependency>
open-db-core的构思,加入druid数据源操作mysql或者oracle同时支持redis的存储。
pom文件
<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.neusoft.unieap</groupId>
<artifactId>micro-unieap-platform</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>open-db-core</artifactId>
<dependencies><!-- 加入redis的处理 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- 使用jasypt对springboot的datasource密码加密 --><dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>1.8</version></dependency><!-- 增加jdbc的支持 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- owen加入druid数据源 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.0.31</version></dependency><!-- owen增加oracle的支持 --><dependency><groupId>com.oracle</groupId><artifactId>ojdbc6</artifactId><version>11.2.0.3</version></dependency><!-- owen增加mybatis的支持 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.0</version></dependency><!-- lombok setter getter 标签 --><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- 字符串操作的commons包 --><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId></dependency><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId></dependency><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency></dependencies>
</project>
application.yml文件
server:
port: 7777
tomcat:
uri-encoding: UTF-8
spring:
application:
name: unieap-crontab-core
http:
encoding:
charset: utf8
force: true
enabled: true
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@127.0.0.1:1521:orcl
username: crm_owner_user
password: bss_crm_test
filters: stat,wall
redis:
database: 1
cluster:
nodes:
130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001
timeout: 1000 # 连接超时时间(毫秒)
pool:max-active: 10 # 连接池最大连接数(使用负值表示没有限制)max-idle: 8 # 连接池中的最大空闲连接min-idle: 2 # 连接池中的最小空闲连接max-wait: 100 # 连接池最大阻塞等待时间(使用负值表示没有限制)
mybatis:
config-location: classpath:mybatis.cfg.xml
mapper-locations: classpath*:com/neusoft/*/dao/.xml
logging:
level:
root: INFO
org.hibernate: INFO
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
com.neusoft: DEBUG
com.netflix: DEBUG #用于心跳检测输出的日志
代码文件结构如下
redis代码说明
redis是key-value的存储,为了保证redis的性能,可以将数据分片存储,例如将oauth2的信息分片存储
"access:111111";
"auth_to_access:111111";
"auth:111111";
"refresh_auth:111111";
"access_to_refresh:111111";
"refresh:111111";
"refresh_to_access:111111";
"client_id_to_access:111111";
"uname_to_access:111111";
key都是111111,加前缀分散存储,废话不多说回到redis构建部分,java需要一个key-value序列化的工具 代码如下
package com.neusoft.unieap.redis.config.util;
/**
- @author 作者 owen E-mail: 624191343@qq.com
- @version 创建时间:2017年7月12日 上午10:50:19
- 类说明
*/
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
// 此时定义的序列化操作表示可以序列化所有类的对象,当然,这个对象所在的类一定要实现序列化接口
public class RedisObjectSerializer implements RedisSerializer<Object> {
// 为了方便进行对象与字节数组的转换,所以应该首先准备出两个转换器
private Converter<Object, byte[]> serializingConverter = new SerializingConverter();
private Converter<byte[], Object> deserializingConverter = new DeserializingConverter();
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; // 做一个空数组,不是null
@Override
public byte[] serialize(Object obj) throws SerializationException {if (obj == null) { // 这个时候没有要序列化的对象出现,所以返回的字节数组应该就是一个空数组return EMPTY_BYTE_ARRAY;}return this.serializingConverter.convert(obj); // 将对象变为字节数组
}@Override
public Object deserialize(byte[] data) throws SerializationException {if (data == null || data.length == 0) { // 此时没有对象的内容信息return null;}return this.deserializingConverter.convert(data);
}
}
序列化工具准备好后,配置redistemplate操作类注入到spring容器中供别人操作使用
package com.neusoft.unieap.redis.config;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import com.neusoft.unieap.redis.config.util.RedisObjectSerializer;
/**
- @author 作者 owen E-mail: 624191343@qq.com
@version 创建时间:2017年7月12日 下午3:28:10 类说明br/>*/
@Configuration
//没有此属性就不会装配bean
@ConditionalOnProperty( name="spring.redis.cluster.nodes" , matchIfMissing=false)
public class RedisConfig {@Bean("redisTemplate")br/>@Primary
public RedisTemplate<String, Object> getRedisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
redisTemplate.setConnectionFactory(factory);RedisSerializer stringSerializer = new StringRedisSerializer(); RedisSerializer redisObjectSerializer = new RedisObjectSerializer(); redisTemplate.setKeySerializer(stringSerializer); // key的序列化类型 redisTemplate.setHashKeySerializer(stringSerializer); redisTemplate.setValueSerializer(redisObjectSerializer); // value的序列化类型 redisTemplate.afterPropertiesSet(); redisTemplate.opsForValue().set("hello", "wolrd");return redisTemplate;
}
}
这时,redis的封装已经结束,我们开始下一步关系型数据库的构建,报文采取的是oracle数据库,支持单数据源以及多数据源的方式。
单数据源整合druid的代码如下
package com.neusoft.unieap.db.config;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
/**
- @author 作者 owen E-mail: 624191343@qq.com
- @version 创建时间:2017年11月9日 下午1:47:37 类说明
*/
@Configuration
@ConditionalOnProperty(name = { "spring.datasource.enable.dynamic" }, matchIfMissing = true)
public class DruidConfig {
// 将druid纳入监控步骤如下
// 1通过springboot配置文件注入datasource中
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = false)
public DataSource druidDataSource() {return DataSourceBuilder.create().type(DruidDataSource.class).build();
}// 2.StatViewServlet注入到spring中
// Druid内置提供了一个StatViewServlet用于展示Druid的统计信息。
// 这个StatViewServlet的用途包括:
// 提供监控信息展示的html页面
// 提供监控信息的JSON API
// 注意:使用StatViewServlet,建议使用druid 0.2.6以上版本。
// 注入第三方没有注解的servlet
@Bean
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = false)
public ServletRegistrationBean druidServlet() { // 主要实现WEB监控的配置处理ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*"); // 现在要进行druid监控的配置处理操作servletRegistrationBean.addInitParameter("allow", "127.0.0.1,130.75.131.208"); // 白名单servletRegistrationBean.addInitParameter("deny", "192.168.28.200"); // 黑名单servletRegistrationBean.addInitParameter("loginUsername", "owen"); // 用户名servletRegistrationBean.addInitParameter("loginPassword", "1q2w3e4r"); // 密码servletRegistrationBean.addInitParameter("resetEnable", "false"); // 是否可以重置数据源return servletRegistrationBean;
}// 3.对请求进行过滤
// WebStatFilter注入到spring容器中
// 注入第三方没有注解的过滤器
@Bean
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "com.alibaba.druid.pool.DruidDataSource", matchIfMissing = false)
public FilterRegistrationBean filterRegistrationBean() {FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();filterRegistrationBean.setFilter(new WebStatFilter());filterRegistrationBean.addUrlPatterns("/*"); // 所有请求进行监控处理filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*");return filterRegistrationBean;
}
}
此时单库的数据源集成druid mybatis已经集成完毕,下面说明动态数据源的配置。
1.需要继承spring的动态数据源
package com.neusoft.unieap.db.config.dynamic.config.util;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
- @author 作者 owen E-mail: 624191343@qq.com
- @version 创建时间:2017年11月10日 下午3:52:46
类说明
*/
public class DynamicDataSource extends AbstractRoutingDataSource{private Map<Object, Object> datasources;
public DynamicDataSource() {
datasources = new HashMap<>();super.setTargetDataSources(datasources);
}
public <T extends DataSource> void addDataSource(DataSourceKey key, T data) {
datasources.put(key, data);
}@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDataSourceKey();
}
}
2.定义两个库的标识
package com.neusoft.unieap.db.config.dynamic.config.util;
/**
- 数据源定义
- @author owen
- @create 2017年7月2日
*/
public enum DataSourceKey {
crm, bill
}
3.定义线程变量,供每个调用时分配动态数据源
package com.neusoft.unieap.db.config.dynamic.config.util;
/**
- 用于数据源切换
- @author owen
@create 2017年7月2日
*/
public class DataSourceHolder {
private static final ThreadLocal<DataSourceKey> dataSourceKey = new ThreadLocal<>();public static DataSourceKey getDataSourceKey() {
return dataSourceKey.get();
}public static void setDataSourceKey(DataSourceKey type) {
dataSourceKey.set(type);
}public static void clearDataSourceKey() {
dataSourceKey.remove();
}
}
4.springboot整合动态数据源双库配置
package com.neusoft.unieap.db.config.dynamic.config;
import java.util.ArrayList;
import java.util.List;
import javax.sql.DataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.neusoft.unieap.db.config.dynamic.config.util.DataSourceKey;
import com.neusoft.unieap.db.config.dynamic.config.util.DynamicDataSource;
/**
- 定义数据源
- @author owen
@create 2017年7月2日br/>*/
@Configuration
@PropertySource("classpath:jdbc.test.properties")
@ConditionalOnProperty(name = { "spring.datasource.enable.dynamic" }, matchIfMissing = false, havingValue = "true")
public class DynamicDataSourceConfig {private Logger logger = LoggerFactory.getLogger(DynamicDataSourceConfig.class);
// crm库br/>@Value("${spring.datasource.primary.url:#{null}}")
private String primaryDbUrl;
@Value("${spring.datasource.primary.username: #{null}}")
private String primaryUsername;br/>@Value("${spring.datasource.primary.password:#{null}}")
private String primaryPassword;// bill库br/>@Value("${spring.datasource.secondary.url:#{null}}")
private String secondaryDbUrl;
@Value("${spring.datasource.secondary.username: #{null}}")
private String secondaryUsername;br/>@Value("${spring.datasource.secondary.password:#{null}}")
private String secondaryPassword;// 公共配置br/>@Value("${spring.datasource.driverClassName:#{null}}")
private String driverClassName;br/>@Value("${spring.datasource.initialSize:#{null}}")
private Integer initialSize;br/>@Value("${spring.datasource.minIdle:#{null}}")
private Integer minIdle;br/>@Value("${spring.datasource.maxActive:#{null}}")
private Integer maxActive;br/>@Value("${spring.datasource.maxWait:#{null}}")
private Integer maxWait;br/>@Value("${spring.datasource.timeBetweenEvictionRunsMillis:#{null}}")
private Integer timeBetweenEvictionRunsMillis;br/>@Value("${spring.datasource.minEvictableIdleTimeMillis:#{null}}")
private Integer minEvictableIdleTimeMillis;br/>@Value("${spring.datasource.validationQuery:#{null}}")
private String validationQuery;br/>@Value("${spring.datasource.testWhileIdle:#{null}}")
private Boolean testWhileIdle;br/>@Value("${spring.datasource.testOnBorrow:#{null}}")
private Boolean testOnBorrow;br/>@Value("${spring.datasource.testOnReturn:#{null}}")
private Boolean testOnReturn;br/>@Value("${spring.datasource.poolPreparedStatements:#{null}}")
private Boolean poolPreparedStatements;br/>@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize:#{null}}")
private Integer maxPoolPreparedStatementPerConnectionSize;br/>@Value("${spring.datasource.filters:#{null}}")
private String filters;br/>@Value("{spring.datasource.connectionProperties:#{null}}")
private String connectionProperties;// 不需要纳入spring容器
public DataSource crmDataSource() {
DruidDataSource crmDataSource = new DruidDataSource();
crmDataSource.setUrl(this.primaryDbUrl);
crmDataSource.setUsername(this.primaryUsername);// 用户名
crmDataSource.setPassword(this.primaryPassword);// 密码
crmDataSource.setDriverClassName(driverClassName);
this.setCommons(crmDataSource);
return crmDataSource;
}// 不需要纳入spring容器
public DataSource billDataSource() {
DruidDataSource billDataSource = new DruidDataSource();
billDataSource.setUrl(secondaryDbUrl);
billDataSource.setUsername(secondaryUsername);// 用户名
billDataSource.setPassword(secondaryPassword);// 密码
billDataSource.setDriverClassName(driverClassName);this.setCommons(billDataSource);return billDataSource;
}
@Bean // 只需要纳入动态数据源到spring容器br/>@Primary
public DataSource dataSource() {
DynamicDataSource dataSource = new DynamicDataSource();
DataSource crmDataSource = this.crmDataSource();
DataSource billDataSource = this.billDataSource();
dataSource.addDataSource(DataSourceKey.crm, crmDataSource);
dataSource.addDataSource(DataSourceKey.bill, billDataSource);
dataSource.setDefaultTargetDataSource(crmDataSource);return dataSource;
}
@Bean
public StatFilter statFilter() {
StatFilter statFilter = new StatFilter();
statFilter.setLogSlowSql(true);
statFilter.setMergeSql(true);
statFilter.setSlowSqlMillis(1000);return statFilter;
}
@Bean
public WallFilter wallFilter() {
WallFilter wallFilter = new WallFilter();// 允许执行多条SQL WallConfig config = new WallConfig(); config.setMultiStatementAllow(true); wallFilter.setConfig(config);return wallFilter;
}
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(new StatViewServlet());
servletRegistrationBean.addUrlMappings("/druid/*");
return servletRegistrationBean;
}@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {return new JdbcTemplate(dataSource);
}
@Bean
public NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource) {return new NamedParameterJdbcTemplate(dataSource);
}
private void setCommons(DruidDataSource dataSource) {
// configuration
if (initialSize != null) {
dataSource.setInitialSize(initialSize);
}
if (minIdle != null) {
dataSource.setMinIdle(minIdle);
}
if (maxActive != null) {
dataSource.setMaxActive(maxActive);
}
if (maxWait != null) {
dataSource.setMaxWait(maxWait);
}
if (timeBetweenEvictionRunsMillis != null) {
dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
}
if (minEvictableIdleTimeMillis != null) {
dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
}
if (validationQuery != null) {
dataSource.setValidationQuery(validationQuery);
}
if (testWhileIdle != null) {
dataSource.setTestWhileIdle(testWhileIdle);
}
if (testOnBorrow != null) {
dataSource.setTestOnBorrow(testOnBorrow);
}
if (testOnReturn != null) {
dataSource.setTestOnReturn(testOnReturn);
}
if (poolPreparedStatements != null) {
dataSource.setPoolPreparedStatements(poolPreparedStatements);
}
if (maxPoolPreparedStatementPerConnectionSize != null) {
dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
}if (connectionProperties != null) {dataSource.setConnectionProperties(connectionProperties); }List<Filter> filters = new ArrayList<>(); filters.add(statFilter()); filters.add(wallFilter()); dataSource.setProxyFilters(filters);
}
@Bean // 将数据源纳入spring事物管理br/>@Primary
public DataSourceTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}@Bean
public PlatformTransactionManager annotationDrivenTransactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
此处一个支持单数据源或者多数据源的关系型数据库核心模块已经集成完毕,支持redis-cluster分布式redis存储的nosql核心模块也已经集成完毕,可以根据业务看是否集成elasticsearch mogondb等存储到此模块,目前我们只使用oracle和redis,只做了以上封装。
转载于:https://blog.51cto.com/13005375/2053873
00.springboot 操作数据库的封装相关推荐
- SpringBoot操作数据库
SpringBoot操作数据库 1.SpringData简介 对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring D ...
- 狂神说笔记——SpringBoot操作数据库22-5
SpringBoot操作数据库(5) 8.富文本编辑器 1.简介 思考:我们平时在博客园,或者CSDN等平台进行写作的时候,有同学思考过他们的编辑器是怎么实现的吗? 在博客园后台的选项设置中,可以看到 ...
- 数据库封装 sql server mysql_mysql操作数据库进行封装实现增删改查功能
SqlTool.class.php class SqlTool{ private $conn; private $host = "localhost"; private $user ...
- boot spring test 文档_SpringBoot入门建站全系列(五)使用Spring-data-jpa操作数据库
SpringBoot入门建站全系列(五)使用Spring-data-jpa操作数据库 SpringBoot操作数据库有多种方式,如 JDBC直接操作:太古老了,没人愿意这样玩 Mybatis插件:比较 ...
- node之操作数据库
目录 mongoDB数据库的操作 开启一个服务器和静态服务器 server.js 对所有的路径的设置 index.js user.js => 方式1 链接数据库,并且操作数据库 user.js ...
- SpringBoot(13)--- 数据库操作(集成MyBatis)
SpringBoot 数据库操作(集成MyBatis) Spring对持久化的支持,不单只支持JDBC,为各种支持的持久化技术都提供了简单的模板和回调: ORM持久化技术 模板类 JDBC(JdbcT ...
- thinkphp mysql类_PHP封装类似thinkphp连贯操作数据库的Db类(简单版)
为了方便操作Mysql数据库, 封装类似thinkphp连贯操作数据库的Db类<?php header("Content-Type:text/html;charset=utf-8&qu ...
- SpringBoot的数据库操作
SpringBoot的数据库操作 1.添加依赖,一个是我们数据库也要用到的data-jpa(简化程序与数据库之间的交互),一个数据库驱动.(文件名:pom.xml),基本的配置在建好项目的时候就有了, ...
- php db类 应用实例,PHP封装类似thinkphp连贯操作数据库Db类与简单应用示例
本文实例讲述了PHP封装类似thinkphp连贯操作数据库Db类与简单应用.分享给大家供大家参考,具体如下: header("Content-Type:text/html;charset=u ...
- SpringBoot 学习二:操作数据库
2019独角兽企业重金招聘Python工程师标准>>> 本文将从以下几个方面介绍: 前言 配置数据源 SpringBoot 整合 Mybatis SpringBoot 整合 Jdbc ...
最新文章
- redis 通过aof日志恢复_Redis之-aof恢复
- python.freelycode.com-Python日期时间处理: datestuff
- 3、编写一个prod()函数,可以接受一个list并利用reduce()求积
- DirectX10一变换(三)
- oracle中pdb,Oracle12c数据库创建pdb的3种方法
- intellij选择困难症Spring Batch/Data JPA/Integration/MVC/Security/Web Flow/Web Services到底选哪个?
- mysql 手动配置服务器_Win7系统下手动配置Apache+PHP+MySQL环境WEB服务器 -电脑资料...
- fiddler证书 iphone_使用Fiddler进行iOS APP的HTTP/HTTPS抓包
- 人脸识别**检测技术讨论:基于背景人脸相对运动的**判断方法
- 关于Base32和Base64的一点区分注意
- php 简转繁体,PHP简体转繁体——MediaWiki-zhconvert
- C#使用struct直接转换下位机数据的示例代码
- linux虚拟机双显卡,Kali Linux 2.0 安装 NVIDIA显卡驱动实现双显卡(联想笔记本)
- 三代Pacbio进行细菌16S全长测序
- Mac环境下安装hadoop
- 关于Intriguing properties of neural networks的理解
- ChatGPT/大模型+零代码,给中小企业带来哪些机会?
- golang并发资源的竞争
- linux HID驱动分析
- 中国陷入超低生育率陷阱
热门文章
- paip.验证码识别---使用字符集的选取
- paip.svn服务服务器安装配置
- 阿里云资深技术专家杨皓然:Serverless 是正在发生的未来
- 拥抱开源,需要跨越哪些鸿沟? ————《Open Life —— 有关开源的哲学》读后感...
- 【静脉检测】基于matlab手指静脉图像检测【含Matlab源码 1654期】
- 【图像分割】基于matlab超像素SFFCM图像分割【含Matlab源码 1374期】
- 【飞行器】基于matlab多源信息融合算法多旋翼无人机组合导航系统【含Matlab源码 1267期】
- 【优化求解】基于matlab GUI模拟退火算法求解全局最大值最小值问题【含Matlab源码 1242期】
- 【优化算法】蝴蝶优化算法(MBO)【含Matlab源码 952期】
- 【车流量计数】基于matlab光流场交通汽车检测跟踪【含Matlab源码 504期】