parent
275599c5fb
commit
cf42b08ad0
@ -1,432 +0,0 @@
|
||||
package ${domain};
|
||||
package com.example.module;
|
||||
|
||||
import okhttp3.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ConnectException;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class ApiClient {
|
||||
private static ApiClient ourInstance = null;
|
||||
|
||||
public static void init(String serverUrl, String appKey, String appSecret) {
|
||||
init(serverUrl, appKey, appSecret, DEFAULT_CONNECT_TIMEOUT, DEFAULT_READ_TIMEOUT);
|
||||
}
|
||||
|
||||
public static void init(String serverUrl, String appKey, String appSecret, int connectTimeout, int readTimeout) {
|
||||
ourInstance = new ApiClient(serverUrl, appKey, appSecret, connectTimeout, readTimeout);
|
||||
}
|
||||
|
||||
public static ApiClient getInstance() {
|
||||
if (ourInstance == null) {
|
||||
System.err.print("ApiClient need init");
|
||||
}
|
||||
return ourInstance;
|
||||
}
|
||||
|
||||
//基本请求参数KEY
|
||||
private static final String P_APP_KEY = "app_key";
|
||||
private static final String P_TYPE = "type";
|
||||
private static final String P_TARGET = "target";
|
||||
private static final String P_FILE_NAME = "file_name";
|
||||
private static final String P_TIMESTAMP = "timestamp";
|
||||
private static final String P_METHOD = "method";
|
||||
private static final String P_SIGN = "sign";
|
||||
private static final String P_TOKEN = "token_id";
|
||||
private static final String P_ENHANCED = "enhanced";
|
||||
//参数类型
|
||||
private static final String TYPE_JSON = "json";
|
||||
private static final String TYPE_FILE = "file";
|
||||
//应用码
|
||||
private String appKey;
|
||||
//应用安全码
|
||||
private String appSecret;
|
||||
//服务器地址
|
||||
private String serverUrl;
|
||||
//公钥
|
||||
private PublicKey publicKey = null;
|
||||
private OkHttpClient httpClient = null;
|
||||
//默认参数
|
||||
private static final int DEFAULT_CONNECT_TIMEOUT = 3;//秒
|
||||
private static final int DEFAULT_READ_TIMEOUT = 30;//秒
|
||||
//请求配置
|
||||
private int connectTimeout;//3秒
|
||||
private int readTimeout;//30秒
|
||||
private boolean needCheckRequest = true; // 是否在客户端校验请求
|
||||
private boolean needEnableParser = true; // 是否对响应结果进行解释
|
||||
|
||||
private Before before = null;
|
||||
private After after = null;
|
||||
private String token = "";
|
||||
private boolean debug = false;
|
||||
|
||||
private ApiClient(String serverUrl, String appKey, String appSecret, int connectTimeout, int readTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
this.readTimeout = readTimeout;
|
||||
this.appKey = appKey;
|
||||
this.appSecret = appSecret;
|
||||
this.serverUrl = serverUrl;
|
||||
this.httpClient = new OkHttpClient.Builder()
|
||||
.readTimeout(readTimeout, TimeUnit.SECONDS)
|
||||
.connectTimeout(connectTimeout, TimeUnit.SECONDS)
|
||||
.build();
|
||||
}
|
||||
|
||||
public void setPublicKey(PublicKey publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public interface Callback<T extends ApiResponse> {
|
||||
void call(T response);
|
||||
}
|
||||
|
||||
public interface Before {
|
||||
void call(ApiRequest request);
|
||||
}
|
||||
|
||||
public interface After {
|
||||
void call(ApiRequest request, ApiResponse response);
|
||||
}
|
||||
|
||||
public void setAfter(After after) {
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
public void setBefore(Before before) {
|
||||
this.before = before;
|
||||
}
|
||||
|
||||
public <T extends ApiResponse> T execute(ApiRequest<T> request, boolean isEnhanced, ProgressRequestBody.ProgressListener listener) {
|
||||
if (before != null) {
|
||||
before.call(request);
|
||||
}
|
||||
|
||||
// 检查请求参数
|
||||
T t = MapperUtil.toJava("{}", request.responseClass());
|
||||
if (isEnhanced && publicKey == null) {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "publicKey can not be null.");
|
||||
}
|
||||
if (t.hasError()) {
|
||||
return t;
|
||||
}
|
||||
|
||||
try {
|
||||
//装载请求参数
|
||||
String currentTime = String.valueOf(System.currentTimeMillis());
|
||||
RequestBody requestBody = new MultipartBody.Builder()
|
||||
.addFormDataPart(P_APP_KEY, appKey)
|
||||
.addFormDataPart("isEnhanced", "false")
|
||||
.addFormDataPart("encryptData", null, ProgressRequestBody.createProgressRequestBody(encode(request, isEnhanced), listener))
|
||||
.addFormDataPart(P_TIMESTAMP, currentTime)
|
||||
.addFormDataPart(P_SIGN, sign(request, currentTime))
|
||||
.addFormDataPart(P_ENHANCED, String.valueOf(isEnhanced))
|
||||
.addFormDataPart(P_TOKEN, token)
|
||||
.build();
|
||||
|
||||
Request build = new Request.Builder()
|
||||
.url(serverUrl + request.apiMethod())
|
||||
.post(requestBody)
|
||||
.build();
|
||||
|
||||
Response response = httpClient.newCall(build).execute();
|
||||
String responseJson = decryptResponse(response, isEnhanced);
|
||||
t = MapperUtil.toJava(responseJson, request.responseClass());
|
||||
|
||||
} catch (ConnectException e) {
|
||||
t = MapperUtil.toJava("{}", request.responseClass());
|
||||
t.addError(ErrorType.SYSTEM_ERROR, "网络异常!");
|
||||
} catch (SocketTimeoutException e) {
|
||||
t = MapperUtil.toJava("{}", request.responseClass());
|
||||
t.addError(ErrorType.SYSTEM_ERROR, "请求超时!");
|
||||
} catch (IOException e) {
|
||||
t = MapperUtil.toJava("{}", request.responseClass());
|
||||
t.addError(ErrorType.SYSTEM_ERROR, "请求异常!");
|
||||
} finally {
|
||||
if (after != null) {
|
||||
after.call(request, t);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
public <T extends ApiResponse> void execute(ApiRequest<T> request, Callback callback) {
|
||||
execute(request, false, callback, null);
|
||||
}
|
||||
|
||||
public <T extends ApiResponse> void execute(final ApiRequest<T> request, final boolean isEnhanced, final Callback callback, ProgressRequestBody.ProgressListener listener) {
|
||||
if (before != null) {
|
||||
before.call(request);
|
||||
}
|
||||
|
||||
// 检查请求参数
|
||||
T t = MapperUtil.toJava("{}", request.responseClass());
|
||||
if (isEnhanced && publicKey == null) {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "publicKey can not be null.");
|
||||
}
|
||||
if (t.hasError()) {
|
||||
if (after != null) {
|
||||
after.call(request, t);
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.call(t);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
//装载请求参数
|
||||
String currentTime = String.valueOf(System.currentTimeMillis());
|
||||
RequestBody requestBody = new FormBody.Builder()
|
||||
.add(P_APP_KEY, appKey)
|
||||
.add(P_METHOD, request.apiMethod())
|
||||
.add(P_TYPE, TYPE_JSON)
|
||||
// .add(P_TARGET, null, ProgressRequestBody.createProgressRequestBody(encode(request, isEnhanced), listener))
|
||||
.add(P_TIMESTAMP, currentTime)
|
||||
.add(P_SIGN, sign(request, currentTime))
|
||||
.add(P_ENHANCED, String.valueOf(isEnhanced))
|
||||
.add(P_TOKEN, token)
|
||||
.build();
|
||||
|
||||
Request build = new Request.Builder()
|
||||
.url(serverUrl + request.apiMethod())
|
||||
.post(requestBody)
|
||||
.build();
|
||||
|
||||
httpClient.newCall(build).enqueue(new okhttp3.Callback() {
|
||||
public void onFailure(Call call, IOException e) {
|
||||
e.printStackTrace();
|
||||
T t = MapperUtil.toJava("{}", request.responseClass());
|
||||
if (e instanceof ConnectException) {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "网络异常!");
|
||||
} else if (e instanceof SocketTimeoutException) {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "请求超时!");
|
||||
} else {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "请求异常!");
|
||||
}
|
||||
|
||||
if (after != null) {
|
||||
after.call(request, t);
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.call(t);
|
||||
}
|
||||
}
|
||||
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
T t = null;
|
||||
try {
|
||||
|
||||
String responseJson = decryptResponse(response, isEnhanced);
|
||||
t = MapperUtil.toJava(responseJson, request.responseClass());
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
t = MapperUtil.toJava("{}", request.responseClass());
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "服务器走了下神!");
|
||||
}
|
||||
if (after != null) {
|
||||
after.call(request, t);
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.call(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
T baseResponse = MapperUtil.toJava("{}", request.responseClass());
|
||||
baseResponse.addError(ErrorType.SYSTEM_ERROR, "请求异常!");
|
||||
if (after != null) {
|
||||
after.call(request, baseResponse);
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.call(baseResponse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void fileUpload(final FileUploadRequest request, final Callback<FileUploadResponse> callback, ProgressRequestBody.ProgressListener listener) {
|
||||
if (before != null) {
|
||||
before.call(request);
|
||||
}
|
||||
|
||||
try {
|
||||
//检查文件是否存在
|
||||
if (!request.isExist()) {
|
||||
FileUploadResponse fileUploadResponse = new FileUploadResponse();
|
||||
fileUploadResponse.addError(ErrorType.BUSINESS_ERROR, "文件不存在!");
|
||||
if (after != null) {
|
||||
after.call(request, fileUploadResponse);
|
||||
}
|
||||
callback.call(fileUploadResponse);
|
||||
return;
|
||||
}
|
||||
|
||||
//装载请求参数
|
||||
String currentTime = String.valueOf(System.currentTimeMillis());
|
||||
MultipartBody.Builder builder = new MultipartBody.Builder()
|
||||
.addFormDataPart(P_APP_KEY, appKey)
|
||||
.addFormDataPart(P_METHOD, request.apiMethod())
|
||||
.addFormDataPart(P_TYPE, TYPE_FILE)
|
||||
.addFormDataPart(P_TIMESTAMP, currentTime)
|
||||
.addFormDataPart(P_SIGN, sign(request, currentTime))
|
||||
.addFormDataPart(P_TOKEN, token);
|
||||
|
||||
if (request.getFile() != null) {
|
||||
builder.addFormDataPart(P_TARGET, request.getFile().getName(), ProgressRequestBody.createProgressRequestBody(MediaType.parse("image/*"), request.getFile(), listener));
|
||||
builder.addFormDataPart(P_FILE_NAME, request.getFileName());
|
||||
} else {
|
||||
builder.addFormDataPart(P_TARGET, null, ProgressRequestBody.createProgressRequestBody(Base64Util.encodeToString(request.getBytes()), listener));
|
||||
builder.addFormDataPart(P_FILE_NAME, request.getFileName());
|
||||
}
|
||||
MultipartBody multipartBody = builder.build();
|
||||
|
||||
Request build = new Request.Builder()
|
||||
.url(serverUrl)
|
||||
.post(multipartBody)
|
||||
.build();
|
||||
|
||||
httpClient.newCall(build).enqueue(new okhttp3.Callback() {
|
||||
public void onFailure(Call call, IOException e) {
|
||||
e.printStackTrace();
|
||||
FileUploadResponse t = MapperUtil.toJava("{}", FileUploadResponse.class);
|
||||
if (e instanceof ConnectException) {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "网络异常!");
|
||||
} else if (e instanceof SocketTimeoutException) {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "请求超时!");
|
||||
} else {
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "请求异常!");
|
||||
}
|
||||
|
||||
if (after != null) {
|
||||
after.call(request, t);
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.call(t);
|
||||
}
|
||||
}
|
||||
|
||||
public void onResponse(Call call, Response response) throws IOException {
|
||||
|
||||
FileUploadResponse t = null;
|
||||
try {
|
||||
|
||||
String responseJson = decryptResponse(response, false);
|
||||
t = MapperUtil.toJava(responseJson, FileUploadResponse.class);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
t = new FileUploadResponse();
|
||||
t.addError(ErrorType.BUSINESS_ERROR, "服务器走了下神!");
|
||||
}
|
||||
|
||||
if (after != null) {
|
||||
after.call(request, t);
|
||||
}
|
||||
if (callback != null) {
|
||||
callback.call(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对请求进行加密编码
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private String encode(ApiRequest request, boolean isEnhanced) {
|
||||
String json = MapperUtil.toJson(request);
|
||||
if (isEnhanced) {
|
||||
return RSAUtil.encrypt2Base64(json.getBytes());
|
||||
} else {
|
||||
return AESUtil.encrypt2Base64(json.getBytes(), appSecret);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 对响应进行解密
|
||||
*
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
private String decryptResponse(Response response, boolean isEnhanced) throws IOException {
|
||||
String responseString = response.body().string();
|
||||
String responseJson;
|
||||
if (isEnhanced) {
|
||||
responseJson = RSAUtil.decrypt2String(responseString);
|
||||
} else {
|
||||
responseJson = AESUtil.decrypt2String(responseString, appSecret);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
System.out.println("加密响应结果:" + responseString);
|
||||
System.out.println("响应结果:" + responseJson);
|
||||
}
|
||||
return responseJson;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对请求进行签名
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private String sign(ApiRequest request, String currentTime) {
|
||||
if (request instanceof FileUploadRequest) {//文件签名、对文件字节生成的信息摘要签名
|
||||
FileUploadRequest fileUploadRequest = (FileUploadRequest) request;
|
||||
String encode = MD5Util.encode(fileUploadRequest.getFile() != null ? toByteArray(fileUploadRequest.getFile()) : fileUploadRequest.getBytes());
|
||||
return MD5Util.encode(appSecret + encode + currentTime);
|
||||
} else {//普通参数签名、此处JSON是经过排序生成的JSON字符串,因此验签时也需要排序
|
||||
String json = MapperUtil.toJson(request);
|
||||
return MD5Util.encode(appSecret + json + currentTime);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] toByteArray(File file) {
|
||||
File f = file;
|
||||
if (!f.exists()) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream((int) f.length());
|
||||
BufferedInputStream in = null;
|
||||
try {
|
||||
in = new BufferedInputStream(new FileInputStream(f));
|
||||
int buf_size = 1024;
|
||||
byte[] buffer = new byte[buf_size];
|
||||
int len = 0;
|
||||
while (-1 != (len = in.read(buffer, 0, buf_size))) {
|
||||
bos.write(buffer, 0, len);
|
||||
}
|
||||
return bos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setTokenId(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public boolean isDebug() {
|
||||
return debug;
|
||||
}
|
||||
|
||||
public void setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package ${domain};
|
||||
|
||||
import ${domain}.request.*;
|
||||
import ${domain}.response.*;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* ApiTest - 测试用例
|
||||
*
|
||||
* @author author
|
||||
* @version 0.0.1
|
||||
* @since 2019-06-11
|
||||
*/
|
||||
public class ApiTest {
|
||||
|
||||
private ApiClient apiClient;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
//实例化API请求客户端
|
||||
ApiClient.init("http://localhost:8080/api", "app_key", "1234567890123456");
|
||||
apiClient = ApiClient.getInstance();
|
||||
ApiClient client = ApiClient.getInstance();
|
||||
|
||||
// 以下为对称加密公钥,对重要关键请求加密,可不设
|
||||
String cryptPublicKeyBase64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCTrwfsrJjCF+pP4S3A/wrD4U1txg53EuBC1mPt" +
|
||||
"3vGXvSK2U0YNRVR3Q65ooHnPKmk4LwI8v+7+ATTxUg3qkuRiDuzBa5zLkYKM50LOgEWSdOKzbnbx" +
|
||||
"a5FnE7IXawNt1p8+MVN1TTI7J/fZy6g1x0WBy1odE5Osru4WfZNOqQtjHwIDAQAB";
|
||||
client.setPublicKey(RSAUtil.parsePublicKey(cryptPublicKeyBase64));
|
||||
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
|
||||
//设置发送网络请求前的统一操作
|
||||
client.setBefore(new ApiClient.Before() {
|
||||
public void call(ApiRequest request) {
|
||||
System.out.println("请求参数" + MapperUtil.toJson(request));
|
||||
System.out.println("请求方法" + request.apiMethod());
|
||||
}
|
||||
});
|
||||
//设置网络请求完成后的统一操作
|
||||
client.setAfter(new ApiClient.After() {
|
||||
public void call(ApiRequest request, ApiResponse response) {
|
||||
System.out.println("响应参数" + MapperUtil.toJson(response));
|
||||
Date end = new Date();
|
||||
System.out.println(simpleDateFormat.format(end));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileUpload() {
|
||||
{//无进度显示
|
||||
final Date start = new Date();
|
||||
|
||||
//文件上传请求
|
||||
FileUploadRequest fileUploadRequest = new FileUploadRequest();
|
||||
fileUploadRequest.setFile(new File("D:\\1.PNG"));
|
||||
apiClient.fileUpload(fileUploadRequest, new ApiClient.Callback<FileUploadResponse>() {
|
||||
public void call(FileUploadResponse response) {
|
||||
Date end = new Date();
|
||||
System.out.println("无进度显示" + (end.getTime() - start.getTime()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
{//有进度显示
|
||||
final Date start = new Date();
|
||||
|
||||
//文件上传请求
|
||||
FileUploadRequest fileUploadRequest = new FileUploadRequest();
|
||||
fileUploadRequest.setFile(new File("D:\\1.PNG"));
|
||||
apiClient.fileUpload(fileUploadRequest, new ApiClient.Callback<FileUploadResponse>() {
|
||||
public void call(FileUploadResponse response) {
|
||||
Date end = new Date();
|
||||
System.out.println("有进度显示" + (end.getTime() - start.getTime()));
|
||||
}
|
||||
}, new ProgressRequestBody.ProgressListener() {
|
||||
public void onProgress(long totalBytes, long remainingBytes, boolean done) {
|
||||
System.out.println((totalBytes - remainingBytes) * 100 / totalBytes + "%");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
<#list apiList as item>
|
||||
|
||||
@Test
|
||||
public void test${item.targetRequest}() {
|
||||
${item.targetRequest} request = new ${item.targetRequest}();
|
||||
${item.targetResponse} response = apiClient.execute(request);
|
||||
Assert.assertTrue(!response.hasError());
|
||||
}
|
||||
</#list>
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package ${domain};
|
||||
|
||||
import ${domain}.request.*;
|
||||
import ${domain}.response.*;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* ApiTest - 测试用例
|
||||
*
|
||||
* @author author
|
||||
* @version 0.0.1
|
||||
* @since 2019-06-11
|
||||
*/
|
||||
public class ApiTest {
|
||||
|
||||
private ApiClient apiClient;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
//实例化API请求客户端
|
||||
ApiClient.init("http://localhost:8080/api", "app_key", "1234567890123456");
|
||||
apiClient = ApiClient.getInstance();
|
||||
ApiClient client = ApiClient.getInstance();
|
||||
client.setDebug(true);
|
||||
|
||||
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
|
||||
//设置发送网络请求前的统一操作
|
||||
client.setBefore(new ApiClient.Before() {
|
||||
public void call(ApiRequest request) {
|
||||
System.out.println("请求参数" + MapperUtil.toJson(request));
|
||||
System.out.println("请求方法" + request.apiMethod());
|
||||
}
|
||||
});
|
||||
//设置网络请求完成后的统一操作
|
||||
client.setAfter(new ApiClient.After() {
|
||||
public void call(ApiRequest request, ApiResponse response) {
|
||||
System.out.println("响应参数" + MapperUtil.toJson(response));
|
||||
Date end = new Date();
|
||||
System.out.println(simpleDateFormat.format(end));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
<#list apiList as item>
|
||||
|
||||
@Test
|
||||
public void test${item.targetRequest}() {
|
||||
${item.targetRequest} request = new ${item.targetRequest}();
|
||||
${item.targetResponse} response = apiClient.execute(request);
|
||||
Assert.assertTrue(!response.hasError());
|
||||
}
|
||||
</#list>
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package ${domain};
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* FileUploadRequest - 文件上传请求
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 2017-01-01
|
||||
*/
|
||||
public class FileUploadRequest implements ApiRequest<FileUploadResponse> {
|
||||
private String fileName;
|
||||
private File file;
|
||||
private byte[] bytes;
|
||||
|
||||
public void setFile(File file) {
|
||||
this.file = file;
|
||||
this.fileName = file.getName();
|
||||
this.bytes = null;
|
||||
}
|
||||
|
||||
public void setFile(byte[] bytes, String fileName) {
|
||||
this.bytes = bytes;
|
||||
this.fileName = fileName;
|
||||
this.file = null;
|
||||
}
|
||||
|
||||
public boolean isExist() {
|
||||
if ((file != null && file.exists()) || bytes != null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void check() {
|
||||
|
||||
}
|
||||
|
||||
public String apiMethod() {
|
||||
return "api.file.upload";
|
||||
}
|
||||
|
||||
public Class<FileUploadResponse> responseClass() {
|
||||
return FileUploadResponse.class;
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package ${domain};
|
||||
|
||||
/**
|
||||
* FileUploadResponse - 文件上传响应
|
||||
*
|
||||
* @author wangbing
|
||||
* @version 0.0.1
|
||||
* @since 2017-01-01
|
||||
*/
|
||||
public class FileUploadResponse extends ApiResponse {
|
||||
|
||||
/**
|
||||
* 文件ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* url地址
|
||||
*/
|
||||
private String url;
|
||||
|
||||
private String attribute1;
|
||||
|
||||
private String attribute2;
|
||||
|
||||
private String attribute3;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getAttribute1() {
|
||||
return attribute1;
|
||||
}
|
||||
|
||||
public void setAttribute1(String attribute1) {
|
||||
this.attribute1 = attribute1;
|
||||
}
|
||||
|
||||
public String getAttribute2() {
|
||||
return attribute2;
|
||||
}
|
||||
|
||||
public void setAttribute2(String attribute2) {
|
||||
this.attribute2 = attribute2;
|
||||
}
|
||||
|
||||
public String getAttribute3() {
|
||||
return attribute3;
|
||||
}
|
||||
|
||||
public void setAttribute3(String attribute3) {
|
||||
this.attribute3 = attribute3;
|
||||
}
|
||||
}
|
@ -1,259 +0,0 @@
|
||||
package ${domain}.action;
|
||||
|
||||
import ${domain}.${module}.mgr.*;
|
||||
import ${domain}.${module}.req.*;
|
||||
import ${domain}.frame.base.BaseResponse;
|
||||
import ${domain}.frame.base.ErrorType;
|
||||
import ${domain}.frame.base.Token;
|
||||
import ${domain}.frame.utils.*;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
@Controller
|
||||
public class ApiController {
|
||||
//基本请求参数KEY
|
||||
private static final String P_APP_KEY = "app_key";
|
||||
private static final String P_TYPE = "type";
|
||||
private static final String P_TARGET = "target";
|
||||
private static final String P_TARGET_JSON = "target_json";
|
||||
private static final String P_FILE_NAME = "file_name";
|
||||
private static final String P_TIMESTAMP = "timestamp";
|
||||
private static final String P_METHOD = "method";
|
||||
private static final String P_SIGN = "sign";
|
||||
private static final String P_ENHANCED = "enhanced";
|
||||
//安全模式,签名或加密
|
||||
private static final String MODE_SIGN = "sign";
|
||||
private static final String MODE_ENCRYPTION = "encryption";
|
||||
//参数类型
|
||||
private static final String TYPE_JSON = "json";
|
||||
private static final String TYPE_FILE = "file";
|
||||
//签名方式
|
||||
private static final String SIGN_METHOD_MD5 = "MD5";
|
||||
private static final String SIGN_METHOD_RSA = "RSA";
|
||||
//加密方式
|
||||
private static final String ENCRYPTION_METHOD_MD5 = "MD5";
|
||||
private static final String ENCRYPTION_METHOD_RSA = "RSA";
|
||||
|
||||
private static final String APP_SECRET = "1234567890123456";
|
||||
|
||||
<#list managerList as i>
|
||||
@Autowired
|
||||
private ${tool.abb2Abb(i)} ${tool.Abb2abb(i)};
|
||||
</#list>
|
||||
|
||||
@RequestMapping("/api")
|
||||
@ResponseBody
|
||||
public String api(HttpServletRequest request) {
|
||||
BaseResponse baseResponse = new BaseResponse();
|
||||
//安全认证
|
||||
validate(request, baseResponse);
|
||||
|
||||
//权限认证
|
||||
if (!baseResponse.hasError()) {
|
||||
authenticate(request, baseResponse);
|
||||
}
|
||||
|
||||
// 业务处理
|
||||
if (!baseResponse.hasError()) {
|
||||
baseResponse = handle(request);
|
||||
}
|
||||
|
||||
return encrypt(request,baseResponse);
|
||||
}
|
||||
|
||||
private String encrypt(HttpServletRequest request,BaseResponse baseResponse){
|
||||
String enhanced = request.getParameter(P_ENHANCED);
|
||||
boolean isEnhanced = !StringUtils.isEmpty(enhanced) && "true".equals(enhanced);
|
||||
byte[] bytes = MapperUtil.toJson(baseResponse).getBytes();
|
||||
if (isEnhanced){
|
||||
return RSAUtil.encrypt2Base64(bytes);
|
||||
}else {
|
||||
return AESUtil.encrypt2Base64(bytes, APP_SECRET);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求处理器
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private BaseResponse handle(HttpServletRequest request) {
|
||||
|
||||
//File请求处理
|
||||
if (TYPE_FILE.equals(request.getParameter(P_TYPE))) {
|
||||
return handleFILE(request);
|
||||
}
|
||||
//JSON请求处理
|
||||
if (TYPE_JSON.equals(request.getParameter(P_TYPE))) {
|
||||
return handleJSON(request);
|
||||
}
|
||||
|
||||
BaseResponse baseResponse = new BaseResponse();
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "请求未处理");
|
||||
return baseResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件请求处理
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private BaseResponse handleFILE(HttpServletRequest request) {
|
||||
BaseResponse baseResponse = new BaseResponse();
|
||||
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
|
||||
|
||||
String fileName = multipartHttpServletRequest.getParameter(P_FILE_NAME);
|
||||
byte[] data = null;
|
||||
|
||||
try {
|
||||
MultipartFile target = multipartHttpServletRequest.getFile(P_TARGET);
|
||||
if (target == null) {
|
||||
String base64 = multipartHttpServletRequest.getParameter(P_TARGET);
|
||||
data = Base64Util.decode(base64);
|
||||
} else {
|
||||
data = target.getBytes();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "文件获取失败!");
|
||||
return baseResponse;
|
||||
}
|
||||
|
||||
//========
|
||||
//处理文件
|
||||
//========
|
||||
|
||||
if (data != null) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传成功,但未处理文件[" + fileName + "]!");
|
||||
}else {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "文件上传失败!");
|
||||
}
|
||||
|
||||
return baseResponse;
|
||||
}
|
||||
|
||||
private BaseResponse handleJSON(HttpServletRequest request){
|
||||
BaseResponse baseResponse = new BaseResponse();
|
||||
String method = null;
|
||||
String targetJson = null;
|
||||
try {
|
||||
method = request.getParameter(P_METHOD);
|
||||
targetJson = (String) request.getAttribute(P_TARGET_JSON);
|
||||
if (method == null) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "请求方法不能为空!");
|
||||
return baseResponse;
|
||||
}
|
||||
if (targetJson == null) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "请求目标不能为空!");
|
||||
return baseResponse;
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
<#list methodList as m >
|
||||
case "${m.stringMethod}":
|
||||
baseResponse = ${m.target}${tool.abb2Abb(m.method)}(targetJson, LocalData.getToken());
|
||||
break;
|
||||
</#list>
|
||||
default:
|
||||
baseResponse.addError(ErrorType.INVALID_PARAMETER, Message.NOT_EXIST_METHOD);
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
baseResponse.addError(ErrorType.SYSTEM_ERROR, Message.ERROR_500);
|
||||
LogUtil.dumpException(ex);
|
||||
} finally {
|
||||
if (baseResponse.hasError()) {
|
||||
LogUtil.e("请求方法:" + method + ", 请求目标:" + targetJson);
|
||||
LogUtil.e("错误原因:" + MapperUtil.toJson(baseResponse.getErrors()));
|
||||
}
|
||||
}
|
||||
return baseResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全认证
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private void validate(HttpServletRequest request, BaseResponse baseResponse) {
|
||||
String type = request.getParameter(P_TYPE);
|
||||
String timestamp = request.getParameter(P_TIMESTAMP);
|
||||
String sign = request.getParameter(P_SIGN);
|
||||
String enhanced = request.getParameter(P_ENHANCED);
|
||||
boolean isEnhanced = !StringUtils.isEmpty(enhanced) && "true".equals(enhanced);
|
||||
|
||||
if(type == null || timestamp == null || sign == null){
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR,"无效参数");
|
||||
return;
|
||||
}
|
||||
|
||||
if (TYPE_JSON.equals(type)) {
|
||||
String target = request.getParameter(P_TARGET);
|
||||
String jsonString = null;
|
||||
try {
|
||||
if (isEnhanced) {
|
||||
jsonString = RSAUtil.decrypt2String(target);
|
||||
} else {
|
||||
jsonString = AESUtil.decrypt2String(target, APP_SECRET);
|
||||
}
|
||||
}catch (Exception e){
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR,"Target解码错误,请确认编码是否正确!");
|
||||
return;
|
||||
}
|
||||
|
||||
String sign_ = MD5Util.encode(APP_SECRET + jsonString + timestamp);
|
||||
if (!sign_.equals(sign)) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "签名验证失败");
|
||||
}
|
||||
request.setAttribute(P_TARGET_JSON,jsonString);
|
||||
} else if (TYPE_FILE.equals(type)) {
|
||||
MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request;
|
||||
MultipartFile file = multipartHttpServletRequest.getFile(P_TARGET);
|
||||
String base64 = multipartHttpServletRequest.getParameter(P_TARGET);
|
||||
|
||||
try {
|
||||
String sign_ = MD5Util.encode(APP_SECRET + MD5Util.encode(file != null ? file.getBytes() : Base64Util.decode(base64)) + timestamp);
|
||||
|
||||
if (!sign_.equals(sign)) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "签名验证失败");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "签名验证失败");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!baseResponse.hasError()){//时效性验证
|
||||
long timestamp_ = Long.parseLong(timestamp);
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if (currentTime - timestamp_ > 2 * 60 * 1000) {
|
||||
baseResponse.addError(ErrorType.BUSINESS_ERROR, "请求过期, 或本地时间错误.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void authenticate(HttpServletRequest request, BaseResponse baseResponse){
|
||||
Token token = new Token();
|
||||
token.setId(0L);
|
||||
token.setUserId(0L);
|
||||
token.setUserName("admin");
|
||||
LocalData.setToken(token);
|
||||
}
|
||||
|
||||
<#list methodList as m>
|
||||
private BaseResponse ${m.target}${tool.abb2Abb(m.method)}(String targetJson, Token token) {
|
||||
${m.request} request = MapperUtil.toJava(targetJson, ${m.request}.class);
|
||||
return ${m.manager}.${m.method}(request, token);
|
||||
}
|
||||
</#list>
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package ${domain}.${module}.enums;
|
||||
|
||||
<#list annotation as i>
|
||||
${i}
|
||||
</#list>
|
||||
public enum ${className} {
|
||||
<#list body as i>
|
||||
${i}
|
||||
</#list>
|
||||
}
|
Loading…
Reference in new issue