This commit is contained in:
六如
2024-10-27 21:31:34 +08:00
parent 40835d2f69
commit a690c4a72d
16 changed files with 256 additions and 13 deletions

View File

@@ -86,4 +86,9 @@ public class ApiConfig {
* 时区,默认:Asia/Shanghai
*/
private String zoneId = "Asia/Shanghai";
/**
* 返回结果字段小写形式
*/
private Boolean fieldLowercase = false;
}

View File

@@ -6,6 +6,7 @@ import com.gitee.sop.gateway.service.ParamExecutorImpl;
import com.gitee.sop.gateway.service.RouteService;
import com.gitee.sop.gateway.service.RouteServiceImpl;
import com.gitee.sop.gateway.service.interceptor.internal.ResultRouteInterceptor;
import com.gitee.sop.gateway.service.interceptor.internal.ResultWrapperInterceptor;
import com.gitee.sop.gateway.service.manager.ApiManager;
import com.gitee.sop.gateway.service.manager.IsvApiPermissionManager;
import com.gitee.sop.gateway.service.manager.IsvManager;

View File

@@ -1,15 +1,15 @@
package com.gitee.sop.gateway.controller;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.gateway.response.Response;
import com.gitee.sop.gateway.service.ParamExecutor;
import com.gitee.sop.gateway.service.RouteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@@ -56,7 +56,7 @@ public class IndexController {
@RequestMapping(value = "${gateway.path:/api}", method = {RequestMethod.GET, RequestMethod.POST})
public void index(HttpServletRequest request, HttpServletResponse response) throws IOException {
ApiRequestContext apiRequestContext = paramExecutor.build(request);
ApiResponse apiResponse = routeService.route(apiRequestContext);
Response apiResponse = routeService.route(apiRequestContext);
paramExecutor.write(apiRequestContext, apiResponse, response);
}

View File

@@ -55,7 +55,7 @@ import java.util.Locale;
* @author 六如
*/
@Data
public class ApiResponse {
public class ApiResponse implements Response {
public static final String SUCCESS_CODE = "0";
public static final String SUCCESS_MSG = "success";

View File

@@ -0,0 +1,128 @@
package com.gitee.sop.gateway.response;
import com.gitee.sop.gateway.exception.ApiException;
import com.gitee.sop.gateway.message.ErrorEnum;
import com.gitee.sop.gateway.message.ErrorMeta;
import com.gitee.sop.gateway.message.IError;
import lombok.Data;
import java.util.Locale;
/**
* 默认的结果封装类.
* <pre>
*
* xml返回结果:
* <response>
* <code>50</code>
* <msg>Remote service error</msg>
* <sub_code>isv.invalid-parameter</sub_code>
* <sub_msg>非法参数</sub_msg>
* </response>
* 成功情况:
* <response>
* <code>0</code>
* <msg>成功消息</msg>
* <data>
* ...返回内容
* </data>
* </response>
*
* json返回格式
* {
* "code":"50",
* "msg":"Remote service error",
* "sub_code":"isv.invalid-parameter",
* "sub_msg":"非法参数"
* }
* 成功情况:
* {
* "code":"0",
* "msg":"成功消息内容。。。",
* "data":{
* ...返回内容
* }
* }
* </pre>
* <p>
* 字段说明:
* code:网关异常码 <br>
* msg:网关异常信息 <br>
* sub_code:业务异常码 <br>
* sub_msg:业务异常信息 <br>
*
* @author 六如
*/
@Data
public class ApiResponseLower implements Response {
public static final String SUCCESS_CODE = "0";
public static final String SUCCESS_MSG = "success";
/**
* 网关异常码范围0~100 成功返回"0"
*/
private String code = SUCCESS_CODE;
/**
* 网关异常信息
*/
private String msg = "";
/**
* 业务异常码
*/
private String sub_code = "";
/**
* 业务异常信息
*/
private String sub_msg = "";
/**
* 返回对象
*/
private Object data;
public static ApiResponseLower success(Object data) {
ApiResponseLower apiResponse = new ApiResponseLower();
apiResponse.setCode(SUCCESS_CODE);
apiResponse.setMsg(SUCCESS_MSG);
apiResponse.setData(data);
return apiResponse;
}
public static ApiResponseLower error(ApiException e) {
ApiResponseLower apiResponse = new ApiResponseLower();
IError error = e.getError();
apiResponse.setCode(error.getCode());
apiResponse.setMsg(error.getMsg());
apiResponse.setSub_code(error.getSubCode());
apiResponse.setSub_msg(error.getSubMsg());
return apiResponse;
}
public static ApiResponseLower error(ErrorEnum errorEnum, Locale locale, String subMsg) {
ApiResponseLower apiResponse = new ApiResponseLower();
ErrorMeta errorMeta = errorEnum.getErrorMeta();
IError error = errorMeta.getError(locale);
apiResponse.setCode(error.getCode());
apiResponse.setMsg(error.getMsg());
apiResponse.setSub_code(error.getSubCode());
apiResponse.setSub_msg(subMsg);
return apiResponse;
}
public static ApiResponseLower error(ErrorEnum errorEnum, Locale locale) {
ApiResponseLower apiResponse = new ApiResponseLower();
ErrorMeta errorMeta = errorEnum.getErrorMeta();
IError error = errorMeta.getError(locale);
apiResponse.setCode(error.getCode());
apiResponse.setMsg(error.getMsg());
apiResponse.setSub_code(error.getSubCode());
apiResponse.setSub_msg(error.getSubMsg());
return apiResponse;
}
}

View File

@@ -0,0 +1,12 @@
package com.gitee.sop.gateway.response;
/**
* @author 六如
*/
public interface Response {
String getCode();
Object getData();
}

View File

@@ -2,6 +2,7 @@ package com.gitee.sop.gateway.service;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.gateway.response.Response;
import java.io.IOException;
@@ -30,6 +31,6 @@ public interface ParamExecutor<Req, Resp> {
* @param response response
* @throws IOException IOException
*/
void write(ApiRequestContext apiRequestContext, ApiResponse apiResponse, Resp response) throws IOException;
void write(ApiRequestContext apiRequestContext, Response apiResponse, Resp response) throws IOException;
}

View File

@@ -8,6 +8,7 @@ import com.gitee.sop.gateway.request.ApiRequest;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.request.UploadContext;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.gateway.response.Response;
import com.gitee.sop.gateway.util.RequestUtil;
import com.gitee.sop.gateway.util.ResponseUtil;
import com.gitee.sop.support.dto.FileData;
@@ -104,7 +105,7 @@ public class ParamExecutorImpl implements ParamExecutor<HttpServletRequest, Http
@Override
public void write(ApiRequestContext apiRequestContext, ApiResponse apiResponse, HttpServletResponse response) throws IOException {
public void write(ApiRequestContext apiRequestContext, Response apiResponse, HttpServletResponse response) throws IOException {
Object data = apiResponse.getData();
if (data instanceof FileData) {
FileData fileData = (FileData) data;

View File

@@ -0,0 +1,16 @@
package com.gitee.sop.gateway.service;
import com.gitee.sop.gateway.common.ApiInfoDTO;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.response.Response;
/**
* 结果包裹
*
* @author 六如
*/
public interface ResultWrapper {
Response wrap(ApiRequestContext context, ApiInfoDTO apiInfoDTO, Object result);
}

View File

@@ -0,0 +1,32 @@
package com.gitee.sop.gateway.service;
import com.gitee.sop.gateway.common.ApiInfoDTO;
import com.gitee.sop.gateway.config.ApiConfig;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.gateway.response.ApiResponseLower;
import com.gitee.sop.gateway.response.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
/**
* @author 六如
*/
@Service
public class ResultWrapperImpl implements ResultWrapper {
@Autowired
private ApiConfig apiConfig;
@Override
public Response wrap(ApiRequestContext context, ApiInfoDTO apiInfoDTO, Object result) {
if (Objects.equals(apiConfig.getFieldLowercase(), true)) {
return ApiResponseLower.success(result);
} else {
return ApiResponse.success(result);
}
}
}

View File

@@ -1,7 +1,7 @@
package com.gitee.sop.gateway.service;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.gateway.response.Response;
/**
* 接口路由
@@ -16,6 +16,6 @@ public interface RouteService {
* @param apiRequestContext 接口上下文
* @return 返回结果
*/
ApiResponse route(ApiRequestContext apiRequestContext);
Response route(ApiRequestContext apiRequestContext);
}

View File

@@ -11,7 +11,7 @@ import com.gitee.sop.gateway.message.ErrorEnum;
import com.gitee.sop.gateway.request.ApiRequest;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.request.UploadContext;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.gateway.response.Response;
import com.gitee.sop.gateway.service.interceptor.RouteInterceptor;
import com.gitee.sop.gateway.service.validate.Validator;
import com.gitee.sop.gateway.util.ClassUtil;
@@ -55,8 +55,11 @@ public class RouteServiceImpl implements RouteService {
@Autowired(required = false)
private List<RouteInterceptor> routeInterceptors;
@Autowired
private ResultWrapper resultWrapper;
@Override
public ApiResponse route(ApiRequestContext apiRequestContext) {
public Response route(ApiRequestContext apiRequestContext) {
ApiRequest apiRequest = apiRequestContext.getApiRequest();
log.info("收到客户端请求, ip={}, apiRequest={}", apiRequestContext.getIp(), apiRequest);
try {
@@ -66,7 +69,7 @@ public class RouteServiceImpl implements RouteService {
// 微服务结果
Object result = doRoute(apiRequestContext, apiInfoDTO);
result = this.doAfterRoute(apiRequestContext, apiInfoDTO, result);
return ApiResponse.success(result);
return resultWrapper.wrap(apiRequestContext, apiInfoDTO, result);
} catch (Exception e) {
log.error("接口请求报错, , ip={}, apiRequest={}", apiRequestContext.getIp(), apiRequest, e);
return exceptionExecutor.executeException(apiRequestContext, e);

View File

@@ -6,5 +6,6 @@ package com.gitee.sop.gateway.service.interceptor;
public class RouteInterceptorOrders {
public static final int RESULT_INTERCEPTOR = -1000;
public static final int RESULT_WRAPPER_INTERCEPTOR = RESULT_INTERCEPTOR + 1;
}

View File

@@ -0,0 +1,42 @@
package com.gitee.sop.gateway.service.interceptor.internal;
import com.gitee.sop.gateway.common.ApiInfoDTO;
import com.gitee.sop.gateway.config.ApiConfig;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.gateway.response.ApiResponseLower;
import com.gitee.sop.gateway.service.interceptor.RouteInterceptor;
import com.gitee.sop.gateway.service.interceptor.RouteInterceptorOrders;
import com.gitee.sop.support.dto.CommonFileData;
import com.gitee.sop.support.dto.FileData;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* 对结果进行包裹
*
* @author 六如
*/
public class ResultWrapperInterceptor implements RouteInterceptor {
@Autowired
private ApiConfig apiConfig;
@Override
public Object afterRoute(ApiRequestContext context, ApiInfoDTO apiInfoDTO, Object result) {
if (Objects.equals(apiConfig.getFieldLowercase(), true)) {
return ApiResponseLower.success(result);
} else {
return ApiResponse.success(result);
}
}
@Override
public int getOrder() {
return RouteInterceptorOrders.RESULT_WRAPPER_INTERCEPTOR;
}
}

View File

@@ -5,7 +5,6 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.gitee.sop.gateway.request.ApiRequest;
import com.gitee.sop.gateway.request.ApiRequestContext;
import com.gitee.sop.gateway.request.RequestFormatEnum;
import com.gitee.sop.gateway.response.ApiResponse;
import com.gitee.sop.support.dto.FileData;
import org.apache.commons.io.IOUtils;
import org.springframework.http.MediaType;
@@ -31,7 +30,7 @@ public class ResponseUtil {
IOUtils.copy(inputStream, response.getOutputStream());
}
public static void writerText(ApiRequestContext apiRequestContext, ApiResponse apiResponse, HttpServletResponse response) throws IOException {
public static void writerText(ApiRequestContext apiRequestContext, Object apiResponse, HttpServletResponse response) throws IOException {
ApiRequest apiRequest = apiRequestContext.getApiRequest();
String charset = apiRequest.getCharset();
response.setCharacterEncoding(charset);

View File

@@ -36,6 +36,8 @@ api.timeout-seconds=300
api.timestamp-pattern=yyyy-MM-dd HH:mm:ss
# default zone
api.zone-id=Asia/Shanghai
# if true, response field name all lowercase, such as : sub_code, sub_msg
api.field-lowercase=false
####### dubbo config #######
dubbo.protocol.name=dubbo