1、Http请求URL注解定义
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface HttpUrl {
String prefixUrl();
}
2、Http请求发送注解定义
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface HttpRequest {
HttpMethod method() default HttpMethod.POST;
String value();
}
3、Http注解启动注解定义
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({HttpRequestRegistrar.class})
public @interface EnableHttpRequest {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] defaultConfiguration() default {};
}
4、解码器定义
public interface Decoder {
Object decode(ResponseEntity responseEntity, Type type) throws Exception;
}
public class DistanceDecoder implements Decoder{
private ObjectMapper objectMapper = new ObjectMapper();
@Override
public Object decode(ResponseEntity response, Type type) throws Exception {
Object body = response.getBody();
String value = null;
if (body instanceof String) {
value = (String)body;
}
JavaType javaType = this.getJavaType(type, null);
return this.objectMapper.readValue(value, javaType);
}
protected JavaType getJavaType(Type type, Class<?> contextClass) {
return contextClass != null ? this.objectMapper.getTypeFactory().constructType(type, contextClass) : this.objectMapper.constructType(type);
}
}
5、请求代理处理器
@Slf4j
public class DistanceHandler implements EnvironmentAware {
@Autowired(required = true)
private HttpRequestHandler httpRequestHandler;
private Environment environment;
public Object handle(Object proxy,Method method, Object[] args) {
RestTemplate restTemplate = RestTemplateSingleton.getInstance();
HttpRequest request = method.getAnnotation(HttpRequest.class);
String value = request.value();
HttpMethod httpMethod = request.method();
Type returnType = method.getGenericReturnType();
Class<?> declaringClass = method.getDeclaringClass();
Annotation[][] annotations = method.getParameterAnnotations();
HttpUrl httpConnection = declaringClass.getAnnotation(HttpUrl.class);
String prefixUrl = httpConnection.prefixUrl();
prefixUrl = this.resolve(prefixUrl);
String requestUrl = prefixUrl + (prefixUrl.endsWith("/") ? "" : "/") + value;
String name = httpMethod.name();
if ("POST".equals(name)) {
return this.httpRequestHandler.doPost(restTemplate, annotations, args, httpMethod, requestUrl, returnType,method);
} else {
return "GET".equals(name) ? this.httpRequestHandler.doGet(restTemplate, annotations, args, httpMethod, requestUrl, returnType,method) : null;
}
}
public HttpRequestHandler getHttpRequestHandler() {
return this.httpRequestHandler;
}
public void setHttpRequestHandler(HttpRequestHandler httpRequestHandler) {
this.httpRequestHandler = httpRequestHandler;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
private String resolve(String value) {
if (StringUtils.hasText(value)) {
return this.environment.resolvePlaceholders(value);
}
return value;
}
}
6、请求处理器
@Slf4j
public class HttpRequestHandler {
@Autowired
private Decoder decoder;
private static final String HTTP_FORM = "application/x-www-form-urlencoded";
private static final String HTTP_JSON = "application/json; charset=UTF-8";
public Object doPost(RestTemplate restTemplate, Annotation[][] annotations, Object[] args, HttpMethod httpMethod, String requestUrl, Type type, Method method) {
HttpHeaders headers = getHeader(args);
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap();
RequestParam requestParam = null;
HttpEntity httpEntity = null;
String jsonStr = null;
MediaType mediaType = null;
String httpFamat = null;
if(ArrayUtils.isNotEmpty(annotations)){
for(int i = 0; i < annotations.length; i++) {
Annotation[] parmAnnotations = annotations[i];
if(ArrayUtils.isNotEmpty(parmAnnotations)){
for (int j = 0;j < parmAnnotations.length;j++){
if (parmAnnotations[j] instanceof RequestBody) {
httpFamat = HTTP_JSON;
break;
}
}
}
}
}
if(StringUtils.isEmpty(httpFamat)){
httpFamat = HTTP_FORM;
mediaType = MediaType.parseMediaType(httpFamat);
headers.setContentType(mediaType);
Map<String,Object> map = null;
if(hasHeader(args)){
if(args[1] instanceof Map){
map = (Map) args[1];
}
}else {
if(args[0] instanceof Map){
map = (Map) args[1];
}
}
if(MapUtils.isEmpty(map)){
if(ArrayUtils.isNotEmpty(annotations)){
for(int i = 0; i < annotations.length; i++) {
Annotation[] parmAnnotations = annotations[i];
if(ArrayUtils.isNotEmpty(parmAnnotations)){
for (int j = 0;j < parmAnnotations.length;j++){
if (parmAnnotations[j] instanceof RequestParam) {
requestParam = (RequestParam)parmAnnotations[j];
jsonStr = requestParam.value();
paramMap.add(jsonStr, args[i]);
break;
}else {
if(hasHeader(args) && i != 0){
paramMap.add(method.getParameters()[i].getName(), args[i]);
}
break;
}
}
}else {
if(hasHeader(args) && i != 0){
paramMap.add(method.getParameters()[i].getName(), args[i]);
}
}
}
}else {
for (int i = 0;i < args.length;i++){
paramMap.add(method.getParameters()[i].getName(),args[i]);
}
}
}else {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
paramMap.add(key,value);
}
}
httpEntity = new HttpEntity(paramMap, headers);
}else {
jsonStr = JSONObject.toJSONString(args[0]);
httpFamat = HTTP_JSON;
mediaType = MediaType.parseMediaType(httpFamat);
headers.setContentType(mediaType);
headers.add("Accept", MediaType.APPLICATION_JSON.toString());
httpEntity = new HttpEntity(jsonStr, headers);
}
log.info("发起HTTP请求,请求URL为:{},请求格式:{},请求方式:{},请求参数:{}",requestUrl,httpFamat,httpMethod.name(), JSON.toJSONString(args));
ResponseEntity<String> responseEntity = null;
ParameterizedTypeReference parameterizedTypeReference = new ParameterizedTypeReference<String>() {
};
responseEntity = restTemplate.exchange(requestUrl, httpMethod, httpEntity, parameterizedTypeReference);
Object decode = null;
try {
decode = this.decoder.decode(responseEntity, type);
} catch (Exception e) {
HttpRequestHandler.log.error("http解码异常{}", e);
}
log.info("HTTP请求响应数据为:{}", JSON.toJSONString(decode));
return decode;
}
public Object doGet(RestTemplate restTemplate, Annotation[][] annotations, Object[] args, HttpMethod httpMethod, String requestUrl, Type type,Method method) {
HttpHeaders headers = getHeader(args);
requestUrl = requestUrl + "?";
Map<String, Object> paramMap = new HashMap();
RequestParam requestParam = null;
ResponseEntity responseEntity = null;
String paramValue = null;
if(ArrayUtils.isNotEmpty(annotations)){
for(int i = 0; i < annotations.length; i++) {
Annotation[] parmAnnotations = annotations[i];
if(ArrayUtils.isNotEmpty(parmAnnotations)){
for (int j = 0;j < parmAnnotations.length;j++){
if (parmAnnotations[j] instanceof RequestParam) {
requestParam = (RequestParam)parmAnnotations[j];
paramMap.put(requestParam.value(), args[i]);
break;
}else {
if(hasHeader(args) && i != 0){
paramMap.put(method.getParameters()[i].getName(), args[i]);
}
break;
}
}
}else {
if(hasHeader(args) && i != 0){
paramMap.put(method.getParameters()[i].getName(), args[i]);
}
}
}
}else {
for (int i = 0;i < args.length;i++){
paramMap.put(method.getParameters()[i].getName(),args[i]);
}
}
for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
requestUrl += key + "={" + value + "}&";
}
HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity(null, headers);
ParameterizedTypeReference parameterizedTypeReference = new ParameterizedTypeReference<String>() {
};
responseEntity = restTemplate.exchange(requestUrl, httpMethod, httpEntity, parameterizedTypeReference, paramMap);
Object decode = null;
try {
decode = this.decoder.decode(responseEntity, type);
} catch (Exception e) {
HttpRequestHandler.log.error("http解码异常{}", e);
}
return decode;
}
private HttpHeaders getHeader(Object[] args){
final HttpHeaders[] headers = {null};
Arrays.stream(args).forEach(
arg -> {
if(arg instanceof HttpHeaders){
headers[0] = (HttpHeaders) arg;
return;
}
}
);
if(headers[0] == null){
headers[0] = new HttpHeaders();
}
return headers[0];
}
private boolean hasHeader(Object[] args){
final boolean[] flag = {false};
Arrays.stream(args).forEach(
arg -> {
if(arg instanceof HttpHeaders){
flag[0] = true;
return;
}
}
);
return flag[0];
}
}
7、核心注册类
@Slf4j
public class HttpRequestRegistrar implements ImportBeanDefinitionRegistrar,ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware, BeanFactoryAware {
private static final String SCAN_BASE_PACKAGE_DEFAULT = "com.wjhd";
private String[] scanBasePackages;
private ClassLoader classLoader;
private ResourceLoader resourceLoader;
private Environment environment;
private BeanFactory beanFactory;
private void registerDefaultConfiguration(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
Map<String, Object> defaultAttrs = metadata
.getAnnotationAttributes(EnableHttpRequest.class.getName(), true);
String[] value = (String[]) defaultAttrs.get("value");
if(ArrayUtils.isNotEmpty(value)){
this.scanBasePackages = value;
}else {
String[] basePackages = (String[]) defaultAttrs.get("basePackages");
if(ArrayUtils.isNotEmpty(basePackages)){
this.scanBasePackages = basePackages;
}
}
if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
BeanDefinitionBuilder builderDistanceDecoder = BeanDefinitionBuilder
.genericBeanDefinition(DistanceDecoder.class);
registry.registerBeanDefinition("distanceDecoder",builderDistanceDecoder.getBeanDefinition());
BeanDefinitionBuilder builderDistanceHandler = BeanDefinitionBuilder
.genericBeanDefinition(DistanceHandler.class);
builderDistanceHandler.setLazyInit(false);
registry.registerBeanDefinition("builderDistanceHandler",builderDistanceHandler.getBeanDefinition());
BeanDefinitionBuilder builderHttpRequestHandler = BeanDefinitionBuilder
.genericBeanDefinition(HttpRequestHandler.class);
builderHttpRequestHandler.setLazyInit(false);
registry.registerBeanDefinition("builderHttpRequestHandler",builderHttpRequestHandler.getBeanDefinition());
}
registerProxy(registry);
}
private void registerProxy(BeanDefinitionRegistry beanDefinitionRegistry){
try {
ClassPathScanningCandidateComponentProvider classScanner = this.getClassScanner();
classScanner.setResourceLoader(this.resourceLoader);
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(HttpUrl.class);
classScanner.addIncludeFilter(annotationTypeFilter);
log.info("开始扫描http请求bean。。。。。");
for (String basePackage : getScanBasePackages()) {
Set<BeanDefinition> beanDefinitionSet = classScanner.findCandidateComponents(basePackage);
Iterator iterator = beanDefinitionSet.iterator();
while(iterator.hasNext()) {
BeanDefinition beanDefinition = (BeanDefinition)iterator.next();
if (beanDefinition instanceof AnnotatedBeanDefinition) {
this.registerBeans((AnnotatedBeanDefinition)beanDefinition);
}
}
}
} catch (Exception e) {
log.error("distance初始化异常" + e);
}
}
private void registerBeans(AnnotatedBeanDefinition annotatedBeanDefinition) {
String className = annotatedBeanDefinition.getBeanClassName();
((DefaultListableBeanFactory)this.beanFactory).registerSingleton(className, this.createProxy(annotatedBeanDefinition));
}
private Object createProxy(AnnotatedBeanDefinition annotatedBeanDefinition) {
try {
AnnotationMetadata annotationMetadata = annotatedBeanDefinition.getMetadata();
Class<?> target = Class.forName(annotationMetadata.getClassName());
InvocationHandler invocationHandler = this.createInvocationHandler();
Object proxy = Proxy.newProxyInstance(target.getClassLoader(), new Class[]{target}, invocationHandler);
return proxy;
} catch (ClassNotFoundException e) {
HttpRequestRegistrar.log.error(e.getMessage());
return null;
}
}
private InvocationHandler createInvocationHandler() {
return new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
DistanceHandler distanceHandler = HttpRequestRegistrar.this.beanFactory.getBean(DistanceHandler.class);
HttpRequestHandler httpRequestHandler = distanceHandler.getHttpRequestHandler();
if (httpRequestHandler == null) {
distanceHandler.setHttpRequestHandler(HttpRequestRegistrar.this.beanFactory.getBean(HttpRequestHandler.class));
}
return distanceHandler.handle(proxy, method, args);
}
};
}
private ClassPathScanningCandidateComponentProvider getClassScanner() {
return new ClassPathScanningCandidateComponentProvider(false, this.environment) {
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
if (beanDefinition.getMetadata().isInterface()) {
try {
Class<?> target = ClassUtils.forName(beanDefinition.getMetadata().getClassName(), HttpRequestRegistrar.this.classLoader);
return !target.isAnnotation();
} catch (Exception var3) {
HttpRequestRegistrar.log.error("loadClass Exception:", var3);
}
}
return false;
}
};
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public String[] getScanBasePackages() {
if (scanBasePackages == null || scanBasePackages.length == 0) {
return new String[]{SCAN_BASE_PACKAGE_DEFAULT};
}
return scanBasePackages;
}
public void setScanBasePackages(String[] scanBasePackages) {
this.scanBasePackages = scanBasePackages;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
this.registerDefaultConfiguration(annotationMetadata,beanDefinitionRegistry);
}
}
8、RestTemplate请求类
public class RestTemplateSingleton {
static volatile RestTemplate restTemplate;
public RestTemplateSingleton() {
}
public static RestTemplate getInstance() {
if (restTemplate == null) {
Class var0 = RestTemplateSingleton.class;
synchronized(RestTemplateSingleton.class) {
if (restTemplate == null) {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(300000);
requestFactory.setReadTimeout(300000);
restTemplate = new RestTemplate(requestFactory);
}
}
}
return restTemplate;
}
}
9、启动类开启注解
@SpringBootApplication
@EnableHttpRequest("com.lpforum.lpforumweb.core.netease")
public class LpforumApplication {
public static void main(String[] args) {
SpringApplication.run(LpforumApplication .class, args);
}
}
10、调用云信第三方接口测试
@HttpRequest(value = "/user/getUinfos.action",method = HttpMethod.GET)
TokenRet createNetEaseAcc(HttpHeaders headers, Map params) throws Exception;