자바 가 어떻게 인 터 페 이 스 를 통 해 대 리 를 만 들 고 http 요청 을 하 는 지 자세히 알 아 보기

장면
지금 이런 일 을 하려 면 회사 의 dubbo 서 비 스 는 모두 내부 네트워크 이지 만 대외 적 인 수출 을 제공 하여 링크 를 통 해 해당 하 는 dubbo 서 비 스 를 요청 할 수 있 습 니 다.구체 적 으로 어떻게 하 는 지 는 게 이 트 웨 이 이 이 고 http 요청 을 dubbo 요청 으로 바 꾸 고 일반화 호출 을 통 해 호출 해 야 합 니 다.코드 가 보이 지 않 습 니 다.)지금 은 테스트 를 편리 하 게 하기 위해 서 설정 한 인 터 페 이 스 를 http 요청 을 통 해 해당 하 는 링크 를 요청 해 야 합 니 다.
분석 하 다.
프로젝트 의 사상 은 사실 mybatis-spring 통합 패키지 의 사상 과 차이 가 많 지 않 고 모두 에이 전 트 를 생 성하 여 인 터 페 이 스 를 실행 하 는 방법 이다.
https://www.jb51.net/article/153378.htm
프로젝트 는 간단 한 spring 프로젝트 면 됩 니 다.그 다음 에 프로젝트 가 프로젝트 의 api 를 도입 한 다음 에 해당 하 는 서비스 이름 을 설정 하여 spring 을 통 해 대 리 를 생 성하 고 spring 용 기 를 주입 한 다음 에 실행 방법 은 해당 하 는 도 메 인+인터페이스 전체 경로+방법 명 에 따라 요청 하 는 것 입 니 다.매개 변 수 는 json 입 니 다.프로젝트 의 편 의 를 위해 hutool 도구 류 를 사용 하고 fastjson 을 직접 사용 하여 직렬 화 합 니 다.
조작 하 다.
우선 공장 bean 을 만 드 는 것 은 대리 로 돌아 가 는 Factory Bean 입 니 다.

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Proxy;

/**
 * @Title:   BeanFactory     ,       ,           bean(        bean)
 * @Description       
 * @Version
 */
public class HttpProxyFactoryBean<T> implements FactoryBean<T> {

    /**
     *【  】
     *              ,        HttpProxyFactoryBean      Spring  
     *                  (      ,    @Component、@Service      )
     *       BeanDefinition      ,       ,       HttpProxyFactoryBean            HttpProxyInvocationHandler  
     *
     *         :
     *   ApplicationContextAware   setApplicationContext   applicationContext,
     *    applicationContext            
     *     applicationContext getBean     InvocationHandler   
     */
    @Autowired
    private HttpProxyInvocationHandler httpProxyInvocationHandler;

    private Class<T> rpcInterface;

    public HttpProxyFactoryBean(Class<T> rpcInterface){
        this.rpcInterface = rpcInterface;
    }


    @Override
    public T getObject() throws Exception {
        //     ComputerService  
        return (T)Proxy.newProxyInstance(rpcInterface.getClassLoader(),new Class[]{rpcInterface} ,httpProxyInvocationHandler);
    }

    @Override
    public Class<?> getObjectType() {
        return rpcInterface;
    }

}
모든 동적 에이전트 클래스 는 Invocation Handler 라 는 인 터 페 이 스 를 실현 해 야 합 니 다.
모든 동적 프 록 시 클래스 는 Invocation Handler 라 는 인 터 페 이 스 를 실현 해 야 하고 모든 프 록 시 클래스 의 인 스 턴 스 는 하나의 handler 와 연결 되 어 있 습 니 다.우리 가 프 록 시 대상 을 통 해 하나의 방법 을 호출 할 때 이 방법의 호출 은 Invocation Handler 라 는 인터페이스의 invoke 방법 으로 전 송 됩 니 다.
우 리 는 Invocation Handler 의 실현 류 를 spring 용기 에 직접 주입 한 다음 에 모든 인터페이스 가 같은 innvoke 방법 으로 갈 수 있 습 니 다.물론 모든 것 이 new 이 고 그 다음 에 구조 방법 에 특정한 매개 변 수 를 넣 을 수 있 습 니 다.내 쪽 은 대응 하 는 모든 대리 들 이 특별한 것 이 없 기 때문에 같은 곳 으로 간다.
일부 인자,요청 한 urlproxy.server Url,추가 요청 항목,proxy.project 를 정의 합 니 다.

