All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.joe.http.ws.ResourceFactory Maven / Gradle / Ivy

package com.joe.http.ws;

import com.joe.http.client.IHttpClient;
import com.joe.http.request.IHttpGet;
import com.joe.http.request.IHttpPost;
import com.joe.http.request.IHttpRequestBase;
import com.joe.http.response.IHttpResponse;
import com.joe.utils.parse.json.JsonParser;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;

/**
 * HTTP资源工厂,主要为了方便测试HTTP接口(接口需要符合JAX-RS (JSR 311)规范),可以达
 * 到像调用本地方法一样调用远程方法。
 * 

* 支持说明:

* 只支持POST和GET方法

* 参数只支持从HEADER、FORM表单、PATH中和JSON数据中取 *

* 用法说明:

* ResourceFactory resourceFactory = ResourceFactory.build("http://127.0.0.1:8080/ws/");

* 通过以下方法得到资源类的实例后就可以与调用普通java方法一样调用资源了(PS:将Resource替换为实际的资源类即可)

* Resource resource = resourceFactory.buildSuccess(Resource.class);

* resource.somemethod("参数"); * * @author joe */ public class ResourceFactory { private static final Logger logger = LoggerFactory.getLogger(ResourceFactory.class); private static final Map cache = new HashMap<>(); private String baseUrl; private ResourceFactory(String baseUrl) { this.baseUrl = baseUrl; } /** * 构建资源工厂 * * @param baseUrl 资源的根目录 * @return 资源工厂 */ public static ResourceFactory build(String baseUrl) { if (!cache.containsKey(baseUrl)) { synchronized (cache) { if (!cache.containsKey(baseUrl)) { cache.put(baseUrl, new ResourceFactory(baseUrl)); } } } return cache.get(baseUrl); } /** * 构建可调用的资源 * * @param t 资源对应的类(该方法假设类中的接口都符合规范,如果接口不符合规范那么将会出现异常) * @param 资源类型 * @return 可调用的资源 */ public T build(Class t) throws NotResourceException { if (t.getAnnotation(Path.class) == null) { logger.error("类{}不是资源类,不能调用", t); throw new NotResourceException(t); } Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(t); enhancer.setCallback(CglibHTTPProxy.build(baseUrl)); @SuppressWarnings("unchecked") T resource = (T) enhancer.create(); return resource; } /** * CGLIB的HTTP代理,用于测试接口使用,暂时只支持返回JSON类型的接口测试 */ private static class CglibHTTPProxy implements MethodInterceptor { private static final JsonParser parser = JsonParser.getInstance(); private static final Logger logger = LoggerFactory.getLogger(CglibHTTPProxy.class); private static final IHttpClient client = IHttpClient.builder().build(); private static final Map cache = new HashMap<>(); private String baseUrl; private CglibHTTPProxy(String baseUrl) { this.baseUrl = baseUrl; } /** * 构建代理,主要为了缓存 * * @param baseUrl 代理的根目录 * @return 代理 */ static CglibHTTPProxy build(String baseUrl) { if (!CglibHTTPProxy.cache.containsKey(baseUrl)) { synchronized (cache) { if (!cache.containsKey(baseUrl)) { cache.put(baseUrl, new CglibHTTPProxy(baseUrl)); } } } return cache.get(baseUrl); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { logger.debug("开始代理方法"); if (method.getAnnotation(Path.class) == null) { logger.error("方法{}不是资源方法,不能调用", method); throw new NotResourceException(method); } logger.debug("开始构建HTTP请求"); IHttpRequestBase request = build(o, objects, method); logger.debug("开始发送HTTP请求"); IHttpResponse response = client.execute(request); logger.debug("HTTP请求发送完成,HTTP请求状态码为:{}", response.getStatus()); String result = response.getResult(); logger.debug("HTTP请求结果为:{}", result); return parser.readAsObject(result, method.getReturnType()); } /** * 根据信息构建HTTP请求 * * @param o 资源对象 * @param objects 参数 * @param method 资源方法 * @return 该资源对应的请求 */ private IHttpRequestBase build(Object o, Object[] objects, Method method) { //此时的o对象已经是cglib动态生成的代理对象了,所以需要获取他的父类才是真正的被代理类 //获取请求前缀 Path prePath = o.getClass().getSuperclass().getDeclaredAnnotation(Path.class); String prefix = prePath.value(); logger.debug("请求的前缀是:{}", prefix); Path namePath = method.getAnnotation(Path.class); String name = namePath.value(); logger.debug("接口名是:{}", name); if (!prefix.startsWith("/")) { prefix = "/" + prefix; } if (!prefix.endsWith("/")) { prefix = prefix + "/"; } if (name.startsWith("/")) { name = name.replaceFirst("/", ""); } String path = prefix + name; logger.debug("请求路径是:{}", path); //判断是否是POST请求 boolean post = false; if (method.getAnnotation(POST.class) != null) { post = true; } logger.debug("请求是{}请求", post ? "POST" : "GET"); if (baseUrl.endsWith("/")) { baseUrl = baseUrl.substring(0, baseUrl.length() - 1); } path = baseUrl + path; logger.debug("要请求的路径初步解析为:{}", path); IHttpRequestBase request; if (post) { request = new IHttpPost(path); } else { request = new IHttpGet(path); } logger.debug("开始解析参数"); // 解析参数,根据参数类型放入不同的地方 Parameter[] parameters = method.getParameters(); String data = null; //最后一个没有注解的参数在参数列表中的下标 int index = -1; for (int i = 0; i < parameters.length; i++) { if (objects[i] == null) { logger.debug("参数为null,跳过该参数"); continue; } Object value = objects[i]; Parameter parameter = parameters[i]; Annotation[] annotations = parameter.getAnnotations(); //如果该参数没有加合适的注解该值到最后还是true,否则会变为false boolean empty = true; for (Annotation annotation : annotations) { if (annotation instanceof QueryParam) { QueryParam queryParam = (QueryParam) annotation; logger.debug("参数是QueryParam,参数名为:{},参数值为:{}", queryParam.value(), value); request.addQueryParam(queryParam.value(), String.valueOf(value)); empty = false; break; } else if (annotation instanceof HeaderParam) { //解析headerparam HeaderParam headerParam = (HeaderParam) annotation; logger.debug("参数是HeaderParam,参数名为:{},参数值为:{}", headerParam.value(), value); request.addHeader(headerParam.value(), String.valueOf(value)); empty = false; break; } else if (annotation instanceof PathParam) { PathParam pathParam = (PathParam) annotation; logger.debug("参数是PathParam,参数名为:{},参数值为:{}", pathParam.value(), value); path = path.replace("{" + pathParam.value() + "}", String.valueOf(value)); empty = false; break; } else if (annotation instanceof FormParam) { FormParam formParam = (FormParam) annotation; logger.debug("参数是FormParam,参数名为:{},参数值为:{}", formParam.value(), value); if (data == null) { data = formParam.value() + "=" + value; } else { data += "&" + formParam.value() + "=" + value; } empty = false; break; } else if (annotation instanceof Context) { //当前是需要context的,跳过 empty = false; break; } } if (empty) { index = i; } } if (index != -1) { logger.debug("参数是json类型的参数"); data = parser.toJson(objects[index]); } if (data != null) { logger.debug("请求包含数据:{}", data); request.setEntity(data); } //获取请求的content-type Consumes consumes = method.getAnnotation(Consumes.class); if (consumes != null) { String contentType = consumes.value()[0]; logger.debug("请求的content-type为:{}", contentType); request.setContentType(contentType); } //有可能有PathPram,有PathPram时就会改变URL,所以需要更新 request.setUrl(path); return request; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy