Spring Boot FeignClient How to Capture Traffic Exception Information
- 2021-10-13 07:36:58
- OfStack
Spring Boot FeignClient Capture Traffic Exception Information
Because spring cloud is adopted in project reconstruction, feign is inevitable. At present, spring cloud is not very mature in China, so stepping on the pit is inevitable. Recently, I searched all over the problem of dealing with global exceptions, but I couldn't find a suitable solution
1. Global exception handling
import com.bossien.common.comm.entity.ResponseDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
@ControllerAdvice
public class GlobalExceptionHandler {
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* @Author: lixg
* @Description: System exception capture processing
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public ResponseDto errorExceptionHandler(Exception ex) {//APIResponse It is the external unification in the project 1 The export package can be changed according to the needs of your own project
logger.error(" Capture to Exception Anomaly ", ex);
// Exception log warehousing
return new ResponseDto(ResponseDto.RESPONSE_FAIL, " The system is busy , Please try again later ");
}
/**
* @Author: lixg
* @Description: Custom Exception Trap Handling
*/
@ResponseBody
@ExceptionHandler(value = BusinessException.class)//BusinessException Is custom 1 Anomalies
public ResponseDto businessExceptionHandler(BusinessException ex) {
logger.error(" Capture to BusinessException Anomaly : code=" + ex.getCode() + " , errorMessage=" + ex.getErrorMessage());
return new ResponseDto(ex.getCode(), ex.getErrorMessage());
}
}
2. Request parameter resolution handler
import com.alibaba.fastjson.JSONObject;
import com.ocean.common.comm.entity.ResponseDto;
import com.ocean.common.core.exception.BusinessException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/***
* @author lixg
*
* feign Request response object processing
*/
public class ResponseHandler {
private final static Logger logger = LoggerFactory.getLogger(ResponseHandler.class);
/**
* Parse the request response object
* @param responseDto
* @param clazz
* @return
* @throws BusinessException
*/
public static Object getResponseData(ResponseDto responseDto, Class clazz) throws BusinessException {
if(EmptyUtil.isEmpty(responseDto)){
throw new BusinessException(BusinessException.OBJECT_IS_NULL," Request response is empty! ");
}
if(ResponseDto.RESPONSE_SUCCESS.equals(responseDto.getCode())){
try {
String json = JSONObject.toJSONString(responseDto.getData());
return JSONObject.parseObject(json, clazz);
}catch (Exception e){
logger.error(" Respond to object conversion exceptions: "+clazz.getName(),e);
throw new BusinessException(BusinessException.OBJECT_IS_NULL," Response object conversion failed! ");
}
}else{
throw new BusinessException(responseDto.getCode(),responseDto.getMessage());
}
}
}
3. Service feign interface
package com.bossien.usercenter.user.feign;
import com.bossien.common.comm.entity.ResponseDto;
import com.bossien.common.comm.util.PageModel;
import com.bossien.common.comm.constant.SearchEntity;
import com.bossien.common.core.exception.BusinessException;
import com.bossien.usercenter.user.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
import java.util.Map;
@FeignClient(value="bossien-usercenter-service",path = "/userFeign")
@Repository
public interface UserFeign {
@RequestMapping(value = "getUserInfo",method = RequestMethod.GET)
User getUserInfo(@RequestParam("userId") Long userId);
@RequestMapping(value = "getUserInfoByTicket",method = RequestMethod.GET)
ResponseDto getUserInfoByTicket(@RequestParam("ticket") String ticket) throws BusinessException;
}
Summary:
@ controllerAdvice or HandlerExceptionResolver can't capture FeignException directly, so it is necessary to get specific exception re-encapsulation at Feign level. Finally, the cloud service internal exception security (1 kind of error code, 1 kind of error message) to the client! !
Feign Call Exception Handling
When the consumer service calls the Producer service interface, prompt 1 for exception
no suitable HttpMessageConverter found for request type
feign.codec.EncodeException: Could not write request: no suitable HttpMessageConverter found for request type [com.xxx.pojo.Xxx] and content type [application/x-www-form-urlencoded]
at org.springframework.cloud.openfeign.support.SpringEncoder.encode(SpringEncoder.java:143) ~[spring-cloud-openfeign-core-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at feign.ReflectiveFeign$BuildEncodedTemplateFromArgs.resolve(ReflectiveFeign.java:372) ~[feign-core-10.1.0.jar:na]
at feign.ReflectiveFeign$BuildTemplateByResolvingArgs.create(ReflectiveFeign.java:224) ~[feign-core-10.1.0.jar:na]
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:74) ~[feign-core-10.1.0.jar:na]
at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:106) ~[feign-hystrix-10.1.0.jar:na]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:302) ~[hystrix-core-1.5.18.jar:1.5.18]
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:298) ~[hystrix-core-1.5.18.jar:1.5.18]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.2.0.jar:1.2.0]
at rx.Observable.unsafeSubscribe(Observable.java:10151) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35) ~[rxjava-1.2.0.jar:1.2.0]
at rx.Observable.unsafeSubscribe(Observable.java:10151) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30) ~[rxjava-1.2.0.jar:1.2.0]
at rx.Observable.unsafeSubscribe(Observable.java:10151) ~[rxjava-1.2.0.jar:1.2.0]
at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94) ~[rxjava-1.2.0.jar:1.2.0]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56) ~[hystrix-core-1.5.18.jar:1.5.18]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47) ~[hystrix-core-1.5.18.jar:1.5.18]
at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69) ~[hystrix-core-1.5.18.jar:1.5.18]
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55) ~[rxjava-1.2.0.jar:1.2.0]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_221]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_221]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_221]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_221]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]
Abnormal cause
As literally:
at org.springframework.cloud.openfeign.support.SpringEncoder.encode
Missing encoder for HttpMessageConverter
Solution
If it is missing, add it
Add SpringFormEncoder to the container
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
/**
* @author jianming
* @create 2021-02-06-15:42
*/
@Configuration
public class FeignSupportConfig {
@Bean
@Primary
@Scope("prototype")
public Encoder multipartFormEncoder() {
return new SpringFormEncoder();
}
}
Problem handling completed
Use of Feign for Consumer
The above encoder is required for processing, and ContentType needs to be specified in the interface
@Service
@FeignClient(value = "XXX-XXX")
public interface LoginService {
/**
* Specify contentType
*/
@PostMapping(value = "/register", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public MsgUtils create(User user);
}