最近同事有个小项目让我写写,其实刚开始的时候,我是拒绝的,因为总不能说,你让我写我就写吧。而且这个事情还得java写。好吧,关注springboot已经很久很久了,光说不练嘴把式。据说springboot是一个相当简单,相当容易框架,把java多年来一直饱受诟病的多配置文件这个优点给升华了。一直没实践过,于是乎这就是一个的机会。
项目内容其实很简单就是从三个数据库取数据,整合后写入一个第三方接口。从三个数据库读取数据,自然是先定义三个数据源,不多说,贴代码。
读配置文件 DataSourceConfig.java
package net.springboot.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
//spring.datasource.primary
//配置文件 application.properties 中的项对应即可,
@Bean(name = "primaryDataSource")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
//类似于primaryDataSource
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
//类似于primaryDataSource
@Bean(name = "thirdDataSource")
@ConfigurationProperties(prefix = "spring.datasource.third")
public DataSource thirdDataSource() {
try
{
return DataSourceBuilder.create().build();
}
catch(Exception e)
{
return null;
}
}
}
PrimaryConfig.java
package net.springboot.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
//开启事务管理
@EnableTransactionManagement
@EnableJpaRepositories(
//在这个JpaRepositories中用到的事务管理器,这里是Ref,即引用
transactionManagerRef = "PrimaryTransactionManager",
//实体类工厂
entityManagerFactoryRef = "PrimaryEntityManagerFactory",
//JpaRepositories所在的包名,这也是为什么我们要细分包名的原因
basePackages = {"net.springboot.repository.sqlserver"}) //设置Repository所在位置
public class PrimaryConfig {
//这个与 DataSourceConfig.java 中定义的类型匹配上,简单看看估计就明白了
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
private JpaProperties jpaProperties;
//配置实体类工厂
@Bean(name = "PrimaryEntityManagerFactory")
//在数据源的配置中,我们将Local配置成了主库,所以必须在这里有@Primary注解
@Primary
public LocalContainerEntityManagerFactoryBean PrimaryEntityManagerFactory(EntityManagerFactoryBuilder builder) {
//创建一个工厂
return builder
.dataSource(primaryDataSource) //数据源实例,在这里指的就是localDatasource这个实例
.properties(jpaProperties.getProperties()) //加Jpa的属性配置加入进来
.packages("net.springboot.entity.sqlserver") //实体类包名
//.persistenceUnit("localPersistenceUnit")
.build();
}
@Bean(name = "PrimaryTransactionManager")
//和上面一样,必须要有该注解
@Primary
public PlatformTransactionManager PrimaryTransactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(PrimaryEntityManagerFactory(builder).getObject());
}
}
SecondaryConfig.java,ThirdConfig.java 其实差不多的,这里就不贴了,注意两个地方就行
basePackages = {"net.springboot.repository.sqlserver"}) //设置Repository的包,就是所在位置位置
packages("net.springboot.entity.sqlserver") //设置实体的包
package net.springboot.entity.sqlserver;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "t_realtime_data")
public class User
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ID")
private String id;
@Column(name="CODE")
private String code;
@Column(name="BRUSHCARDTIME")
private Date brushcardtime;
@Column(name="AREANO")
private String areano;
@Column(name="CATE")
private Integer cate;
public User()
{
}
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public String getCode()
{
return code;
}
public void setCode(String code)
{
this.code = code;
}
public Date getBrushcardtime()
{
return brushcardtime;
}
public void setBrushcardtime(Date brushcardtime)
{
this.brushcardtime = brushcardtime;
}
public String getAreano()
{
return areano;
}
public void setAreano(String areano)
{
this.areano = areano;
}
public Integer getCate()
{
return cate;
}
public void setCate(Integer cate)
{
this.cate = cate;
}
}
贴一个 sqlserver 实体类的代码,至于mysql和postsql的实体类差不多的,就没必要贴,相信大家都会写
package net.springboot.repository.sqlserver;
import org.springframework.data.jpa.repository.JpaRepository;
import net.springboot.entity.sqlserver.User;
public interface UserRepository extends JpaRepository<User, String>
{
User findByCode(String code);
}
贴一下sqlserver的Repository的类,这个相当于hibernate框架的dao类型,有了JPA你就开始腰不酸,腿不痛了,这个东西看上去是个接口,也确实是个接口,但是只用自己写方法,jpa会帮你具体实现,是不是有点高大上啊。
大概是实现方法如下:
@Query(value = "select * from v_device", nativeQuery = true)
List<DeviceData> findmydata();
说白了,就是自己写个sql语句查询,当然这个也可以搞个以前hibernate所支持HQL语句,这个有心人自己去实践吧。
然后三个数据库的数据查询出来,剩下的事情就是整合到一起
package net.springboot.service;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import net.springboot.comm.DateTimeUtile;
import net.springboot.comm.LogHelper;
import net.springboot.comm.StringUtil;
import net.springboot.entity.mysql.MyRealData;
import net.springboot.entity.postsql.vRecordData;
import net.springboot.entity.sqlserver.RealData;
import net.springboot.repository.mysql.MyRealDataRepository;
import net.springboot.repository.postsql.RecordDataRepository;
import net.springboot.repository.sqlserver.RealdataRepository;
@Component
public class ScheduledService {
private final static Logger logger = LoggerFactory.getLogger(ScheduledService.class);
@Autowired
MysqlRepository mysqlRepository; //这个类得自己写哦,参考sqlserver
@Autowired
PostsqlRepository postsqlRepository; //这个类得自己写哦 参考sqlserver
@Autowired
UserRepository userRepository //sqlserverRepository;
//定时任务,这个可以自己改
//这个表示延迟1000毫秒后执行,任务执行完6000毫秒之后执
@Scheduled(initialDelay=1000, fixedDelay = 6000)
public void scheduled2() {
GatherSqlserverData();
//GathermysqlData
//GatherpostsqlData
//调第三方接口,这个不写了 todo...
logger.info("GatherData success");
}
private void GatherSqlserverData()
{
try
{
List<RealData> list = this.realdataRepo.findAll();
//to do anything
}
catch(Exception e)
{
LogHelper.log("TranData fail" + e.getMessage());
}
}
}
最后是启动代码,springboot基本上都是这个样子,没啥特别的。
package net.springboot;
import java.util.Collections;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.scheduling.annotation.EnableScheduling;
//webapp访问路径,可以自己定义
//MyDataWebApp 这个类名是自己定义,随便改
@EnableScheduling
@SpringBootApplication
public class MyDataWebApp {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyDataWebApp .class);
app.setDefaultProperties(Collections.singletonMap("server.servlet.context-path", "/webapp"));
app.run(args);
}
}
pom文件的的主要部分,剩下自己想要啥再加点啥
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
resources 下的配置文件 application.properties大概如下,配置三个数据库是一件麻烦事情,这个想实践就得不怕麻烦,还有数据库连接属性种方言与数据库版本有关系哦
#由DataSourceConfig.java 来解析,具体怎么解析,怎么实现,可以看看springboot源码
#sqlserver
spring.datasource.primary.jdbc-url=jdbc:sqlserver://127.0.0.1:1433;database=test
spring.datasource.primary.username=sa
spring.datasource.primary.password=sa
spring.datasource.primary.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.properties.hibernate.primary.dialect=org.hibernate.dialect.SQLServer2008Dialect
#postsql
spring.datasource.secondary.jdbc-url=jdbc:postgresql://127.0.0.1:5432/test
spring.datasource.secondary.username=postgres
spring.datasource.secondary.password=postgres
spring.datasource.secondary.driverClassName=org.postgresql.Driver
spring.jpa.properties.hibernate.secondary.dialect=org.hibernate.dialect.PostgreSQLDialect
#mysql
spring.datasource.third.jdbc-url=jdbc:mysql://127.0.0.1:3306/rlsb-sys?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.third.username=root
spring.datasource.third.password=root
spring.datasource.third.driverClassName=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.third.dialect=org.hibernate.dialect.MySQL57Dialect
到这里基本上就结束了,这个其实还算简单,mysql,postsql的Repository类和实体类这里就不写,其实都差不多的。感觉很简单吧,其实是很多很多事情框架帮我们做了。
说明一下,很多很多事情多个数据源种如果其中一个无法连接,系统以jar方式运行的时候,建立连接池时会抛错哦。