在上一遍文章中(微服务SpringCloud组件的断路器Hystrix的介绍),我简单的介绍了断路器Hystrix的含义。
然后,在开发中,怎么使用断路器Hystrix是一个问题。用原生的,写起来很繁琐。所以,我利用AOP的方法,将其进行了封装,让我们在开发中使用时非常简单。只需要一个注释就可以了。废话不多说,看代码。
该工程源码在github上可下,github地址:断路器的封装
(一):定义注释 (MyHystrixCommand.java)
package com.eamon.myHystrix.hystrixTool;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @description
* @author EamonKang
* @Date 2018年1月24日
*/
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyHystrixCommand {
/**
* Title: groupKey
*/
String groupKey() default "my_groupKey";
/**
* Title: commandKey
*/
String commandKey() default "my_commandKey";
/**
* Title: threadPoolKey
*/
String threadPoolKey() default "my_threadPoolKey";
/**
* Title: timeOutSecond 用来配置执行的超时时间
*/
int timeOutSecond() default 30;
/**
* Title: timeOutEnabled 用来配置是否开启的超时功能
*/
boolean timeOutEnabled() default true;
}
(二)、定义
通知器(MyHystrixCommandAdvice.java)
package com.eamon.myHystrix.hystrixTool;
import org.aspectj.lang.ProceedingJoinPoint;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolKey;
import lombok.Data;
/**
* @description
* @author EamonKang
* @Date 2018年1月24日
*/
@Data
public class MyHystrixCommandAdvice {
private String groupName;
private String commandName;
private String threadKey;
private int timeOutSecond;
private boolean timeOutEnable;
public Object runCommand(final ProceedingJoinPoint pjp) {
return wrapWithHystrixCommnad(pjp).execute();
}
private HystrixCommand<Object> wrapWithHystrixCommnad(final ProceedingJoinPoint pjp) {
return new HystrixCommand<Object>(setter()) {
@Override
protected Object run() throws Exception {
try {
return pjp.proceed();
} catch (Throwable throwable) {
throw (Exception) throwable;
}
}
@Override
protected Object getFallback() {
return "ERROR";
}
};
}
private HystrixCommand.Setter setter() {
HystrixCommand.Setter setter = HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupName))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandName))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(threadKey));
HystrixCommandProperties.Setter commandPropertiesDefaults = HystrixCommandProperties.Setter().withExecutionTimeoutEnabled(timeOutEnable)
.withExecutionTimeoutInMilliseconds(timeOutSecond * 1000);
setter.andCommandPropertiesDefaults(commandPropertiesDefaults);
return setter;
}
}
(三)、 定义切面(MyHystrixCommandAspect.java)
package com.eamon.myHystrix.hystrixTool;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSONObject;
import com.eamon.myHystrix.common.BaseResponse;
import com.eamon.myHystrix.common.CommonResponseUtil;
import com.google.gson.Gson;
/**
* @description
* @author EamonKang
* @Date 2018年1月24日
*/
@Aspect
@Component
public class MyHystrixCommandAspect {
ThreadLocal<Long> startTime = new ThreadLocal<>();
MyHystrixCommandAdvice hystrixCommandAdvice = new MyHystrixCommandAdvice();
String methodName = "";
Gson gson = new Gson();
@Pointcut("@annotation(com.ec.common.hystrix.MyHystrixCommand)")
public void requestMethod() {
};
@Around("requestMethod()")
public void around(ProceedingJoinPoint joinPoint) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
MyHystrixCommand action = method.getAnnotation(MyHystrixCommand.class);
hystrixCommandAdvice.setCommandName(action.commandKey());
hystrixCommandAdvice.setGroupName(action.groupKey());
hystrixCommandAdvice.setThreadKey(action.threadPoolKey());
hystrixCommandAdvice.setTimeOutSecond(action.timeOutSecond());
hystrixCommandAdvice.setTimeOutEnable(action.timeOutEnabled());
Object object = hystrixCommandAdvice.runCommand(joinPoint);
if ("ERROR".equals((String)object)) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
HttpServletResponse response = attributes.getResponse();
String requestJson = request.getParameter("data");
JSONObject jsonObject = JSONObject.parseObject(requestJson);
String lang = jsonObject.getString("lang");
BaseResponse responseVO = new BaseResponse();
String description = "请求超时,稍后重试";
responseVO.outPutFailedResponse("errorCode1", description);
responseVO.setExpendField("这是断路器返回的");
String responseJson = gson.toJson(responseVO);
try {
CommonResponseUtil.writeResponse(request, response, responseJson);
} catch (Exception e) {
}
}
}
}
(四)、在对应的接口上,添加@MyHistrixCommand注释就可以了。
编写不易,转载请注明出处,谢谢!