import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description                  http  
 * @Version
 */
@Component
public class HttpProxyInvocationHandler implements InvocationHandler {

    @Value("${proxy.serverUrl}")
    private String serverUrl;

    @Value("${proxy.project}")
    private String serverProject;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Class<?> declaringClass = method.getDeclaringClass();
        if (Object.class.equals(declaringClass)) {
            return method.invoke(this, args);
        }

        String methodName = method.getName();
        String name = method.getDeclaringClass().getName();

        //      
        String url = serverUrl + name + "/" + methodName;
//        String url = "http://test:8080/soa/com.rdd.TestService/createActivity";
        HashMap<String, String> paramMap = new HashMap<>();
    
//        String result = HttpRequest.post(url).headerMap(paramMap, true).body("[" + JSONObject.toJSONString(args) + "]").execute().body();
        String result = HttpRequest.post(url).headerMap(paramMap, true).body(JSONObject.toJSONString(args)).execute().body();

        System.out.println(">>>" + url + "      :" + result);

        //                  
        Class<?> returnType = method.getReturnType();
        if (returnType.isPrimitive() || String.class.isAssignableFrom(returnType)) {
            if (returnType == int.class || returnType == Integer.class) {
                return Integer.valueOf(result);
            } else if (returnType == long.class || returnType == Long.class) {
                return Long.valueOf(result);
            }
            return result;
        } else if (Collection.class.isAssignableFrom(returnType)) {
            return JSONArray.parseArray(result, Object.class);
        } else if (Map.class.isAssignableFrom(returnType)) {
            return JSON.parseObject(result, Map.class);
        } else {
            return JSONObject.parseObject(result, returnType);
        }
    }
}
마지막 으로 대응 하 는 공장 bean 을 bean 정의 로 밀봉 하여 spring 용기 에 주입 합 니 다.
우리 의 인 터 페 이 스 는 일반적으로 jar 형식 입 니 다.저 는 proxy.txt 파일 에 간단하게 쓴 다음 에 해당 하 는 인터페이스 전 경 로 를 읽 고 spring 용기 에 주입 할 수 있 습 니 다.물론 특정한 가방 을 스 캔 하고 사용자 정의 주석 등 방식 으로 이 루어 질 수 있 습 니 다.

import cn.hutool.core.io.file.FileReader;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Title:bean        ,      bean
 * @Date 2021/3/23 10:13
 * @Description
 * @Version
 */
@Component
@PropertySource("classpath:application.properties")
public class HttpProxyRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    /**
     *           bean spring   
     *
     * @param beanDefinitionRegistry
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        //  UTF-8  ,                 
        FileReader fileReader = new FileReader("proxy.txt");
        List<String> classStrList = fileReader.readLines();
        Set<Class<?>> proxyClazzSet = new HashSet<>();
        for (String s : classStrList) {
            if (StringUtils.isBlank(s)) {
                continue;
            }
            try {
                Class<?> aClass = Class.forName(s);
                proxyClazzSet.add(aClass);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        for (Class<?> targetClazz : proxyClazzSet) {
            BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(targetClazz);
            GenericBeanDefinition definition = (GenericBeanDefinition) beanDefinitionBuilder.getRawBeanDefinition();
            //             Class<?>,      Class,    Class     
            //definition.getConstructorArgumentValues().addGenericArgumentValue(targetClazz);
            definition.getConstructorArgumentValues().addGenericArgumentValue(targetClazz.getName());

            //Bean   ,            
            definition.setBeanClass(HttpProxyFactoryBean.class);
            //                 
            definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            beanDefinitionRegistry.registerBeanDefinition(targetClazz.getName(),definition);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}
자바 가 어떻게 인 터 페 이 스 를 통 해 프 록 시 를 만 들 고 http 요청 을 하 는 지 에 대한 자세 한 설명 은 여기까지 입 니 다.자바 생 성 프 록 시 에 대한 http 요청 내용 은 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 지원 바 랍 니 다!

좋은 웹페이지 즐겨찾기