mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
5.0
This commit is contained in:
56
sop-admin/sop-admin-frontend/src/api/apiTable.ts
Normal file
56
sop-admin/sop-admin-frontend/src/api/apiTable.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import qs from 'query-string';
|
||||||
|
import type { DescData } from '@arco-design/web-vue/es/descriptions/interface';
|
||||||
|
|
||||||
|
export interface PolicyRecord {
|
||||||
|
id: string;
|
||||||
|
number: number;
|
||||||
|
name: string;
|
||||||
|
contentType: 'img' | 'horizontalVideo' | 'verticalVideo';
|
||||||
|
filterType: 'artificial' | 'rules';
|
||||||
|
count: number;
|
||||||
|
status: 'online' | 'offline';
|
||||||
|
createdTime: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PolicyParams extends Partial<PolicyRecord> {
|
||||||
|
pageIndex: number;
|
||||||
|
pageSize: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PolicyListRes {
|
||||||
|
list: PolicyRecord[];
|
||||||
|
total: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryPolicyList(params: PolicyParams) {
|
||||||
|
return axios.get<PolicyListRes>('/api/page', {
|
||||||
|
params,
|
||||||
|
paramsSerializer: (obj) => {
|
||||||
|
return qs.stringify(obj);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServiceRecord {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
name?: string;
|
||||||
|
actionType?: string;
|
||||||
|
icon?: string;
|
||||||
|
data?: DescData[];
|
||||||
|
enable?: boolean;
|
||||||
|
expires?: boolean;
|
||||||
|
}
|
||||||
|
export function queryInspectionList() {
|
||||||
|
return axios.get('/api/list/quality-inspection');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryTheServiceList() {
|
||||||
|
return axios.get('/api/list/the-service');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryRulesPresetList() {
|
||||||
|
return axios.get('/api/list/rules-preset');
|
||||||
|
}
|
514
sop-admin/sop-admin-frontend/src/views/api/table/index.vue
Normal file
514
sop-admin/sop-admin-frontend/src/views/api/table/index.vue
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<Breadcrumb :items="['menu.list', 'menu.list.searchTable']" />
|
||||||
|
<a-card class="general-card" :title="$t('menu.list.searchTable')">
|
||||||
|
<a-row>
|
||||||
|
<a-col :flex="1">
|
||||||
|
<a-form
|
||||||
|
:model="formModel"
|
||||||
|
:label-col-props="{ span: 6 }"
|
||||||
|
:wrapper-col-props="{ span: 18 }"
|
||||||
|
label-align="left"
|
||||||
|
>
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item
|
||||||
|
field="number"
|
||||||
|
:label="$t('searchTable.form.number')"
|
||||||
|
>
|
||||||
|
<a-input
|
||||||
|
v-model="formModel.number"
|
||||||
|
:placeholder="$t('searchTable.form.number.placeholder')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item field="name" :label="$t('searchTable.form.name')">
|
||||||
|
<a-input
|
||||||
|
v-model="formModel.name"
|
||||||
|
:placeholder="$t('searchTable.form.name.placeholder')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item
|
||||||
|
field="contentType"
|
||||||
|
:label="$t('searchTable.form.contentType')"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="formModel.contentType"
|
||||||
|
:options="contentTypeOptions"
|
||||||
|
:placeholder="$t('searchTable.form.selectDefault')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item
|
||||||
|
field="filterType"
|
||||||
|
:label="$t('searchTable.form.filterType')"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="formModel.filterType"
|
||||||
|
:options="filterTypeOptions"
|
||||||
|
:placeholder="$t('searchTable.form.selectDefault')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item
|
||||||
|
field="createdTime"
|
||||||
|
:label="$t('searchTable.form.createdTime')"
|
||||||
|
>
|
||||||
|
<a-range-picker
|
||||||
|
v-model="formModel.createdTime"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="8">
|
||||||
|
<a-form-item
|
||||||
|
field="status"
|
||||||
|
:label="$t('searchTable.form.status')"
|
||||||
|
>
|
||||||
|
<a-select
|
||||||
|
v-model="formModel.status"
|
||||||
|
:options="statusOptions"
|
||||||
|
:placeholder="$t('searchTable.form.selectDefault')"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
</a-col>
|
||||||
|
<a-divider style="height: 84px" direction="vertical" />
|
||||||
|
<a-col :flex="'86px'" style="text-align: right">
|
||||||
|
<a-space direction="vertical" :size="18">
|
||||||
|
<a-button type="primary" @click="search">
|
||||||
|
<template #icon>
|
||||||
|
<icon-search />
|
||||||
|
</template>
|
||||||
|
{{ $t('searchTable.form.search') }}
|
||||||
|
</a-button>
|
||||||
|
<a-button @click="reset">
|
||||||
|
<template #icon>
|
||||||
|
<icon-refresh />
|
||||||
|
</template>
|
||||||
|
{{ $t('searchTable.form.reset') }}
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-divider style="margin-top: 0" />
|
||||||
|
<a-row style="margin-bottom: 16px">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-space>
|
||||||
|
<a-button type="primary">
|
||||||
|
<template #icon>
|
||||||
|
<icon-plus />
|
||||||
|
</template>
|
||||||
|
{{ $t('searchTable.operation.create') }}
|
||||||
|
</a-button>
|
||||||
|
<a-upload action="/">
|
||||||
|
<template #upload-button>
|
||||||
|
<a-button>
|
||||||
|
{{ $t('searchTable.operation.import') }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-upload>
|
||||||
|
</a-space>
|
||||||
|
</a-col>
|
||||||
|
<a-col
|
||||||
|
:span="12"
|
||||||
|
style="display: flex; align-items: center; justify-content: end"
|
||||||
|
>
|
||||||
|
<a-button>
|
||||||
|
<template #icon>
|
||||||
|
<icon-download />
|
||||||
|
</template>
|
||||||
|
{{ $t('searchTable.operation.download') }}
|
||||||
|
</a-button>
|
||||||
|
<a-tooltip :content="$t('searchTable.actions.refresh')">
|
||||||
|
<div class="action-icon" @click="search"
|
||||||
|
><icon-refresh size="18"
|
||||||
|
/></div>
|
||||||
|
</a-tooltip>
|
||||||
|
<a-dropdown @select="handleSelectDensity">
|
||||||
|
<a-tooltip :content="$t('searchTable.actions.density')">
|
||||||
|
<div class="action-icon"><icon-line-height size="18" /></div>
|
||||||
|
</a-tooltip>
|
||||||
|
<template #content>
|
||||||
|
<a-doption
|
||||||
|
v-for="item in densityList"
|
||||||
|
:key="item.value"
|
||||||
|
:value="item.value"
|
||||||
|
:class="{ active: item.value === size }"
|
||||||
|
>
|
||||||
|
<span>{{ item.name }}</span>
|
||||||
|
</a-doption>
|
||||||
|
</template>
|
||||||
|
</a-dropdown>
|
||||||
|
<a-tooltip :content="$t('searchTable.actions.columnSetting')">
|
||||||
|
<a-popover
|
||||||
|
trigger="click"
|
||||||
|
position="bl"
|
||||||
|
@popup-visible-change="popupVisibleChange"
|
||||||
|
>
|
||||||
|
<div class="action-icon"><icon-settings size="18" /></div>
|
||||||
|
<template #content>
|
||||||
|
<div id="tableSetting">
|
||||||
|
<div
|
||||||
|
v-for="(item, index) in showColumns"
|
||||||
|
:key="item.dataIndex"
|
||||||
|
class="setting"
|
||||||
|
>
|
||||||
|
<div style="margin-right: 4px; cursor: move">
|
||||||
|
<icon-drag-arrow />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a-checkbox
|
||||||
|
v-model="item.checked"
|
||||||
|
@change="
|
||||||
|
handleChange($event, item as TableColumnData, index)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
</a-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="title">
|
||||||
|
{{ item.title === '#' ? '序列号' : item.title }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</a-popover>
|
||||||
|
</a-tooltip>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-table
|
||||||
|
row-key="id"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
:columns="(cloneColumns as TableColumnData[])"
|
||||||
|
:data="renderData"
|
||||||
|
:bordered="false"
|
||||||
|
:size="size"
|
||||||
|
@page-change="onPageChange"
|
||||||
|
>
|
||||||
|
<template #index="{ rowIndex }">
|
||||||
|
{{ rowIndex + 1 + (pagination.current - 1) * pagination.pageSize }}
|
||||||
|
</template>
|
||||||
|
<template #contentType="{ record }">
|
||||||
|
<a-space>
|
||||||
|
<a-avatar
|
||||||
|
v-if="record.contentType === 'img'"
|
||||||
|
:size="16"
|
||||||
|
shape="square"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="avatar"
|
||||||
|
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/581b17753093199839f2e327e726b157.svg~tplv-49unhts6dw-image.image"
|
||||||
|
/>
|
||||||
|
</a-avatar>
|
||||||
|
<a-avatar
|
||||||
|
v-else-if="record.contentType === 'horizontalVideo'"
|
||||||
|
:size="16"
|
||||||
|
shape="square"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt="avatar"
|
||||||
|
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/77721e365eb2ab786c889682cbc721c1.svg~tplv-49unhts6dw-image.image"
|
||||||
|
/>
|
||||||
|
</a-avatar>
|
||||||
|
<a-avatar v-else :size="16" shape="square">
|
||||||
|
<img
|
||||||
|
alt="avatar"
|
||||||
|
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/ea8b09190046da0ea7e070d83c5d1731.svg~tplv-49unhts6dw-image.image"
|
||||||
|
/>
|
||||||
|
</a-avatar>
|
||||||
|
{{ $t(`searchTable.form.contentType.${record.contentType}`) }}
|
||||||
|
</a-space>
|
||||||
|
</template>
|
||||||
|
<template #filterType="{ record }">
|
||||||
|
{{ $t(`searchTable.form.filterType.${record.filterType}`) }}
|
||||||
|
</template>
|
||||||
|
<template #status="{ record }">
|
||||||
|
<span v-if="record.status === 'offline'" class="circle"></span>
|
||||||
|
<span v-else class="circle pass"></span>
|
||||||
|
{{ $t(`searchTable.form.status.${record.status}`) }}
|
||||||
|
</template>
|
||||||
|
<template #operations>
|
||||||
|
<a-button v-permission="['admin']" type="text" size="small">
|
||||||
|
{{ $t('searchTable.columns.operations.view') }}
|
||||||
|
</a-button>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { computed, ref, reactive, watch, nextTick } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import useLoading from '@/hooks/loading';
|
||||||
|
import { queryPolicyList, PolicyRecord, PolicyParams } from '@/api/apiTable';
|
||||||
|
import { Pagination } from '@/types/global';
|
||||||
|
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
|
||||||
|
import type { TableColumnData } from '@arco-design/web-vue/es/table/interface';
|
||||||
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
|
import Sortable from 'sortablejs';
|
||||||
|
|
||||||
|
type SizeProps = 'mini' | 'small' | 'medium' | 'large';
|
||||||
|
type Column = TableColumnData & { checked?: true };
|
||||||
|
|
||||||
|
const generateFormModel = () => {
|
||||||
|
return {
|
||||||
|
number: '',
|
||||||
|
name: '',
|
||||||
|
contentType: '',
|
||||||
|
filterType: '',
|
||||||
|
createdTime: [],
|
||||||
|
status: '',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const { loading, setLoading } = useLoading(true);
|
||||||
|
const { t } = useI18n();
|
||||||
|
const renderData = ref<PolicyRecord[]>([]);
|
||||||
|
const formModel = ref(generateFormModel());
|
||||||
|
const cloneColumns = ref<Column[]>([]);
|
||||||
|
const showColumns = ref<Column[]>([]);
|
||||||
|
|
||||||
|
const size = ref<SizeProps>('medium');
|
||||||
|
|
||||||
|
const basePagination: Pagination = {
|
||||||
|
current: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
};
|
||||||
|
const pagination = reactive({
|
||||||
|
...basePagination,
|
||||||
|
});
|
||||||
|
const densityList = computed(() => [
|
||||||
|
{
|
||||||
|
name: t('searchTable.size.mini'),
|
||||||
|
value: 'mini',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('searchTable.size.small'),
|
||||||
|
value: 'small',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('searchTable.size.medium'),
|
||||||
|
value: 'medium',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: t('searchTable.size.large'),
|
||||||
|
value: 'large',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const columns = computed<TableColumnData[]>(() => [
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.index'),
|
||||||
|
dataIndex: 'index',
|
||||||
|
slotName: 'index',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.number'),
|
||||||
|
dataIndex: 'number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.name'),
|
||||||
|
dataIndex: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.contentType'),
|
||||||
|
dataIndex: 'contentType',
|
||||||
|
slotName: 'contentType',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.filterType'),
|
||||||
|
dataIndex: 'filterType',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.count'),
|
||||||
|
dataIndex: 'count',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.createdTime'),
|
||||||
|
dataIndex: 'createdTime',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.status'),
|
||||||
|
dataIndex: 'status',
|
||||||
|
slotName: 'status',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('searchTable.columns.operations'),
|
||||||
|
dataIndex: 'operations',
|
||||||
|
slotName: 'operations',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const contentTypeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: t('searchTable.form.contentType.img'),
|
||||||
|
value: 'img',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('searchTable.form.contentType.horizontalVideo'),
|
||||||
|
value: 'horizontalVideo',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('searchTable.form.contentType.verticalVideo'),
|
||||||
|
value: 'verticalVideo',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const filterTypeOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: t('searchTable.form.filterType.artificial'),
|
||||||
|
value: 'artificial',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('searchTable.form.filterType.rules'),
|
||||||
|
value: 'rules',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const statusOptions = computed<SelectOptionData[]>(() => [
|
||||||
|
{
|
||||||
|
label: t('searchTable.form.status.online'),
|
||||||
|
value: 'online',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('searchTable.form.status.offline'),
|
||||||
|
value: 'offline',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
const fetchData = async (
|
||||||
|
params: PolicyParams = { current: 1, pageSize: 20 }
|
||||||
|
) => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const { data } = await queryPolicyList(params);
|
||||||
|
renderData.value = data.list;
|
||||||
|
pagination.current = params.current;
|
||||||
|
pagination.total = data.total;
|
||||||
|
} catch (err) {
|
||||||
|
// you can report use errorHandler or other
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const search = () => {
|
||||||
|
fetchData({
|
||||||
|
...basePagination,
|
||||||
|
...formModel.value,
|
||||||
|
} as unknown as PolicyParams);
|
||||||
|
};
|
||||||
|
const onPageChange = (current: number) => {
|
||||||
|
fetchData({ ...basePagination, current });
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchData();
|
||||||
|
const reset = () => {
|
||||||
|
formModel.value = generateFormModel();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSelectDensity = (
|
||||||
|
val: string | number | Record<string, any> | undefined,
|
||||||
|
e: Event
|
||||||
|
) => {
|
||||||
|
size.value = val as SizeProps;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (
|
||||||
|
checked: boolean | (string | boolean | number)[],
|
||||||
|
column: Column,
|
||||||
|
index: number
|
||||||
|
) => {
|
||||||
|
if (!checked) {
|
||||||
|
cloneColumns.value = showColumns.value.filter(
|
||||||
|
(item) => item.dataIndex !== column.dataIndex
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cloneColumns.value.splice(index, 0, column);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const exchangeArray = <T extends Array<any>>(
|
||||||
|
array: T,
|
||||||
|
beforeIdx: number,
|
||||||
|
newIdx: number,
|
||||||
|
isDeep = false
|
||||||
|
): T => {
|
||||||
|
const newArray = isDeep ? cloneDeep(array) : array;
|
||||||
|
if (beforeIdx > -1 && newIdx > -1) {
|
||||||
|
// 先替换后面的,然后拿到替换的结果替换前面的
|
||||||
|
newArray.splice(
|
||||||
|
beforeIdx,
|
||||||
|
1,
|
||||||
|
newArray.splice(newIdx, 1, newArray[beforeIdx]).pop()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return newArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
const popupVisibleChange = (val: boolean) => {
|
||||||
|
if (val) {
|
||||||
|
nextTick(() => {
|
||||||
|
const el = document.getElementById('tableSetting') as HTMLElement;
|
||||||
|
const sortable = new Sortable(el, {
|
||||||
|
onEnd(e: any) {
|
||||||
|
const { oldIndex, newIndex } = e;
|
||||||
|
exchangeArray(cloneColumns.value, oldIndex, newIndex);
|
||||||
|
exchangeArray(showColumns.value, oldIndex, newIndex);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => columns.value,
|
||||||
|
(val) => {
|
||||||
|
cloneColumns.value = cloneDeep(val);
|
||||||
|
cloneColumns.value.forEach((item, index) => {
|
||||||
|
item.checked = true;
|
||||||
|
});
|
||||||
|
showColumns.value = cloneDeep(cloneColumns.value);
|
||||||
|
},
|
||||||
|
{ deep: true, immediate: true }
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
export default {
|
||||||
|
name: 'SearchTable',
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="less">
|
||||||
|
.container {
|
||||||
|
padding: 0 20px 20px 20px;
|
||||||
|
}
|
||||||
|
:deep(.arco-table-th) {
|
||||||
|
&:last-child {
|
||||||
|
.arco-table-th-item-title {
|
||||||
|
margin-left: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.action-icon {
|
||||||
|
margin-left: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.active {
|
||||||
|
color: #0960bd;
|
||||||
|
background-color: #e3f4fc;
|
||||||
|
}
|
||||||
|
.setting {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
width: 200px;
|
||||||
|
.title {
|
||||||
|
margin-left: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@@ -0,0 +1,44 @@
|
|||||||
|
export default {
|
||||||
|
'menu.list.searchTable': 'Search Table',
|
||||||
|
'searchTable.form.number': 'Set Number',
|
||||||
|
'searchTable.form.number.placeholder': 'Please enter Set Number',
|
||||||
|
'searchTable.form.name': 'Set Name',
|
||||||
|
'searchTable.form.name.placeholder': 'Please enter Set Name',
|
||||||
|
'searchTable.form.contentType': 'Content Type',
|
||||||
|
'searchTable.form.contentType.img': 'image-text',
|
||||||
|
'searchTable.form.contentType.horizontalVideo': 'Horizontal short video',
|
||||||
|
'searchTable.form.contentType.verticalVideo': 'Vertical short video',
|
||||||
|
'searchTable.form.filterType': 'Filter Type',
|
||||||
|
'searchTable.form.filterType.artificial': 'artificial',
|
||||||
|
'searchTable.form.filterType.rules': 'Rules',
|
||||||
|
'searchTable.form.createdTime': 'Create Date',
|
||||||
|
'searchTable.form.status': 'Status',
|
||||||
|
'searchTable.form.status.online': 'Online',
|
||||||
|
'searchTable.form.status.offline': 'Offline',
|
||||||
|
'searchTable.form.search': 'Search',
|
||||||
|
'searchTable.form.reset': 'Reset',
|
||||||
|
'searchTable.form.selectDefault': 'All',
|
||||||
|
'searchTable.operation.create': 'Create',
|
||||||
|
'searchTable.operation.import': 'Import',
|
||||||
|
'searchTable.operation.download': 'Download',
|
||||||
|
// columns
|
||||||
|
'searchTable.columns.index': '#',
|
||||||
|
'searchTable.columns.number': 'Set Number',
|
||||||
|
'searchTable.columns.name': 'Set Name',
|
||||||
|
'searchTable.columns.contentType': 'Content Type',
|
||||||
|
'searchTable.columns.filterType': 'Filter Type',
|
||||||
|
'searchTable.columns.count': 'Count',
|
||||||
|
'searchTable.columns.createdTime': 'CreatedTime',
|
||||||
|
'searchTable.columns.status': 'Status',
|
||||||
|
'searchTable.columns.operations': 'Operations',
|
||||||
|
'searchTable.columns.operations.view': 'View',
|
||||||
|
// size
|
||||||
|
'searchTable.size.mini': 'mini',
|
||||||
|
'searchTable.size.small': 'small',
|
||||||
|
'searchTable.size.medium': 'middle',
|
||||||
|
'searchTable.size.large': 'large',
|
||||||
|
// actions
|
||||||
|
'searchTable.actions.refresh': 'refresh',
|
||||||
|
'searchTable.actions.density': 'density',
|
||||||
|
'searchTable.actions.columnSetting': 'columnSetting',
|
||||||
|
};
|
@@ -0,0 +1,45 @@
|
|||||||
|
export default {
|
||||||
|
'menu.list.searchTable': '查询表格',
|
||||||
|
'searchTable.form.number': '集合编号',
|
||||||
|
'searchTable.form.number.placeholder': '请输入集合编号',
|
||||||
|
'searchTable.form.name': '集合名称',
|
||||||
|
'searchTable.form.name.placeholder': '请输入集合名称',
|
||||||
|
'searchTable.form.contentType': '内容体裁',
|
||||||
|
'searchTable.form.contentType.img': '图文',
|
||||||
|
'searchTable.form.contentType.horizontalVideo': '横版短视频',
|
||||||
|
'searchTable.form.contentType.verticalVideo': '竖版小视频',
|
||||||
|
'searchTable.form.filterType': '筛选方式',
|
||||||
|
'searchTable.form.filterType.artificial': '人工筛选',
|
||||||
|
'searchTable.form.filterType.rules': '规则筛选',
|
||||||
|
'searchTable.form.createdTime': '创建时间',
|
||||||
|
'searchTable.form.status': '状态',
|
||||||
|
'searchTable.form.status.online': '已上线',
|
||||||
|
'searchTable.form.status.offline': '已下线',
|
||||||
|
'searchTable.form.search': '查询',
|
||||||
|
'searchTable.form.reset': '重置',
|
||||||
|
'searchTable.form.selectDefault': '全部',
|
||||||
|
'searchTable.operation.create': '新建',
|
||||||
|
'searchTable.operation.import': '批量导入',
|
||||||
|
'searchTable.operation.download': '下载',
|
||||||
|
// columns
|
||||||
|
'searchTable.columns.index': '#',
|
||||||
|
'searchTable.columns.number': '集合编号',
|
||||||
|
'searchTable.columns.name': '集合名称',
|
||||||
|
'searchTable.columns.contentType': '内容体裁',
|
||||||
|
'searchTable.columns.filterType': '筛选方式',
|
||||||
|
'searchTable.columns.count': '内容量',
|
||||||
|
'searchTable.columns.createdTime': '创建时间',
|
||||||
|
'searchTable.columns.status': '状态',
|
||||||
|
'searchTable.columns.operations': '操作',
|
||||||
|
'searchTable.columns.operations.view': '查看',
|
||||||
|
|
||||||
|
// size
|
||||||
|
'searchTable.size.mini': '迷你',
|
||||||
|
'searchTable.size.small': '偏小',
|
||||||
|
'searchTable.size.medium': '中等',
|
||||||
|
'searchTable.size.large': '偏大',
|
||||||
|
// actions
|
||||||
|
'searchTable.actions.refresh': '刷新',
|
||||||
|
'searchTable.actions.density': '密度',
|
||||||
|
'searchTable.actions.columnSetting': '列设置',
|
||||||
|
};
|
@@ -36,16 +36,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||||
<version>${dubbo.version}</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- nacos注册中心
|
<!-- nacos注册中心 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.boot</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
|
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
|
||||||
<version>0.2.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
-->
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
@@ -80,6 +77,18 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.dubbo</groupId>
|
||||||
|
<artifactId>dubbo-bom</artifactId>
|
||||||
|
<version>${dubbo.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<!-- 打包时跳过测试 -->
|
<!-- 打包时跳过测试 -->
|
||||||
|
@@ -1,7 +1 @@
|
|||||||
server.port=8082
|
|
||||||
spring.application.name=story-service
|
|
||||||
|
|
||||||
dubbo.protocol.name=dubbo
|
|
||||||
dubbo.protocol.port=-1
|
|
||||||
dubbo.application.qos-enable=false
|
|
||||||
dubbo.registry.address=zookeeper://localhost:2181
|
dubbo.registry.address=zookeeper://localhost:2181
|
||||||
|
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
dubbo.registry.address=nacos://localhost:8848
|
@@ -1 +1,9 @@
|
|||||||
spring.profiles.active=dev
|
spring.profiles.active=test
|
||||||
|
|
||||||
|
server.port=8082
|
||||||
|
spring.application.name=story-service
|
||||||
|
|
||||||
|
dubbo.protocol.name=dubbo
|
||||||
|
dubbo.protocol.port=-1
|
||||||
|
dubbo.application.qos-enable=false
|
||||||
|
dubbo.registry.address=zookeeper://localhost:2181
|
||||||
|
@@ -64,10 +64,10 @@
|
|||||||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- nacos注册中心 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba.boot</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
|
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
|
||||||
<version>0.2.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -85,6 +85,12 @@
|
|||||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
@@ -103,6 +109,13 @@
|
|||||||
<artifactId>hibernate-validator</artifactId>
|
<artifactId>hibernate-validator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||||
|
<artifactId>jackson-dataformat-xml</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- test-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
@@ -153,14 +166,10 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.dubbo</groupId>
|
<groupId>org.apache.dubbo</groupId>
|
||||||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
<artifactId>dubbo-bom</artifactId>
|
||||||
<version>${dubbo.version}</version>
|
<version>${dubbo.version}</version>
|
||||||
</dependency>
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
<dependency>
|
|
||||||
<groupId>com.alibaba.boot</groupId>
|
|
||||||
<artifactId>nacos-discovery-spring-boot-starter</artifactId>
|
|
||||||
<version>0.2.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@@ -12,53 +12,5 @@ public class SopConstants {
|
|||||||
|
|
||||||
public static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
|
public static final Charset CHARSET_UTF8 = StandardCharsets.UTF_8;
|
||||||
public static final String UTF8 = "UTF-8";
|
public static final String UTF8 = "UTF-8";
|
||||||
public static final String FORMAT_JSON = "json";
|
|
||||||
public static final String DEFAULT_SIGN_METHOD = "md5";
|
|
||||||
public static final String EMPTY_JSON = "{}";
|
|
||||||
|
|
||||||
public static final String METADATA_SERVER_CONTEXT_PATH = "server.servlet.context-path";
|
|
||||||
|
|
||||||
public static final String METADATA_SERVER_CONTEXT_PATH_COMPATIBILITY = "context-path";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在拦截器中调用获取参数:
|
|
||||||
* String cachedBody = (String)exchange.getAttribute(SopConstants.CACHE_REQUEST_BODY_OBJECT_KEY);
|
|
||||||
*/
|
|
||||||
public static final String CACHE_REQUEST_BODY_OBJECT_KEY = "cachedRequestBodyObject";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在拦截器中调用获取参数:
|
|
||||||
* Map<String, String> params = exchange.getAttribute(SopConstants.CACHE_REQUEST_BODY_FOR_MAP);
|
|
||||||
*/
|
|
||||||
public static final String CACHE_REQUEST_BODY_FOR_MAP = "cacheRequestBodyForMap";
|
|
||||||
|
|
||||||
public static final String CACHE_API_PARAM = "cacheApiParam";
|
|
||||||
|
|
||||||
public static final String CACHE_UPLOAD_REQUEST = "cacheUploadRequest";
|
|
||||||
|
|
||||||
public static final String X_SERVICE_ERROR_CODE = "x-service-error-code";
|
|
||||||
|
|
||||||
public static final String X_SERVICE_ERROR_MESSAGE = "x-service-error-message";
|
|
||||||
|
|
||||||
public static final String X_SERVICE_ERROR_RESPONSE = "x-service-error-response";
|
|
||||||
|
|
||||||
public static final int BIZ_ERROR_STATUS = 4000;
|
|
||||||
public static final int UNKNOWN_ERROR_STATUS = 5050;
|
|
||||||
|
|
||||||
public static final String UNKNOWN_SERVICE= "_sop_unknown_service_";
|
|
||||||
public static final String UNKNOWN_METHOD = "_sop_unknown_method_";
|
|
||||||
public static final String UNKNOWN_VERSION = "_sop_unknown_version_";
|
|
||||||
|
|
||||||
public static final String METADATA_ENV_KEY = "env";
|
|
||||||
public static final String METADATA_ENV_PRE_VALUE = "pre";
|
|
||||||
public static final String METADATA_ENV_GRAY_VALUE = "gray";
|
|
||||||
|
|
||||||
public static final String CACHE_ROUTE_INTERCEPTOR_CONTEXT = "cacheRouteInterceptorContext";
|
|
||||||
public static final String TARGET_SERVICE = "sop-target-service";
|
|
||||||
public static final String RESTFUL_REQUEST = "sop-restful-request";
|
|
||||||
|
|
||||||
public static final String METADATA_KEY_TIME_STARTUP = "server.startup-time";
|
|
||||||
|
|
||||||
public static final String CACHE_ROUTE_INFO = "cacheRouteInfo";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,14 @@
|
|||||||
|
package com.gitee.sop.index.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定的扩展组件放这里
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CustomConfig {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,11 +1,18 @@
|
|||||||
package com.gitee.sop.index.config;
|
package com.gitee.sop.index.config;
|
||||||
|
|
||||||
import com.gitee.sop.index.message.ErrorFactory;
|
import com.gitee.sop.index.message.ErrorFactory;
|
||||||
|
import com.gitee.sop.index.service.ParamExecutor;
|
||||||
|
import com.gitee.sop.index.service.ParamExecutorImpl;
|
||||||
|
import com.gitee.sop.index.service.RouteService;
|
||||||
|
import com.gitee.sop.index.service.RouteServiceImpl;
|
||||||
import com.gitee.sop.index.service.interceptor.internal.ResultRouteInterceptor;
|
import com.gitee.sop.index.service.interceptor.internal.ResultRouteInterceptor;
|
||||||
import com.gitee.sop.index.service.manager.impl.LocalApiCacheManagerImpl;
|
import com.gitee.sop.index.service.manager.ApiManager;
|
||||||
|
import com.gitee.sop.index.service.manager.IsvManager;
|
||||||
|
import com.gitee.sop.index.service.manager.SecretManager;
|
||||||
|
import com.gitee.sop.index.service.manager.impl.LocalApiManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.LocalIsvManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.LocalIsvManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.LocalSecretManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.LocalSecretManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.RedisApiCacheManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.RedisApiManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.RedisIsvManagerImpl;
|
import com.gitee.sop.index.service.manager.impl.RedisIsvManagerImpl;
|
||||||
import com.gitee.sop.index.service.manager.impl.RedisSecretManager;
|
import com.gitee.sop.index.service.manager.impl.RedisSecretManager;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -24,38 +31,38 @@ import javax.annotation.PostConstruct;
|
|||||||
public class IndexConfig {
|
public class IndexConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "manager.api-cache", havingValue = "local", matchIfMissing = true)
|
@ConditionalOnProperty(value = "manager.api", havingValue = "local", matchIfMissing = true)
|
||||||
public LocalApiCacheManagerImpl localApiCacheManager() {
|
public ApiManager localApiManager() {
|
||||||
return new LocalApiCacheManagerImpl();
|
return new LocalApiManagerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "manager.api-cache", havingValue = "redis")
|
@ConditionalOnProperty(value = "manager.api", havingValue = "redis")
|
||||||
public RedisApiCacheManagerImpl redisApiCacheManager() {
|
public ApiManager redisApiManager() {
|
||||||
return new RedisApiCacheManagerImpl();
|
return new RedisApiManagerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "manager.isv", havingValue = "local", matchIfMissing = true)
|
@ConditionalOnProperty(value = "manager.isv", havingValue = "local", matchIfMissing = true)
|
||||||
public LocalIsvManagerImpl localIsvManager() {
|
public IsvManager localIsvManager() {
|
||||||
return new LocalIsvManagerImpl();
|
return new LocalIsvManagerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "manager.isv", havingValue = "redis")
|
@ConditionalOnProperty(value = "manager.isv", havingValue = "redis")
|
||||||
public RedisIsvManagerImpl redisIsvManager() {
|
public IsvManager redisIsvManager() {
|
||||||
return new RedisIsvManagerImpl();
|
return new RedisIsvManagerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "manager.secret", havingValue = "local", matchIfMissing = true)
|
@ConditionalOnProperty(value = "manager.secret", havingValue = "local", matchIfMissing = true)
|
||||||
public LocalSecretManagerImpl localSecretManager() {
|
public SecretManager localSecretManager() {
|
||||||
return new LocalSecretManagerImpl();
|
return new LocalSecretManagerImpl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnProperty(value = "manager.secret", havingValue = "redis")
|
@ConditionalOnProperty(value = "manager.secret", havingValue = "redis")
|
||||||
public RedisSecretManager redisSecretManager() {
|
public SecretManager redisSecretManager() {
|
||||||
return new RedisSecretManager();
|
return new RedisSecretManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +74,17 @@ public class IndexConfig {
|
|||||||
return new ResultRouteInterceptor();
|
return new ResultRouteInterceptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public ParamExecutor paramExecutor() {
|
||||||
|
return new ParamExecutorImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public RouteService routeService() {
|
||||||
|
return new RouteServiceImpl();
|
||||||
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
package com.gitee.sop.index.controller;
|
package com.gitee.sop.index.controller;
|
||||||
|
|
||||||
import com.gitee.sop.index.response.ApiResponse;
|
|
||||||
import com.gitee.sop.index.request.ApiRequestContext;
|
import com.gitee.sop.index.request.ApiRequestContext;
|
||||||
import com.gitee.sop.index.request.ApiRequestContextFactory;
|
import com.gitee.sop.index.request.ApiRequestContextFactory;
|
||||||
|
import com.gitee.sop.index.response.ApiResponse;
|
||||||
|
import com.gitee.sop.index.service.ParamExecutor;
|
||||||
import com.gitee.sop.index.service.RouteService;
|
import com.gitee.sop.index.service.RouteService;
|
||||||
import com.gitee.sop.index.util.ResponseUtil;
|
|
||||||
import com.gitee.sop.support.request.FileData;
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
@@ -27,28 +26,39 @@ public class IndexController {
|
|||||||
@Resource
|
@Resource
|
||||||
private RouteService routeService;
|
private RouteService routeService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ParamExecutor<HttpServletRequest, HttpServletResponse> paramExecutor;
|
||||||
|
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public void home(HttpServletResponse response) throws IOException {
|
public void home(HttpServletResponse response) throws IOException {
|
||||||
response.getWriter().write("Open Platform");
|
response.getWriter().write("Open Platform");
|
||||||
|
// 跳转到网站首页
|
||||||
|
// response.sendRedirect("https://www.baidu.com");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求入口
|
* 请求入口
|
||||||
*
|
*
|
||||||
* @return 返回响应内容
|
* @apiNote 参数描述
|
||||||
|
<pre>
|
||||||
|
参数 类型 是否必填 最大长度 描述 示例值
|
||||||
|
app_id String 是 32 支付宝分配给开发者的应用ID 2014072300007148
|
||||||
|
method String 是 128 接口名称 alipay.trade.fastpay.refund.query
|
||||||
|
format String 否 40 仅支持JSON JSON
|
||||||
|
charset String 是 10 请求使用的编码格式,如utf-8,gbk,gb2312等 utf-8
|
||||||
|
sign_type String 是 10 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 RSA2
|
||||||
|
sign String 是 344 商户请求参数的签名串,详见签名 详见示例
|
||||||
|
timestamp String 是 19 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" 2014-07-24 03:07:50
|
||||||
|
version String 是 3 调用的接口版本,固定为:1.0 1.0
|
||||||
|
app_auth_token String 否 40 详见应用授权概述
|
||||||
|
biz_content String 是 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档
|
||||||
|
</pre>
|
||||||
*/
|
*/
|
||||||
@RequestMapping(value = "api", method = {RequestMethod.GET, RequestMethod.POST})
|
@RequestMapping(value = "${index.path:/api}", method = {RequestMethod.GET, RequestMethod.POST})
|
||||||
public void index(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
public void index(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
ApiRequestContext apiRequestContext = ApiRequestContextFactory.build(request);
|
ApiRequestContext apiRequestContext = paramExecutor.build(request);
|
||||||
ApiResponse apiResponse = routeService.route(apiRequestContext);
|
ApiResponse apiResponse = routeService.route(apiRequestContext);
|
||||||
Object data = apiResponse.getData();
|
paramExecutor.write(apiRequestContext, apiResponse, response);
|
||||||
if (data instanceof FileData) {
|
|
||||||
FileData fileData = (FileData) data;
|
|
||||||
ResponseUtil.writerFile(fileData, response);
|
|
||||||
} else {
|
|
||||||
// 此处还可以判断charset,返回xml格式
|
|
||||||
ResponseUtil.writerJson(apiRequestContext, apiResponse, response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -8,4 +8,8 @@ import com.gitee.sop.index.dao.entity.IsvKeys;
|
|||||||
*/
|
*/
|
||||||
public interface IsvKeysMapper extends BaseMapper<IsvKeys> {
|
public interface IsvKeysMapper extends BaseMapper<IsvKeys> {
|
||||||
|
|
||||||
|
default IsvKeys getByAppId(String appId) {
|
||||||
|
return this.get(IsvKeys::getAppId, appId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,26 @@
|
|||||||
|
package com.gitee.sop.index.request;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum RequestFormatEnum {
|
||||||
|
NONE(""),
|
||||||
|
JSON("json"),
|
||||||
|
XML("xml"),
|
||||||
|
;
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public static RequestFormatEnum of(String value) {
|
||||||
|
for (RequestFormatEnum requestFormatEnum : RequestFormatEnum.values()) {
|
||||||
|
if (requestFormatEnum.value.equalsIgnoreCase(value)) {
|
||||||
|
return requestFormatEnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NONE;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,31 +0,0 @@
|
|||||||
package com.gitee.sop.index.service;
|
|
||||||
|
|
||||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
|
||||||
import com.gitee.sop.index.dao.entity.ApiInfo;
|
|
||||||
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
|
||||||
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
|
||||||
import com.gitee.sop.index.util.CopyUtil;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author 六如
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class ApiInfoService {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ApiCacheManager apiCacheManager;
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private ApiInfoMapper apiInfoMapper;
|
|
||||||
|
|
||||||
public ApiInfoDTO getApi(String apiName, String apiVersion) {
|
|
||||||
return apiCacheManager.getOrElse(apiName, apiVersion, () -> {
|
|
||||||
ApiInfo apiInfo = apiInfoMapper.getByNameVersion(apiName, apiVersion);
|
|
||||||
return CopyUtil.copyBean(apiInfo, ApiInfoDTO::new);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -0,0 +1,33 @@
|
|||||||
|
package com.gitee.sop.index.service;
|
||||||
|
|
||||||
|
import com.gitee.sop.index.request.ApiRequestContext;
|
||||||
|
import com.gitee.sop.index.response.ApiResponse;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数处理
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public interface ParamExecutor<Req, Resp> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建请求参数上下文
|
||||||
|
*
|
||||||
|
* @param request request
|
||||||
|
* @return 返回请求参数上下文
|
||||||
|
*/
|
||||||
|
ApiRequestContext build(Req request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结果返回写入
|
||||||
|
*
|
||||||
|
* @param apiRequestContext 请求参数上下文
|
||||||
|
* @param apiResponse 最终返回结果
|
||||||
|
* @param response response
|
||||||
|
* @throws IOException IOException
|
||||||
|
*/
|
||||||
|
void write(ApiRequestContext apiRequestContext, ApiResponse apiResponse, Resp response) throws IOException;
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
package com.gitee.sop.index.service;
|
||||||
|
|
||||||
|
import com.gitee.sop.index.request.ApiRequestContext;
|
||||||
|
import com.gitee.sop.index.request.ApiRequestContextFactory;
|
||||||
|
import com.gitee.sop.index.response.ApiResponse;
|
||||||
|
import com.gitee.sop.index.util.ResponseUtil;
|
||||||
|
import com.gitee.sop.support.request.FileData;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求参数默认实现
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public class ParamExecutorImpl implements ParamExecutor<HttpServletRequest, HttpServletResponse> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiRequestContext build(HttpServletRequest request) {
|
||||||
|
return ApiRequestContextFactory.build(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(ApiRequestContext apiRequestContext, ApiResponse apiResponse, HttpServletResponse response) throws IOException {
|
||||||
|
Object data = apiResponse.getData();
|
||||||
|
if (data instanceof FileData) {
|
||||||
|
FileData fileData = (FileData) data;
|
||||||
|
ResponseUtil.writerFile(fileData, response);
|
||||||
|
} else {
|
||||||
|
// 此处还可以判断charset,返回xml格式
|
||||||
|
ResponseUtil.writerText(apiRequestContext, apiResponse, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -3,7 +3,6 @@ package com.gitee.sop.index.service;
|
|||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
import com.gitee.sop.index.common.ApiInfoDTO;
|
||||||
import com.gitee.sop.index.response.ApiResponse;
|
|
||||||
import com.gitee.sop.index.common.AttachmentNames;
|
import com.gitee.sop.index.common.AttachmentNames;
|
||||||
import com.gitee.sop.index.common.ParamInfoDTO;
|
import com.gitee.sop.index.common.ParamInfoDTO;
|
||||||
import com.gitee.sop.index.exception.ApiException;
|
import com.gitee.sop.index.exception.ApiException;
|
||||||
@@ -12,6 +11,7 @@ import com.gitee.sop.index.message.ErrorEnum;
|
|||||||
import com.gitee.sop.index.request.ApiRequest;
|
import com.gitee.sop.index.request.ApiRequest;
|
||||||
import com.gitee.sop.index.request.ApiRequestContext;
|
import com.gitee.sop.index.request.ApiRequestContext;
|
||||||
import com.gitee.sop.index.request.UploadContext;
|
import com.gitee.sop.index.request.UploadContext;
|
||||||
|
import com.gitee.sop.index.response.ApiResponse;
|
||||||
import com.gitee.sop.index.service.interceptor.RouteInterceptor;
|
import com.gitee.sop.index.service.interceptor.RouteInterceptor;
|
||||||
import com.gitee.sop.index.service.validate.Validator;
|
import com.gitee.sop.index.service.validate.Validator;
|
||||||
import com.gitee.sop.index.util.ClassUtil;
|
import com.gitee.sop.index.util.ClassUtil;
|
||||||
@@ -22,7 +22,6 @@ import org.apache.dubbo.common.utils.ClassUtils;
|
|||||||
import org.apache.dubbo.rpc.RpcContext;
|
import org.apache.dubbo.rpc.RpcContext;
|
||||||
import org.apache.dubbo.rpc.RpcContextAttachment;
|
import org.apache.dubbo.rpc.RpcContextAttachment;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@@ -34,7 +33,6 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -44,7 +42,6 @@ import java.util.Optional;
|
|||||||
*
|
*
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
@Service
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class RouteServiceImpl implements RouteService {
|
public class RouteServiceImpl implements RouteService {
|
||||||
|
|
||||||
@@ -204,7 +201,7 @@ public class RouteServiceImpl implements RouteService {
|
|||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() {
|
||||||
if (routeInterceptors == null) {
|
if (routeInterceptors == null) {
|
||||||
routeInterceptors = Collections.emptyList();
|
routeInterceptors = new ArrayList<>();
|
||||||
}
|
}
|
||||||
routeInterceptors.sort(Comparator.comparing(RouteInterceptor::getOrder));
|
routeInterceptors.sort(Comparator.comparing(RouteInterceptor::getOrder));
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ import com.gitee.sop.index.common.ApiInfoDTO;
|
|||||||
import com.gitee.sop.index.common.StatusEnum;
|
import com.gitee.sop.index.common.StatusEnum;
|
||||||
import com.gitee.sop.index.dao.entity.ApiInfo;
|
import com.gitee.sop.index.dao.entity.ApiInfo;
|
||||||
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
||||||
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
import com.gitee.sop.index.service.manager.ApiManager;
|
||||||
import com.gitee.sop.index.util.CopyUtil;
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
import com.gitee.sop.support.service.ApiRegisterService;
|
import com.gitee.sop.support.service.ApiRegisterService;
|
||||||
import com.gitee.sop.support.service.dto.RegisterDTO;
|
import com.gitee.sop.support.service.dto.RegisterDTO;
|
||||||
@@ -21,7 +21,7 @@ import javax.annotation.Resource;
|
|||||||
public class ApiRegisterServiceImpl implements ApiRegisterService {
|
public class ApiRegisterServiceImpl implements ApiRegisterService {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiCacheManager apiCacheManager;
|
private ApiManager apiCacheManager;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiInfoMapper apiInfoMapper;
|
private ApiInfoMapper apiInfoMapper;
|
||||||
|
@@ -5,6 +5,6 @@ package com.gitee.sop.index.service.interceptor;
|
|||||||
*/
|
*/
|
||||||
public class RouteInterceptorOrders {
|
public class RouteInterceptorOrders {
|
||||||
|
|
||||||
public static final int DOWNLOAD = -10;
|
public static final int RESULT_INTERCEPTOR = -1000;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package com.gitee.sop.index.service.interceptor.internal;
|
|||||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
import com.gitee.sop.index.common.ApiInfoDTO;
|
||||||
import com.gitee.sop.index.request.ApiRequestContext;
|
import com.gitee.sop.index.request.ApiRequestContext;
|
||||||
import com.gitee.sop.index.service.interceptor.RouteInterceptor;
|
import com.gitee.sop.index.service.interceptor.RouteInterceptor;
|
||||||
|
import com.gitee.sop.index.service.interceptor.RouteInterceptorOrders;
|
||||||
import com.gitee.sop.support.request.CommonFileData;
|
import com.gitee.sop.support.request.CommonFileData;
|
||||||
import com.gitee.sop.support.request.FileData;
|
import com.gitee.sop.support.request.FileData;
|
||||||
|
|
||||||
@@ -19,6 +20,10 @@ import java.util.Objects;
|
|||||||
public class ResultRouteInterceptor implements RouteInterceptor {
|
public class ResultRouteInterceptor implements RouteInterceptor {
|
||||||
|
|
||||||
private static final String CLASS = "class";
|
private static final String CLASS = "class";
|
||||||
|
private static final String KEY_NAME = "name";
|
||||||
|
private static final String KEY_ORIGINAL_FILENAME = "originalFilename";
|
||||||
|
private static final String KEY_CONTENT_TYPE = "contentType";
|
||||||
|
private static final String KEY_BYTES = "bytes";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object afterRoute(ApiRequestContext context, ApiInfoDTO apiInfoDTO, Object result) {
|
public Object afterRoute(ApiRequestContext context, ApiInfoDTO apiInfoDTO, Object result) {
|
||||||
@@ -44,10 +49,10 @@ public class ResultRouteInterceptor implements RouteInterceptor {
|
|||||||
"empty": false
|
"empty": false
|
||||||
*/
|
*/
|
||||||
CommonFileData commonFileData = new CommonFileData();
|
CommonFileData commonFileData = new CommonFileData();
|
||||||
commonFileData.setName(String.valueOf(map.get("name")));
|
commonFileData.setName(String.valueOf(map.get(KEY_NAME)));
|
||||||
commonFileData.setOriginalFilename(String.valueOf(map.get("originalFilename")));
|
commonFileData.setOriginalFilename(String.valueOf(map.get(KEY_ORIGINAL_FILENAME)));
|
||||||
commonFileData.setContentType(String.valueOf(map.get("contentType")));
|
commonFileData.setContentType(String.valueOf(map.get(KEY_CONTENT_TYPE)));
|
||||||
commonFileData.setData((byte[]) map.get("bytes"));
|
commonFileData.setData((byte[]) map.get(KEY_BYTES));
|
||||||
return commonFileData;
|
return commonFileData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,6 +66,6 @@ public class ResultRouteInterceptor implements RouteInterceptor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
return RouteInterceptor.super.getOrder();
|
return RouteInterceptorOrders.RESULT_INTERCEPTOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ import java.util.function.Supplier;
|
|||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public interface ApiCacheManager {
|
public interface ApiManager {
|
||||||
|
|
||||||
void save(ApiInfoDTO apiInfoDTO);
|
void save(ApiInfoDTO apiInfoDTO);
|
||||||
|
|
@@ -7,7 +7,18 @@ import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
|||||||
*/
|
*/
|
||||||
public interface IsvManager {
|
public interface IsvManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取isv信息
|
||||||
|
*
|
||||||
|
* @param appId appId
|
||||||
|
* @return 返回isv信息, 没有返回null
|
||||||
|
*/
|
||||||
IsvDTO getIsv(String appId);
|
IsvDTO getIsv(String appId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新加载isv信息到内存中
|
||||||
|
*
|
||||||
|
* @param appId appId
|
||||||
|
*/
|
||||||
void reload(String appId);
|
void reload(String appId);
|
||||||
}
|
}
|
||||||
|
@@ -15,5 +15,5 @@ public interface SecretManager {
|
|||||||
*/
|
*/
|
||||||
String getIsvPublicKey(String appId);
|
String getIsvPublicKey(String appId);
|
||||||
|
|
||||||
|
String reload(String appId);
|
||||||
}
|
}
|
||||||
|
@@ -1,27 +0,0 @@
|
|||||||
package com.gitee.sop.index.service.manager.impl;
|
|
||||||
|
|
||||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
|
||||||
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 本地存储接口信息.
|
|
||||||
* @author 六如
|
|
||||||
*/
|
|
||||||
public class LocalApiCacheManagerImpl implements ApiCacheManager {
|
|
||||||
|
|
||||||
private static final Map<String, ApiInfoDTO> CACHE = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(ApiInfoDTO apiInfoDTO) {
|
|
||||||
String key = apiInfoDTO.buildApiNameVersion();
|
|
||||||
CACHE.put(key, apiInfoDTO);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiInfoDTO get(String apiName, String apiVersion) {
|
|
||||||
return CACHE.get(apiName + apiVersion);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,39 @@
|
|||||||
|
package com.gitee.sop.index.service.manager.impl;
|
||||||
|
|
||||||
|
import com.gitee.sop.index.common.ApiInfoDTO;
|
||||||
|
import com.gitee.sop.index.dao.entity.ApiInfo;
|
||||||
|
import com.gitee.sop.index.dao.mapper.ApiInfoMapper;
|
||||||
|
import com.gitee.sop.index.service.manager.ApiManager;
|
||||||
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地存储接口信息.
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public class LocalApiManagerImpl implements ApiManager {
|
||||||
|
|
||||||
|
private static final Map<String, Optional<ApiInfoDTO>> CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
protected ApiInfoMapper apiInfoMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(ApiInfoDTO apiInfoDTO) {
|
||||||
|
String key = apiInfoDTO.buildApiNameVersion();
|
||||||
|
CACHE.put(key, Optional.of(apiInfoDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiInfoDTO get(String apiName, String apiVersion) {
|
||||||
|
String key = apiName + apiVersion;
|
||||||
|
return CACHE.computeIfAbsent(key, k-> {
|
||||||
|
ApiInfo apiInfo = apiInfoMapper.getByNameVersion(apiName, apiVersion);
|
||||||
|
return Optional.ofNullable(CopyUtil.copyBean(apiInfo, ApiInfoDTO::new));
|
||||||
|
}).orElse(null);
|
||||||
|
}
|
||||||
|
}
|
@@ -7,23 +7,34 @@ import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
|||||||
import com.gitee.sop.index.util.CopyUtil;
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public class LocalIsvManagerImpl implements IsvManager {
|
public class LocalIsvManagerImpl implements IsvManager {
|
||||||
|
|
||||||
|
private static final Map<String, Optional<IsvDTO>> CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IsvInfoMapper isvInfoMapper;
|
protected IsvInfoMapper isvInfoMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IsvDTO getIsv(String appId) {
|
public IsvDTO getIsv(String appId) {
|
||||||
|
return CACHE.computeIfAbsent(appId, k -> {
|
||||||
IsvInfo isvInfo = isvInfoMapper.getByAppId(appId);
|
IsvInfo isvInfo = isvInfoMapper.getByAppId(appId);
|
||||||
return CopyUtil.copyBean(isvInfo, IsvDTO::new);
|
return Optional.ofNullable(CopyUtil.copyBean(isvInfo, IsvDTO::new));
|
||||||
|
}).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload(String appId) {
|
public void reload(String appId) {
|
||||||
|
IsvInfo isvInfo = isvInfoMapper.getByAppId(appId);
|
||||||
|
IsvDTO isvDTO = CopyUtil.copyBean(isvInfo, IsvDTO::new);
|
||||||
|
CACHE.put(appId, Optional.ofNullable(isvDTO));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,19 +5,37 @@ import com.gitee.sop.index.dao.mapper.IsvKeysMapper;
|
|||||||
import com.gitee.sop.index.service.manager.SecretManager;
|
import com.gitee.sop.index.service.manager.SecretManager;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public class LocalSecretManagerImpl implements SecretManager {
|
public class LocalSecretManagerImpl implements SecretManager {
|
||||||
|
|
||||||
|
private static final Map<String, Optional<String>> CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IsvKeysMapper isvKeysMapper;
|
protected IsvKeysMapper isvKeysMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIsvPublicKey(String appId) {
|
public String getIsvPublicKey(String appId) {
|
||||||
return isvKeysMapper.query()
|
return CACHE.computeIfAbsent(appId, k -> {
|
||||||
|
String publicKey = isvKeysMapper.query()
|
||||||
.eq(IsvKeys::getAppId, appId)
|
.eq(IsvKeys::getAppId, appId)
|
||||||
.getValue(IsvKeys::getPublicKeyIsv);
|
.getValue(IsvKeys::getPublicKeyIsv);
|
||||||
|
return Optional.ofNullable(publicKey);
|
||||||
|
})
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String reload(String appId) {
|
||||||
|
String publicKey = isvKeysMapper.query()
|
||||||
|
.eq(IsvKeys::getAppId, appId)
|
||||||
|
.getValue(IsvKeys::getPublicKeyIsv);
|
||||||
|
CACHE.put(appId, Optional.ofNullable(publicKey));
|
||||||
|
return publicKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,24 +0,0 @@
|
|||||||
package com.gitee.sop.index.service.manager.impl;
|
|
||||||
|
|
||||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
|
||||||
import com.gitee.sop.index.service.manager.ApiCacheManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* redis存储接口信息
|
|
||||||
*
|
|
||||||
* @author 六如
|
|
||||||
*/
|
|
||||||
public class RedisApiCacheManagerImpl implements ApiCacheManager {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void save(ApiInfoDTO apiInfoDTO) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ApiInfoDTO get(String apiName, String apiVersion) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,62 @@
|
|||||||
|
package com.gitee.sop.index.service.manager.impl;
|
||||||
|
|
||||||
|
import com.gitee.sop.index.common.ApiInfoDTO;
|
||||||
|
import com.gitee.sop.index.dao.entity.ApiInfo;
|
||||||
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
|
import com.gitee.sop.index.util.JsonUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis存储接口信息
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class RedisApiManagerImpl extends LocalApiManagerImpl {
|
||||||
|
|
||||||
|
private static final String KEY_API = "sop:api";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void save(ApiInfoDTO apiInfoDTO) {
|
||||||
|
String key = apiInfoDTO.buildApiNameVersion();
|
||||||
|
stringRedisTemplate.opsForHash().put(KEY_API, key, JsonUtil.toJSONString(apiInfoDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void cache(String key, ApiInfo apiInfo) {
|
||||||
|
ApiInfoDTO apiInfoDTO = CopyUtil.copyBean(apiInfo, ApiInfoDTO::new);
|
||||||
|
stringRedisTemplate.opsForHash().put(KEY_API, key, JsonUtil.toJSONString(apiInfoDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApiInfoDTO get(String apiName, String apiVersion) {
|
||||||
|
String key = apiName + apiName;
|
||||||
|
try {
|
||||||
|
Object value = stringRedisTemplate.opsForHash().get(KEY_API, key);
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JsonUtil.parseObject(String.valueOf(value), ApiInfoDTO.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("redis访问失败", e);
|
||||||
|
return super.get(apiName, apiVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
log.info("load apiInfo to redis");
|
||||||
|
List<ApiInfo> apiInfos = this.apiInfoMapper.listAll();
|
||||||
|
for (ApiInfo apiInfo : apiInfos) {
|
||||||
|
String key = apiInfo.getApiName() + apiInfo.getApiVersion();
|
||||||
|
this.cache(key, apiInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,20 +1,61 @@
|
|||||||
package com.gitee.sop.index.service.manager.impl;
|
package com.gitee.sop.index.service.manager.impl;
|
||||||
|
|
||||||
import com.gitee.sop.index.service.manager.IsvManager;
|
import com.gitee.sop.index.dao.entity.IsvInfo;
|
||||||
import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
import com.gitee.sop.index.service.manager.dto.IsvDTO;
|
||||||
|
import com.gitee.sop.index.util.CopyUtil;
|
||||||
|
import com.gitee.sop.index.util.JsonUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public class RedisIsvManagerImpl implements IsvManager {
|
@Slf4j
|
||||||
|
public class RedisIsvManagerImpl extends LocalIsvManagerImpl {
|
||||||
|
|
||||||
|
private static final String KEY_ISV = "sop:isv";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IsvDTO getIsv(String appId) {
|
public IsvDTO getIsv(String appId) {
|
||||||
return null;
|
try {
|
||||||
|
Object value = stringRedisTemplate.opsForHash().get(KEY_ISV, appId);
|
||||||
|
if (value == null) {
|
||||||
|
IsvInfo isvInfo = this.isvInfoMapper.getByAppId(appId);
|
||||||
|
return this.cache(isvInfo);
|
||||||
|
}
|
||||||
|
return JsonUtil.parseObject(String.valueOf(value), IsvDTO.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("操作redis失败", e);
|
||||||
|
return super.getIsv(appId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload(String appId) {
|
public void reload(String appId) {
|
||||||
|
IsvInfo isvInfo = isvInfoMapper.getByAppId(appId);
|
||||||
|
this.cache(isvInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
log.info("load isvInfo to redis");
|
||||||
|
List<IsvInfo> isvInfos = this.isvInfoMapper.listAll();
|
||||||
|
for (IsvInfo isvInfo : isvInfos) {
|
||||||
|
this.cache(isvInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IsvDTO cache(IsvInfo isvInfo) {
|
||||||
|
IsvDTO isvDTO = CopyUtil.copyBean(isvInfo, IsvDTO::new);
|
||||||
|
stringRedisTemplate.opsForHash().put(KEY_ISV, isvInfo.getAppId(), JsonUtil.toJSONString(isvDTO));
|
||||||
|
return isvDTO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,59 @@
|
|||||||
package com.gitee.sop.index.service.manager.impl;
|
package com.gitee.sop.index.service.manager.impl;
|
||||||
|
|
||||||
import com.gitee.sop.index.service.manager.SecretManager;
|
import com.gitee.sop.index.dao.entity.IsvKeys;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public class RedisSecretManager implements SecretManager {
|
@Slf4j
|
||||||
|
public class RedisSecretManager extends LocalSecretManagerImpl {
|
||||||
|
|
||||||
|
private static final String KEY_ISV = "sop:sec";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getIsvPublicKey(String appId) {
|
public String getIsvPublicKey(String appId) {
|
||||||
return "";
|
try {
|
||||||
|
Object value = stringRedisTemplate.opsForHash().get(KEY_ISV, appId);
|
||||||
|
if (value == null) {
|
||||||
|
return this.reload(appId);
|
||||||
}
|
}
|
||||||
|
return String.valueOf(value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("操作redis失败", e);
|
||||||
|
return super.getIsvPublicKey(appId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String reload(String appId) {
|
||||||
|
IsvKeys isvKeys = this.isvKeysMapper.getByAppId(appId);
|
||||||
|
return this.cache(appId, isvKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String cache(String appId, IsvKeys isvKeys) {
|
||||||
|
String publicKey = Optional.ofNullable(isvKeys).map(IsvKeys::getPublicKeyIsv).orElse("");
|
||||||
|
stringRedisTemplate.opsForHash().put(KEY_ISV, appId, publicKey);
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
log.info("load isvKey to redis");
|
||||||
|
List<IsvKeys> isvKeys = this.isvKeysMapper.listAll();
|
||||||
|
for (IsvKeys isvKey : isvKeys) {
|
||||||
|
this.cache(isvKey.getAppId(), isvKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,15 +1,16 @@
|
|||||||
package com.gitee.sop.index.service.validate;
|
package com.gitee.sop.index.service.validate;
|
||||||
|
|
||||||
import com.gitee.sop.index.common.ApiInfoDTO;
|
import com.gitee.sop.index.common.ApiInfoDTO;
|
||||||
import com.gitee.sop.index.request.ApiRequest;
|
|
||||||
import com.gitee.sop.index.request.ApiRequestContext;
|
|
||||||
import com.gitee.sop.index.common.ParamNames;
|
import com.gitee.sop.index.common.ParamNames;
|
||||||
import com.gitee.sop.index.common.StatusEnum;
|
import com.gitee.sop.index.common.StatusEnum;
|
||||||
import com.gitee.sop.index.config.ApiConfig;
|
import com.gitee.sop.index.config.ApiConfig;
|
||||||
import com.gitee.sop.index.exception.ApiException;
|
import com.gitee.sop.index.exception.ApiException;
|
||||||
import com.gitee.sop.index.message.ErrorEnum;
|
import com.gitee.sop.index.message.ErrorEnum;
|
||||||
|
import com.gitee.sop.index.request.ApiRequest;
|
||||||
|
import com.gitee.sop.index.request.ApiRequestContext;
|
||||||
|
import com.gitee.sop.index.request.RequestFormatEnum;
|
||||||
import com.gitee.sop.index.request.UploadContext;
|
import com.gitee.sop.index.request.UploadContext;
|
||||||
import com.gitee.sop.index.service.ApiInfoService;
|
import com.gitee.sop.index.service.manager.ApiManager;
|
||||||
import com.gitee.sop.index.service.manager.IpBlacklistManager;
|
import com.gitee.sop.index.service.manager.IpBlacklistManager;
|
||||||
import com.gitee.sop.index.service.manager.IsvApiPermissionManager;
|
import com.gitee.sop.index.service.manager.IsvApiPermissionManager;
|
||||||
import com.gitee.sop.index.service.manager.IsvManager;
|
import com.gitee.sop.index.service.manager.IsvManager;
|
||||||
@@ -27,7 +28,6 @@ import org.springframework.web.multipart.MultipartFile;
|
|||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -41,9 +41,7 @@ import java.util.Locale;
|
|||||||
@Service
|
@Service
|
||||||
public class ApiValidator implements Validator {
|
public class ApiValidator implements Validator {
|
||||||
|
|
||||||
private static final int MILLISECOND_OF_ONE_SECOND = 1000;
|
private static final long MILLISECOND_OF_ONE_SECOND = 1000;
|
||||||
|
|
||||||
private static final List<String> FORMAT_LIST = Arrays.asList("json", "xml");
|
|
||||||
|
|
||||||
private final Signer signer = new AlipaySigner();
|
private final Signer signer = new AlipaySigner();
|
||||||
|
|
||||||
@@ -63,7 +61,7 @@ public class ApiValidator implements Validator {
|
|||||||
private ApiConfig apiConfig;
|
private ApiConfig apiConfig;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApiInfoService apiInfoService;
|
private ApiManager apiCacheManager;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private IpBlacklistManager ipBlacklistManager;
|
private IpBlacklistManager ipBlacklistManager;
|
||||||
@@ -94,7 +92,7 @@ public class ApiValidator implements Validator {
|
|||||||
checkIP(apiRequestContext);
|
checkIP(apiRequestContext);
|
||||||
|
|
||||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||||
ApiInfoDTO apiInfo = apiInfoService.getApi(apiRequest.getMethod(), apiRequest.getVersion());
|
ApiInfoDTO apiInfo = apiCacheManager.get(apiRequest.getMethod(), apiRequest.getVersion());
|
||||||
// 检查接口信息
|
// 检查接口信息
|
||||||
checkApiInfo(apiRequestContext, apiInfo);
|
checkApiInfo(apiRequestContext, apiInfo);
|
||||||
|
|
||||||
@@ -271,8 +269,10 @@ public class ApiValidator implements Validator {
|
|||||||
protected void checkFormat(ApiRequestContext apiRequestContext) {
|
protected void checkFormat(ApiRequestContext apiRequestContext) {
|
||||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||||
String format = apiRequest.getFormat();
|
String format = apiRequest.getFormat();
|
||||||
boolean contains = FORMAT_LIST.contains(format.toLowerCase());
|
if (ObjectUtils.isEmpty(format)) {
|
||||||
if (!contains) {
|
return;
|
||||||
|
}
|
||||||
|
if (RequestFormatEnum.of(format) == RequestFormatEnum.NONE) {
|
||||||
throw new ApiException(ErrorEnum.ISV_INVALID_FORMAT, apiRequestContext.getLocale(),
|
throw new ApiException(ErrorEnum.ISV_INVALID_FORMAT, apiRequestContext.getLocale(),
|
||||||
apiRequest.takeNameVersion(), format);
|
apiRequest.takeNameVersion(), format);
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,29 @@
|
|||||||
|
package com.gitee.sop.index.util;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* json工具类,默认用fastjson2实现
|
||||||
|
*
|
||||||
|
* @author 六如
|
||||||
|
*/
|
||||||
|
public class JsonUtil {
|
||||||
|
|
||||||
|
public static String toJSONString(Object object) {
|
||||||
|
if (object == null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
return JSON.toJSONString(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> T parseObject(String value, Class<T> clazz) {
|
||||||
|
if (Objects.equals(value, "null") || ObjectUtils.isEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return JSON.parseObject(value, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,8 +1,10 @@
|
|||||||
package com.gitee.sop.index.util;
|
package com.gitee.sop.index.util;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
|
||||||
import com.gitee.sop.index.request.ApiRequest;
|
import com.gitee.sop.index.request.ApiRequest;
|
||||||
import com.gitee.sop.index.request.ApiRequestContext;
|
import com.gitee.sop.index.request.ApiRequestContext;
|
||||||
|
import com.gitee.sop.index.request.RequestFormatEnum;
|
||||||
import com.gitee.sop.index.response.ApiResponse;
|
import com.gitee.sop.index.response.ApiResponse;
|
||||||
import com.gitee.sop.support.request.FileData;
|
import com.gitee.sop.support.request.FileData;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
@@ -16,7 +18,7 @@ import java.io.InputStream;
|
|||||||
* @author 六如
|
* @author 六如
|
||||||
*/
|
*/
|
||||||
public class ResponseUtil {
|
public class ResponseUtil {
|
||||||
|
private static final XmlMapper XML_MAPPER = new XmlMapper();
|
||||||
|
|
||||||
public static void writerFile(FileData fileData, HttpServletResponse response) throws IOException {
|
public static void writerFile(FileData fileData, HttpServletResponse response) throws IOException {
|
||||||
InputStream inputStream = fileData.getInputStream();
|
InputStream inputStream = fileData.getInputStream();
|
||||||
@@ -29,12 +31,20 @@ public class ResponseUtil {
|
|||||||
IOUtils.copy(inputStream, response.getOutputStream());
|
IOUtils.copy(inputStream, response.getOutputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writerJson(ApiRequestContext apiRequestContext, ApiResponse apiResponse, HttpServletResponse response) throws IOException {
|
public static void writerText(ApiRequestContext apiRequestContext, ApiResponse apiResponse, HttpServletResponse response) throws IOException {
|
||||||
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
ApiRequest apiRequest = apiRequestContext.getApiRequest();
|
||||||
String charset = apiRequest.getCharset();
|
String charset = apiRequest.getCharset();
|
||||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
|
||||||
response.setCharacterEncoding(charset);
|
response.setCharacterEncoding(charset);
|
||||||
response.getWriter().write(JSON.toJSONString(apiResponse));
|
String format = apiRequest.getFormat();
|
||||||
|
if (RequestFormatEnum.of(format) == RequestFormatEnum.XML) {
|
||||||
|
response.setContentType(MediaType.APPLICATION_XML_VALUE);
|
||||||
|
String xml = XML_MAPPER.writeValueAsString(apiResponse);
|
||||||
|
response.getWriter().write(xml);
|
||||||
|
} else {
|
||||||
|
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||||
|
String json = JSON.toJSONString(apiResponse);
|
||||||
|
response.getWriter().write(json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
dubbo.registry.address=zookeeper://localhost:2181
|
dubbo.registry.address=zookeeper://localhost:2181
|
||||||
|
|
||||||
|
mybatis.print-sql=true
|
||||||
|
|
||||||
# mysql config
|
# mysql config
|
||||||
mysql.host=127.0.0.1:3306
|
mysql.host=127.0.0.1:3306
|
||||||
mysql.username=root
|
mysql.username=root
|
||||||
|
20
sop-index/src/main/resources/application-test.properties
Normal file
20
sop-index/src/main/resources/application-test.properties
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
dubbo.registry.address=nacos://localhost:8848
|
||||||
|
|
||||||
|
mybatis.print-sql=true
|
||||||
|
|
||||||
|
# api manager,local/redis
|
||||||
|
manager.api=redis
|
||||||
|
# isv manager,local/redis
|
||||||
|
manager.isv=redis
|
||||||
|
# secret manger,local/redis
|
||||||
|
manager.secret=redis
|
||||||
|
|
||||||
|
# mysql config
|
||||||
|
mysql.host=127.0.0.1:3306
|
||||||
|
mysql.username=root
|
||||||
|
mysql.password=root
|
||||||
|
|
||||||
|
# redis config
|
||||||
|
spring.redis.host=localhost
|
||||||
|
spring.redis.port=6379
|
||||||
|
spring.redis.database=0
|
@@ -1,7 +1,18 @@
|
|||||||
spring.profiles.active=dev
|
spring.profiles.active=test
|
||||||
spring.application.name=sop-index
|
spring.application.name=sop-index
|
||||||
server.port=8081
|
server.port=8081
|
||||||
|
|
||||||
|
####### index config #######
|
||||||
|
# request entry path
|
||||||
|
index.path=/api
|
||||||
|
# api manager,local/redis
|
||||||
|
manager.api=local
|
||||||
|
# isv manager,local/redis
|
||||||
|
manager.isv=local
|
||||||
|
# secret manger,local/redis
|
||||||
|
manager.secret=local
|
||||||
|
|
||||||
|
|
||||||
####### dubbo config #######
|
####### dubbo config #######
|
||||||
dubbo.protocol.name=dubbo
|
dubbo.protocol.name=dubbo
|
||||||
dubbo.protocol.port=-1
|
dubbo.protocol.port=-1
|
||||||
@@ -40,16 +51,19 @@ spring.datasource.url=jdbc:mysql://${mysql.host}/${mysql.db}?useUnicode=true&cha
|
|||||||
spring.datasource.username=${mysql.username}
|
spring.datasource.username=${mysql.username}
|
||||||
spring.datasource.password=${mysql.password}
|
spring.datasource.password=${mysql.password}
|
||||||
|
|
||||||
|
####### redis config #######
|
||||||
|
spring.redis.host=localhost
|
||||||
|
spring.redis.port=6379
|
||||||
|
spring.redis.database=0
|
||||||
|
|
||||||
####### mybatis config #######
|
####### mybatis config #######
|
||||||
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillInsert=add_time
|
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillInsert=add_time
|
||||||
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillUpdate=update_time
|
mybatis.fill.com.gitee.fastmybatis.core.support.LocalDateTimeFillUpdate=update_time
|
||||||
# mybatis config file
|
# mybatis config file
|
||||||
mybatis.config-location=classpath:mybatis/mybatisConfig.xml
|
mybatis.config-location=classpath:mybatis/mybatisConfig.xml
|
||||||
|
|
||||||
|
|
||||||
# print SQL
|
# print SQL
|
||||||
logging.level.com.gitee.sop.index.dao=error
|
logging.level.com.gitee.sop.index.dao=error
|
||||||
logging.level.com.gitee.fastmybatis=debug
|
logging.level.com.gitee.fastmybatis=info
|
||||||
mybatis.print-sql=true
|
mybatis.print-sql=false
|
||||||
|
|
||||||
# Need not register api
|
|
||||||
open.register.enable=false
|
|
||||||
|
@@ -68,6 +68,43 @@ public class AlipayClientPostTest extends TestBase {
|
|||||||
System.out.println(responseData);
|
System.out.println(responseData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 输出返回xml格式
|
||||||
|
@Test
|
||||||
|
public void testGetXml() throws Exception {
|
||||||
|
|
||||||
|
// 公共请求参数
|
||||||
|
Map<String, String> params = new HashMap<String, String>();
|
||||||
|
params.put("app_id", appId);
|
||||||
|
params.put("method", "story.get");
|
||||||
|
params.put("format", "xml"); // xml
|
||||||
|
params.put("charset", "utf-8");
|
||||||
|
params.put("sign_type", "RSA2");
|
||||||
|
params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
|
||||||
|
params.put("version", "1.0");
|
||||||
|
|
||||||
|
// 业务参数
|
||||||
|
Map<String, Object> bizContent = new HashMap<>();
|
||||||
|
bizContent.put("id", "1");
|
||||||
|
bizContent.put("name", "葫芦娃");
|
||||||
|
|
||||||
|
params.put("biz_content", JSON.toJSONString(bizContent));
|
||||||
|
String content = AlipaySignature.getSignContent(params);
|
||||||
|
String sign = AlipaySignature.rsa256Sign(content, privateKey, "utf-8");
|
||||||
|
params.put("sign", sign);
|
||||||
|
|
||||||
|
System.out.println("----------- 请求信息 -----------");
|
||||||
|
System.out.println("请求参数:" + buildParamQuery(params));
|
||||||
|
System.out.println("商户秘钥:" + privateKey);
|
||||||
|
System.out.println("待签名内容:" + content);
|
||||||
|
System.out.println("签名(sign):" + sign);
|
||||||
|
System.out.println("URL参数:" + buildUrlQuery(params));
|
||||||
|
|
||||||
|
System.out.println("----------- 返回结果 -----------");
|
||||||
|
String responseData = postJson(url, params);// 发送请求
|
||||||
|
// <ApiResponse><code>0</code><msg>success</msg><sub_code></sub_code><sub_msg></sub_msg><data><name>乌鸦喝水</name><id>1</id></data></ApiResponse>
|
||||||
|
System.out.println(responseData);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFind() throws Exception {
|
public void testFind() throws Exception {
|
||||||
|
|
||||||
|
@@ -1,12 +1,10 @@
|
|||||||
package com.gitee.sop.test;
|
package com.gitee.sop.test;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONArray;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -101,7 +99,7 @@ public class AllInOneTest extends TestBase {
|
|||||||
Assert.assertEquals("isv.route-no-permissions", jsonObject.getString("sub_code"));
|
Assert.assertEquals("isv.route-no-permissions", jsonObject.getString("sub_code"));
|
||||||
});
|
});
|
||||||
|
|
||||||
client.execute(requestBuilder);
|
//client.execute(requestBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user