Browse Source

open

master
pioneer 1 year ago
commit
ee0857614e
  1. 6
      README.md
  2. BIN
      lib/commons-codec-1.11.jar
  3. BIN
      lib/commons-logging-1.2.jar
  4. BIN
      lib/httpclient-4.5.5.jar
  5. BIN
      lib/httpcore-4.4.9.jar
  6. BIN
      lib/java-sdk-core-3.0.10.jar
  7. BIN
      lib/joda-time-2.9.9.jar
  8. BIN
      lib/okhttp-3.11.0.jar
  9. BIN
      lib/okio-1.15.0.jar
  10. 37
      plugin.xml
  11. 10
      src/main/java/com/fr/plugin/xx/zheneng/proxy/MyLocaleFinder.java
  12. 38
      src/main/java/com/fr/plugin/xx/zheneng/proxy/config/ApiProxyConfig.java
  13. 19
      src/main/java/com/fr/plugin/xx/zheneng/proxy/http/HttpHandlerProvider.java
  14. 45
      src/main/java/com/fr/plugin/xx/zheneng/proxy/http/HuaweiWebProvider.java
  15. 15
      src/main/java/com/fr/plugin/xx/zheneng/proxy/http/URLAliasBridge.java
  16. 45
      src/main/java/com/fr/plugin/xx/zheneng/proxy/http/xxWebProvider.java
  17. 98
      src/main/java/com/fr/plugin/xx/zheneng/proxy/huawei/HuaweiAppRequest.java
  18. 5
      src/main/java/com/fr/plugin/xx/zheneng/proxy/util/Constants.java
  19. 98
      src/main/java/com/fr/plugin/xx/zheneng/proxy/xx/HuaweiAppRequest.java
  20. 98
      src/main/java/com/fr/plugin/xx/zheneng/proxy/xx/xxAppRequest.java
  21. 1
      src/main/resources/com/fr/plugin/demo.properties
  22. 1
      src/main/resources/com/fr/plugin/demo_zh_CN.properties

6
README.md

@ -0,0 +1,6 @@
# open-JSD-10242
JSD-10242 平台开放接口给第三方调用\
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\
仅作为开发者学习参考使用!禁止用于任何商业用途!\
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。

BIN
lib/commons-codec-1.11.jar

Binary file not shown.

BIN
lib/commons-logging-1.2.jar

Binary file not shown.

BIN
lib/httpclient-4.5.5.jar

Binary file not shown.

BIN
lib/httpcore-4.4.9.jar

Binary file not shown.

BIN
lib/java-sdk-core-3.0.10.jar

Binary file not shown.

BIN
lib/joda-time-2.9.9.jar

Binary file not shown.

BIN
lib/okhttp-3.11.0.jar

Binary file not shown.

BIN
lib/okio-1.15.0.jar

Binary file not shown.

37
plugin.xml

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<plugin>
<id>com.fr.plugin.xx.zheneng.proxy</id>
<name><![CDATA[API代理插件]]></name>
<active>yes</active>
<version>1.0.0</version>
<env-version>10.0~11.0</env-version>
<jartime>2021-01-01</jartime>
<vendor>fr.open</vendor>
<description><![CDATA[API代理插件]]></description>
<change-notes><![CDATA[
[2022-05-17]初始化插件<br/>
]]></change-notes>
<prefer-packages>
<!-- 防止客户自行引入jar造成访问class错误-->
<prefer-package>org.apache.commons.codec</prefer-package>
<prefer-package>org.apache.commons.logging</prefer-package>
<prefer-package>org.apache.http</prefer-package>
<prefer-package>com.cloud</prefer-package>
<prefer-package>org.joda.time</prefer-package>
<prefer-package>okhttp3</prefer-package>
<prefer-package>okio</prefer-package>
</prefer-packages>
<extra-core>
<!-- <LocaleFinder class="com.fr.plugin.xx.zheneng.proxy.MyLocaleFinder"/>-->
</extra-core>
<extra-decision>
<HttpHandlerProvider class="com.fr.plugin.xx.zheneng.proxy.http.HttpHandlerProvider"/>
<URLAliasProvider class="com.fr.plugin.xx.zheneng.proxy.http.URLAliasBridge"/>
</extra-decision>
<function-recorder class="com.fr.plugin.xx.zheneng.proxy.http.HuaweiWebProvider"/>
</plugin>

