JobSchedulerServiceImpl.java 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. package com.cpic.home.governor.service.impl;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.lang.annotation.Annotation;
  6. import java.lang.reflect.Method;
  7. import java.lang.reflect.Parameter;
  8. import java.lang.reflect.Type;
  9. import java.util.HashMap;
  10. import java.util.Map;
  11. import org.aopalliance.intercept.MethodInterceptor;
  12. import org.aopalliance.intercept.MethodInvocation;
  13. import org.apache.http.HttpResponse;
  14. import org.apache.http.client.HttpClient;
  15. import org.apache.http.client.methods.HttpPost;
  16. import org.apache.http.entity.ContentType;
  17. import org.apache.http.entity.mime.MultipartEntityBuilder;
  18. import org.apache.http.entity.mime.content.FileBody;
  19. import org.apache.http.entity.mime.content.InputStreamBody;
  20. import org.apache.http.entity.mime.content.StringBody;
  21. import org.apache.http.impl.client.HttpClientBuilder;
  22. import org.apache.http.util.EntityUtils;
  23. import org.slf4j.Logger;
  24. import org.slf4j.LoggerFactory;
  25. import org.springframework.aop.framework.ProxyFactory;
  26. import org.springframework.beans.factory.FactoryBean;
  27. import org.springframework.beans.factory.InitializingBean;
  28. import org.springframework.beans.factory.annotation.Value;
  29. import org.springframework.stereotype.Component;
  30. import org.springframework.web.multipart.MultipartFile;
  31. import com.alibaba.fastjson.JSON;
  32. import com.cpic.caf.compon.tech.utils.CharsetUtil;
  33. import com.cpic.home.governor.service.JobSchedulerService;
  34. import feign.Feign;
  35. import feign.Param;
  36. import feign.RequestLine;
  37. import feign.RequestTemplate;
  38. import feign.Response;
  39. import feign.Util;
  40. import feign.codec.Decoder;
  41. import feign.codec.Encoder;
  42. import feign.gson.GsonDecoder;
  43. /**
  44. * 该类为 JobSchedulerService 实例,因需要调用 JobScheduler, 需远程执行接口。
  45. *
  46. *
  47. * <pre>
  48. *
  49. * Created by zhenqin.
  50. * User: zhenqin
  51. * Date: 2019/3/26
  52. * Time: 18:43
  53. * Vendor: primeton.com
  54. *
  55. * </pre>
  56. *
  57. * @author zhenqin
  58. */
  59. @Component("jobSchedulerService")
  60. public class JobSchedulerServiceImpl implements InitializingBean, FactoryBean<JobSchedulerService>,
  61. MethodInterceptor {
  62. /**
  63. * JobScheduler 地址
  64. */
  65. @Value("${jobscheduler.url}")
  66. String jobSchedulerUrl;
  67. private HttpClient httpclient = null;
  68. static Logger logger = LoggerFactory.getLogger(JobSchedulerServiceImpl.class);
  69. @Override
  70. public void afterPropertiesSet() throws Exception {
  71. HttpClient httpclient = HttpClientBuilder.create().build();
  72. this.httpclient = httpclient;
  73. }
  74. @Override
  75. public JobSchedulerService getObject() throws Exception {
  76. JobSchedulerService jobSchedulerService = Feign.builder()
  77. .encoder(feignEncoder())
  78. .decoder(feignDecoder())
  79. .target(JobSchedulerService.class, jobSchedulerUrl);
  80. // AOP,拦截上传文件的接口
  81. ProxyFactory proxyFactory = new ProxyFactory();
  82. proxyFactory.addAdvice(this);
  83. proxyFactory.setTarget(jobSchedulerService);
  84. // 获得代理类
  85. return (JobSchedulerService) proxyFactory.getProxy();
  86. }
  87. @Override
  88. public Class<?> getObjectType() {
  89. return JobSchedulerService.class;
  90. }
  91. /**
  92. * AOP 织入
  93. *
  94. * @param invocation
  95. * @return
  96. * @throws Throwable
  97. */
  98. @Override
  99. public Object invoke(MethodInvocation invocation) throws Throwable {
  100. Object[] arguments = invocation.getArguments();
  101. boolean isMutilForm = false;
  102. for (Object argument : arguments) {
  103. // 文件
  104. isMutilForm = argument instanceof File || argument instanceof MultipartFile;
  105. if (isMutilForm) {
  106. // 有一个是文件的,则是上传
  107. break;
  108. }
  109. }
  110. Object result = null;
  111. if (!isMutilForm) {
  112. // 普通表单
  113. result = invocation.proceed();
  114. } else {
  115. // 文件上传
  116. result = new HashMap<>();
  117. Method method = invocation.getMethod();
  118. RequestLine requestLine = method.getAnnotation(RequestLine.class);
  119. if (requestLine != null) {
  120. String[] split = requestLine.value().split("\\s+");
  121. String url = jobSchedulerUrl + split[1];
  122. Map<String, Object> form = new HashMap<>();
  123. Parameter[] parameters = method.getParameters();
  124. Annotation[][] annotations = method.getParameterAnnotations();
  125. int i = 0;
  126. for (Parameter parameter : parameters) {
  127. form.put(getFormName(parameter, annotations[i]), invocation.getArguments()[i]);
  128. i++;
  129. }
  130. // 提交表单
  131. return executeRest(url, form);
  132. }
  133. }
  134. return result;
  135. }
  136. /**
  137. * 提交表单
  138. *
  139. * @param form 提交表单,携带文件
  140. * @return
  141. */
  142. public Map<String, Object> executeRest(String url, Map<String, Object> form) {
  143. HttpPost request = new HttpPost(url);
  144. MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
  145. InputStream in = null;
  146. try {
  147. for (Map.Entry<String, Object> entry : form.entrySet()) {
  148. if (entry.getValue() instanceof File || entry.getValue() instanceof MultipartFile) {
  149. if (entry.getValue() instanceof File) {
  150. String name = ((File) entry.getValue()).getName();
  151. multipartEntityBuilder.addPart(entry.getKey(), new FileBody((File) entry.getValue()));
  152. multipartEntityBuilder.addPart("name", new StringBody(name, ContentType.MULTIPART_FORM_DATA));
  153. } else {
  154. MultipartFile uploadFile = (MultipartFile) entry.getValue();
  155. in = uploadFile.getInputStream();
  156. String name = ((MultipartFile) entry.getValue()).getOriginalFilename();
  157. multipartEntityBuilder.addPart(entry.getKey(), new InputStreamBody(in, ContentType.MULTIPART_FORM_DATA, name));
  158. multipartEntityBuilder.addPart("name", new StringBody(name, ContentType.MULTIPART_FORM_DATA));
  159. }
  160. } else {
  161. multipartEntityBuilder.addPart(entry.getKey(),
  162. (entry.getValue() instanceof String ? new StringBody((String) entry.getValue(), ContentType.MULTIPART_FORM_DATA) :
  163. new StringBody(String.valueOf(entry.getValue()), ContentType.MULTIPART_FORM_DATA)));
  164. }
  165. }
  166. request.setEntity(multipartEntityBuilder.build());
  167. HttpResponse response = httpclient.execute(request);
  168. if (response.getStatusLine().getStatusCode() == 200) {
  169. String json = EntityUtils.toString(response.getEntity(), CharsetUtil.CHARSET_UTF_8);
  170. logger.info(json);
  171. return JSON.parseObject(json);
  172. } else {
  173. logger.error("execute {} error.", request.getURI());
  174. }
  175. } catch (IOException e) {
  176. logger.error("execute rest api error.", e);
  177. } finally {
  178. if (in != null) {
  179. try {
  180. in.close();
  181. } catch (IOException e) {
  182. }
  183. }
  184. }
  185. return new HashMap<>();
  186. }
  187. /**
  188. * 获取该 参数的名称,@Param 注解名称,若没有选择字段名称
  189. *
  190. * @param parameter
  191. * @param param
  192. * @return
  193. */
  194. String getFormName(Parameter parameter, Annotation[] param) {
  195. if (param == null || param.length == 0) {
  196. return parameter.getName();
  197. }
  198. // 选择 param 的名称
  199. Param params = (Param) param[0];
  200. return params.value();
  201. }
  202. public void setJobSchedulerUrl(String jobSchedulerUrl) {
  203. this.jobSchedulerUrl = jobSchedulerUrl;
  204. }
  205. public static Decoder feignDecoder() {
  206. // JSON
  207. GsonDecoder gsonDecoder = new GsonDecoder();
  208. return (Response response, Type type) -> {
  209. Response.Body body = response.body();
  210. if (body == null) {
  211. return null;
  212. }
  213. if (String.class.equals(type)) {
  214. return Util.toString(body.asReader());
  215. }
  216. return gsonDecoder.decode(response, type);
  217. };
  218. }
  219. public static Encoder feignEncoder() {
  220. // JSON
  221. return (Object object, Type bodyType, RequestTemplate template) -> {
  222. if (bodyType == String.class) {
  223. template.body((String)object);
  224. } else if (bodyType == byte[].class) {
  225. template.body((byte[]) object, CharsetUtil.CHARSET_UTF_8);
  226. } else if (object instanceof Number) {
  227. template.body(String.valueOf(object));
  228. }
  229. template.body(JSON.toJSONString(object));
  230. };
  231. }
  232. }