package la.niub.abcapi.servicecompre.component.client.coder;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import feign.Response;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
//@Configuration
public class ErrorDecoder implements feign.codec.ErrorDecoder {
static Logger logger = LogManager.getLogger(ErrorDecoder.class);
@Override
public Exception decode(String methodKey, Response response) {
logger.error(response.reason());
if(response.status() >= 400 && response.status() <= 499){
return new HystrixBadRequestException("request exception wrapper");
}
return feign.FeignException.errorStatus(methodKey, response);
}
}
package la.niub.abcapi.servicecompre.component.client.coder;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import la.niub.abcapi.servicecompre.component.util.RandomUtil;
import java.lang.reflect.Type;
import java.util.Map;
public class FormDataEncoder implements Encoder {
@Override
public void encode(Object o, Type type, RequestTemplate requestTemplate) throws EncodeException {
String end = "\r\n";
String twoHyphens = "--";
// String boundary = "---------------------------681240323617137932268833";
String boundary = "---------------------------"+ RandomUtil.getRandomStr(25,"PNUMBER");
Map params = (Map)o;
StringBuilder builder = new StringBuilder();
for (Map.Entry param : params.entrySet()){
builder.append(twoHyphens + boundary + end);
builder.append("Content-Disposition: form-data; name=\"");
builder.append(param.getKey());
builder.append("\"" + end);
builder.append(end);
builder.append(param.getValue());
builder.append(end);
}
builder.append(twoHyphens + boundary + twoHyphens + end);
builder.append(end);
requestTemplate.header("Content-Type","multipart/form-data; boundary="+boundary);
requestTemplate.body(builder.toString());
}
}
package la.niub.abcapi.servicecompre.component.client.coder;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.MediaType;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
public class ObjectEncoder implements Encoder {
@Override
public void encode(Object o, Type type, RequestTemplate requestTemplate) throws EncodeException {
Map params = (Map)o;
Map querys = new HashMap<>();
for (Map.Entry param : params.entrySet()){
querys.putAll(bean2Map(param.getValue(),true));
}
Map querysStr = new HashMap<>();
for (Map.Entry entry : querys.entrySet()){
if (entry.getValue() == null){
continue;
}
String value = "";
if (entry.getValue().getClass().equals(Boolean.class)){
value = ((boolean)entry.getValue()) ? "1" : "0";
}else if (entry.getValue().getClass().equals(Integer.class)){
value = String.valueOf(entry.getValue());
}else{
value = String.valueOf(entry.getValue());
try {
value = URLEncoder.encode(URLDecoder.decode(value,"UTF-8"),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
continue;
}
}
querysStr.put(entry.getKey(),value);
}
if (requestTemplate.method().equals("POST")){
StringBuilder builder = new StringBuilder();
for (Map.Entry entry : querysStr.entrySet()){
builder.append(entry.getKey()+"="+ entry.getValue()+"&");
}
String queryStr = StringUtils.stripEnd(builder.toString(),"&");
requestTemplate.header("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE);
requestTemplate.body(queryStr);
}else{
for (Map.Entry entry : querysStr.entrySet()){
requestTemplate.query(entry.getKey(),entry.getValue());
}
}
}
/**
* 从bean转换为map
* @param bean
* @param includeParent 是否包含父类属性
* @return
*/
public static Map bean2Map(Object bean,Boolean includeParent) {
Map map = new HashMap<>();
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields){
try {
field.setAccessible(true);
map.put(field.getName(),field.get(bean));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (includeParent){
Class parent = bean.getClass().getSuperclass();
while (!parent.equals(Object.class)){
fields = parent.getDeclaredFields();
for (Field field : fields){
try {
field.setAccessible(true);
map.put(field.getName(),field.get(bean));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
parent = parent.getClass().getSuperclass();
}
}
return map;
}
}
package la.niub.abcapi.servicecompre.component.client.coder;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import la.niub.abcapi.servicecompre.component.util.RandomUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class ObjectFormDataEncoder implements Encoder {
@Override
public void encode(Object o, Type type, RequestTemplate requestTemplate) throws EncodeException {
Map params = (Map)o;
Map querys = new HashMap<>();
for (Map.Entry param : params.entrySet()){
querys.putAll(bean2Map(param.getValue(),true));
}
String end = "\r\n";
String twoHyphens = "--";
// String boundary = "---------------------------681240323617137932268833";
String boundary = "---------------------------"+ RandomUtil.getRandomStr(25,"PNUMBER");
StringBuilder builder = new StringBuilder();
for (Map.Entry param : querys.entrySet()){
builder.append(twoHyphens + boundary + end);
builder.append("Content-Disposition: form-data; name=\"");
builder.append(param.getKey());
builder.append("\"" + end);
builder.append(end);
builder.append(param.getValue());
builder.append(end);
}
builder.append(twoHyphens + boundary + twoHyphens + end);
builder.append(end);
requestTemplate.header("Content-Type","multipart/form-data; boundary="+boundary);
requestTemplate.body(builder.toString());
}
/**
* 从bean转换为map
* @param bean
* @param includeParent 是否包含父类属性
* @return
*/
public static Map bean2Map(Object bean,Boolean includeParent) {
Map map = new HashMap<>();
Field[] fields = bean.getClass().getDeclaredFields();
for (Field field : fields){
try {
field.setAccessible(true);
map.put(field.getName(),field.get(bean));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if (includeParent){
Class parent = bean.getClass().getSuperclass();
while (!parent.equals(Object.class)){
fields = parent.getDeclaredFields();
for (Field field : fields){
try {
field.setAccessible(true);
map.put(field.getName(),field.get(bean));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
parent = parent.getClass().getSuperclass();
}
}
return map;
}
}
package la.niub.abcapi.servicecompre.component.client.configuration;
import com.netflix.hystrix.HystrixCommand;
import feign.Logger;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.hystrix.HystrixFeign;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
public class UserInfoFeignConfiguration {
@Bean
@ConditionalOnMissingBean
public Decoder decoder() {
return new JacksonDecoder();
}
@Bean
public Encoder encoder(){
return new JacksonEncoder();
}
@Bean
@ConditionalOnMissingBean
Logger.Level feignLoggerLevel() {
return Logger.Level.BASIC;
}
}
package la.niub.abcapi.servicecompre.component.client.fallback;
import feign.hystrix.FallbackFactory;
import la.niub.abcapi.servicecompre.component.client.IApiBestNewsClient;
import la.niub.abcapi.servicecompre.model.request.client.ClientBestNewsRequest;
import la.niub.abcapi.servicecompre.model.response.client.ApiBestNewsResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
@Component
public class ApiBestNewsFallbackFactory implements IApiBestNewsClient,FallbackFactory {
static Logger logger = LogManager.getLogger(ApiBestNewsFallbackFactory.class);
private Throwable throwable;
private void handleError(Object request){
logger.error(this.getClass().getSimpleName()+" for request "+ request);
logger.error(throwable.getMessage(),throwable);
}
@Override
public IApiBestNewsClient create(Throwable throwable) {
this.throwable = throwable;
return this;
}
@Override
public ApiBestNewsResponse bestNews(ClientBestNewsRequest request) {
handleError(request);
return null;
}
}
package la.niub.abcapi.servicecompre.config.configuration;
import com.netflix.hystrix.HystrixCommand;
import feign.codec.Encoder;
import feign.hystrix.HystrixFeign;
import la.niub.abcapi.servicecompre.component.client.coder.ObjectEncoder;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
public class FeignObjectConfiguration {
@Bean
public Encoder encoder(){
return new ObjectEncoder();
}
}