10
src/main/java/com/fr/plugin/xx/zheneng/proxy/MyLocaleFinder.java

@ -0,0 +1,10 @@
package com.fr.plugin.xx.zheneng.proxy;
import com.fr.stable.fun.impl.AbstractLocaleFinder;
public class MyLocaleFinder extends AbstractLocaleFinder {
@Override
public String find() {
return "com/fr/plugin/demo";
}
}

38
src/main/java/com/fr/plugin/xx/zheneng/proxy/config/ApiProxyConfig.java

@ -0,0 +1,38 @@
package com.fr.plugin.xx.zheneng.proxy.config;
import com.fr.config.*;
import com.fr.config.holder.Conf;
import com.fr.config.holder.factory.Holders;
@Visualization(category = "API请求代理配置-华为", priority = 1)
public class ApiProxyConfig extends DefaultConfiguration {
private static volatile ApiProxyConfig config = null;
public static ApiProxyConfig getInstance() {
synchronized (ApiProxyConfig.class) {
if (config == null) {
config = ConfigContext.getTenantConfig(ApiProxyConfig.class);
}
}
return config;
}
@Identifier(value = "appKey", name = "AppKey", description = "华为AppKey", status = Status.SHOW)
private Conf<String> appKey = Holders.simple("");
@Identifier(value = "appSecret", name = "AppSecret", description = "华为AppSecret", status = Status.SHOW, encrypted = true)
private Conf<String> appSecret = Holders.simple("");
public String getAppKey() {
return appKey.get();
}
public String getAppSecret() {
return appSecret.get();
}
@Override
public String getNameSpace() {
return this.getClass().getName();
}
}

19
src/main/java/com/fr/plugin/xx/zheneng/proxy/http/HttpHandlerProvider.java

@ -0,0 +1,19 @@
package com.fr.plugin.xx.zheneng.proxy.http;
import com.fr.decision.fun.HttpHandler;
import com.fr.decision.fun.impl.AbstractHttpHandlerProvider;
import com.fr.plugin.xx.zheneng.proxy.config.ApiProxyConfig;
import com.fr.plugin.xx.zheneng.proxy.util.Constants;
import com.fr.stable.fun.Authorize;
@Authorize(callSignKey = Constants.PLUGIN_ID)
public class HttpHandlerProvider extends AbstractHttpHandlerProvider {
@Override
public HttpHandler[] registerHandlers() {
ApiProxyConfig.getInstance();
return new HttpHandler[]{
new xxWebProvider(),
};
}
}

45
src/main/java/com/fr/plugin/xx/zheneng/proxy/http/HuaweiWebProvider.java

@ -0,0 +1,45 @@
package com.fr.plugin.xx.zheneng.proxy.http;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.Original;
import com.fr.plugin.xx.zheneng.proxy.xx.xxAppRequest;
import com.fr.plugin.xx.zheneng.proxy.util.Constants;
import com.fr.record.analyzer.EnableMetrics;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@EnableMetrics
public class xxWebProvider extends BaseHttpHandler {
@Override
public RequestMethod getMethod() {
return RequestMethod.POST;
}
@Override
public String getPath() {
return "/proxy/xx";
}
@Override
public boolean isPublic() {
return true;
}
@Focus(id = Constants.PLUGIN_ID, text = "API代理插件 ", source = Original.PLUGIN)
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
String proxyRequestType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyRequestType");
if ("IAM".equals(proxyRequestType)) {
} else if ("NOTYPE".equals(proxyRequestType)) {
} else {
xxAppRequest.action(httpServletRequest, httpServletResponse);
}
}
}

15
src/main/java/com/fr/plugin/xx/zheneng/proxy/http/URLAliasBridge.java

@ -0,0 +1,15 @@
package com.fr.plugin.xx.zheneng.proxy.http;
import com.fr.decision.fun.impl.AbstractURLAliasProvider;
import com.fr.decision.webservice.url.alias.URLAlias;
import com.fr.decision.webservice.url.alias.URLAliasFactory;
public class URLAliasBridge extends AbstractURLAliasProvider {
@Override
public URLAlias[] registerAlias() {
return new URLAlias[]{
URLAliasFactory.createPluginAlias("/proxy/xx", "/proxy/xx", true),
// URLAliasFactory.createPluginAlias("/multicpt/ppt/export", "/multicpt/ppt/export", true),
};
}
}

