nz-talon首次提交
This commit is contained in:
13
src/main/java/net/geedge/confagent/ConfagentApplication.java
Normal file
13
src/main/java/net/geedge/confagent/ConfagentApplication.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package net.geedge.confagent;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class ConfagentApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ConfagentApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.geedge.confagent.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target( {ElementType.METHOD,ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface UnCheckToken {
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package net.geedge.confagent.config;
|
||||
|
||||
import net.geedge.confagent.interceptor.TokenInterceptor;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class ConfagentConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Autowired
|
||||
private TokenInterceptor tokenInterceptor;
|
||||
|
||||
@Bean(name={"tomcatServletWebServerFactory"})
|
||||
public ConfigurableServletWebServerFactory webServerFactory() {
|
||||
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
|
||||
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
|
||||
@Override
|
||||
public void customize(Connector connector) {
|
||||
connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}");
|
||||
|
||||
connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}");
|
||||
}
|
||||
});
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(tokenInterceptor).addPathPatterns("/**");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package net.geedge.confagent.controller;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import net.geedge.confagent.annotation.UnCheckToken;
|
||||
import net.geedge.confagent.entity.AuthEntity;
|
||||
import net.geedge.confagent.util.R;
|
||||
import net.geedge.confagent.util.RCode;
|
||||
import net.geedge.confagent.util.Tool;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value={"/auth"})
|
||||
public class AuthController extends BaseController{
|
||||
private final static Log log = Log.get();
|
||||
|
||||
@Value("${confagent.authFile:auth.yml}")
|
||||
private String authFile;
|
||||
|
||||
private static String rootPath = Tool.WebPathUtil.getRootPath();
|
||||
/**
|
||||
* @Description 每次请求auth接口重新生成 token并记录到文件
|
||||
* @Author rui
|
||||
* @Date 2021/3/23
|
||||
*/
|
||||
@RequestMapping
|
||||
@UnCheckToken
|
||||
public R auth(AuthEntity auth){
|
||||
|
||||
if(Tool.StrUtil.isBlank(auth.getName())||Tool.StrUtil.isBlank(auth.getPin())){
|
||||
return R.error(RCode.AUTH_NAME_PIN_ISNULL);
|
||||
}
|
||||
|
||||
File af = Tool.FileUtil.file(rootPath, authFile);
|
||||
log.debug("auth file path : {}" ,af.getAbsolutePath());
|
||||
Properties properties = Tool.YamlUtil.yamlToProperties(af.getAbsolutePath());
|
||||
|
||||
String name = properties.getProperty("auth.name","nezha");
|
||||
String pin = properties.getProperty("auth.pin","nezha");
|
||||
|
||||
if(Tool.StrUtil.equals(name,auth.getName())&& Tool.StrUtil.equals(pin,auth.getPin())){
|
||||
String token = Tool.IdUtil.fastShortUUID();
|
||||
log.debug("write token {} to {}",token,af.getAbsolutePath());
|
||||
writeToken(token);
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("token", token);
|
||||
return R.ok(map);
|
||||
}
|
||||
|
||||
return R.error(RCode.AUTH_NAME_PIN_INVALID);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 验证当前token是否和文件记录一致,一致后重新生成则更新文件并返回最新token
|
||||
* @Author rui
|
||||
* @Date 2021/3/24
|
||||
*/
|
||||
@GetMapping("/refresh")
|
||||
public R refresh(){
|
||||
String t = Tool.IdUtil.fastShortUUID();
|
||||
writeToken(t);
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("token", t);
|
||||
return R.ok(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 注销当前 token
|
||||
* @Author rui
|
||||
* @Date 2021/3/24
|
||||
*/
|
||||
@GetMapping("logout")
|
||||
public R logout(){
|
||||
File tf = Tool.FileUtil.file(rootPath, tokenFile);
|
||||
log.debug("token file path : {}" ,tf.getAbsolutePath());
|
||||
|
||||
if(Tool.FileUtil.exist(tf)){
|
||||
Tool.FileUtil.del(tf);
|
||||
}
|
||||
if(Tool.FileUtil.exist(promtailConfPath)){
|
||||
Tool.YamlUtil.writeAsMap(null,promtailConfPath);
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
private void writeToken(String token){
|
||||
File tf = Tool.FileUtil.file(rootPath, tokenFile);
|
||||
log.debug("token file path : {}" ,tf.getAbsolutePath());
|
||||
Tool.FileUtil.writeUtf8String(token, tf);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.geedge.confagent.controller;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
public abstract class BaseController {
|
||||
private Log log = Log.get();
|
||||
|
||||
protected static final String PROMTAIL_LISTEN_SERVER = "server";
|
||||
protected static final String PROMTAIL_LISTEN_PORT = "http_listen_port";
|
||||
|
||||
@Value("${confagent.tokenFile:config/token.auth}")
|
||||
protected String tokenFile; //token文件位置
|
||||
|
||||
@Value("${confagent.promtail.cmdLine}")
|
||||
protected String promtailCmdLinePath; // promtail config.conf 启动参数文件存放位置
|
||||
|
||||
@Value("${confagent.promtail.defaultIP:127.0.0.1}")
|
||||
protected String defaultPromtailIP; //promtail 默认监听ip
|
||||
|
||||
protected static final int DEFAULT_PROMTAIL_PORT=9080; //prometheus 默认监听端口
|
||||
|
||||
@Value("${confagent.promtail.config}")
|
||||
protected String promtailConfPath;
|
||||
|
||||
/**
|
||||
* 调用 /-/reload 接口,热加载 server 配置文件,
|
||||
*
|
||||
* @param cmdLinePath
|
||||
* @param serverListenAddr
|
||||
* @param defaultServerPort
|
||||
* @param defaultServerIP
|
||||
* @return
|
||||
*/
|
||||
// public boolean reloadServerConfiguration(String cmdLinePath, String serverListenAddr, int defaultServerPort, String defaultServerIP) {
|
||||
// UrlBuilder serverReloadUrl = new UrlBuilder();
|
||||
// int serverPort = ConfagentUtil.getConfFilePort(cmdLinePath, serverListenAddr, defaultServerPort);
|
||||
// serverReloadUrl.setScheme("http").setHost(defaultServerIP).setPort(serverPort).addPath("/-/reload");
|
||||
//
|
||||
// String url = serverReloadUrl.toString();
|
||||
// HttpRequest post = Tool.HttpUtil.createPost(url);
|
||||
// HttpResponse response = post.execute();
|
||||
// return 200 == response.getStatus();
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package net.geedge.confagent.controller;
|
||||
|
||||
import cn.hutool.core.net.url.UrlBuilder;
|
||||
import cn.hutool.http.HttpConnection;
|
||||
import cn.hutool.log.Log;
|
||||
import net.geedge.confagent.annotation.UnCheckToken;
|
||||
import net.geedge.confagent.util.ConfagentUtil;
|
||||
import net.geedge.confagent.util.R;
|
||||
import net.geedge.confagent.util.RCode;
|
||||
import net.geedge.confagent.util.Tool;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("healthy")
|
||||
public class HealthyController extends BaseController{
|
||||
|
||||
@Autowired
|
||||
private ConfagentUtil confagentUtil;
|
||||
private final static Log log = Log.get();
|
||||
|
||||
private UrlBuilder promtailHealthy;
|
||||
|
||||
@GetMapping
|
||||
@UnCheckToken
|
||||
public R checkHealthy(@RequestHeader(value="Authorization",required = false) String token) {
|
||||
|
||||
Map<String,String> result = new HashMap<>();
|
||||
|
||||
buildHealthyURL(result);
|
||||
|
||||
if(Tool.StrUtil.isNotBlank(token)){
|
||||
if(confagentUtil.checkToken(token).getCode() == RCode.SUCCESS.getCode()){
|
||||
result.put("auth","TRUE");
|
||||
}else{
|
||||
result.put("auth","FALSE");
|
||||
}
|
||||
}
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
public void buildHealthyURL(Map<String,String> result){
|
||||
|
||||
Map<String,Object> promtailConf = Tool.YamlUtil.readAsMap(promtailConfPath);
|
||||
|
||||
if(promtailConf==null) {
|
||||
result.put("promtail","DOWN");
|
||||
return ;
|
||||
}
|
||||
|
||||
Map<String,Integer> promtailPortMap = (Map<String,Integer>)promtailConf.get(PROMTAIL_LISTEN_SERVER);
|
||||
|
||||
if(promtailPortMap==null) {
|
||||
result.put("promtail","DOWN");
|
||||
return ;
|
||||
}
|
||||
|
||||
Integer promtailPort = promtailPortMap.get(PROMTAIL_LISTEN_PORT);
|
||||
if(promtailPort==null) {
|
||||
promtailPort = DEFAULT_PROMTAIL_PORT;
|
||||
}
|
||||
promtailHealthy = new UrlBuilder();
|
||||
promtailHealthy.setScheme("http").setHost(defaultPromtailIP).setPort(promtailPort).addPath("/ready");
|
||||
|
||||
result.put("promtail",checkState(promtailHealthy.toString()));
|
||||
}
|
||||
|
||||
|
||||
private String checkState(String url){
|
||||
HttpURLConnection conn = null;
|
||||
try{
|
||||
conn = HttpConnection.create(url,null).getHttpURLConnection();
|
||||
log.debug("connect to {}",url);
|
||||
conn.connect();
|
||||
int responseCode = conn.getResponseCode();
|
||||
|
||||
if(200 == responseCode){
|
||||
return "UP";
|
||||
}
|
||||
|
||||
return "DOWN";
|
||||
}catch (IOException e){
|
||||
log.error("failed connect ",e);
|
||||
return "DOWN";
|
||||
}finally {
|
||||
if (conn != null) {
|
||||
conn.disconnect();
|
||||
conn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package net.geedge.confagent.controller;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import net.geedge.confagent.util.ConfagentUtil;
|
||||
import net.geedge.confagent.util.R;
|
||||
import net.geedge.confagent.util.RCode;
|
||||
import net.geedge.confagent.util.Tool;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/promtail")
|
||||
public class PromtailController extends BaseController{
|
||||
private final static Log log = Log.get();
|
||||
|
||||
@Autowired
|
||||
private ConfagentUtil confagentUtil;
|
||||
|
||||
@Value("${confagent.promtail.query.auth:true}")
|
||||
private Boolean queryAuth;
|
||||
|
||||
private final String[] QUERY_API_SUFFIX = {"query","query_range","series","labels","values"};
|
||||
|
||||
@Value("${confagent.promtail.restart:systemctl restart promtail}")
|
||||
private String restartCmd;
|
||||
|
||||
@Value("${confagent.versionFile:promtail.version}")
|
||||
private String versionFile;
|
||||
|
||||
private static String rootPath = Tool.WebPathUtil.getRootPath();
|
||||
|
||||
/**
|
||||
* @Description 获取promtail相关配置
|
||||
* @Author rui
|
||||
* @Date 2021/3/24
|
||||
*/
|
||||
@GetMapping("/config")
|
||||
public R queryConfig(){
|
||||
Map<String,String> cmdLine = ConfagentUtil.loadServiceConfigFile(promtailCmdLinePath);
|
||||
Map<String,Object> promtailConf = Tool.YamlUtil.readAsMap(promtailConfPath);
|
||||
String version = confagentUtil.readVersion();
|
||||
|
||||
Map<String,Object> result = new LinkedHashMap<>();
|
||||
|
||||
result.put("version",version);
|
||||
result.put("cmdline",cmdLine);
|
||||
result.put("config",promtailConf);
|
||||
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 写入promtail配置文件
|
||||
* @Author rui
|
||||
* @Date 2021/3/25
|
||||
*/
|
||||
@PostMapping("/config")
|
||||
public R overwriteConfig( @RequestBody Map<String,Object> configs){
|
||||
|
||||
Object version = configs.get("version");
|
||||
File tf = Tool.FileUtil.file(rootPath, versionFile);
|
||||
log.debug("version file path : {}" ,tf.getAbsolutePath());
|
||||
if(version==null){
|
||||
return R.error(RCode.PROMTAIL_CONFIG_VERSION_ISNULL);
|
||||
}else {
|
||||
Tool.FileUtil.writeUtf8String(version.toString(), tf);
|
||||
}
|
||||
|
||||
Map<String,String> cmdLine =(Map<String,String>) configs.get("cmdline");
|
||||
Map<String,Object> promtailConf =(Map<String,Object>) configs.get("config");
|
||||
|
||||
// boolean reload = false;
|
||||
// boolean restart = false;
|
||||
if(!Tool.MapUtil.isEmpty(cmdLine)){
|
||||
log.info("write promtail cmdLine conf:{}", Tool.JSONUtil.toJsonStr(cmdLine));
|
||||
writeServiceConfigFile(cmdLine,promtailCmdLinePath);
|
||||
// restart = true;
|
||||
}
|
||||
if(!Tool.MapUtil.isEmpty(promtailConf)){
|
||||
log.info("write promtail conf:{}", Tool.JSONUtil.toJsonStr(promtailConf));
|
||||
Tool.YamlUtil.writeAsMap(promtailConf,promtailConfPath);
|
||||
// reload = true;
|
||||
}
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 获取promtail相关配置版本
|
||||
* @Author rui
|
||||
* @Date 2021/3/24
|
||||
*/
|
||||
@GetMapping("/config/version")
|
||||
public R queryVersion(){
|
||||
Map<String,Object> result = new HashMap<>();
|
||||
String version = confagentUtil.readVersion();
|
||||
result.put("version",version);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 写 promtail config.conf 启动参数配置文件
|
||||
* @Author rui
|
||||
* @Date 2021/3/25
|
||||
*/
|
||||
private void writeServiceConfigFile(Map<String,String> conf,String path){
|
||||
StringBuffer sb = new StringBuffer();
|
||||
sb.append("OPTION=\"");
|
||||
for (Map.Entry<String,String> entry:conf.entrySet()){
|
||||
String key = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
sb.append("--"+key+"=");
|
||||
sb.append("'"+value+"' ");
|
||||
}
|
||||
sb.append("\"");
|
||||
|
||||
Tool.FileUtil.writeUtf8String(sb.toString(),path);
|
||||
|
||||
}
|
||||
|
||||
// private boolean reloadPromtail(){
|
||||
//
|
||||
// UrlBuilder promtailReload = new UrlBuilder();
|
||||
// int promtailPort = ConfagentUtil.getConfFilePort(promtailCmdLinePath, PROMTAIL_LISTEN_ADDR, DEFAULT_PROMTAIL_PORT);
|
||||
// promtailReload.setScheme("http").setHost(defaultPromtailIP).setPort(promtailPort).addPath("/-/reload");
|
||||
//
|
||||
// String url = promtailReload.toString();
|
||||
// HttpRequest post = Tool.HttpUtil.createPost(url);
|
||||
// HttpResponse response = post.execute();
|
||||
// return 200 == response.getStatus();
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.geedge.confagent.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AuthEntity {
|
||||
private String name;
|
||||
private String pin;
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package net.geedge.confagent.interceptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import net.geedge.confagent.annotation.UnCheckToken;
|
||||
import net.geedge.confagent.util.ConfagentUtil;
|
||||
import net.geedge.confagent.util.R;
|
||||
import net.geedge.confagent.util.RCode;
|
||||
import net.geedge.confagent.util.Tool;
|
||||
|
||||
@Component
|
||||
public class TokenInterceptor implements HandlerInterceptor {
|
||||
private final static Log log = Log.get();
|
||||
@Autowired
|
||||
private ConfagentUtil confagentUtil;
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
if(handler instanceof HandlerMethod){
|
||||
HandlerMethod handlerMethod = (HandlerMethod) handler;
|
||||
Boolean hasAnnotation = Tool.AnnotationUtil.hasAnnotation(handlerMethod.getMethod(), UnCheckToken.class);
|
||||
if(hasAnnotation){
|
||||
return true;
|
||||
}
|
||||
hasAnnotation = Tool.AnnotationUtil.hasAnnotation(handlerMethod.getBeanType(),UnCheckToken.class);
|
||||
if(hasAnnotation){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
String token = request.getHeader("Authorization");
|
||||
R r = confagentUtil.checkToken(token);
|
||||
if(r.getCode() == RCode.SUCCESS.getCode()){
|
||||
return true;
|
||||
}
|
||||
writeResult(response,r);
|
||||
return false;
|
||||
}
|
||||
|
||||
private void writeResult(HttpServletResponse response,Object o){
|
||||
PrintWriter writer=null;
|
||||
try{
|
||||
writer = response.getWriter();
|
||||
writer.print(Tool.JSONUtil.parse(o));
|
||||
writer.flush();
|
||||
}catch (IOException e){
|
||||
log.error("un-know error",e);
|
||||
}finally {
|
||||
Tool.IoUtil.close(writer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
138
src/main/java/net/geedge/confagent/util/ConfagentUtil.java
Normal file
138
src/main/java/net/geedge/confagent/util/ConfagentUtil.java
Normal file
@@ -0,0 +1,138 @@
|
||||
package net.geedge.confagent.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.log.Log;
|
||||
|
||||
@Configuration
|
||||
@Order(value = 1)
|
||||
public class ConfagentUtil {
|
||||
private final static Log log = Log.get();
|
||||
|
||||
@Value("${confagent.tokenFile:config/token.auth}")
|
||||
protected String tokenFile; //token文件位置
|
||||
@Value("${confagent.versionFile:promtail.version}")
|
||||
private String versionFile;
|
||||
private static String rootPath = Tool.WebPathUtil.getRootPath();
|
||||
/**
|
||||
* @Description 读取token文件中的token
|
||||
* @Author rui
|
||||
* @Date 2021/3/25
|
||||
*/
|
||||
public String readToken() throws IORuntimeException {
|
||||
File tf = Tool.FileUtil.file(rootPath, tokenFile);
|
||||
log.info("token file path : {}" ,tf.getAbsolutePath());
|
||||
String token = Tool.FileUtil.readString(tf, Tool.CharsetUtil.UTF_8);
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 读取version
|
||||
* @Author rui
|
||||
* @Date 2021/3/25
|
||||
*/
|
||||
public String readVersion() throws IORuntimeException {
|
||||
String version = "1";
|
||||
File tf = Tool.FileUtil.file(rootPath, versionFile);
|
||||
if(tf!=null && tf.exists()) {
|
||||
log.info("version file path : {}" ,tf.getAbsolutePath());
|
||||
version = Tool.FileUtil.readString(tf, Tool.CharsetUtil.UTF_8);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 检查token 是否和文件中的一致
|
||||
* @Author rui
|
||||
* @Date 2021/3/25
|
||||
*/
|
||||
public R checkToken(String token){
|
||||
if(Tool.StrUtil.isBlank(token)){
|
||||
return R.error(RCode.AUTH_TOKEN_ISNULL);
|
||||
}
|
||||
try{
|
||||
String readToken = this.readToken();
|
||||
if(Tool.StrUtil.equals(readToken,token)){
|
||||
return R.ok();
|
||||
}
|
||||
return R.error(RCode.AUTH_TOKEN_INVALID);
|
||||
}catch (IORuntimeException e){
|
||||
log.error("read token file failed",e);
|
||||
return R.error(RCode.AUTH_READ_TOKEN_FAILD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 加载service EnvironmentFile中的内容,并整理为map
|
||||
* @Author rui
|
||||
* @Date 2021/3/24
|
||||
*/
|
||||
public static Map<String,String> loadServiceConfigFile(String path){
|
||||
File file = Tool.FileUtil.file(path);
|
||||
if(!Tool.FileUtil.exist(file)){
|
||||
return null;
|
||||
}
|
||||
|
||||
String readLine = Tool.FileUtil.readUtf8String(file);
|
||||
|
||||
//匹配有参类型 --[\w\.-]+?\s 可匹配无参类型
|
||||
Pattern pattern = Pattern.compile("--([\\w\\.-]+?)='?(.+?)'?\\s+?");
|
||||
Matcher matcher = pattern.matcher(readLine);
|
||||
|
||||
Map<String, String> result = new HashMap<>();
|
||||
while(matcher.find()){
|
||||
result.put(matcher.group(1).trim(),matcher.group(2).trim());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Description 获取配置在config.conf启动参数文件中的端口
|
||||
* @Author rui
|
||||
* @Date 2021/3/25
|
||||
*/
|
||||
public static Integer getConfFilePort(String path,String key,Integer defaultValue){
|
||||
Map<String, String> configs = loadServiceConfigFile(path);
|
||||
|
||||
if(configs!=null) {
|
||||
String address = configs.get(key);
|
||||
|
||||
String[] split = address.split(":");
|
||||
|
||||
return Tool.StrUtil.isNotBlank(split[1])? Integer.parseInt(split[1]):defaultValue;
|
||||
}else {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void writeResponse(HttpServletResponse response, Object o) {
|
||||
OutputStream outputStream = null;
|
||||
|
||||
try {
|
||||
outputStream = response.getOutputStream();
|
||||
|
||||
Tool.IoUtil.writeUtf8 (outputStream,true, Tool.JSONUtil.parseObj(o).toString());
|
||||
outputStream.flush();
|
||||
}catch (IOException e){
|
||||
log.error("write response failed :",e);
|
||||
}finally {
|
||||
Tool.IoUtil.close(outputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/main/java/net/geedge/confagent/util/IdUtil.java
Normal file
10
src/main/java/net/geedge/confagent/util/IdUtil.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package net.geedge.confagent.util;
|
||||
|
||||
public class IdUtil extends cn.hutool.core.util.IdUtil {
|
||||
|
||||
public static String fastShortUUID(){
|
||||
String uuid = fastSimpleUUID();
|
||||
return uuid.substring(0,8);
|
||||
}
|
||||
|
||||
}
|
||||
17
src/main/java/net/geedge/confagent/util/IoUtil.java
Normal file
17
src/main/java/net/geedge/confagent/util/IoUtil.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package net.geedge.confagent.util;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
public class IoUtil extends cn.hutool.core.io.IoUtil {
|
||||
|
||||
|
||||
public static void close(final Closeable ... closeables){
|
||||
if (closeables == null) {
|
||||
return;
|
||||
}
|
||||
for (final Closeable closeable:closeables){
|
||||
close(closeable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
907
src/main/java/net/geedge/confagent/util/JSONUtil.java
Normal file
907
src/main/java/net/geedge/confagent/util/JSONUtil.java
Normal file
@@ -0,0 +1,907 @@
|
||||
package net.geedge.confagent.util;
|
||||
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.file.FileReader;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.util.*;
|
||||
import cn.hutool.json.*;
|
||||
import cn.hutool.json.serialize.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* JSON工具类
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class JSONUtil {
|
||||
|
||||
// -------------------------------------------------------------------- Pause start
|
||||
|
||||
/**
|
||||
* 创建JSONObject
|
||||
*
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject createObj() {
|
||||
return new JSONObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建JSONObject
|
||||
*
|
||||
* @param config JSON配置
|
||||
* @return JSONObject
|
||||
* @since 5.2.5
|
||||
*/
|
||||
public static JSONObject createObj(JSONConfig config) {
|
||||
return new JSONObject(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 JSONArray
|
||||
*
|
||||
* @return JSONArray
|
||||
*/
|
||||
public static JSONArray createArray() {
|
||||
return new JSONArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 JSONArray
|
||||
*
|
||||
* @param config JSON配置
|
||||
* @return JSONArray
|
||||
* @since 5.2.5
|
||||
*/
|
||||
public static JSONArray createArray(JSONConfig config) {
|
||||
return new JSONArray(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONObject对象
|
||||
*
|
||||
* @param jsonStr JSON字符串
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject parseObj(String jsonStr) {
|
||||
return new JSONObject(jsonStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONObject对象<br>
|
||||
* 此方法会忽略空值,但是对JSON字符串不影响
|
||||
*
|
||||
* @param obj Bean对象或者Map
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject parseObj(Object obj) {
|
||||
return new JSONObject(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONObject对象<br>
|
||||
* 此方法会忽略空值,但是对JSON字符串不影响
|
||||
*
|
||||
* @param obj Bean对象或者Map
|
||||
* @param config JSON配置
|
||||
* @return JSONObject
|
||||
* @since 5.3.1
|
||||
*/
|
||||
public static JSONObject parseObj(Object obj, JSONConfig config) {
|
||||
return new JSONObject(obj, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONObject对象
|
||||
*
|
||||
* @param obj Bean对象或者Map
|
||||
* @param ignoreNullValue 是否忽略空值,如果source为JSON字符串,不忽略空值
|
||||
* @return JSONObject
|
||||
* @since 3.0.9
|
||||
*/
|
||||
public static JSONObject parseObj(Object obj, boolean ignoreNullValue) {
|
||||
return new JSONObject(obj, ignoreNullValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONObject对象
|
||||
*
|
||||
* @param obj Bean对象或者Map
|
||||
* @param ignoreNullValue 是否忽略空值,如果source为JSON字符串,不忽略空值
|
||||
* @param isOrder 是否有序
|
||||
* @return JSONObject
|
||||
* @since 4.2.2
|
||||
*/
|
||||
public static JSONObject parseObj(Object obj, boolean ignoreNullValue, boolean isOrder) {
|
||||
return new JSONObject(obj, ignoreNullValue, isOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONArray
|
||||
*
|
||||
* @param jsonStr JSON字符串
|
||||
* @return JSONArray
|
||||
*/
|
||||
public static JSONArray parseArray(String jsonStr) {
|
||||
return new JSONArray(jsonStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONArray
|
||||
*
|
||||
* @param arrayOrCollection 数组或集合对象
|
||||
* @return JSONArray
|
||||
* @since 3.0.8
|
||||
*/
|
||||
public static JSONArray parseArray(Object arrayOrCollection) {
|
||||
return new JSONArray(arrayOrCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONArray
|
||||
*
|
||||
* @param arrayOrCollection 数组或集合对象
|
||||
* @param config JSON配置
|
||||
* @return JSONArray
|
||||
* @since 5.3.1
|
||||
*/
|
||||
public static JSONArray parseArray(Object arrayOrCollection, JSONConfig config) {
|
||||
return new JSONArray(arrayOrCollection, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转JSONArray
|
||||
*
|
||||
* @param arrayOrCollection 数组或集合对象
|
||||
* @param ignoreNullValue 是否忽略空值
|
||||
* @return JSONArray
|
||||
* @since 3.2.3
|
||||
*/
|
||||
public static JSONArray parseArray(Object arrayOrCollection, boolean ignoreNullValue) {
|
||||
return new JSONArray(arrayOrCollection, ignoreNullValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON<br>
|
||||
* 支持的对象:<br>
|
||||
* String: 转换为相应的对象<br>
|
||||
* Array Collection:转换为JSONArray<br>
|
||||
* Bean对象:转为JSONObject
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return JSON
|
||||
*/
|
||||
public static JSON parse(Object obj) {
|
||||
return parse(obj, JSONConfig.create());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换对象为JSON<br>
|
||||
* 支持的对象:<br>
|
||||
* String: 转换为相应的对象<br>
|
||||
* Array、Iterable、Iterator:转换为JSONArray<br>
|
||||
* Bean对象:转为JSONObject
|
||||
*
|
||||
* @param obj 对象
|
||||
* @param config JSON配置
|
||||
* @return JSON
|
||||
* @since 5.3.1
|
||||
*/
|
||||
public static JSON parse(Object obj, JSONConfig config) {
|
||||
if (null == obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
JSON json;
|
||||
if (obj instanceof JSON) {
|
||||
json = (JSON) obj;
|
||||
} else if (obj instanceof CharSequence) {
|
||||
final String jsonStr = StrUtil.trim((CharSequence) obj);
|
||||
json = StrUtil.startWith(jsonStr, '[') ? parseArray(jsonStr) : parseObj(jsonStr);
|
||||
} else if (obj instanceof Iterable || obj instanceof Iterator || ArrayUtil.isArray(obj)) {// 列表
|
||||
json = new JSONArray(obj, config);
|
||||
} else {// 对象
|
||||
json = new JSONObject(obj, config);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* XML字符串转为JSONObject
|
||||
*
|
||||
* @param xmlStr XML字符串
|
||||
* @return JSONObject
|
||||
*/
|
||||
public static JSONObject parseFromXml(String xmlStr) {
|
||||
return XML.toJSONObject(xmlStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map转化为JSONObject
|
||||
*
|
||||
* @param map {@link Map}
|
||||
* @return JSONObjec
|
||||
* @deprecated 请直接使用 {@link #parseObj(Object)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static JSONObject parseFromMap(Map<?, ?> map) {
|
||||
return new JSONObject(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* ResourceBundle转化为JSONObject
|
||||
*
|
||||
* @param bundle ResourceBundle文件
|
||||
* @return JSONObject
|
||||
* @deprecated 请直接使用 {@link #parseObj(Object)}
|
||||
*/
|
||||
@Deprecated
|
||||
public static JSONObject parseFromResourceBundle(ResourceBundle bundle) {
|
||||
return new JSONObject(bundle);
|
||||
}
|
||||
// -------------------------------------------------------------------- Pause end
|
||||
|
||||
// -------------------------------------------------------------------- Read start
|
||||
|
||||
/**
|
||||
* 读取JSON
|
||||
*
|
||||
* @param file JSON文件
|
||||
* @param charset 编码
|
||||
* @return JSON(包括JSONObject和JSONArray)
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static JSON readJSON(File file, Charset charset) throws IORuntimeException {
|
||||
return parse(FileReader.create(file, charset).readString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取JSONObject
|
||||
*
|
||||
* @param file JSON文件
|
||||
* @param charset 编码
|
||||
* @return JSONObject
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static JSONObject readJSONObject(File file, Charset charset) throws IORuntimeException {
|
||||
return parseObj(FileReader.create(file, charset).readString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取JSONArray
|
||||
*
|
||||
* @param file JSON文件
|
||||
* @param charset 编码
|
||||
* @return JSONArray
|
||||
* @throws IORuntimeException IO异常
|
||||
*/
|
||||
public static JSONArray readJSONArray(File file, Charset charset) throws IORuntimeException {
|
||||
return parseArray(FileReader.create(file, charset).readString());
|
||||
}
|
||||
// -------------------------------------------------------------------- Read end
|
||||
|
||||
// -------------------------------------------------------------------- toString start
|
||||
|
||||
/**
|
||||
* 转为JSON字符串
|
||||
*
|
||||
* @param json JSON
|
||||
* @param indentFactor 每一级别的缩进
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String toJsonStr(JSON json, int indentFactor) {
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
return json.toJSONString(indentFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为JSON字符串
|
||||
*
|
||||
* @param json JSON
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String toJsonStr(JSON json) {
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
return json.toJSONString(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为JSON字符串,并写出到write
|
||||
*
|
||||
* @param json JSON
|
||||
* @param writer Writer
|
||||
* @since 5.3.3
|
||||
*/
|
||||
public static void toJsonStr(JSON json, Writer writer) {
|
||||
if (null != json) {
|
||||
json.write(writer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为JSON字符串
|
||||
*
|
||||
* @param json JSON
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String toJsonPrettyStr(JSON json) {
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
return json.toJSONString(4);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为JSON字符串
|
||||
*
|
||||
* @param obj 被转为JSON的对象
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String toJsonStr(Object obj) {
|
||||
if (null == obj) {
|
||||
return null;
|
||||
}
|
||||
if (obj instanceof CharSequence) {
|
||||
return StrUtil.str((CharSequence) obj);
|
||||
}
|
||||
return toJsonStr(parse(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为JSON字符串并写出到writer
|
||||
*
|
||||
* @param obj 被转为JSON的对象
|
||||
* @param writer Writer
|
||||
* @since 5.3.3
|
||||
*/
|
||||
public static void toJsonStr(Object obj, Writer writer) {
|
||||
if (null != obj) {
|
||||
toJsonStr(parse(obj), writer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为格式化后的JSON字符串
|
||||
*
|
||||
* @param obj Bean对象
|
||||
* @return JSON字符串
|
||||
*/
|
||||
public static String toJsonPrettyStr(Object obj) {
|
||||
return toJsonPrettyStr(parse(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为XML字符串
|
||||
*
|
||||
* @param json JSON
|
||||
* @return XML字符串
|
||||
*/
|
||||
public static String toXmlStr(JSON json) {
|
||||
return XML.toXml(json);
|
||||
}
|
||||
// -------------------------------------------------------------------- toString end
|
||||
|
||||
// -------------------------------------------------------------------- toBean start
|
||||
|
||||
/**
|
||||
* JSON字符串转为实体类对象,转换异常将被抛出
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param jsonString JSON字符串
|
||||
* @param beanClass 实体类对象
|
||||
* @return 实体类对象
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static <T> T toBean(String jsonString, Class<T> beanClass) {
|
||||
return toBean(parseObj(jsonString), beanClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为实体类对象,转换异常将被抛出
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param json JSONObject
|
||||
* @param beanClass 实体类对象
|
||||
* @return 实体类对象
|
||||
*/
|
||||
public static <T> T toBean(JSONObject json, Class<T> beanClass) {
|
||||
return null == json ? null : json.toBean(beanClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转为实体类对象,转换异常将被抛出
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param jsonString JSON字符串
|
||||
* @param typeReference {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型
|
||||
* @param ignoreError 是否忽略错误
|
||||
* @return 实体类对象
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public static <T> T toBean(String jsonString, TypeReference<T> typeReference, boolean ignoreError) {
|
||||
return toBean(jsonString, typeReference.getType(), ignoreError);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转为实体类对象,转换异常将被抛出
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param jsonString JSON字符串
|
||||
* @param beanType 实体类对象类型
|
||||
* @param ignoreError 是否忽略错误
|
||||
* @return 实体类对象
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public static <T> T toBean(String jsonString, Type beanType, boolean ignoreError) {
|
||||
return toBean(parse(jsonString), beanType, ignoreError);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为实体类对象
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param json JSONObject
|
||||
* @param typeReference {@link TypeReference}类型参考子类,可以获取其泛型参数中的Type类型
|
||||
* @param ignoreError 是否忽略转换错误
|
||||
* @return 实体类对象
|
||||
* @since 4.6.2
|
||||
*/
|
||||
public static <T> T toBean(JSON json, TypeReference<T> typeReference, boolean ignoreError) {
|
||||
return toBean(json, typeReference.getType(), ignoreError);
|
||||
}
|
||||
|
||||
/**
|
||||
* 转为实体类对象
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param json JSONObject
|
||||
* @param beanType 实体类对象类型
|
||||
* @param ignoreError 是否忽略转换错误
|
||||
* @return 实体类对象
|
||||
* @since 4.3.2
|
||||
*/
|
||||
public static <T> T toBean(JSON json, Type beanType, boolean ignoreError) {
|
||||
if (null == json) {
|
||||
return null;
|
||||
}
|
||||
return json.toBean(beanType, ignoreError);
|
||||
}
|
||||
// -------------------------------------------------------------------- toBean end
|
||||
|
||||
/**
|
||||
* 将JSONArray字符串转换为Bean的List,默认为ArrayList
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param jsonArray JSONArray字符串
|
||||
* @param elementType List中元素类型
|
||||
* @return List
|
||||
* @since 5.5.2
|
||||
*/
|
||||
public static <T> List<T> toList(String jsonArray, Class<T> elementType) {
|
||||
return toList(parseArray(jsonArray), elementType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将JSONArray转换为Bean的List,默认为ArrayList
|
||||
*
|
||||
* @param <T> Bean类型
|
||||
* @param jsonArray {@link JSONArray}
|
||||
* @param elementType List中元素类型
|
||||
* @return List
|
||||
* @since 4.0.7
|
||||
*/
|
||||
public static <T> List<T> toList(JSONArray jsonArray, Class<T> elementType) {
|
||||
return null == jsonArray ? null : jsonArray.toList(elementType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过表达式获取JSON中嵌套的对象<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
*
|
||||
* @param json {@link JSON}
|
||||
* @param expression 表达式
|
||||
* @return 对象
|
||||
* @see JSON#getByPath(String)
|
||||
*/
|
||||
public static Object getByPath(JSON json, String expression) {
|
||||
return (null == json || StrUtil.isBlank(expression)) ? null : json.getByPath(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表达式指定位置(或filed对应)的值<br>
|
||||
* 若表达式指向一个JSONArray则设置其坐标对应位置的值,若指向JSONObject则put对应key的值<br>
|
||||
* 注意:如果为JSONArray,则设置值得下标不能大于已有JSONArray的长度<br>
|
||||
* <ol>
|
||||
* <li>.表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值</li>
|
||||
* <li>[]表达式,可以获取集合等对象中对应index的值</li>
|
||||
* </ol>
|
||||
* <p>
|
||||
* 表达式栗子:
|
||||
*
|
||||
* <pre>
|
||||
* persion
|
||||
* persion.name
|
||||
* persons[3]
|
||||
* person.friends[5].name
|
||||
* </pre>
|
||||
*
|
||||
* @param json JSON,可以为JSONObject或JSONArray
|
||||
* @param expression 表达式
|
||||
* @param value 值
|
||||
*/
|
||||
public static void putByPath(JSON json, String expression, Object value) {
|
||||
json.putByPath(expression, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对所有双引号做转义处理(使用双反斜杠做转义)<br>
|
||||
* 为了能在HTML中较好的显示,会将</转义为<\/<br>
|
||||
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
|
||||
*
|
||||
* @param string 字符串
|
||||
* @return 适合在JSON中显示的字符串
|
||||
*/
|
||||
public static String quote(String string) {
|
||||
return quote(string, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对所有双引号做转义处理(使用双反斜杠做转义)<br>
|
||||
* 为了能在HTML中较好的显示,会将</转义为<\/<br>
|
||||
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
|
||||
*
|
||||
* @param string 字符串
|
||||
* @param isWrap 是否使用双引号包装字符串
|
||||
* @return 适合在JSON中显示的字符串
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public static String quote(String string, boolean isWrap) {
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
return quote(string, sw, isWrap).toString();
|
||||
} catch (IOException ignored) {
|
||||
// will never happen - we are writing to a string writer
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对所有双引号做转义处理(使用双反斜杠做转义)<br>
|
||||
* 为了能在HTML中较好的显示,会将</转义为<\/<br>
|
||||
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param writer Writer
|
||||
* @return Writer
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static Writer quote(String str, Writer writer) throws IOException {
|
||||
return quote(str, writer, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对所有双引号做转义处理(使用双反斜杠做转义)<br>
|
||||
* 为了能在HTML中较好的显示,会将</转义为<\/<br>
|
||||
* JSON字符串中不能包含控制字符和未经转义的引号和反斜杠
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param writer Writer
|
||||
* @param isWrap 是否使用双引号包装字符串
|
||||
* @return Writer
|
||||
* @throws IOException IO异常
|
||||
* @since 3.3.1
|
||||
*/
|
||||
public static Writer quote(String str, Writer writer, boolean isWrap) throws IOException {
|
||||
if (StrUtil.isEmpty(str)) {
|
||||
if (isWrap) {
|
||||
writer.write("\"\"");
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
char b; // 前一个字符
|
||||
char c; // 当前字符
|
||||
int len = str.length();
|
||||
if (isWrap) {
|
||||
writer.write('"');
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
// b = c;
|
||||
c = str.charAt(i);
|
||||
switch (c) {
|
||||
case '\\':
|
||||
case '"':
|
||||
writer.write("\\");
|
||||
writer.write(c);
|
||||
break;
|
||||
//此处转义导致输出不和预期一致
|
||||
// case '/':
|
||||
// if (b == '<') {
|
||||
// writer.write('\\');
|
||||
// }
|
||||
// writer.write(c);
|
||||
// break;
|
||||
default:
|
||||
writer.write(escape(c));
|
||||
}
|
||||
}
|
||||
if (isWrap) {
|
||||
writer.write('"');
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义显示不可见字符
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return 转义后的字符串
|
||||
*/
|
||||
public static String escape(String str) {
|
||||
if (StrUtil.isEmpty(str)) {
|
||||
return str;
|
||||
}
|
||||
|
||||
final int len = str.length();
|
||||
final StringBuilder builder = new StringBuilder(len);
|
||||
char c;
|
||||
for (int i = 0; i < len; i++) {
|
||||
c = str.charAt(i);
|
||||
builder.append(escape(c));
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 在需要的时候包装对象<br>
|
||||
* 包装包括:
|
||||
* <ul>
|
||||
* <li><code>null</code> =》 <code>JSONNull.NULL</code></li>
|
||||
* <li>array or collection =》 JSONArray</li>
|
||||
* <li>map =》 JSONObject</li>
|
||||
* <li>standard property (Double, String, et al) =》 原对象</li>
|
||||
* <li>来自于java包 =》 字符串</li>
|
||||
* <li>其它 =》 尝试包装为JSONObject,否则返回<code>null</code></li>
|
||||
* </ul>
|
||||
*
|
||||
* @param object 被包装的对象
|
||||
* @param jsonConfig JSON选项
|
||||
* @return 包装后的值,null表示此值需被忽略
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static Object wrap(Object object, JSONConfig jsonConfig) {
|
||||
if (object == null) {
|
||||
return jsonConfig.isIgnoreNullValue() ? null : JSONNull.NULL;
|
||||
}
|
||||
if (object instanceof JSON //
|
||||
|| JSONNull.NULL.equals(object) //
|
||||
|| object instanceof JSONString //
|
||||
|| object instanceof CharSequence //
|
||||
|| object instanceof Number //
|
||||
|| ObjectUtil.isBasicType(object) //
|
||||
) {
|
||||
return object;
|
||||
}
|
||||
|
||||
// 自定义序列化
|
||||
final JSONSerializer serializer = GlobalSerializeMapping.getSerializer(object.getClass());
|
||||
if (null != serializer) {
|
||||
final Type jsonType = TypeUtil.getTypeArgument(serializer.getClass());
|
||||
if (null != jsonType) {
|
||||
if (serializer instanceof JSONObjectSerializer) {
|
||||
serializer.serialize(new JSONObject(jsonConfig), object);
|
||||
} else if (serializer instanceof JSONArraySerializer) {
|
||||
serializer.serialize(new JSONArray(jsonConfig), object);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// JSONArray
|
||||
if (object instanceof Iterable || ArrayUtil.isArray(object)) {
|
||||
return new JSONArray(object, jsonConfig);
|
||||
}
|
||||
// JSONObject
|
||||
if (object instanceof Map) {
|
||||
return new JSONObject(object, jsonConfig);
|
||||
}
|
||||
|
||||
// 日期类型原样保存,便于格式化
|
||||
if (object instanceof Date
|
||||
|| object instanceof Calendar
|
||||
|| object instanceof TemporalAccessor
|
||||
) {
|
||||
return object;
|
||||
}
|
||||
// 枚举类保存其字符串形式(4.0.2新增)
|
||||
if (object instanceof Enum) {
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
// Java内部类不做转换
|
||||
if (ClassUtil.isJdkClass(object.getClass())) {
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
// 默认按照JSONObject对待
|
||||
return new JSONObject(object, jsonConfig);
|
||||
} catch (Exception exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化JSON字符串,此方法并不严格检查JSON的格式正确与否
|
||||
*
|
||||
* @param jsonStr JSON字符串
|
||||
* @return 格式化后的字符串
|
||||
* @since 3.1.2
|
||||
*/
|
||||
public static String formatJsonStr(String jsonStr) {
|
||||
return JSONStrFormater.format(jsonStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为JSON字符串,首尾都为大括号或中括号判定为JSON字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return 是否为JSON字符串
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public static boolean isJson(String str) {
|
||||
return isJsonObj(str) || isJsonArray(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为JSONObject字符串,首尾都为大括号判定为JSONObject字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return 是否为JSON字符串
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public static boolean isJsonObj(String str) {
|
||||
if (StrUtil.isBlank(str)) {
|
||||
return false;
|
||||
}
|
||||
return StrUtil.isWrap(str.trim(), '{', '}');
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为JSONArray字符串,首尾都为中括号判定为JSONArray字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return 是否为JSON字符串
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public static boolean isJsonArray(String str) {
|
||||
if (StrUtil.isBlank(str)) {
|
||||
return false;
|
||||
}
|
||||
return StrUtil.isWrap(str.trim(), '[', ']');
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为null对象,null的情况包括:
|
||||
*
|
||||
* <pre>
|
||||
* 1. {@code null}
|
||||
* 2. {@link JSONNull}
|
||||
* </pre>
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 是否为null
|
||||
* @since 4.5.7
|
||||
*/
|
||||
public static boolean isNull(Object obj) {
|
||||
return null == obj || obj instanceof JSONNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* XML转JSONObject<br>
|
||||
* 转换过程中一些信息可能会丢失,JSON中无法区分节点和属性,相同的节点将被处理为JSONArray。
|
||||
*
|
||||
* @param xml XML字符串
|
||||
* @return JSONObject
|
||||
* @since 4.0.8
|
||||
*/
|
||||
public static JSONObject xmlToJson(String xml) {
|
||||
return XML.toJSONObject(xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的序列化器
|
||||
*
|
||||
* @param type 对象类型
|
||||
* @param serializer 序列化器实现
|
||||
* @see GlobalSerializeMapping#put(Type, JSONArraySerializer)
|
||||
* @since 4.6.5
|
||||
*/
|
||||
public static void putSerializer(Type type, JSONArraySerializer<?> serializer) {
|
||||
GlobalSerializeMapping.put(type, serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的序列化器
|
||||
*
|
||||
* @param type 对象类型
|
||||
* @param serializer 序列化器实现
|
||||
* @see GlobalSerializeMapping#put(Type, JSONObjectSerializer)
|
||||
* @since 4.6.5
|
||||
*/
|
||||
public static void putSerializer(Type type, JSONObjectSerializer<?> serializer) {
|
||||
GlobalSerializeMapping.put(type, serializer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入自定义的反序列化器
|
||||
*
|
||||
* @param type 对象类型
|
||||
* @param deserializer 反序列化器实现
|
||||
* @see GlobalSerializeMapping#put(Type, JSONDeserializer)
|
||||
* @since 4.6.5
|
||||
*/
|
||||
public static void putDeserializer(Type type, JSONDeserializer<?> deserializer) {
|
||||
GlobalSerializeMapping.put(type, deserializer);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 转义不可见字符<br>
|
||||
* 见:https://en.wikibooks.org/wiki/Unicode/Character_reference/0000-0FFF
|
||||
*
|
||||
* @param c 字符
|
||||
* @return 转义后的字符串
|
||||
*/
|
||||
private static String escape(char c) {
|
||||
switch (c) {
|
||||
case '\b':
|
||||
return "\\b";
|
||||
case '\t':
|
||||
return "\\t";
|
||||
case '\n':
|
||||
return "\\n";
|
||||
case '\f':
|
||||
return "\\f";
|
||||
case '\r':
|
||||
return "\\r";
|
||||
default:
|
||||
if (c < StrUtil.C_SPACE || //
|
||||
(c >= '\u0080' && c <= '\u00a0') || //
|
||||
(c >= '\u2000' && c <= '\u2010') || //
|
||||
(c >= '\u2028' && c <= '\u202F') || //
|
||||
(c >= '\u2066' && c <= '\u206F')//
|
||||
) {
|
||||
return HexUtil.toUnicodeHex(c);
|
||||
} else {
|
||||
return Character.toString(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------------------------- Private method end
|
||||
}
|
||||
66
src/main/java/net/geedge/confagent/util/R.java
Normal file
66
src/main/java/net/geedge/confagent/util/R.java
Normal file
@@ -0,0 +1,66 @@
|
||||
package net.geedge.confagent.util;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 返回数据
|
||||
*
|
||||
* 错误码、错误内容统一在枚举类RCode中定义, 错误码格式见RCode注释,错误码内容必须用英文,作为国际化的code
|
||||
* 自定义的错误类型必须加注释
|
||||
*/
|
||||
public class R extends HashMap<String, Object> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public R() {
|
||||
put("code", RCode.SUCCESS.getCode());
|
||||
put("msg", RCode.SUCCESS.getMsg());
|
||||
}
|
||||
|
||||
public static R error() {
|
||||
return error(RCode.ERROR.getCode(), RCode.ERROR.getMsg());
|
||||
}
|
||||
|
||||
public static R error(RCode rCode) {
|
||||
R r = new R();
|
||||
r.put("code", rCode.getCode());
|
||||
r.put("msg", rCode.getMsg());
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R error(Integer code, String msg) {
|
||||
R r = new R();
|
||||
r.put("code", code);
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok(String msg) {
|
||||
R r = new R();
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok() {
|
||||
return new R();
|
||||
}
|
||||
|
||||
public static R ok(Object data) {
|
||||
R r = new R();
|
||||
r.put("data", data);
|
||||
return r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R put(String key, Object value) {
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Integer getCode(){
|
||||
return (Integer) super.get("code");
|
||||
}
|
||||
public String getMsg(){
|
||||
return (String) super.get("msg");
|
||||
}
|
||||
}
|
||||
|
||||
33
src/main/java/net/geedge/confagent/util/RCode.java
Normal file
33
src/main/java/net/geedge/confagent/util/RCode.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package net.geedge.confagent.util;
|
||||
|
||||
public enum RCode {
|
||||
SUCCESS(200, "success"), //成功
|
||||
|
||||
AUTH_NAME_PIN_ISNULL(10000,"The name and password is required"),
|
||||
AUTH_NAME_PIN_INVALID(10001,"The name or password is invalid"),
|
||||
AUTH_TOKEN_INVALID(10002,"The token is invalid"),
|
||||
AUTH_TOKEN_ISNULL(10003,"Token is required"),
|
||||
AUTH_READ_TOKEN_FAILD(10004,"Read token failed"),
|
||||
|
||||
CONFIG_PROMTAIL_RELOAD_FAILED(10005,"Reload prometheus failed"),
|
||||
CONFIG_BLAVKBOX_RELOAD_FAILED(10006,"Reload blackbox_exporter failed"),
|
||||
CONFIG_SNMP_EXPORTER_RELOAD_FAILED(10007,"Reload snmp_exporter failed"),
|
||||
|
||||
PROMTAIL_CONFIG_VERSION_ISNULL(10008,"The promtail config version is required"),
|
||||
|
||||
ERROR(999, "error"); //通用错误/未知错误
|
||||
private RCode(Integer code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
private Integer code;
|
||||
private String msg;
|
||||
|
||||
public Integer getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
1106
src/main/java/net/geedge/confagent/util/Tool.java
Normal file
1106
src/main/java/net/geedge/confagent/util/Tool.java
Normal file
File diff suppressed because it is too large
Load Diff
112
src/main/java/net/geedge/confagent/util/YamlUtil.java
Normal file
112
src/main/java/net/geedge/confagent/util/YamlUtil.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package net.geedge.confagent.util;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
public class YamlUtil {
|
||||
|
||||
public static void writeAsMap(Map map,String path){
|
||||
Map writeObj = map;
|
||||
if(writeObj == null)
|
||||
writeObj = new HashMap<>();
|
||||
Yaml yaml = new Yaml();
|
||||
Tool.FileUtil.writeUtf8String(yaml.dumpAsMap(writeObj), path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 将yaml文件中的内容读取到map中
|
||||
* @Author rui
|
||||
* @Date 2021/3/24
|
||||
*/
|
||||
public static Map<String,Object> readAsMap(String path){
|
||||
File file = Tool.FileUtil.file(path);
|
||||
Yaml yaml = new Yaml();
|
||||
BufferedReader reader = Tool.FileUtil.getReader(file, Tool.CharsetUtil.UTF_8);
|
||||
Map<String,Object> map = yaml.loadAs(reader, Map.class);
|
||||
|
||||
Tool.IoUtil.close(reader);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 读取yaml文件中的属性,支持spring.profiles.active 连点形式
|
||||
* @Author rui
|
||||
* @Date 2021/3/23
|
||||
*/
|
||||
public String readProperty(String file,String key){
|
||||
Resource resource = getResource(file);
|
||||
Properties properties = yamlToProperties(resource);
|
||||
return properties.getProperty(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 读取yaml文件中的属性,可以指定默认值
|
||||
* @Author rui
|
||||
* @Date 2021/3/23
|
||||
*/
|
||||
public String readProperty(String file,String key,String defValue){
|
||||
Resource resource = getResource(file);
|
||||
Properties properties = yamlToProperties(resource);
|
||||
return properties.getProperty(key,defValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 获取application相关配置文件
|
||||
* @Author rui
|
||||
* @Date 2021/3/23
|
||||
*/
|
||||
public static Resource getApplication(String mode, String profile){
|
||||
return getResource("application"+ (StrUtil.isEmpty(profile)?"":"-"+profile )+".yml");
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 获取配置文件
|
||||
* @Author rui
|
||||
* @Date 2021/3/23
|
||||
*/
|
||||
public static Resource getResource(String file){
|
||||
return new FileSystemResource(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 读取yaml文件并转为properties对象
|
||||
* @Author rui
|
||||
* @Date 2021/3/23
|
||||
*/
|
||||
public static Properties yamlToProperties(String file){
|
||||
Resource resource = getResource(file);
|
||||
return yamlToProperties(resource);
|
||||
}
|
||||
|
||||
public static Properties yamlToProperties(String ... filepath){
|
||||
return yamlToProperties(getFileAbsolutePath(filepath));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 读取yaml文件并转为properties对象
|
||||
* @Author rui
|
||||
* @Date 2021/3/23
|
||||
*/
|
||||
public static Properties yamlToProperties(Resource resource){
|
||||
YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
|
||||
// 2:将加载的配置文件交给 YamlPropertiesFactoryBean
|
||||
yamlPropertiesFactoryBean.setResources(resource);
|
||||
|
||||
// 3:将yml转换成 key:val
|
||||
return yamlPropertiesFactoryBean.getObject();
|
||||
}
|
||||
|
||||
public static String getFileAbsolutePath(String ... path){
|
||||
return Tool.FileUtil.file(path).getAbsolutePath();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user