先回顾下《AOP 基础知识》的内容。
业务场景: 在创建用户、组织,修改组织和删除的后,要回调外系统的接口。
思考: 外系统的url的配置在数据库,根据模块和操作去匹配。 因为都是相似的操作,考虑用注解的方式去处理。因为是执行完成后再进行回调的,因此用@AfterReturnning
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "WebHook配置")
public class WebHookConfig {
@ApiModelProperty("webHook编码")
private String webHookCode;
@ApiModelProperty("webHook名称")
private String webHookName;
@ApiModelProperty("描述")
private String description;
@ApiModelProperty("webhook类型,org:create,org:update,org:delete")
private String webHookTypes;
@ApiModelProperty("webHook地址")
private String webHookUrl;
@ApiModelProperty("状态(0SA:在用|0SX:删除)")
private String state;
}
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "WebHook参数")
public class WebHookParam {
@ApiModelProperty("webHook类型, org:update")
private String webHookType;
@ApiModelProperty("数据对象")
private Object data;
@ApiModelProperty("是否同步调用")
private Boolean sync;
}
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface WebHookCallBack {
/**
* 模块:对应 webhook_item 里面配置的 module值
*/
String module() default "";
/**
* 操作:增删改,对应 webhook_item 里面配置的 action值
*/
String action() default "";
/**
* 是否同步调用
*/
boolean sync() default true;
}
@Aspect
@Component
public class WebHookCallBackAspect {
protected final Logger log = LoggerFactory.getLogger(getClass());
@Resource
private WebHookService webHookService;
@Pointcut("@annotation(com.yan.studyAlone.spring.aop.annotate.after.WebHookCallBack)")
public void callBackPointCut() {
}
// result是结果值
@AfterReturning(value = "callBackPointCut()", returning = "result")
protected Object callBackExcute(JoinPoint joinPoint, Object result) {
log.debug("-----do AfterReturning-----");
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
WebHookCallBack annotation = method.getAnnotation(WebHookCallBack.class);
log.debug("WebHookCallBack: {}", JSON.toJSONString(annotation));
String module = annotation.module();
String action = annotation.action();
if(StringUtils.isBlank(module) || StringUtils.isBlank(action)){
return null;
}
WebHookParam param = new WebHookParam();
param.setWebHookType(module+":"+action);
// 获取到请求参数
Object[] args = joinPoint.getArgs();
if(args.length == 1){
param.setData(args[0]);
}else{
param.setData(args);
}
param.setSync(annotation.sync());
webHookService.execute(param);
return null;
}
}
@Service
@Log4j2
public class WebHookService {
@Resource
private RestTemplate restTemplate;
public Object execute(WebHookParam webHookParam) {
// 根据 webHookParam.getWebHookType() 获取到配置
List configs = new ArrayList<>();
if (CollectionUtils.isEmpty(configs)) {
return "没有查询到对应配置数据";
}
JSONObject param;
for (WebHookConfig webHook : configs) {
if (StringUtils.isEmpty(webHook.getWebHookUrl())) {
return "配置的webhookUrl为空";
}
param = new JSONObject();
param.put("webHookCode", webHook.getWebHookCode());
param.put("webHookUrl", webHook.getWebHookUrl());
param.put("webhookTypes", webHook.getWebHookTypes());
param.put("data", webHookParam.getData());
if (webHookParam.getSync()) {
ResponseEntity responseEntity = executeSync(param);
return responseEntity.getBody();
} else {
CompletableFuture> future = executeAsync(param);
try {
return future.get().getBody();
} catch (InterruptedException e) {
return "异步执行execute异常1" + e.getMessage();
} catch (ExecutionException e) {
return "异步执行execute异常2" + e.getMessage();
}
}
}
return "成功";
}
public ResponseEntity executeSync(JSONObject json) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
return restTemplate.exchange(json.getString("webHookUrl"), HttpMethod.POST, new HttpEntity<>(json, headers), String.class);
}
public CompletableFuture> executeAsync(JSONObject json) {
return CompletableFuture.supplyAsync(() -> executeSync(json));
}
}
@Configuration
public class RestTemplateConfiguration {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
这个或者启动那边加
OrgController
@Api(value = "OrgController",tags = {"组织管理"})
@RestController
@RequestMapping("/org")
public class OrgController {
@ApiOperation(value = "组织新增")
@PostMapping("/create")
@WebHookCallBack(module = "org", action = "create", sync = true)
public void create(@RequestBody OrgParam param) {
// 插入组织信息
}
}
如果要进行回调,内容都相似,可以考虑用注解@AfterReturnning去处理。如果实现的内容都不相同,可以考虑定义个统一回调接口,不同类去实现该方法去处理。