Commit 01c22ae6 authored by Quxl's avatar Quxl

x

parent 40182a8f
package com.egolm.sentinel.web;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.CallableStatementCallback;
import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.druid.pool.DruidDataSource;
import com.egolm.common.StringUtil;
import com.egolm.common.bean.Rjx;
import com.egolm.common.jdbc.JUtil;
import com.egolm.sentinel.config.XRException;
@RestController
public class SqlConcurrentController {
@PostMapping("concurrentSql")
public Rjx doExecute(String jdbcUrl, String username, String password, String sql, String parameters, int threadCount, int executeCount) throws InterruptedException, IOException, SQLException {
ThreadPoolExecutor executor = new ThreadPoolExecutor(threadCount, threadCount, 5, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(executeCount));
CountDownLatch latch = new CountDownLatch(executeCount);
DruidDataSource dataSource = null;
Long start = System.currentTimeMillis();
try {
dataSource = this.getDataSource(jdbcUrl, username, password);
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
for(int i = 0; i < executeCount; i++) {
executor.execute(new Runner(jdbcTemplate, latch, sql));
}
latch.await();
} finally {
dataSource.close();
}
Long end = System.currentTimeMillis();
return Rjx.jsonOk().set("执行时间", (end-start)).set("执行次数", executeCount).set("并发线程", threadCount);
}
public static class Runner implements Runnable {
JdbcTemplate jdbcTemplate;
private CountDownLatch latch;
private String sql;
private String parameters;
public Runner(JdbcTemplate jdbcTemplate, CountDownLatch latch, String sql) {
super();
this.jdbcTemplate = jdbcTemplate;
this.latch = latch;
this.sql = sql;
}
@Override
public void run() {
try {
List<Object> argList = new ArrayList<Object>();
if(StringUtil.isNotBlank(parameters)) {
List<String> parametersSplitAry = Arrays.asList(parameters.split(",\\s+"));
for(String arg : parametersSplitAry) {
arg = arg.trim();
if(arg.matches("[0-9]+")) {
argList.add(Long.valueOf(arg));
} else if(arg.matches("([0-9]+)?\\.[0-9]+")) {
argList.add(Double.valueOf(arg));
} else if(arg.startsWith("\"") && arg.endsWith("\"")) {
argList.add(StringUtil.trim(arg, "\""));
} else if(arg.startsWith("'") && arg.endsWith("'")) {
argList.add(StringUtil.trim(arg, "'"));
} else {
throw new XRException("参数错误");
}
}
}
Object[] args = argList.toArray(new Object[argList.size()]);
jdbcTemplate.execute(new CallableStatementCreator() {
public CallableStatement createCallableStatement(final Connection con) throws SQLException {
final CallableStatement cs = con.prepareCall(sql);
for(int i = 0; i < args.length; i++) {
cs.setObject(i+1, args[i]);
}
return cs;
}
}, new CallableStatementCallback<List<Object>>() {
public List<Object> doInCallableStatement(final CallableStatement cs) throws SQLException, DataAccessException {
List<Object> datas = new ArrayList<Object>();
cs.execute();
while(true) {
Integer count = cs.getUpdateCount();
ResultSet resultSet = cs.getResultSet();
if(count == -1 && resultSet == null) {
break;
} else {
if(resultSet != null) {
datas.add(JUtil.resultSetToList(resultSet));
} else {
datas.add(count);
}
cs.getMoreResults();
}
}
return datas;
}
});
} finally {
latch.countDown();
}
}
}
public DruidDataSource getDataSource(String jdbcUrl, String username, String password) throws IOException, SQLException {
DruidDataSource dataSource = new DruidDataSource();
String driverClass = null;
if(jdbcUrl.toLowerCase().contains("jtds")) {
driverClass = "net.sourceforge.jtds.jdbc.Driver";
} else if(jdbcUrl.toLowerCase().contains("mysql")) {
driverClass = "com.mysql.jdbc.Driver";
} else if(jdbcUrl.toLowerCase().contains("sqlserver")) {
driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
} else if(jdbcUrl.toLowerCase().contains("sybase")) {
driverClass = "com.sybase.jdbc4.jdbc.SybDriver";
} else {
throw new XRException("URL无法识别, 没有对应的驱动程序");
}
dataSource.setUrl(jdbcUrl);
dataSource.setDriverClassName(driverClass);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.init();
return dataSource;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SQLTEST</title>
<link rel="icon" href="assets/favicon/favicon.ico" type="image/x-icon" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://unpkg.com/element-ui@2.0.4/lib/theme-chalk/index.css">
<script type="text/javascript" src="assets/vue/vue.min.js"></script>
<script type="text/javascript" src="assets/vue/vue-resource.js"></script>
<script type="text/javascript" src="https://unpkg.com/element-ui@2.0.4/lib/index.js"></script>
<script type="text/javascript" src="assets/jquery/jquery.min.js"></script>
</head>
<body>
<div id="app">
<el-form @submit.native.prevent="loadData" size="mini" :model="form" :inline="true" class="demo-form-inline">
<el-input size="mini" :rows="8" type="textarea" placeholder="SQL" v-model="form.sql" style="margin-bottom:5px;"></el-input>
<el-form-item>
<el-input size="mini" placeholder="URL" v-model="form.jdbcUrl" style="width:584px;"></el-input>
</el-form-item>
<el-form-item>
<el-input size="mini" placeholder="Username" v-model="form.username"></el-input>
</el-form-item>
<el-form-item>
<el-input size="mini" placeholder="Password" v-model="form.password"></el-input>
</el-form-item>
<el-form-item>
<el-input size="mini" placeholder="ThreadCount" v-model="form.threadCount"></el-input>
</el-form-item>
<el-form-item>
<el-input size="mini" placeholder="ExecuteCount" v-model="form.executeCount"></el-input>
</el-form-item>
<el-form-item>
<el-input size="mini" placeholder="参数" v-model="form.parameters" style="width:300px;"></el-input>
</el-form-item>
<el-form-item>
<el-button size="mini" type="primary" @click="doExecute">执行</el-button>
</el-form-item>
</el-form>
<xmp v-for="log in logs">{{log}}</xmp>
</div>
<script type="text/javascript" src="assets/common.js"></script>
<script>
var vue = new Vue({
el:"#app",
data: {
form: {},
logs: [],
},
methods: {
doExecute() {
var scope = this;
window.localStorage.setItem("DataSource", JSON.stringify(scope.form));
$.post("concurrentSql", scope.form, function(json) {
scope.logs.push(JSON.stringify(json, null, 8));
});
}
},
mounted() {
var dataSourceJsonString = localStorage.getItem("DataSource");
if(dataSourceJsonString) {
this.form = eval("(" + dataSourceJsonString + ")");
}
}
});
</script>
</body>
</html>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment