0.0.1-SNAPSHOT
wangbing 5 years ago
parent aa2ee4165b
commit f8dcfe3d26

@ -4,14 +4,23 @@ import com.example.frame.base.BaseResponse;
import com.example.frame.base.Error; import com.example.frame.base.Error;
import com.example.frame.base.ErrorType; import com.example.frame.base.ErrorType;
import com.example.frame.base.Token; import com.example.frame.base.Token;
import com.example.frame.utils.*; import com.example.frame.utils.LocalData;
import com.example.frame.utils.LogUtil;
import com.example.frame.utils.MD5Util;
import com.example.frame.utils.MapperUtil;
import com.example.frame.utils.Message;
import com.example.frame.utils.ProcessUtil;
import com.example.frame.utils.ValidationUtil;
import com.example.module.admin.ent.Mapping;
import com.example.module.admin.ent.NginxCtrl; import com.example.module.admin.ent.NginxCtrl;
import com.example.module.admin.ent.Service;
import com.example.module.admin.mgr.MappingManager; import com.example.module.admin.mgr.MappingManager;
import com.example.module.admin.req.*; import com.example.module.admin.req.LoginRequest;
import com.example.module.admin.req.MappingCreateRequest;
import com.example.module.admin.req.MappingDeleteRequest;
import com.example.module.admin.req.MappingFindRequest;
import com.example.module.admin.req.MappingUpdateRequest;
import com.example.module.admin.rsp.LoginResponse; import com.example.module.admin.rsp.LoginResponse;
import com.example.module.admin.rsp.MappingFindResponse; import com.example.module.admin.rsp.MappingFindResponse;
import com.example.module.admin.rsp.PortLoadResponse;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -22,17 +31,23 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer; import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import xyz.wbsite.wsqlite.ObjectClient; import xyz.wbsite.wsqlite.ObjectClient;
import xyz.wbsite.wsqlite.Where;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.*; import java.io.BufferedReader;
import java.sql.SQLException; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@Controller @Controller
public class AjaxController { public class AjaxController {
@ -87,6 +102,9 @@ public class AjaxController {
case "nginx.reload": case "nginx.reload":
baseResponse = nginxReload(jsonString, token); baseResponse = nginxReload(jsonString, token);
break; break;
case "ajax.admin.mapping.find":
baseResponse = findMapping(jsonString, token);
break;
// 创建映射 // 创建映射
case "ajax.admin.mapping.create": case "ajax.admin.mapping.create":
baseResponse = createMapping(jsonString, token); baseResponse = createMapping(jsonString, token);
@ -102,9 +120,6 @@ public class AjaxController {
baseResponse = updateMapping(jsonString, token); baseResponse = updateMapping(jsonString, token);
flushConfig(); flushConfig();
break; break;
case "ajax.admin.service.load":
baseResponse = loadPort(jsonString, token);
break;
case "ajax.admin.config.flush": case "ajax.admin.config.flush":
flushConfig(); flushConfig();
baseResponse = new BaseResponse(); baseResponse = new BaseResponse();
@ -214,39 +229,31 @@ public class AjaxController {
return mappingManager.find(request, token); return mappingManager.find(request, token);
} }
private BaseResponse loadPort(String jsonString, Token token) {
PortLoadResponse response = new PortLoadResponse();
try {
List<Service> select = objectClient.select(Service.class, Where.builder().build(), 1, 0);
for (Service service : select) {
MappingFindRequest mappingFindRequest = new MappingFindRequest();
mappingFindRequest.setServiceId(service.getId());
mappingFindRequest.setPageSize(0);
MappingFindResponse mappingFindResponse = mappingManager.find(mappingFindRequest, token);
if (mappingFindResponse.hasError()) {
response.addErrors(mappingFindResponse.getErrors());
return response;
}
service.setMappingList(mappingFindResponse.getResult());
}
response.setResult(select);
} catch (SQLException | ClassNotFoundException e) {
e.printStackTrace();
response.addError(ErrorType.BUSINESS_ERROR, "配置加载错误");
return response;
}
return response;
}
private synchronized void flushConfig() { private synchronized void flushConfig() {
Writer wr = null; Writer wr = null;
try { try {
File config = nginxCtrl.getConfig(); File config = nginxCtrl.getConfig();
HashMap<String, Object> context = new HashMap<>(); HashMap<String, Object> context = new HashMap<>();
PortLoadResponse portLoadResponse = (PortLoadResponse) loadPort("", LocalData.getSysToken()); MappingFindRequest mappingFindRequest = new MappingFindRequest();
context.put("services", portLoadResponse.getResult()); mappingFindRequest.setPageSize(0);
mappingFindRequest.setSortKey("SERVICE_PORT");
MappingFindResponse mappingFindResponse = mappingManager.find(mappingFindRequest, LocalData.getSysToken());
Map<String, List<Mapping>> services = new HashMap<>();
for (Mapping mapping : mappingFindResponse.getResult()) {
List<Mapping> mappings = services.get(mapping.getServicePort());
if (mappings == null) {
mappings = new ArrayList<>();
services.put(mapping.getServicePort(), mappings);
}
mappings.add(mapping);
}
context.put("services", services);
Template template = freeMarkerConfigurer.getConfiguration().getTemplate("nginx.conf.ftl"); Template template = freeMarkerConfigurer.getConfiguration().getTemplate("nginx.conf.ftl");
wr = new OutputStreamWriter(new FileOutputStream(config), "UTF-8"); wr = new OutputStreamWriter(new FileOutputStream(config), "UTF-8");
//写入 //写入

@ -88,10 +88,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
token1.putResource("nginx.start"); token1.putResource("nginx.start");
token1.putResource("nginx.stop"); token1.putResource("nginx.stop");
token1.putResource("nginx.reload"); token1.putResource("nginx.reload");
token1.putResource("ajax.admin.mapping.find");
token1.putResource("ajax.admin.mapping.create"); token1.putResource("ajax.admin.mapping.create");
token1.putResource("ajax.admin.mapping.delete"); token1.putResource("ajax.admin.mapping.delete");
token1.putResource("ajax.admin.mapping.update"); token1.putResource("ajax.admin.mapping.update");
token1.putResource("ajax.admin.service.load");
token1.putResource("ajax.admin.config.flush"); token1.putResource("ajax.admin.config.flush");
LocalData.setToken(token1); LocalData.setToken(token1);
} }

@ -2,7 +2,6 @@ package com.example.config;
import com.example.frame.utils.IDgenerator; import com.example.frame.utils.IDgenerator;
import com.example.module.admin.ent.Mapping; import com.example.module.admin.ent.Mapping;
import com.example.module.admin.ent.Service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.system.ApplicationHome; import org.springframework.boot.system.ApplicationHome;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -37,14 +36,8 @@ public class SqliteConfig {
ArrayList<Class> objects = new ArrayList<>(); ArrayList<Class> objects = new ArrayList<>();
objects.add(Mapping.class); objects.add(Mapping.class);
objects.add(Service.class);
ObjectClient objectClient = new ObjectClient(new File(dbpath, "data.db"), objects); ObjectClient objectClient = new ObjectClient(new File(dbpath, "data.db"), objects);
List<Service> select = objectClient.select(Service.class, Where.builder().build(),1, 1);
if (select.size() == 0 && objectClient.insert(Service.class, new Service(IDgenerator.nextId(), "8888", "默认端口")) != 1) {
throw new RuntimeException("Nginx default port 8888 init failed.");
}
return objectClient; return objectClient;
} catch (ClassNotFoundException e) { } catch (ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();

@ -19,12 +19,8 @@ public class Mapping {
*/ */
@TableField @TableField
private Long id; private Long id;
/**
* ID - ID
*/
@TableField @TableField
private Long serviceId; private String servicePort;
@TableField @TableField
private String name; private String name;
@TableField @TableField
@ -48,12 +44,12 @@ public class Mapping {
this.type = type; this.type = type;
} }
public Long getServiceId() { public String getServicePort() {
return serviceId; return servicePort;
} }
public void setServiceId(Long serviceId) { public void setServicePort(String servicePort) {
this.serviceId = serviceId; this.servicePort = servicePort;
} }
public String getName() { public String getName() {

@ -1,77 +0,0 @@
package com.example.module.admin.ent;
import xyz.wbsite.wsqlite.anonation.TableField;
import java.util.Date;
import java.util.List;
/**
* MAPPING -
*
* @author author
* @version 0.0.1
* @since 2019-09-28
*/
public class Service {
/**
* VALUE - ID
*/
@TableField
private Long id;
/**
* VALUE -
*/
@TableField
private String value;
/**
* VALUE -
*/
@TableField
private String bz;
private List<Mapping> mappingList;
public List<Mapping> getMappingList() {
return mappingList;
}
public void setMappingList(List<Mapping> mappingList) {
this.mappingList = mappingList;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getBz() {
return bz;
}
public void setBz(String bz) {
this.bz = bz;
}
public Service() {
}
public Service(Long id, String value, String bz) {
this.id = id;
this.value = value;
this.bz = bz;
}
}

@ -1,9 +1,8 @@
package com.example.module.admin.mgr; package com.example.module.admin.mgr;
import com.example.frame.utils.IDgenerator;
import com.example.frame.utils.Message;
import com.example.frame.base.ErrorType; import com.example.frame.base.ErrorType;
import com.example.frame.base.Token; import com.example.frame.base.Token;
import com.example.frame.utils.IDgenerator;
import com.example.frame.utils.MapperUtil; import com.example.frame.utils.MapperUtil;
import com.example.frame.utils.ValidationUtil; import com.example.frame.utils.ValidationUtil;
import com.example.module.admin.ent.Mapping; import com.example.module.admin.ent.Mapping;
@ -52,6 +51,21 @@ public class MappingManagerImpl implements MappingManager {
return response; return response;
} }
try {
Where where = Where.builder().eq("SERVICEPORT", request.getServicePort()).eq("CONTEXT", request.getContext()).build();
List<Mapping> select = objectClient.select(Mapping.class, where, 1, 0);
if (select.size() > 0) {
response.addError(ErrorType.BUSINESS_ERROR, request.getServicePort() + ":" + request.getContext() + "已经被占用");
return response;
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
long id = IDgenerator.nextId(); long id = IDgenerator.nextId();
Mapping entity = MapperUtil.map(request, Mapping.class); Mapping entity = MapperUtil.map(request, Mapping.class);
entity.setId(id); entity.setId(id);

@ -21,8 +21,9 @@ public class MappingCreateRequest extends BaseRequest {
@NotNull(message = "映射名称不能为空") @NotNull(message = "映射名称不能为空")
private String name; private String name;
@NotNull(message = "服务Id不能为空") @NotNull(message = "服务端口不能为空")
private Long serviceId; @Pattern(regexp = "^[0-9]*$", message = "服务端口必须是数字")
private String servicePort;
@NotNull(message = "映射路径不能为空") @NotNull(message = "映射路径不能为空")
@Pattern(regexp = "^/[a-zA-Z][a-zA-Z0-9_-]*$|^[A-Z]:/.*$|^/$", message = "映射路径须是(/)或(/+字母+字母数字及_") @Pattern(regexp = "^/[a-zA-Z][a-zA-Z0-9_-]*$|^[A-Z]:/.*$|^/$", message = "映射路径须是(/)或(/+字母+字母数字及_")
@ -36,12 +37,12 @@ public class MappingCreateRequest extends BaseRequest {
private String bz; private String bz;
public Long getServiceId() { public String getServicePort() {
return serviceId; return servicePort;
} }
public void setServiceId(Long serviceId) { public void setServicePort(String servicePort) {
this.serviceId = serviceId; this.servicePort = servicePort;
} }
public String getName() { public String getName() {

@ -11,16 +11,13 @@ import com.example.frame.base.BaseFindRequest;
*/ */
public class MappingFindRequest extends BaseFindRequest { public class MappingFindRequest extends BaseFindRequest {
/** private String search;
*
*/
private Long serviceId;
public Long getServiceId() { public String getSearch() {
return serviceId; return search;
} }
public void setServiceId(Long serviceId) { public void setSearch(String search) {
this.serviceId = serviceId; this.search = search;
} }
} }

@ -1,8 +0,0 @@
package com.example.module.admin.rsp;
import com.example.frame.base.BaseFindResponse;
import com.example.module.admin.ent.Service;
public class PortLoadResponse extends BaseFindResponse<Service> {
}

@ -128,6 +128,12 @@ window.ajax = {
data: fd data: fd
}) })
}, },
mappingFind: function (data) {
return jsonRequest({
method:"ajax.admin.mapping.find",
data: JSON.stringify(data),
})
},
mappingCreate: function (data) { mappingCreate: function (data) {
return jsonRequest({ return jsonRequest({
method:"ajax.admin.mapping.create", method:"ajax.admin.mapping.create",
@ -146,12 +152,6 @@ window.ajax = {
data: JSON.stringify(data), data: JSON.stringify(data),
}) })
}, },
serviceLoad: function(data) {
return jsonRequest({
method:"ajax.admin.service.load",
data: JSON.stringify(data),
})
},
configFlush: function(data) { configFlush: function(data) {
return jsonRequest({ return jsonRequest({
method:"ajax.admin.config.flush", method:"ajax.admin.config.flush",

@ -31,17 +31,17 @@ http {
keepalive_timeout 65; keepalive_timeout 65;
#gzip on; #gzip on;
<#list services as item> <#list services.keySet() as key>
server { server {
listen ${item.value}; listen ${key};
server_name localhost; server_name localhost;
#charset koi8-r; #charset koi8-r;
#access_log logs/host.access.log main; #access_log logs/host.access.log main;
<#list item.mappingList as mapping> <#list services[key] as mapping>
<#if mapping.type="HTTP"> <#if mapping.type="HTTP">
location ${mapping.context} { location ${mapping.context} {
proxy_pass ${mapping.location}; proxy_pass ${mapping.location};

@ -33,93 +33,80 @@
</el-col> </el-col>
</el-row> </el-row>
</el-card> </el-card>
<el-row>
<el-col :span="24">
<span style="float: right;">
<el-button type="success" size="small" icon="el-icon-plus" @click="onAction(['create',{}])">新增
</el-button>
<el-button size="small" icon="el-icon-refresh" @click="onRefresh"></el-button>
</span>
</el-col>
</el-row>
<el-card class="box-card" v-for="item in services" :key="item.id"> <el-table
<el-row> :data="result.filter(data => !vm.search || data.name.toLowerCase().includes(vm.search.toLowerCase())|| data.value.toLowerCase().includes(vm.search.toLowerCase()))"
<el-col :span="4"> style="width: 100%">
<el-input size="small" v-model="item.value" placeholder="请输入端口" style="width: 160px;text-align: center" <el-table-column
suffix-icon="el-icon-edit"> width="150px"
<template slot="prepend">端口</template> label="名称"
</el-input> prop="name">
</el-col> <template slot-scope="scope">
<el-col :span="5"> <span style="margin-left: 10px">{{ scope.row.name }}</span>
<el-input size="small" v-model="item.bz" placeholder="请输入备注" style="width: 200px;text-align: center" <el-popover
suffix-icon="el-icon-collection-tag"> placement="top-start"
<template slot="prepend">备注</template> width="200"
</el-input> trigger="hover"
</el-col> :content="scope.row.bz">
<el-col :span="2"> <i slot="reference" class="el-icon-warning-outline"></i>
<el-button type="primary" size="small" icon="el-icon-refresh">保存</el-button> </el-popover>
</el-col> </template>
<el-col :span="13"> </el-table-column>
<span style="float: right;"> <el-table-column
<el-button type="success" size="small" icon="el-icon-plus" @click="onAction(['create',item])">新增 width="130px"
label="端口"
prop="servicePort">
</el-table-column>
<el-table-column
width="130px"
label="路径"
prop="context">
</el-table-column>
<el-table-column
width="220px"
label="地址"
prop="location">
</el-table-column>
<el-table-column
width="150px"
label="创建日期"
prop="createTime">
</el-table-column>
<el-table-column
label="备注"
prop="bz">
</el-table-column>
<el-table-column
width="150px"
align="right">
<template slot="header" slot-scope="scope">
<el-input
v-model="vm.search"
size="small"
placeholder="输入关键字搜索"/>
</template>
<template slot-scope="scope">
<el-button
size="mini"
@click="onAction(['edit',scope.row,item])">编辑
</el-button> </el-button>
<el-button size="small" icon="el-icon-refresh" @click="onRefresh"></el-button> <el-button
</span> size="mini"
</el-col> type="danger"
</el-row> @click="onAction(['delete', scope.row])">删除
</el-button>
<el-table </template>
:data="item.mappingList.filter(data => !item.search || data.name.toLowerCase().includes(item.search.toLowerCase())|| data.value.toLowerCase().includes(item.search.toLowerCase()))" </el-table-column>
style="width: 100%"> </el-table>
<el-table-column
width="150px"
label="名称"
prop="name">
<template slot-scope="scope">
<span style="margin-left: 10px">{{ scope.row.name }}</span>
<el-popover
placement="top-start"
width="200"
trigger="hover"
:content="scope.row.bz">
<i slot="reference" class="el-icon-warning-outline"></i>
</el-popover>
</template>
</el-table-column>
<el-table-column
width="130px"
label="路径"
prop="context">
</el-table-column>
<el-table-column
width="220px"
label="地址"
prop="location">
</el-table-column>
<el-table-column
width="150px"
label="创建日期"
prop="createTime">
</el-table-column>
<el-table-column
label="备注"
prop="bz">
</el-table-column>
<el-table-column
width="150px"
align="right">
<template slot="header" slot-scope="scope">
<el-input
v-model="item.search"
size="small"
placeholder="输入关键字搜索"/>
</template>
<template slot-scope="scope">
<el-button
size="mini"
@click="onAction(['edit',scope.row,item])">编辑
</el-button>
<el-button
size="mini"
type="danger"
@click="onAction(['delete', scope.row])">删除
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog :title="form.title" :visible.sync="form.dialog" width="550px"> <el-dialog :title="form.title" :visible.sync="form.dialog" width="550px">
<el-form :model="form" :rules="formRules" ref="form" label-width="80px" <el-form :model="form" :rules="formRules" ref="form" label-width="80px"
@ -131,15 +118,21 @@
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item label="映射端口" required prop="servicePort">
<el-row>
<el-col :span="22">
<el-input v-model="form.servicePort" type="number" clearable size="small" placeholder="映射端口"></el-input>
</el-col>
</el-row>
</el-form-item>
<el-form-item label="映射路径" required prop="context"> <el-form-item label="映射路径" required prop="context">
<el-row> <el-row>
<el-col :span="22"> <el-col :span="22">
<el-input v-model="form.context" clearable size="small" placeholder="字母数字组合"> <el-input v-model="form.context" clearable size="small" placeholder="字母数字组合">
<template slot="prepend">:{{form.port}}</template> <template slot="prepend">http://host:{{form.servicePort}}</template>
</el-input> </el-input>
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
<el-form-item label="映射类型" required prop="type"> <el-form-item label="映射类型" required prop="type">
<el-radio v-model="form.type" label="HTTP">HTTP</el-radio> <el-radio v-model="form.type" label="HTTP">HTTP</el-radio>
@ -212,6 +205,9 @@
var app = new Vue({ var app = new Vue({
el: "#app", el: "#app",
data: { data: {
vm: {
search: ""
},
form: { form: {
title: "", title: "",
dialog: false, dialog: false,
@ -227,6 +223,10 @@
{required: true, message: '映射名称不能为空', trigger: 'blur'}, {required: true, message: '映射名称不能为空', trigger: 'blur'},
{min: 1, max: 50, message: '长度在 1 到 50 字符', trigger: 'blur'} {min: 1, max: 50, message: '长度在 1 到 50 字符', trigger: 'blur'}
], ],
servicePort: [
{required: true, message: '映射端口不能为空', trigger: 'blur'},
{pattern: "^[0-9]*$", message: '映射端口只能为数字', trigger: 'blur'},
],
context: [ context: [
{required: true, message: '映射路径不能为空', trigger: 'blur'}, {required: true, message: '映射路径不能为空', trigger: 'blur'},
{pattern: "^/[a-zA-Z][a-zA-Z0-9_-]*$|^/$", message: '上下文须是(/)或(/+字母+字母数字及_', trigger: 'blur'}, {pattern: "^/[a-zA-Z][a-zA-Z0-9_-]*$|^/$", message: '上下文须是(/)或(/+字母+字母数字及_', trigger: 'blur'},
@ -253,19 +253,16 @@
} }
], ],
}, },
services: [], result: [],
run: ${run?default('false')} run: ${run?default('false')}
}, },
methods: { methods: {
onFind: function () { onFind: function () {
ajax.serviceLoad().then(function (response) { ajax.mappingFind(this.vm).then(function (response) {
if (response.errors.length > 0) { if (response.errors.length > 0) {
nav.e(response.errors[0].message); nav.e(response.errors[0].message);
} else { } else {
for (var i in response.result) { this.result = response.result;
response.result[i].search = "";
}
this.services = response.result;
} }
}.bind(this)) }.bind(this))
}, },
@ -274,7 +271,7 @@
switch (action) { switch (action) {
case "create": case "create":
this.form.title = '新增'; this.form.title = '新增';
this.form.serviceId = arg[1].id; this.form.servicePoert = "8080";
this.form.port = arg[1].value; this.form.port = arg[1].value;
this.form.id = ''; this.form.id = '';
this.form.name = ''; this.form.name = '';

@ -65,7 +65,7 @@ public class Where {
public Builder like(boolean condition, String name, Object value) { public Builder like(boolean condition, String name, Object value) {
if (condition) { if (condition) {
sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("like ?"); sb.append(sb.length() > 0 ? " and " : " where ").append(name).append(" like ?");
argsList.add(value); argsList.add(value);
} }
return this; return this;
@ -73,7 +73,7 @@ public class Where {
public Builder isNull(boolean condition, String name, Object value) { public Builder isNull(boolean condition, String name, Object value) {
if (condition) { if (condition) {
sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("is null"); sb.append(sb.length() > 0 ? " and " : " where ").append(name).append(" is null");
argsList.add(value); argsList.add(value);
} }
return this; return this;
@ -81,7 +81,7 @@ public class Where {
public Builder isNotNull(boolean condition, String name, Object value) { public Builder isNotNull(boolean condition, String name, Object value) {
if (condition) { if (condition) {
sb.append(sb.length() > 0 ? " and " : " where ").append(name).append("is not null"); sb.append(sb.length() > 0 ? " and " : " where ").append(name).append(" is not null");
argsList.add(value); argsList.add(value);
} }
return this; return this;

Loading…
Cancel
Save

Powered by TurnKey Linux.