1 pom.xml
创建Springboot项目,在pom.xml中加入如下依赖:
<?xml version="1.0" encoding="UTF-8"?>
<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>com.mlsama</groupId>
<artifactId>springboot-oracle</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>springboot-oracle</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<autoconfig.plugin.version>1.2</autoconfig.plugin.version>
</properties>
<dependencies>
<!-- 配置WEB启动器 SpringMVC、Restful、jackson -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!--整合junit-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--aop依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--lombok约束-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--日记-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
</dependency>
<!--oracle-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.1.0</version>
</dependency>
<!--c3p0连接池-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- 配置devtools开启热部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- FreeMarker启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<!--ThreadFactory,ThreadPoolExecutor等-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.0.1</version>
</dependency>
<!--Springbatch-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<build>
<!--构建后项目的名称-->
<finalName>${project.artifactId}</finalName>
<!--构建后项目存放
的文件夹.project.basedir:项目根目录-->
<directory>${project.basedir}/target</directory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork><!-- 如果没有该项配置,devtools不会起作用,即应用不会restart -->
</configuration>
</plugin>
<!-- spring Boot在编译的时候,是有默认JDK版本的,如果我们期望使用我们要的JDK版本的话,那么要配置-->
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<!--<plugin>
<!–需要使用这个插件配合下面的resources标签–>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
<version>2.6</version>
</plugin>
<plugin>
<groupId>com.alibaba.citrus.tool</groupId>
<artifactId>autoconfig-maven-plugin</artifactId>
<version>${autoconfig.plugin.version}</version>
<configuration>
<charset>UTF-8</charset>
<dest>${project.artifact.file}</dest>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>autoconfig</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<goals>
<goal>revision</goal>
</goals>
</execution>
</executions>
<configuration>
<verbose>true</verbose>
<dateFormat>yyyyMMddHHmmss</dateFormat>
<!– ".git"文件路径;默认值:${project.basedir}/.git; –>
<dotGitDirectory>${project.basedir}/.git</dotGitDirectory>
<!–若项目打包类型为pom,是否取消构建;默认值:true;–>
<skipPoms>false</skipPoms>
<!–是否生成"git.properties"文件;默认值:false;–>
<generateGitPropertiesFile>false</generateGitPropertiesFile>
</configuration>
</plugin>-->
</plugins>
<!-- 需要使用这个标签合配合上面的maven-resources-pluginc插件,不然ops.properties不能获取项目信息和git的信息-->
<!-- 发现有原来有引用 ../*-persistence模块config文件下面ds 数据源配置文件的依赖 -->
<!-- 发现有原来有引用 ../*-persistence模块config文件下面mapper xml文件的依赖 -->
<!-- 这里要求吧上面的文件在另外的模块打入jar里面,加入dependency -->
<!-- 不允许源文件级别的依赖,请干净地使用下面配置-->
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</project>
2 接口信息配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--初始化对象时,加载类中的init方法-->
<bean id="serviceHander" class="com.mlsama.springbootoracle.hander.ServiceHander" init-method="init">
<!--给类属性赋值-->
<property name="serviceNames">
<map>
<!--代收-->
<entry key="16245840" value="collection"/>
</map>
</property>
</bean>
</beans>
3 初始化接口信息
创建类com.mlsama.springbootoracle.hander.ServiceHander
@Data
@Slf4j
public class ServiceHander {
/**
* 接口信息与对象,必须是静态的,否则再次调用时,map为null
*/
private static Map<String, Map<String,Object>> serviceCache = new HashMap<>(16);
/**
* 配置在application.xml中的接口名称
*/
private Map<String, String> serviceNames;
/**
* 1.实现ApplicationContextAware接口,获取applicationContext上下文对象
* 进而获取bean对象
* 2.@Autowired
*/
@Autowired
private ApplicationContext applicationContext;
public static ServiceHander INSTANCE = new ServiceHander();
private ServiceHander(){}
/**
* 初始化接口
*/
public void init() {
if (serviceNames != null){
log.info("初始化的接口信息如下:");
for (String procCode : serviceNames.keySet()){
if (StringUtils.isNotBlank(serviceNames.get(procCode))){
List<String> methods = Arrays.asList(serviceNames.get(procCode).split(","));
log.info("{}:{}",procCode,methods);
Map<String,Object> map = new HashMap<>(16);
for (String method : methods){
map.put(method,applicationContext.getBean(procCode+"_"+method));
}
serviceCache.put(procCode,map);
}
}
}else {
throw new CommonSystemServiceException(ResultCodeConstant.RESPONSE_CODE_6601,"服务没有配置");
}
}
/**
* 根据通道号和接口名称获取接口对象
* @param procCode
* @param method
* @return
*/
public Object getBean(String procCode,String method){
if (serviceCache.containsKey(procCode) &&
serviceCache.get(procCode).containsKey(method)){
return serviceCache.get(procCode).get(method);
}
return null;
}
}
3 初始化各渠道线程池
@Slf4j
@Service
public class ThreadPool {
/**
* 这个应该配在数据库,这里为了方便
*/
private final static String PROC_CODE_THREAD_CONFIG = "16245840=5";
private Map<String,ThreadPoolExecutor> procCodeThreadPool = new HashMap<>(16);
/**
* 创建bean后,初始化线程池
*/
@PostConstruct
public void init(){
if (StringUtils.isNotBlank(PROC_CODE_THREAD_CONFIG)){
String[] procCodeConfigs = PROC_CODE_THREAD_CONFIG.split(",");
for (String procCodeConfig : procCodeConfigs){
String[] configs = procCodeConfig.split("=");
if (StringUtils.isNotBlank(configs[0]) && StringUtils.isNotBlank(configs[1])){
//创建线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
0,Integer.parseInt(configs[1]),10L,
TimeUnit.SECONDS, new SynchronousQueue(),
new ThreadPoolExecutorFactoryBean(),
new ThreadPoolExecutor.AbortPolicy());
log.info("************threadPool="+threadPool+"******************");
procCodeThreadPool1.put(configs[0],threadPool);
}else {
throw new CommonSystemServiceException(ResultCodeConstant.RESPONSE_CODE_6604,"该通道线程池没 有配置或格式错误");
}
}
}else {
throw new CommonSystemServiceException(ResultCodeConstant.RESPONSE_CODE_6603,"线程池没有配置");
}
}
/**
* 根据项目编号获取对应的线程池
* @param procCode 项目编号
* @return
*/
public ThreadPoolExecutor getThreadPool(String procCode){
if (procCodeThreadPool != null && procCodeThreadPool.get(procCode) != null){
return procCodeThreadPool.get(procCode);
}
return null;
}
}
4 pojo
BaseReq
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaseReq {
private String logSeq;
private String procCode;
private String serviceName;
@Override
public String toString() {
return "logSeq='" + logSeq + '\'' +
", procCode='" + procCode + '\'' +
", serviceName='" + serviceName + '\'' +
'}';
}
}
CollectionReq
@Data
public class CollectionReq extends BaseReq {
private String account;
public CollectionReq(){}
public CollectionReq(String logSeq, String procCode, String serviceName) {
super(logSeq, procCode, serviceName);
}
@Override
public String toString() {
String string = super.toString();
return "CollectionReq{" +
"account='" + account + '\'' +","+ string;
}
}
BaseResp
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BaseResp {
private String resultCode;
private String resultMsg;
@Override
public String toString() {
return "resultCode='" + resultCode + '\'' +
", resultMsg='" + resultMsg + '\'' +
'}';
}
}
CollectionResp
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CollectionResp extends BaseResp {
private String paySeq;
@Override
public String toString(){
String string = super.toString();
return "collectionResp{" + "paySeq=" + paySeq +","+ string;
}
}
5 统一管理层
5.1基础类
public abstract class BaseManager<T extends BaseReq,R extends BaseResp> {
}
5.2 实现类
@Slf4j
public abstract class CollectionManager extends BaseManager<CollectionReq,CollectionResp> {
//注入请求处理对象
@Autowired
private RequestHandel requestHandel;
public void init(CollectionReq req,CollectionResp resp){
log.info("logSeq:{},当前对象是{}通道的{}接口",req.getLogSeq(),req.getProcCode(),req.getServiceName());
}
public collectionResp domain(CollectionReq req,CollectionResp resp){
//同步返回处理中
resp.setPaySeq(req.getLogSeq());
resp.setResultCode(ResultCodeConstant.RESPONSE_CODE_0050);
resp.setResultMsg("交易已接受");
//异步处理请求
try {
requestHandel.handel4(new RequestTask(req.getProcCode()) {
@Override
public void run() {
log.info("***************开始异步处理请求*************");
//进入方法的时间
long startTime = System.currentTimeMillis();
//处理核心请求
main(req,resp);
long endTime = System.currentTimeMillis();
log.info("collection async send to bank and deal response cost {} ms.", endTime - startTime);
}
});
}catch (Exception e){
log.info("添加到发送银行的队列失败,case:", e);
resp.setResultCode(ResultCodeConstant.RESPONSE_CODE_6702);
resp.setResultMsg("添加到发送银行的队列失败");
}
return resp;
}
public abstract CollectionResp main(CollectionReq req,CollectionResp resp);
}
6 服务层
6.1 API
基础接口
public interface BaseService<T extends BaseReq,R extends BaseResp> {
R exeute(T req);
}
渠道接口
public interface CollectionService extends BaseService<CollectionReq,CollectionResp> {
}
6.2 impl
@Service("collection")
public class Collection implements CollectionService {
@Override
public CollectionResp exeute(CollectionReq req) {
//获取真正的操作对象
CollectionManager manager = (collectionManager) ServiceManagerFactory.INSTANCE.getManager(req.getProcCode(), req.getServiceName());
CollectionResp resp = new CollectionResp();
manager.init(req,resp);
manager.domain(req,resp);
return resp;
}
}
7 渠道接口
@Slf4j
@Service("16245840_collection")
public class SzYlcollectionManager extends CollectionManager {
@Override
public collectionResp main(CollectionReq req,CollectionResp resp) {
log.info("1201接口调用成功.");
resp.setPaySeq(req.getLogSeq());
resp.setResultCode("0000");
resp.setResultMsg("成功");
System.out.println(resp.toString());
return resp;
}
}
8 controller
@Controller
public class CollectionController {
@Autowired
private Collection collection;
// http://localhost:8888/collection?procCode=16245840&serviceName=collection
@GetMapping("/collection")
@ResponseBody
public String collection(@RequestParam("procCode")String procCode,@RequestParam("serviceName")String serviceName){
CollectionReq req = new CollectionReq(BaseUtil.getLogSeq(),procCode,serviceName);
return collection.exeute(req).toString();
}
}
9 访问
http://localhost:8888/collection?procCode=16245840&serviceName=collection