package com.cpic.home.governor.service.impl; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.InputStreamBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import com.alibaba.fastjson.JSON; import com.cpic.caf.compon.tech.utils.CharsetUtil; import com.cpic.home.governor.service.JobSchedulerService; import feign.Feign; import feign.Param; import feign.RequestLine; import feign.RequestTemplate; import feign.Response; import feign.Util; import feign.codec.Decoder; import feign.codec.Encoder; import feign.gson.GsonDecoder; /** * 该类为 JobSchedulerService 实例,因需要调用 JobScheduler, 需远程执行接口。 * * *
 *
 * Created by zhenqin.
 * User: zhenqin
 * Date: 2019/3/26
 * Time: 18:43
 * Vendor: primeton.com
 * To change this template use File | Settings | File Templates.
 *
 * 
* * @author zhenqin */ @Component("jobSchedulerService") public class JobSchedulerServiceImpl implements InitializingBean, FactoryBean, MethodInterceptor { /** * JobScheduler 地址 */ @Value("${jobscheduler.url}") String jobSchedulerUrl; private HttpClient httpclient = null; static Logger logger = LoggerFactory.getLogger(JobSchedulerServiceImpl.class); @Override public void afterPropertiesSet() throws Exception { HttpClient httpclient = HttpClientBuilder.create().build(); this.httpclient = httpclient; } @Override public JobSchedulerService getObject() throws Exception { JobSchedulerService jobSchedulerService = Feign.builder() .encoder(feignEncoder()) .decoder(feignDecoder()) .target(JobSchedulerService.class, jobSchedulerUrl); // AOP,拦截上传文件的接口 ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.addAdvice(this); proxyFactory.setTarget(jobSchedulerService); // 获得代理类 return (JobSchedulerService) proxyFactory.getProxy(); } @Override public Class getObjectType() { return JobSchedulerService.class; } /** * AOP 织入 * * @param invocation * @return * @throws Throwable */ @Override public Object invoke(MethodInvocation invocation) throws Throwable { Object[] arguments = invocation.getArguments(); boolean isMutilForm = false; for (Object argument : arguments) { // 文件 isMutilForm = argument instanceof File || argument instanceof MultipartFile; if (isMutilForm) { // 有一个是文件的,则是上传 break; } } Object result = null; if (!isMutilForm) { // 普通表单 result = invocation.proceed(); } else { // 文件上传 result = new HashMap<>(); Method method = invocation.getMethod(); RequestLine requestLine = method.getAnnotation(RequestLine.class); if (requestLine != null) { String[] split = requestLine.value().split("\\s+"); String url = jobSchedulerUrl + split[1]; Map form = new HashMap<>(); Parameter[] parameters = method.getParameters(); Annotation[][] annotations = method.getParameterAnnotations(); int i = 0; for (Parameter parameter : parameters) { form.put(getFormName(parameter, annotations[i]), invocation.getArguments()[i]); i++; } // 提交表单 return executeRest(url, form); } } return result; } /** * 提交表单 * * @param form 提交表单,携带文件 * @return */ public Map executeRest(String url, Map form) { HttpPost request = new HttpPost(url); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); InputStream in = null; try { for (Map.Entry entry : form.entrySet()) { if (entry.getValue() instanceof File || entry.getValue() instanceof MultipartFile) { if (entry.getValue() instanceof File) { String name = ((File) entry.getValue()).getName(); multipartEntityBuilder.addPart(entry.getKey(), new FileBody((File) entry.getValue())); multipartEntityBuilder.addPart("name", new StringBody(name, ContentType.MULTIPART_FORM_DATA)); } else { MultipartFile uploadFile = (MultipartFile) entry.getValue(); in = uploadFile.getInputStream(); String name = ((MultipartFile) entry.getValue()).getOriginalFilename(); multipartEntityBuilder.addPart(entry.getKey(), new InputStreamBody(in, ContentType.MULTIPART_FORM_DATA, name)); multipartEntityBuilder.addPart("name", new StringBody(name, ContentType.MULTIPART_FORM_DATA)); } } else { multipartEntityBuilder.addPart(entry.getKey(), (entry.getValue() instanceof String ? new StringBody((String) entry.getValue(), ContentType.MULTIPART_FORM_DATA) : new StringBody(String.valueOf(entry.getValue()), ContentType.MULTIPART_FORM_DATA))); } } request.setEntity(multipartEntityBuilder.build()); HttpResponse response = httpclient.execute(request); if (response.getStatusLine().getStatusCode() == 200) { String json = EntityUtils.toString(response.getEntity(), CharsetUtil.CHARSET_UTF_8); logger.info(json); return JSON.parseObject(json); } else { logger.error("execute {} error.", request.getURI()); } } catch (IOException e) { logger.error("execute rest api error.", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { } } } return new HashMap<>(); } /** * 获取该 参数的名称,@Param 注解名称,若没有选择字段名称 * * @param parameter * @param param * @return */ String getFormName(Parameter parameter, Annotation[] param) { if (param == null || param.length == 0) { return parameter.getName(); } // 选择 param 的名称 Param params = (Param) param[0]; return params.value(); } public void setJobSchedulerUrl(String jobSchedulerUrl) { this.jobSchedulerUrl = jobSchedulerUrl; } public static Decoder feignDecoder() { // JSON GsonDecoder gsonDecoder = new GsonDecoder(); return (Response response, Type type) -> { Response.Body body = response.body(); if (body == null) { return null; } if (String.class.equals(type)) { return Util.toString(body.asReader()); } return gsonDecoder.decode(response, type); }; } public static Encoder feignEncoder() { // JSON return (Object object, Type bodyType, RequestTemplate template) -> { if (bodyType == String.class) { template.body((String)object); } else if (bodyType == byte[].class) { template.body((byte[]) object, CharsetUtil.CHARSET_UTF_8); } else if (object instanceof Number) { template.body(String.valueOf(object)); } template.body(JSON.toJSONString(object)); }; } }