45
src/main/java/com/fr/plugin/xx/zheneng/proxy/http/xxWebProvider.java

@ -0,0 +1,45 @@
package com.fr.plugin.xx.zheneng.proxy.http;
import com.fr.decision.fun.impl.BaseHttpHandler;
import com.fr.intelli.record.Focus;
import com.fr.intelli.record.Original;
import com.fr.plugin.xx.zheneng.proxy.xx.xxAppRequest;
import com.fr.plugin.xx.zheneng.proxy.util.Constants;
import com.fr.record.analyzer.EnableMetrics;
import com.fr.third.springframework.web.bind.annotation.RequestMethod;
import com.fr.web.utils.WebUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@EnableMetrics
public class xxWebProvider extends BaseHttpHandler {
@Override
public RequestMethod getMethod() {
return RequestMethod.POST;
}
@Override
public String getPath() {
return "/proxy/xx";
}
@Override
public boolean isPublic() {
return true;
}
@Focus(id = Constants.PLUGIN_ID, text = "API代理插件 ", source = Original.PLUGIN)
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
String proxyRequestType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyRequestType");
if ("IAM".equals(proxyRequestType)) {
} else if ("NOTYPE".equals(proxyRequestType)) {
} else {
xxAppRequest.action(httpServletRequest, httpServletResponse);
}
}
}

98
src/main/java/com/fr/plugin/xx/zheneng/proxy/huawei/HuaweiAppRequest.java

@ -0,0 +1,98 @@
package com.fr.plugin.xx.zheneng.proxy.huawei;
import com.cloud.apigateway.sdk.utils.Client;
import com.cloud.apigateway.sdk.utils.Request;
import com.fr.decision.webservice.Response;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.xx.zheneng.proxy.config.ApiProxyConfig;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.web.utils.WebUtils;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.UUID;
public class HuaweiAppRequest {
private static final ObjectMapper objectMapper = new ObjectMapper();
public static void action(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
String url = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyUrl");
String requestType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyRequestType");
// String contentType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyContentType");
if (StringUtils.isBlank(url) && StringUtils.isBlank(requestType)) {
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求中 URL 和请求类型不应为空")));
return;
}
if (url.contains("public/com.fr.plugin.xx.zheneng.proxy/proxy/huawei") || url.contains("url/proxy/huawei")) {
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求中 URL 不能代理为自己")));
return;
}
Request request = new Request();
try {
//key和secret, 为访问API所属的APP的key和secret
request.setKey(ApiProxyConfig.getInstance().getAppKey());
request.setSecret(ApiProxyConfig.getInstance().getAppSecret());
//接口访问类型
request.setMethod(requestType);
//接口访问url
request.setUrl(url);
//API中 header头传输的参数
request.addHeader("x-api-id", UUID.randomUUID().toString().replace("-", ""));
request.addHeader("Content-Type", "application/json");
//API中 Query传输的参数
// request.addQueryStringParam("name", "value");
Enumeration<String> enumeration = httpServletRequest.getHeaderNames();
while (enumeration.hasMoreElements()) {
String headerName = enumeration.nextElement();
String headerValue = httpServletRequest.getHeader(headerName);
request.addHeader(headerName, headerValue);
}
//API中 Body体参数
if ("POST".equals(requestType)) {
String bodyData = IOUtils.inputStream2String(httpServletRequest.getInputStream());
System.out.println(bodyData);
request.setBody(bodyData);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求参数错误 " + e.getMessage())));
return;
}
try {
//Sign the request.
okhttp3.Request signedRequest = Client.signOkhttp(request);
String authorization = signedRequest.header("Authorization");
signedRequest = signedRequest.newBuilder().addHeader("x-Authorization", authorization).build();
//Send the request.
long startDate = System.currentTimeMillis();
FineLoggerFactory.getLogger().info("Api request start with {}", url);
OkHttpClient client = new OkHttpClient.Builder().build();
okhttp3.Response response = client.newCall(signedRequest).execute();
//Print the status line of the response.
FineLoggerFactory.getLogger().info("Api request end with {} use {}", url, (System.currentTimeMillis() - startDate), String.valueOf(response.code()));
//Print the header fields of the response.
Headers resHeaders = response.headers();
for (String h : resHeaders.names()) {
httpServletResponse.addHeader(h, resHeaders.get(h));
}
//Print the body of the response.
ResponseBody resEntity = response.body();
if (resEntity != null) {
String data = resEntity.string();
FineLoggerFactory.getLogger().debug("Api request end with {} and data is", url, resEntity);
WebUtils.printAsString(httpServletResponse, data);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("500", request.getUrl() + " 请求错误 " + e.getMessage())));
}
}
}

