-
Notifications
You must be signed in to change notification settings - Fork 0
feat: http请求框架 #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,143 @@ | ||
| package com.szy.core.httpcenter; | ||
|
|
||
| import com.szy.core.eunm.SzyExceptionEnum; | ||
| import com.szy.core.httpcenter.annotation.*; | ||
| import com.szy.core.util.GenericBuilder; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.beans.factory.FactoryBean; | ||
| import org.springframework.cglib.proxy.CallbackHelper; | ||
| import org.springframework.cglib.proxy.Enhancer; | ||
| import org.springframework.cglib.proxy.InvocationHandler; | ||
| import org.springframework.cglib.proxy.NoOp; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import javax.annotation.Resource; | ||
| import java.lang.annotation.Annotation; | ||
| import java.lang.reflect.Method; | ||
| import java.lang.reflect.Type; | ||
| import java.text.MessageFormat; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
| @Component | ||
| @Slf4j | ||
| public class HttpCenterFactory<T> implements FactoryBean<T> { | ||
|
|
||
| private Class<T> interfaceType; | ||
|
|
||
| @Resource | ||
| SzyHttpClientFactory szyHttpClientFactory; | ||
|
|
||
| SzyHttpClient szyHttpClient; | ||
| private final InvocationHandler invocationHandler = (o, method1, objects) -> { | ||
|
|
||
| SzyExceptionEnum.HTTP_CENTER_HTTPSUBPATH_NOT_FOUND | ||
| .throwsIf(!method1.isAnnotationPresent(SHttpSubPath.class)); | ||
|
|
||
| SzyExceptionEnum.HTTP_CENTER_HTTPMETHOD_NOT_FOUND | ||
| .throwsIf(!method1.isAnnotationPresent(SHttpMethod.class)); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 参考processor接口,参数校验全写在preCheck里 |
||
|
|
||
| szyHttpClient = szyHttpClientFactory.getClient(); | ||
|
|
||
| String url = method1.getAnnotation(SHttpSubPath.class).value(); | ||
|
|
||
| Annotation[][] parameterAnnotations = method1.getParameterAnnotations(); | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| String[] pathVars = new String[parameterAnnotations.length]; | ||
| int pathVarIndex = 0; | ||
| for(int i = 0; i < parameterAnnotations.length; i ++){ | ||
| if(parameterAnnotations[i][0].annotationType() == SPathVar.class){ | ||
| pathVars[pathVarIndex ++] = objects[i].toString(); | ||
| } | ||
|
|
||
| } | ||
| if(pathVarIndex > 0){ | ||
| url = MessageFormat.format(url, pathVars); | ||
| } | ||
|
|
||
| String httpMethod = method1.getAnnotation(SHttpMethod.class).value(); | ||
| szyHttpClient.setHttpMethod(httpMethod); | ||
|
|
||
| if(interfaceType.isAnnotationPresent(SHttpPath.class)){ | ||
| url = interfaceType.getAnnotation(SHttpPath.class).value() + url; | ||
| } | ||
|
|
||
|
|
||
| if (method1.isAnnotationPresent(SHttpHeaders.class)) { | ||
| SHttpHeader[] annotationsByType = method1.getAnnotationsByType(SHttpHeader.class); | ||
| log.info("annotationsByType:" + annotationsByType); | ||
| for (SHttpHeader annotation : annotationsByType) { | ||
| szyHttpClient.setHeader(annotation.key(), annotation.value()); | ||
| } | ||
| } | ||
|
|
||
| HashMap<String, Object> requestParammap = new HashMap<>(); | ||
| for(int i = 0; i < parameterAnnotations.length; i ++){ | ||
| if(parameterAnnotations[i][0] instanceof SRequestParam){ | ||
| requestParammap.put(((SRequestParam) parameterAnnotations[i][0]).value(), objects[i]); | ||
| } | ||
| } | ||
| if(requestParammap.size() > 0){ | ||
| url = url + "?"; | ||
| for(Map.Entry<String, Object> entry : requestParammap.entrySet()){ | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| url = url + entry.getKey() + "=" + entry.getValue() + "&"; | ||
| } | ||
| } | ||
| szyHttpClient.setUrl(url); | ||
|
|
||
|
|
||
| int bodyIndex = -1; | ||
| for(int i = 0; i < parameterAnnotations.length; i ++){ | ||
| if(parameterAnnotations[i][0].annotationType() == SHttpBody.class){ | ||
| bodyIndex = i; | ||
| } | ||
| } | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 一个循环分拣出所有参数 |
||
| if(bodyIndex != -1){ | ||
| szyHttpClient.setBody(objects[bodyIndex]); | ||
| } | ||
|
|
||
| Type type = method1.getGenericReturnType(); | ||
|
|
||
| return szyHttpClient.excute(type); | ||
|
|
||
| }; | ||
|
|
||
| /** | ||
| * 由 beanDefinition 注入 | ||
| */ | ||
| public HttpCenterFactory(Class<T> interfaceType) { | ||
| this.interfaceType = interfaceType; | ||
| } | ||
|
|
||
| @Override | ||
| public T getObject() { | ||
| CallbackHelper callbackHelper = new CallbackHelper(Object.class, new Class[]{interfaceType}) { | ||
| @Override | ||
| protected Object getCallback(Method method) { | ||
| return method.isDefault() | ||
| ? NoOp.INSTANCE | ||
| : invocationHandler; | ||
| } | ||
| }; | ||
|
|
||
| Enhancer enhancer = GenericBuilder.of(Enhancer::new) | ||
| .with(Enhancer::setSuperclass, Object.class) | ||
| .with(Enhancer::setInterfaces, new Class[] {interfaceType}) | ||
| .with(Enhancer::setCallbackFilter, callbackHelper) | ||
| .with(Enhancer::setCallbackTypes, callbackHelper.getCallbackTypes()) | ||
| .with(Enhancer::setCallbacks, callbackHelper.getCallbacks()) | ||
| .build(); | ||
|
|
||
| return (T) enhancer.create(); | ||
| } | ||
|
|
||
| @Override | ||
| public Class<?> getObjectType() { | ||
| return interfaceType; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isSingleton() { | ||
| return true; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| package com.szy.core.httpcenter; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个类去实现通用的模版方法 |
||
|
|
||
| import com.szy.core.httpcenter.annotation.HttpCenterScan; | ||
| import com.szy.core.httpcenter.annotation.SHttpCenter; | ||
| import lombok.SneakyThrows; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
| import org.springframework.beans.factory.support.BeanDefinitionRegistry; | ||
| import org.springframework.beans.factory.support.GenericBeanDefinition; | ||
| import org.springframework.context.EnvironmentAware; | ||
| import org.springframework.context.ResourceLoaderAware; | ||
| import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; | ||
| import org.springframework.core.annotation.AnnotationAttributes; | ||
| import org.springframework.core.env.Environment; | ||
| import org.springframework.core.io.Resource; | ||
| import org.springframework.core.io.ResourceLoader; | ||
| import org.springframework.core.io.support.ResourcePatternResolver; | ||
| import org.springframework.core.io.support.ResourcePatternUtils; | ||
| import org.springframework.core.type.AnnotationMetadata; | ||
| import org.springframework.core.type.classreading.CachingMetadataReaderFactory; | ||
| import org.springframework.core.type.classreading.MetadataReader; | ||
| import org.springframework.core.type.classreading.MetadataReaderFactory; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.util.ClassUtils; | ||
|
|
||
| import java.io.IOException; | ||
| import java.lang.annotation.Annotation; | ||
| import java.util.LinkedHashSet; | ||
| import java.util.Set; | ||
|
|
||
| @Component | ||
| @Slf4j | ||
| public class HttpCenterProcessor implements | ||
| ImportBeanDefinitionRegistrar, | ||
| ResourceLoaderAware, | ||
| EnvironmentAware { | ||
|
|
||
| private static final String DEFAULT_RESOURCE_PATTERN = "**/*.class"; | ||
|
|
||
| private MetadataReaderFactory metadataReaderFactory; | ||
|
|
||
| private ResourcePatternResolver resourcePatternResolver; | ||
|
|
||
| private Environment environment; | ||
|
|
||
| @SneakyThrows | ||
| @Override | ||
| public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { | ||
| ImportBeanDefinitionRegistrar.super.registerBeanDefinitions(importingClassMetadata, registry); | ||
| AnnotationAttributes httpScanAttr = AnnotationAttributes.fromMap( | ||
| importingClassMetadata.getAnnotationAttributes(HttpCenterScan.class.getName())); | ||
| String basePackageName = httpScanAttr.getString("value"); | ||
| Set<Class<?>> beanClazzs = scannerPackages(basePackageName); | ||
| for (Class beanClazz : beanClazzs) { | ||
| BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(beanClazz); | ||
| GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition(); | ||
|
|
||
| definition.getConstructorArgumentValues().addGenericArgumentValue(beanClazz); | ||
| definition.setBeanClass(HttpCenterFactory.class); | ||
|
|
||
| //这里采用的是byType方式注入,类似的还有byName等 | ||
| definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); | ||
| registry.registerBeanDefinition(beanClazz.getSimpleName(), definition); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * 根据包路径获取包及子包下的所有类 | ||
| * | ||
| * @param basePackage basePackage | ||
| */ | ||
| private Set<Class<?>> scannerPackages(String basePackage) throws ClassNotFoundException, IOException { | ||
| Set<Class<?>> set = new LinkedHashSet<>(); | ||
| String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + | ||
| resolveBasePackage(basePackage) + '/' + DEFAULT_RESOURCE_PATTERN; | ||
| Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); | ||
| for (Resource resource : resources) { | ||
| if (!resource.isReadable()) { | ||
| continue; | ||
| } | ||
| MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); | ||
| String className = metadataReader.getClassMetadata().getClassName(); | ||
| Class<?> clazz; | ||
| clazz = Class.forName(className); | ||
| Annotation annotation = clazz.getAnnotation(SHttpCenter.class); | ||
| if (annotation == null) { | ||
| continue; | ||
| } | ||
| set.add(clazz); | ||
| } | ||
| return set; | ||
| } | ||
|
|
||
| protected String resolveBasePackage(String basePackage) { | ||
| return ClassUtils.convertClassNameToResourcePath(this.environment.resolveRequiredPlaceholders(basePackage)); | ||
| } | ||
|
|
||
| @Override | ||
| public void setResourceLoader(ResourceLoader resourceLoader) { | ||
| this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader); | ||
| this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader); | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public void setEnvironment(Environment environment) { | ||
| this.environment = environment; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package com.szy.core.httpcenter; | ||
|
|
||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import java.lang.reflect.Type; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
|
|
||
|
|
||
| /** | ||
| * @author zzsnowy | ||
| */ | ||
| @Component | ||
| public interface SzyHttpClient { | ||
|
|
||
| SzyHttpClient setUrl(String url); | ||
| SzyHttpClient setHttpMethod(String methodName); | ||
| SzyHttpClient setHeader(String key, String value); | ||
| <T> SzyHttpClient setBody(T t); | ||
| <R> R excute(Type type); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| package com.szy.core.httpcenter; | ||
|
|
||
|
|
||
| import org.springframework.stereotype.Component; | ||
|
|
||
| /** | ||
| * @author zzsnowy | ||
| */ | ||
| @Component | ||
| public interface SzyHttpClientFactory { | ||
|
|
||
| SzyHttpClient getClient(); | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.szy.core.httpcenter; | ||
|
|
||
| public interface SzyHttpMethod { | ||
| String POST = "POST"; | ||
| String GET = "GET"; | ||
| String HEAD = "HEAD"; | ||
| String PUT = "PUT"; | ||
| String PATCH = "PATCH"; | ||
| String DELETE = "DELETE"; | ||
| String OPTIONS = "OPTIONS"; | ||
| String TRACE = "TRACE"; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.szy.core.httpcenter.annotation; | ||
|
|
||
| import com.szy.core.httpcenter.HttpCenterProcessor; | ||
| import com.szy.core.httpcenter.impl.DefaultSzyHttpClientFactory; | ||
| import org.springframework.context.annotation.Import; | ||
|
|
||
| import java.lang.annotation.*; | ||
|
|
||
| @Target({ElementType.TYPE}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| @Documented | ||
| @Import({HttpCenterProcessor.class, DefaultSzyHttpClientFactory.class}) | ||
| public @interface HttpCenterScan { | ||
| String value(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.szy.core.httpcenter.annotation; | ||
|
|
||
| import java.lang.annotation.*; | ||
|
|
||
| @Target({ElementType.PARAMETER}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| @Documented | ||
| public @interface SHttpBody { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package com.szy.core.httpcenter.annotation; | ||
|
|
||
| import java.lang.annotation.*; | ||
|
|
||
| @Target({ElementType.TYPE}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| @Documented | ||
| public @interface SHttpCenter { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.szy.core.httpcenter.annotation; | ||
|
|
||
| import java.lang.annotation.*; | ||
|
|
||
| @Target({ElementType.METHOD}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| @Documented | ||
| @Repeatable(SHttpHeaders.class) | ||
| public @interface SHttpHeader { | ||
| String key(); | ||
| String value(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.szy.core.httpcenter.annotation; | ||
|
|
||
| import java.lang.annotation.*; | ||
|
|
||
| @Target({ElementType.METHOD}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| @Documented | ||
| public @interface SHttpHeaders { | ||
| SHttpHeader[] value(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| package com.szy.core.httpcenter.annotation; | ||
|
|
||
| import java.lang.annotation.*; | ||
|
|
||
| @Target({ ElementType.METHOD}) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| @Documented | ||
| public @interface SHttpMethod { | ||
| String value(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
看看哪里用到了