JobSchedulerServiceImpl.java 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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. * To change this template use File | Settings | File Templates.
  55. *
  56. * </pre>
  57. *
  58. * @author zhenqin
  59. */
  60. @Component("jobSchedulerService")
  61. public class JobSchedulerServiceImpl implements InitializingBean, FactoryBean<JobSchedulerService>,
  62. MethodInterceptor {
  63. /**
  64. * JobScheduler 地址
  65. */
  66. @Value("${jobscheduler.url}")
  67. String jobSchedulerUrl;
  68. private HttpClient httpclient = null;
  69. static Logger logger = LoggerFactory.getLogger(JobSchedulerServiceImpl.class);
  70. @Override
  71. public void afterPropertiesSet() throws Exception {
  72. HttpClient httpclient = HttpClientBuilder.create().build();
  73. this.httpclient = httpclient;
  74. }
  75. @Override
  76. public JobSchedulerService getObject() throws Exception {
  77. JobSchedulerService jobSchedulerService = Feign.builder()
  78. .encoder(feignEncoder())
  79. .decoder(feignDecoder())
  80. .target(JobSchedulerService.class, jobSchedulerUrl);
  81. // AOP,拦截上传文件的接口
  82. ProxyFactory proxyFactory = new ProxyFactory();
  83. proxyFactory.addAdvice(this);
  84. proxyFactory.setTarget(jobSchedulerService);
  85. // 获得代理类
  86. return (JobSchedulerService) proxyFactory.getProxy();
  87. }
  88. @Override
  89. public Class<?> getObjectType() {
  90. return JobSchedulerService.class;
  91. }
  92. /**
  93. * AOP 织入
  94. *
  95. * @param invocation
  96. * @return
  97. * @throws Throwable
  98. */
  99. @Override
  100. public Object invoke(MethodInvocation invocation) throws Throwable {
  101. Object[] arguments = invocation.getArguments();
  102. boolean isMutilForm = false;
  103. for (Object argument : arguments) {
  104. // 文件
  105. isMutilForm = argument instanceof File || argument instanceof MultipartFile;
  106. if (isMutilForm) {
  107. // 有一个是文件的,则是上传
  108. break;
  109. }
  110. }
  111. Object result = null;
  112. if (!isMutilForm) {
  113. // 普通表单
  114. result = invocation.proceed();
  115. } else {
  116. // 文件上传
  117. result = new HashMap<>();
  118. Method method = invocation.getMethod();
  119. RequestLine requestLine = method.getAnnotation(RequestLine.class);
  120. if (requestLine != null) {
  121. String[] split = requestLine.value().split("\\s+");
  122. String url = jobSchedulerUrl + split[1];
  123. Map<String, Object> form = new HashMap<>();
  124. Parameter[] parameters = method.getParameters();
  125. Annotation[][] annotations = method.getParameterAnnotations();
  126. int i = 0;
  127. for (Parameter parameter : parameters) {
  128. form.put(getFormName(parameter, annotations[i]), invocation.getArguments()[i]);
  129. i++;
  130. }
  131. // 提交表单
  132. return executeRest(url, form);
  133. }
  134. }
  135. return result;
  136. }
  137. /**
  138. * 提交表单
  139. *
  140. * @param form 提交表单,携带文件
  141. * @return
  142. */
  143. public Map<String, Object> executeRest(String url, Map<String, Object> form) {
  144. HttpPost request = new HttpPost(url);
  145. MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();
  146. InputStream in = null;
  147. try {
  148. for (Map.Entry<String, Object> entry : form.entrySet()) {
  149. if (entry.getValue() instanceof File || entry.getValue() instanceof MultipartFile) {
  150. if (entry.getValue() instanceof File) {
  151. String name = ((File) entry.getValue()).getName();
  152. multipartEntityBuilder.addPart(entry.getKey(), new FileBody((File) entry.getValue()));
  153. multipartEntityBuilder.addPart("name", new StringBody(name, ContentType.MULTIPART_FORM_DATA));
  154. } else {
  155. MultipartFile uploadFile = (MultipartFile) entry.getValue();
  156. in = uploadFile.getInputStream();
  157. String name = ((MultipartFile) entry.getValue()).getOriginalFilename();
  158. multipartEntityBuilder.addPart(entry.getKey(), new InputStreamBody(in, ContentType.MULTIPART_FORM_DATA, name));
  159. multipartEntityBuilder.addPart("name", new StringBody(name, ContentType.MULTIPART_FORM_DATA));
  160. }
  161. } else {
  162. multipartEntityBuilder.addPart(entry.getKey(),
  163. (entry.getValue() instanceof String ? new StringBody((String) entry.getValue(), ContentType.MULTIPART_FORM_DATA) :
  164. new StringBody(String.valueOf(entry.getValue()), ContentType.MULTIPART_FORM_DATA)));
  165. }
  166. }
  167. request.setEntity(multipartEntityBuilder.build());
  168. HttpResponse response = httpclient.execute(request);
  169. if (response.getStatusLine().getStatusCode() == 200) {
  170. String json = EntityUtils.toString(response.getEntity(), CharsetUtil.CHARSET_UTF_8);
  171. logger.info(json);
  172. return JSON.parseObject(json);
  173. } else {
  174. logger.error("execute {} error.", request.getURI());
  175. }
  176. } catch (IOException e) {
  177. logger.error("execute rest api error.", e);
  178. } finally {
  179. if (in != null) {
  180. try {
  181. in.close();
  182. } catch (IOException e) {
  183. }
  184. }
  185. }
  186. return new HashMap<>();
  187. }
  188. /**
  189. * 获取该 参数的名称,@Param 注解名称,若没有选择字段名称
  190. *
  191. * @param parameter
  192. * @param param
  193. * @return
  194. */
  195. String getFormName(Parameter parameter, Annotation[] param) {
  196. if (param == null || param.length == 0) {
  197. return parameter.getName();
  198. }
  199. // 选择 param 的名称
  200. Param params = (Param) param[0];
  201. return params.value();
  202. }
  203. public void setJobSchedulerUrl(String jobSchedulerUrl) {
  204. this.jobSchedulerUrl = jobSchedulerUrl;
  205. }
  206. public static Decoder feignDecoder() {
  207. // JSON
  208. GsonDecoder gsonDecoder = new GsonDecoder();
  209. return (Response response, Type type) -> {
  210. Response.Body body = response.body();
  211. if (body == null) {
  212. return null;
  213. }
  214. if (String.class.equals(type)) {
  215. return Util.toString(body.asReader());
  216. }
  217. return gsonDecoder.decode(response, type);
  218. };
  219. }
  220. public static Encoder feignEncoder() {
  221. // JSON
  222. return (Object object, Type bodyType, RequestTemplate template) -> {
  223. if (bodyType == String.class) {
  224. template.body((String)object);
  225. } else if (bodyType == byte[].class) {
  226. template.body((byte[]) object, CharsetUtil.CHARSET_UTF_8);
  227. } else if (object instanceof Number) {
  228. template.body(String.valueOf(object));
  229. }
  230. template.body(JSON.toJSONString(object));
  231. };
  232. }
  233. }