- 后端:更新 README
- 后端:重构部分代码
This commit is contained in:
@@ -1,17 +1,20 @@
|
||||
package cn.iocoder.mall.pay.biz.component;
|
||||
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.ReferenceConfig;
|
||||
import org.apache.dubbo.config.RegistryConfig;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
import cn.iocoder.common.framework.util.StringUtil;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import lombok.Data;
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.config.ReferenceConfig;
|
||||
import org.apache.dubbo.config.RegistryConfig;
|
||||
import org.apache.dubbo.rpc.service.GenericService;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class DubboReferencePool {
|
||||
|
||||
@@ -44,7 +47,8 @@ public class DubboReferencePool {
|
||||
private String dubboApplicationName;
|
||||
|
||||
private ReferenceMeta createGenericService(String notifyUrl) {
|
||||
String[] notifyUrlParts = notifyUrl.split("#");
|
||||
// 使用 # 号分隔,格式为 服务名#方法名#版本号
|
||||
List<String> notifyUrlParts = StringUtil.split(notifyUrl, "#");
|
||||
// 创建 ApplicationConfig 对象
|
||||
ApplicationConfig application = new ApplicationConfig();
|
||||
application.setName(dubboApplicationName);
|
||||
@@ -55,14 +59,14 @@ public class DubboReferencePool {
|
||||
application.setRegistry(registry);
|
||||
// 创建 ReferenceConfig 对象
|
||||
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
|
||||
reference.setInterface(notifyUrlParts[0]); // 弱类型接口名
|
||||
reference.setInterface(notifyUrlParts.get(0)); // 弱类型接口名
|
||||
reference.setGeneric(true); // 声明为泛化接口
|
||||
reference.setApplication(application);
|
||||
// reference.setVersion("*"); // TODO 芋艿,后面要优化下。
|
||||
reference.setVersion(notifyUrlParts.size() > 2 ? notifyUrlParts.get(2) : "1.0.0"); // 如果未配置服务的版本号,则默认使用 1.0.0
|
||||
// 获得 GenericService 对象
|
||||
GenericService genericService = reference.get();
|
||||
// 构建最终的 ReferenceMeta 对象
|
||||
return new ReferenceMeta(reference, genericService, notifyUrlParts[1]);
|
||||
return new ReferenceMeta(reference, genericService, notifyUrlParts.get(1));
|
||||
}
|
||||
|
||||
public ReferenceMeta getReferenceMeta(String notifyUrl) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.pay.biz.convert;
|
||||
|
||||
import cn.iocoder.mall.pay.api.bo.PayRefundBO;
|
||||
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundBO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mappings;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package cn.iocoder.mall.pay.biz.convert;
|
||||
|
||||
import cn.iocoder.mall.pay.api.bo.PayTransactionBO;
|
||||
import cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionCreateDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionSubmitDTO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
|
||||
import org.mapstruct.Mapper;
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.Date;
|
||||
topic = PayRefundSuccessMessage.TOPIC,
|
||||
consumerGroup = "pay-consumer-group-" + PayRefundSuccessMessage.TOPIC
|
||||
)
|
||||
@Deprecated // 艿艿:突然发现,业务方实际无需回调。参考了 https://help.youzan.com/displaylist/detail_4_998 的文章。业务方,只要记录下退款单号,进行关联即可。
|
||||
public class PayRefundSuccessConsumer extends AbstractPayNotifySuccessConsumer<PayRefundSuccessMessage>
|
||||
implements RocketMQListener<PayRefundSuccessMessage> {
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package cn.iocoder.mall.pay.biz.service;
|
||||
|
||||
import cn.iocoder.common.framework.constant.CommonStatusEnum;
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
|
||||
import cn.iocoder.mall.pay.biz.dao.PayAppMapper;
|
||||
import cn.iocoder.mall.pay.biz.dataobject.PayAppDO;
|
||||
@@ -15,17 +14,17 @@ public class PayAppServiceImpl {
|
||||
@Autowired
|
||||
private PayAppMapper payAppMapper;
|
||||
|
||||
public CommonResult<PayAppDO> validPayApp(String appId) {
|
||||
public PayAppDO validPayApp(String appId) {
|
||||
PayAppDO payAppDO = payAppMapper.selectById(appId);
|
||||
// 校验是否存在
|
||||
if (payAppDO == null) {
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_APP_NOT_FOUND.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_APP_NOT_FOUND.getCode());
|
||||
}
|
||||
// 校验是否禁用
|
||||
if (CommonStatusEnum.DISABLE.getValue().equals(payAppDO.getStatus())) {
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_APP_IS_DISABLE.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_APP_IS_DISABLE.getCode());
|
||||
}
|
||||
return CommonResult.success(payAppDO);
|
||||
return payAppDO;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class PayNotifyServiceImpl {
|
||||
@Resource
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
@Deprecated // 参见 PayRefundSuccessConsumer 类的说明
|
||||
public void addRefundNotifyTask(PayRefundDO refund) {
|
||||
PayNotifyTaskDO payTransactionNotifyTask = this.createBasePayNotifyTaskDO(refund.getAppId(), refund.getNotifyUrl())
|
||||
.setType(PayNotifyType.REFUND.getValue());
|
||||
|
||||
@@ -5,13 +5,13 @@ import cn.iocoder.common.framework.util.MathUtil;
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.PayRefundService;
|
||||
import cn.iocoder.mall.pay.api.bo.PayRefundPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.PayRefundSubmitBO;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.refund.PayRefundSubmitBO;
|
||||
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
|
||||
import cn.iocoder.mall.pay.api.constant.PayRefundStatus;
|
||||
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum;
|
||||
import cn.iocoder.mall.pay.api.dto.PayRefundPageDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundPageDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
|
||||
import cn.iocoder.mall.pay.biz.client.AbstractPaySDK;
|
||||
import cn.iocoder.mall.pay.biz.client.PaySDKFactory;
|
||||
import cn.iocoder.mall.pay.biz.client.RefundSuccessBO;
|
||||
@@ -51,13 +51,9 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
private RocketMQTemplate rocketMQTemplate;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("Duplicates")
|
||||
public CommonResult<PayRefundSubmitBO> submitRefund(PayRefundSubmitDTO payRefundSubmitDTO) {
|
||||
// 校验 App 是否有效
|
||||
CommonResult<PayAppDO> appResult = payAppService.validPayApp(payRefundSubmitDTO.getAppId());
|
||||
if (appResult.isError()) {
|
||||
return CommonResult.error(appResult);
|
||||
}
|
||||
PayAppDO payAppDO = payAppService.validPayApp(payRefundSubmitDTO.getAppId());
|
||||
// 获得 PayTransactionDO ,并校验其是否存在
|
||||
PayTransactionDO payTransaction = payTransactionService.getTransaction(payRefundSubmitDTO.getAppId(), payRefundSubmitDTO.getOrderId());
|
||||
if (payTransaction == null) { // 是否存在
|
||||
@@ -82,7 +78,7 @@ public class PayRefundServiceImpl implements PayRefundService {
|
||||
.setTransactionId(payTransaction.getId())
|
||||
.setRefundCode(generateTransactionCode()) // TODO 芋艿,后续调整
|
||||
.setStatus(PayRefundStatus.WAITING.getValue())
|
||||
.setNotifyUrl(appResult.getData().getRefundNotifyUrl())
|
||||
.setNotifyUrl(payAppDO.getRefundNotifyUrl())
|
||||
.setRefundChannel(payTransaction.getPayChannel());
|
||||
payRefundDO.setCreateTime(new Date());
|
||||
payRefundMapper.insert(payRefundDO);
|
||||
|
||||
@@ -5,14 +5,15 @@ import cn.iocoder.common.framework.util.MathUtil;
|
||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
import cn.iocoder.mall.pay.api.PayTransactionService;
|
||||
import cn.iocoder.mall.pay.api.bo.PayTransactionBO;
|
||||
import cn.iocoder.mall.pay.api.bo.PayTransactionPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.PayTransactionSubmitBO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionPageBO;
|
||||
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionSubmitBO;
|
||||
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
|
||||
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum;
|
||||
import cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.PayTransactionPageDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionCreateDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionGetDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionPageDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionSubmitDTO;
|
||||
import cn.iocoder.mall.pay.biz.client.AbstractPaySDK;
|
||||
import cn.iocoder.mall.pay.biz.client.PaySDKFactory;
|
||||
import cn.iocoder.mall.pay.biz.client.TransactionSuccessBO;
|
||||
@@ -68,23 +69,21 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<PayTransactionBO> getTransaction(Integer userId, String appId, String orderId) {
|
||||
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(appId, orderId);
|
||||
public PayTransactionBO getTransaction(PayTransactionGetDTO payTransactionGetDTO) {
|
||||
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(payTransactionGetDTO.getAppId(),
|
||||
payTransactionGetDTO.getOrderId());
|
||||
if (payTransaction == null) {
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
}
|
||||
// TODO 芋艿 userId 的校验
|
||||
return CommonResult.success(PayTransactionConvert.INSTANCE.convert(payTransaction));
|
||||
return PayTransactionConvert.INSTANCE.convert(payTransaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("Duplicates")
|
||||
public CommonResult<PayTransactionBO> createTransaction(PayTransactionCreateDTO payTransactionCreateDTO) {
|
||||
public PayTransactionBO createTransaction(PayTransactionCreateDTO payTransactionCreateDTO) {
|
||||
// 校验 App
|
||||
CommonResult<PayAppDO> appResult = payAppService.validPayApp(payTransactionCreateDTO.getAppId());
|
||||
if (appResult.isError()) {
|
||||
return CommonResult.error(appResult);
|
||||
}
|
||||
PayAppDO payAppDO = payAppService.validPayApp(payTransactionCreateDTO.getAppId());
|
||||
// 插入 PayTransactionDO
|
||||
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
|
||||
payTransactionCreateDTO.getAppId(), payTransactionCreateDTO.getOrderId());
|
||||
@@ -95,31 +94,28 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
} else {
|
||||
payTransaction = PayTransactionConvert.INSTANCE.convert(payTransactionCreateDTO);
|
||||
payTransaction.setStatus(PayTransactionStatusEnum.WAITING.getValue())
|
||||
.setNotifyUrl(appResult.getData().getNotifyUrl());
|
||||
.setNotifyUrl(payAppDO.getNotifyUrl());
|
||||
payTransaction.setCreateTime(new Date());
|
||||
payTransactionMapper.insert(payTransaction);
|
||||
}
|
||||
// 返回成功
|
||||
return CommonResult.success(PayTransactionConvert.INSTANCE.convert(payTransaction));
|
||||
return PayTransactionConvert.INSTANCE.convert(payTransaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("Duplicates")
|
||||
public CommonResult<PayTransactionSubmitBO> submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO) {
|
||||
public PayTransactionSubmitBO submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO) {
|
||||
// TODO 校验支付渠道是否有效
|
||||
// 校验 App 是否有效
|
||||
CommonResult<PayAppDO> appResult = payAppService.validPayApp(payTransactionSubmitDTO.getAppId());
|
||||
if (appResult.isError()) {
|
||||
return CommonResult.error(appResult);
|
||||
}
|
||||
payAppService.validPayApp(payTransactionSubmitDTO.getAppId());
|
||||
// 获得 PayTransactionDO ,并校验其是否存在
|
||||
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
|
||||
payTransactionSubmitDTO.getAppId(), payTransactionSubmitDTO.getOrderId());
|
||||
if (payTransaction == null) { // 是否存在
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.WAITING.getValue().equals(payTransaction.getStatus())) { // 校验状态,必须是待支付
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
|
||||
}
|
||||
// 插入 PayTransactionExtensionDO
|
||||
PayTransactionExtensionDO payTransactionExtensionDO = PayTransactionConvert.INSTANCE.convert(payTransactionSubmitDTO)
|
||||
@@ -131,33 +127,32 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payTransactionSubmitDTO.getPayChannel());
|
||||
CommonResult<String> invokeResult = paySDK.submitTransaction(payTransaction, payTransactionExtensionDO, null); // TODO 暂时传入 extra = null
|
||||
if (invokeResult.isError()) {
|
||||
return CommonResult.error(invokeResult);
|
||||
throw ServiceExceptionUtil.exception(invokeResult.getCode(), invokeResult.getMessage());
|
||||
}
|
||||
// TODO 轮询三方接口,是否已经支付的任务
|
||||
// 返回成功
|
||||
PayTransactionSubmitBO payTransactionSubmitBO = new PayTransactionSubmitBO()
|
||||
.setId(payTransactionExtensionDO.getId()).setInvokeResponse(invokeResult.getData());
|
||||
return CommonResult.success(payTransactionSubmitBO);
|
||||
return new PayTransactionSubmitBO().setId(payTransactionExtensionDO.getId())
|
||||
.setInvokeResponse(invokeResult.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CommonResult<Boolean> updateTransactionPaySuccess(Integer payChannel, String params) {
|
||||
public Boolean updateTransactionPaySuccess(Integer payChannel, String params) {
|
||||
// TODO 芋艿,记录回调日志
|
||||
// 解析传入的参数,成 TransactionSuccessBO 对象
|
||||
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payChannel);
|
||||
CommonResult<TransactionSuccessBO> paySuccessResult = paySDK.parseTransactionSuccessParams(params);
|
||||
if (paySuccessResult.isError()) {
|
||||
return CommonResult.error(paySuccessResult);
|
||||
throw ServiceExceptionUtil.exception(paySuccessResult.getCode(), paySuccessResult.getMessage());
|
||||
}
|
||||
// TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。
|
||||
// 1.1 查询 PayTransactionExtensionDO
|
||||
PayTransactionExtensionDO extension = payTransactionExtensionMapper.selectByTransactionCode(paySuccessResult.getData().getTransactionCode());
|
||||
if (extension == null) {
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_NOT_FOUND.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.WAITING.getValue().equals(extension.getStatus())) { // 校验状态,必须是待支付
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING.getCode());
|
||||
}
|
||||
// 1.2 更新 PayTransactionExtensionDO
|
||||
PayTransactionExtensionDO updatePayTransactionExtension = new PayTransactionExtensionDO()
|
||||
@@ -172,7 +167,7 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
// 2.1 判断 PayTransactionDO 是否处于待支付
|
||||
PayTransactionDO transaction = payTransactionMapper.selectById(extension.getTransactionId());
|
||||
if (transaction == null) {
|
||||
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
|
||||
}
|
||||
if (!PayTransactionStatusEnum.WAITING.getValue().equals(transaction.getStatus())) { // 校验状态,必须是待支付
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
|
||||
@@ -191,10 +186,10 @@ public class PayTransactionServiceImpl implements PayTransactionService {
|
||||
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
|
||||
}
|
||||
logger.info("[updateTransactionPaySuccess][PayTransactionDO({}) 更新为已支付]", transaction.getId());
|
||||
// 3 新增 PayNotifyTaskDO
|
||||
payNotifyService.addTransactionNotifyTask(transaction, extension);
|
||||
// 3 新增 PayNotifyTaskDO 注释原因,参见 PayRefundSuccessConsumer 类。
|
||||
// payNotifyService.addTransactionNotifyTask(transaction, extension);
|
||||
// 返回结果
|
||||
return CommonResult.success(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.iocoder.mall.pay.biz.service;
|
||||
|
||||
import cn.iocoder.mall.pay.api.PayRefundService;
|
||||
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
|
||||
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package cn.iocoder.mall.pay.biz.service;
|
||||
|
||||
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user