5
src/main/java/com/fr/plugin/xx/zheneng/proxy/util/Constants.java

@ -0,0 +1,5 @@
package com.fr.plugin.xx.zheneng.proxy.util;
public interface Constants {
String PLUGIN_ID = "com.fr.plugin.xx.zheneng.proxy";
}

98
src/main/java/com/fr/plugin/xx/zheneng/proxy/xx/HuaweiAppRequest.java

@ -0,0 +1,98 @@
package com.fr.plugin.xx.zheneng.proxy.xx;
import com.cloud.apigateway.sdk.utils.Client;
import com.cloud.apigateway.sdk.utils.Request;
import com.fr.decision.webservice.Response;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.xx.zheneng.proxy.config.ApiProxyConfig;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.web.utils.WebUtils;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.UUID;
public class xxAppRequest {
private static final ObjectMapper objectMapper = new ObjectMapper();
public static void action(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
String url = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyUrl");
String requestType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyRequestType");
// String contentType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyContentType");
if (StringUtils.isBlank(url) && StringUtils.isBlank(requestType)) {
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求中 URL 和请求类型不应为空")));
return;
}
if (url.contains("public/com.fr.plugin.xx.zheneng.proxy/proxy/xx") || url.contains("url/proxy/xx")) {
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求中 URL 不能代理为自己")));
return;
}
Request request = new Request();
try {
//key和secret, 为访问API所属的APP的key和secret
request.setKey(ApiProxyConfig.getInstance().getAppKey());
request.setSecret(ApiProxyConfig.getInstance().getAppSecret());
//接口访问类型
request.setMethod(requestType);
//接口访问url
request.setUrl(url);
//API中 header头传输的参数
request.addHeader("x-api-id", UUID.randomUUID().toString().replace("-", ""));
request.addHeader("Content-Type", "application/json");
//API中 Query传输的参数
// request.addQueryStringParam("name", "value");
Enumeration<String> enumeration = httpServletRequest.getHeaderNames();
while (enumeration.hasMoreElements()) {
String headerName = enumeration.nextElement();
String headerValue = httpServletRequest.getHeader(headerName);
request.addHeader(headerName, headerValue);
}
//API中 Body体参数
if ("POST".equals(requestType)) {
String bodyData = IOUtils.inputStream2String(httpServletRequest.getInputStream());
System.out.println(bodyData);
request.setBody(bodyData);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求参数错误 " + e.getMessage())));
return;
}
try {
//Sign the request.
okhttp3.Request signedRequest = Client.signOkhttp(request);
String authorization = signedRequest.header("Authorization");
signedRequest = signedRequest.newBuilder().addHeader("x-Authorization", authorization).build();
//Send the request.
long startDate = System.currentTimeMillis();
FineLoggerFactory.getLogger().info("Api request start with {}", url);
OkHttpClient client = new OkHttpClient.Builder().build();
okhttp3.Response response = client.newCall(signedRequest).execute();
//Print the status line of the response.
FineLoggerFactory.getLogger().info("Api request end with {} use {}", url, (System.currentTimeMillis() - startDate), String.valueOf(response.code()));
//Print the header fields of the response.
Headers resHeaders = response.headers();
for (String h : resHeaders.names()) {
httpServletResponse.addHeader(h, resHeaders.get(h));
}
//Print the body of the response.
ResponseBody resEntity = response.body();
if (resEntity != null) {
String data = resEntity.string();
FineLoggerFactory.getLogger().debug("Api request end with {} and data is", url, resEntity);
WebUtils.printAsString(httpServletResponse, data);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("500", request.getUrl() + " 请求错误 " + e.getMessage())));
}
}
}

