Commit 543350cb by inrgihc

接口响应数据格式

parent 1280bde0
package com.gitee.sqlrest.common.enums;
import cn.hutool.core.date.DatePattern;
public enum DataTypeFormatEnum {
DATE(java.sql.Date.class.getName(), DatePattern.NORM_DATE_PATTERN),
LOCAL_DATE(java.time.LocalDate.class.getName(), DatePattern.NORM_DATE_PATTERN),
TIME(java.sql.Time.class.getName(), DatePattern.NORM_TIME_PATTERN),
LOCAL_DATE_TIME(java.time.LocalDateTime.class.getName(), DatePattern.NORM_DATETIME_PATTERN),
TIMESTAMP(java.sql.Timestamp.class.getName(), DatePattern.NORM_DATETIME_PATTERN),
BIG_DECIMAL(java.math.BigDecimal.class.getName(), 6),
;
private String className;
private String defaultPattern;
private int numberScale;
DataTypeFormatEnum(String className, String defaultPattern) {
this.className = className;
this.defaultPattern = defaultPattern;
}
DataTypeFormatEnum(String className, int numberScale) {
this.className = className;
this.numberScale = numberScale;
}
public String getClassName() {
return className;
}
public String getDefaultPattern() {
return defaultPattern;
}
public int getNumberScale() {
return numberScale;
}
}
package com.gitee.sqlrest.common.enums;
public enum NamingStrategyEnum {
LOWER_CAMEL_CASE("属性名转换为小驼峰命名"),
UPPER_CAMEL_CASE("属性名转换为大驼峰命名"),
SNAKE_CASE("属性名转换为蛇形命名"),
LOWER_CASE("属性名转换为小写字母"),
;
private String description;
NamingStrategyEnum(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
package com.gitee.sqlrest.core.dto;
import com.gitee.sqlrest.common.dto.ParamValue;
import com.gitee.sqlrest.common.enums.DataTypeFormatEnum;
import com.gitee.sqlrest.common.enums.ExecuteEngineEnum;
import com.gitee.sqlrest.common.enums.NamingStrategyEnum;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
import java.util.Map;
import lombok.Data;
import lombok.NoArgsConstructor;
......@@ -19,6 +22,12 @@ public class ApiDebugExecuteRequest {
@ApiModelProperty("执行引擎:SQL, SCRIPT")
private ExecuteEngineEnum engine;
@ApiModelProperty("数据类型转换格式")
private Map<DataTypeFormatEnum, String> formatMap;
@ApiModelProperty("属性命名策略")
private NamingStrategyEnum namingStrategy;
@ApiModelProperty("SQL列表")
private List<String> contextList;
......
......@@ -85,6 +85,7 @@ public class ScriptExecutorService extends AbstractExecutorEngine {
return "unknown";
}
@Override
public Object execute(List<ApiContextEntity> scripts, Map<String, Object> params) {
EnvVarModule envModule = SpringUtil.getBean(EnvVarModule.class);
DbVarModule dbModule = new DbVarModule(dataSource, productType, params);
......
......@@ -24,6 +24,7 @@ public class SqlExecutorService extends AbstractExecutorEngine {
super(dataSource, productType);
}
@Override
public Object execute(List<ApiContextEntity> scripts, Map<String, Object> params) {
List<Object> dataList = new ArrayList<>();
Configuration cfg = new Configuration();
......
package com.gitee.sqlrest.core.serdes;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.gitee.sqlrest.common.enums.DataTypeFormatEnum;
import com.gitee.sqlrest.core.serdes.datetime.DateValueSerializer;
import com.gitee.sqlrest.core.serdes.datetime.LocalDateTimeValueSerializer;
import com.gitee.sqlrest.core.serdes.datetime.LocalDateValueSerializer;
import com.gitee.sqlrest.core.serdes.datetime.TimeValueSerializer;
import com.gitee.sqlrest.core.serdes.datetime.TimestampValueSerializer;
import com.gitee.sqlrest.core.serdes.number.NumberValueSerializer;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public final class DateTimeSerDesFactory {
private static Map<DataTypeFormatEnum, Function<String, StdSerializer>> DATE_TIME_SER_MAP = new HashMap<>();
static {
DATE_TIME_SER_MAP.put(DataTypeFormatEnum.DATE, DateValueSerializer::new);
DATE_TIME_SER_MAP.put(DataTypeFormatEnum.LOCAL_DATE, LocalDateValueSerializer::new);
DATE_TIME_SER_MAP.put(DataTypeFormatEnum.TIME, TimeValueSerializer::new);
DATE_TIME_SER_MAP.put(DataTypeFormatEnum.TIMESTAMP, TimestampValueSerializer::new);
DATE_TIME_SER_MAP.put(DataTypeFormatEnum.LOCAL_DATE_TIME, LocalDateTimeValueSerializer::new);
DATE_TIME_SER_MAP.put(DataTypeFormatEnum.BIG_DECIMAL, NumberValueSerializer::new);
}
public static Map<DataTypeFormatEnum, Function<String, StdSerializer>> getAllSerDesMap() {
return new HashMap<>(DATE_TIME_SER_MAP);
}
}
package com.gitee.sqlrest.core.serdes.datetime;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import org.apache.commons.lang3.StringUtils;
public class DateValueSerializer extends StdSerializer<Date> {
private static final String DEFAULT_PATTERN = DatePattern.NORM_DATE_PATTERN;
private String pattern;
public DateValueSerializer(String pattern) {
super(Date.class);
this.pattern = StringUtils.defaultIfBlank(pattern, DEFAULT_PATTERN);
}
@Override
public void serialize(Date value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
jsonGenerator.writeString(sdf.format(value));
}
}
}
package com.gitee.sqlrest.core.serdes.datetime;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import org.apache.commons.lang3.StringUtils;
public class LocalDateTimeValueSerializer extends StdSerializer<LocalDateTime> {
private static final String DEFAULT_PATTERN = DatePattern.NORM_DATETIME_PATTERN;
private String pattern;
public LocalDateTimeValueSerializer(String pattern) {
super(LocalDateTime.class);
this.pattern = StringUtils.defaultIfBlank(pattern, DEFAULT_PATTERN);
}
@Override
public void serialize(LocalDateTime value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
jsonGenerator.writeString(sdf.format(value));
}
}
}
package com.gitee.sqlrest.core.serdes.datetime;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import org.apache.commons.lang3.StringUtils;
public class LocalDateValueSerializer extends StdSerializer<LocalDate> {
private static final String DEFAULT_PATTERN = DatePattern.NORM_DATE_PATTERN;
private String pattern;
public LocalDateValueSerializer(String pattern) {
super(LocalDate.class);
this.pattern = StringUtils.defaultIfBlank(pattern, DEFAULT_PATTERN);
}
@Override
public void serialize(LocalDate value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
jsonGenerator.writeString(sdf.format(value));
}
}
}
package com.gitee.sqlrest.core.serdes.datetime;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.sql.Time;
import java.text.SimpleDateFormat;
import org.apache.commons.lang3.StringUtils;
public class TimeValueSerializer extends StdSerializer<Time> {
private static final String DEFAULT_PATTERN = DatePattern.NORM_TIME_PATTERN;
private String pattern;
public TimeValueSerializer(String pattern) {
super(Time.class);
this.pattern = StringUtils.defaultIfBlank(pattern, DEFAULT_PATTERN);
}
@Override
public void serialize(Time value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
jsonGenerator.writeString(sdf.format(value));
}
}
}
package com.gitee.sqlrest.core.serdes.datetime;
import cn.hutool.core.date.DatePattern;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import org.apache.commons.lang3.StringUtils;
public class TimestampValueSerializer extends StdSerializer<Timestamp> {
private static final String DEFAULT_PATTERN = DatePattern.NORM_DATETIME_PATTERN;
private String pattern;
public TimestampValueSerializer(String pattern) {
super(Timestamp.class);
this.pattern = StringUtils.defaultIfBlank(pattern, DEFAULT_PATTERN);
}
@Override
public void serialize(Timestamp value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value != null) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
jsonGenerator.writeString(sdf.format(value));
}
}
}
package com.gitee.sqlrest.core.serdes.number;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.apache.commons.lang3.math.NumberUtils;
public class NumberValueSerializer extends StdSerializer<Number> {
private static final int DEFAULT_DECIMAL_SCALE = 6;
private int decimalScale;
public NumberValueSerializer(String numberScaleStr) {
super(Number.class);
this.decimalScale = NumberUtils.toInt(numberScaleStr, DEFAULT_DECIMAL_SCALE);
}
@Override
public void serialize(Number value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (value != null) {
if (value instanceof BigDecimal) {
BigDecimal decimal = ((BigDecimal) value).setScale(this.decimalScale);
jsonGenerator.writeNumber(decimal);
} else if (value instanceof BigInteger) {
jsonGenerator.writeNumber((BigInteger) value);
} else if (value instanceof Long) {
jsonGenerator.writeNumber(value.longValue());
} else if (value instanceof Double) {
jsonGenerator.writeNumber(value.doubleValue());
} else if (value instanceof Float) {
jsonGenerator.writeNumber(value.floatValue());
} else if (!(value instanceof Integer) && !(value instanceof Byte) && !(value instanceof Short)) {
jsonGenerator.writeNumber(value.toString());
} else {
jsonGenerator.writeNumber(value.intValue());
}
}
}
}
package com.gitee.sqlrest.core.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.gitee.sqlrest.common.dto.PageResult;
import com.gitee.sqlrest.common.dto.ParamValue;
import com.gitee.sqlrest.common.dto.ResultEntity;
......@@ -22,6 +23,7 @@ import com.gitee.sqlrest.core.exec.engine.ApiExecutorEngineFactory;
import com.gitee.sqlrest.core.exec.engine.impl.ScriptExecutorService;
import com.gitee.sqlrest.core.util.ApiPathUtils;
import com.gitee.sqlrest.core.util.DataSourceUtils;
import com.gitee.sqlrest.core.util.JacksonUtils;
import com.gitee.sqlrest.persistence.dao.ApiAssignmentDao;
import com.gitee.sqlrest.persistence.dao.DataSourceDao;
import com.gitee.sqlrest.persistence.entity.ApiAssignmentEntity;
......@@ -30,6 +32,7 @@ import com.gitee.sqlrest.persistence.entity.DataSourceEntity;
import com.gitee.sqlrest.persistence.util.PageUtils;
import com.gitee.sqlrest.template.Configuration;
import com.gitee.sqlrest.template.SqlTemplate;
import com.google.common.base.Charsets;
import com.zaxxer.hikari.HikariDataSource;
import java.io.File;
import java.lang.reflect.Method;
......@@ -48,6 +51,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
......@@ -108,7 +112,7 @@ public class ApiAssignmentService {
.collect(Collectors.toList());
}
public Object debugExecute(ApiDebugExecuteRequest request) {
public void debugExecute(ApiDebugExecuteRequest request, HttpServletResponse response) {
DataSourceEntity dataSourceEntity = dataSourceDao.getById(request.getDataSourceId());
if (null == dataSourceEntity) {
String message = "datasource[id=" + request.getDataSourceId() + " not exist!";
......@@ -139,16 +143,33 @@ public class ApiAssignmentService {
}
}
}
File driverPath = driverLoadService.getVersionDriverFile(dataSourceEntity.getType(), dataSourceEntity.getVersion());
HikariDataSource dataSource = DataSourceUtils.getHikariDataSource(dataSourceEntity, driverPath.getAbsolutePath());
Object result = ApiExecutorEngineFactory
.getExecutor(request.getEngine(), dataSource, dataSourceEntity.getType())
.execute(scripts, params);
if (result instanceof Collection) {
Collection r = (Collection) result;
return ResultEntity.success(scripts.size() == 1 ? r.stream().findFirst().get() : r);
ResultEntity entity;
try {
HikariDataSource dataSource = DataSourceUtils.getHikariDataSource(dataSourceEntity, driverPath.getAbsolutePath());
Object result = ApiExecutorEngineFactory
.getExecutor(request.getEngine(), dataSource, dataSourceEntity.getType())
.execute(scripts, params);
if (result instanceof Collection) {
Collection r = (Collection) result;
result = scripts.size() == 1 ? r.stream().findFirst().get() : r;
}
entity = ResultEntity.success(result);
} catch (Exception e) {
entity = ResultEntity.failed(ResponseErrorCode.ERROR_INTERNAL_ERROR, ExceptionUtil.getMessage(e));
}
String json = JacksonUtils.toJsonStr(entity, request.getFormatMap(), request.getNamingStrategy());
try {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(Charsets.UTF_8.name());
response.getWriter().append(json);
} catch (Exception e) {
throw new RuntimeException(e);
}
return ResultEntity.success(result);
}
public Long createAssignment(ApiAssignmentSaveRequest request) {
......
package com.gitee.sqlrest.core.servlet;
import cn.hutool.json.JSONUtil;
import com.gitee.sqlrest.common.consts.Constants;
import com.gitee.sqlrest.common.dto.ResultEntity;
import com.gitee.sqlrest.common.enums.HttpMethodEnum;
import com.gitee.sqlrest.common.enums.NamingStrategyEnum;
import com.gitee.sqlrest.common.exception.ResponseErrorCode;
import com.gitee.sqlrest.core.exec.ApiExecuteService;
import com.gitee.sqlrest.core.util.JacksonUtils;
import com.gitee.sqlrest.persistence.dao.ApiAssignmentDao;
import com.gitee.sqlrest.persistence.entity.ApiAssignmentEntity;
import com.google.common.base.Charsets;
import java.io.IOException;
import java.util.Collections;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
......@@ -32,19 +34,22 @@ public class ApiServletService {
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setCharacterEncoding(Charsets.UTF_8.name());
String path = request.getRequestURI().substring(Constants.API_PATH_PREFIX.length() + 2);
String json = null;
ApiAssignmentEntity apiConfigEntity = apiAssignmentDao.getByUk(method, path);
if (null == apiConfigEntity || !apiConfigEntity.getStatus()) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
String message = String.format("/%s/%s[%s]", Constants.API_PATH_PREFIX, path, method.name());
ResultEntity result = ResultEntity.failed(ResponseErrorCode.ERROR_PATH_NOT_EXISTS, message);
response.getWriter().append(JSONUtil.toJsonStr(result));
json = JacksonUtils.toJsonStr(result, Collections.emptyMap(), null);
} else {
ResultEntity result = apiExecuteService.execute(apiConfigEntity, request, response);
if (0 != result.getCode()) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
response.getWriter().append(JSONUtil.toJsonStr(result));
json = JacksonUtils.toJsonStr(result, Collections.emptyMap(), NamingStrategyEnum.UPPER_CAMEL_CASE);
}
response.getWriter().append(json);
}
}
package com.gitee.sqlrest.core.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.gitee.sqlrest.common.enums.DataTypeFormatEnum;
import com.gitee.sqlrest.common.enums.NamingStrategyEnum;
import com.gitee.sqlrest.core.serdes.DateTimeSerDesFactory;
import java.util.Collections;
import java.util.Map;
public final class JacksonUtils {
public static String toJsonStr(Object obj) {
return toJsonStr(obj, Collections.emptyMap(), null);
}
public static String toJsonStr(Object obj, Map<DataTypeFormatEnum, String> formatMap, NamingStrategyEnum namingStrategy) {
// https://www.jianshu.com/p/1368547350c6
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(createSerializeModule(formatMap));
if (null != namingStrategy) {
PropertyNamingStrategy strategy = createPropertyNamingStrategy(namingStrategy);
if (null != strategy) {
objectMapper.setPropertyNamingStrategy(strategy);
}
}
try {
return objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
private static PropertyNamingStrategy createPropertyNamingStrategy(NamingStrategyEnum namingStrategy) {
if (namingStrategy == NamingStrategyEnum.LOWER_CAMEL_CASE) {
return PropertyNamingStrategies.LOWER_CAMEL_CASE;
} else if (namingStrategy == NamingStrategyEnum.UPPER_CAMEL_CASE) {
return PropertyNamingStrategies.UPPER_CAMEL_CASE;
} else if (namingStrategy == NamingStrategyEnum.SNAKE_CASE) {
return PropertyNamingStrategies.SNAKE_CASE;
} else if (namingStrategy == NamingStrategyEnum.LOWER_CASE) {
return PropertyNamingStrategies.LOWER_CASE;
} else {
return null;
}
}
private static Module createSerializeModule(Map<DataTypeFormatEnum, String> formatMap) {
Map<DataTypeFormatEnum, String> finalFormatMap = (null == formatMap) ? Collections.emptyMap() : formatMap;
SimpleModule module = new SimpleModule();
DateTimeSerDesFactory.getAllSerDesMap()
.forEach(
(clazz, creator) -> {
StdSerializer serializer = creator.apply(finalFormatMap.get(clazz));
module.addSerializer(serializer.handledType(), serializer);
}
);
return module;
}
}
......@@ -39,7 +39,6 @@ public class SentinelFlowControlManager implements FlowControlManger {
public void loadFlowRules() {
try {
doLoadFlowRules();
log.info("Success load flow rules");
} catch (Exception e) {
log.error("load flow rules failed:{}", e.getMessage(), e);
}
......@@ -64,7 +63,10 @@ public class SentinelFlowControlManager implements FlowControlManger {
rule.setId(assignmentEntity.getId());
rules.add(rule);
}
FlowRuleManager.loadRules(rules);
if (rules.size() > 0) {
FlowRuleManager.loadRules(rules);
log.info("Success refresh flow rules count: {}", rules.size());
}
}
@Override
......
......@@ -46,8 +46,8 @@ public class ApiAssignmentController {
@ApiOperation(value = "调试API配置")
@PostMapping(value = "/debug", produces = MediaType.APPLICATION_JSON_VALUE)
public ResultEntity debug(@RequestBody ApiDebugExecuteRequest request) {
return ResultEntity.success(apiAssignmentService.debugExecute(request));
public void debug(@RequestBody ApiDebugExecuteRequest request, HttpServletResponse response) {
apiAssignmentService.debugExecute(request, response);
}
@ApiOperation(value = "添加API配置")
......
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