98
src/main/java/com/fr/plugin/xx/zheneng/proxy/xx/xxAppRequest.java

@ -0,0 +1,98 @@
package com.fr.plugin.zk.zheneng.proxy.xx;
import com.cloud.apigateway.sdk.utils.Client;
import com.cloud.apigateway.sdk.utils.Request;
import com.fr.decision.webservice.Response;
import com.fr.general.IOUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.zk.zheneng.proxy.config.ApiProxyConfig;
import com.fr.stable.StringUtils;
import com.fr.third.fasterxml.jackson.databind.ObjectMapper;
import com.fr.web.utils.WebUtils;
import okhttp3.Headers;
import okhttp3.OkHttpClient;
import okhttp3.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.UUID;
public class xxAppRequest {
private static final ObjectMapper objectMapper = new ObjectMapper();
public static void action(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
String url = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyUrl");
String requestType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyRequestType");
// String contentType = WebUtils.getHTTPRequestParameter(httpServletRequest, "proxyContentType");
if (StringUtils.isBlank(url) && StringUtils.isBlank(requestType)) {
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求中 URL 和请求类型不应为空")));
return;
}
if (url.contains("public/com.fr.plugin.zk.zheneng.proxy/proxy/xx") || url.contains("url/proxy/xx")) {
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求中 URL 不能代理为自己")));
return;
}
Request request = new Request();
try {
//key和secret, 为访问API所属的APP的key和secret
request.setKey(ApiProxyConfig.getInstance().getAppKey());
request.setSecret(ApiProxyConfig.getInstance().getAppSecret());
//接口访问类型
request.setMethod(requestType);
//接口访问url
request.setUrl(url);
//API中 header头传输的参数
request.addHeader("x-api-id", UUID.randomUUID().toString().replace("-", ""));
request.addHeader("Content-Type", "application/json");
//API中 Query传输的参数
// request.addQueryStringParam("name", "value");
Enumeration<String> enumeration = httpServletRequest.getHeaderNames();
while (enumeration.hasMoreElements()) {
String headerName = enumeration.nextElement();
String headerValue = httpServletRequest.getHeader(headerName);
request.addHeader(headerName, headerValue);
}
//API中 Body体参数
if ("POST".equals(requestType)) {
String bodyData = IOUtils.inputStream2String(httpServletRequest.getInputStream());
System.out.println(bodyData);
request.setBody(bodyData);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("400", "请求参数错误 " + e.getMessage())));
return;
}
try {
//Sign the request.
okhttp3.Request signedRequest = Client.signOkhttp(request);
String authorization = signedRequest.header("Authorization");
signedRequest = signedRequest.newBuilder().addHeader("x-Authorization", authorization).build();
//Send the request.
long startDate = System.currentTimeMillis();
FineLoggerFactory.getLogger().info("Api request start with {}", url);
OkHttpClient client = new OkHttpClient.Builder().build();
okhttp3.Response response = client.newCall(signedRequest).execute();
//Print the status line of the response.
FineLoggerFactory.getLogger().info("Api request end with {} use {}", url, (System.currentTimeMillis() - startDate), String.valueOf(response.code()));
//Print the header fields of the response.
Headers resHeaders = response.headers();
for (String h : resHeaders.names()) {
httpServletResponse.addHeader(h, resHeaders.get(h));
}
//Print the body of the response.
ResponseBody resEntity = response.body();
if (resEntity != null) {
String data = resEntity.string();
FineLoggerFactory.getLogger().debug("Api request end with {} and data is", url, resEntity);
WebUtils.printAsString(httpServletResponse, data);
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
WebUtils.printAsString(httpServletResponse, objectMapper.writeValueAsString(Response.error("500", request.getUrl() + " 请求错误 " + e.getMessage())));
}
}
}

1
src/main/resources/com/fr/plugin/demo.properties

@ -0,0 +1 @@
Plugin-Test_Function_Abs=Test ABS

1
src/main/resources/com/fr/plugin/demo_zh_CN.properties

@ -0,0 +1 @@
Plugin-Test_Function_Abs=测试ABS函数
Loading…
Cancel
Save