1 背景概述
远程调用:后台管理服务需要调用实验服务的某一接口,注册中心显示服务名如下:
2 实验部分(被调用方)
@ApiOperation(value = "删除一个实验", httpMethod = "DELETE")
@DeleteMapping("/jobs")
public boolean deleteExperiment(@RequestParam("experimentId")int experimentId,
HttpServletRequest request, HttpServletResponse response) {
int uid = UidCheckSingleTon.identityCheck(request);
int isSuper = request.getHeader("Gw-Super")!=null? Integer.parseInt(request.getHeader("Gw-Super")):0;
int record = experimentJobService.deleteExperimentJob(experimentId,uid,isSuper);
if(record > 0) {
return true;
}else {
throw new BusinessException(BusinessExceptionEnum.EXPERIMENT_DELETE_FAILED);
}
}
3 后台管理部分(调用方)
3.1 编写远程调用接口
@FeignClient(value = "srv-dmp-experiment-dev}")
public interface TaskDeleteService {
/**
* 远程接口 删除实验任务相关信息
* @param experimentId experimentId
* @return base model
* @throws Exception ex
*/
@DeleteMapping("/dmp/experiment/jobs")
boolean deleteExperiment(@RequestParam("experimentId")int experimentId) throws Exception;
}
3.2 在controller中使用
@Resource
private TaskDeleteService taskDeleteService;
@ApiOperation(value = "根据任务的实验主键ID删除相关记录")
@ApiImplicitParams({
@ApiImplicitParam(name = "experimentId", value = "experimentId", dataType = "Integer", example = "1"),
})
@DeleteMapping(value = "/tasks/{experimentId}")
public boolean deleteTaskInfo(@PathVariable(value = "experimentId") int experimentId) throws Exception {
if (!taskDeleteService.deleteExperiment(experimentId)){
throw new ManageBusinessException(ManageExceptionEnum.DELETE_EXPERIMENT_RPC_FAILED);
}
return true;
}
3.3 解决远程调用时的token验证
Feign提供了一个接口:RequestInterceptor。只要实现该拦截器接口,重写apply方法,再将该配置实现类交由Spring容器管理即可。比如我们项目中网关会对注册用户进行token校验,只有请求header中的Gw-token和Gw-Uid合法才会放行,故添加如下设置,再在调用方的@FeignClient注解里引入该配置(configuration = TaskDeleteFeignConfig.class),这样就实现了把当前请求的token放到了feign请求头上:
@Configuration
public class TaskDeleteFeignConfig implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) {
return;
}
HttpServletRequest request = attributes.getRequest();
//添加token
requestTemplate.header("Gw-Token", request.getHeader("Gw-Token"));
requestTemplate.header("Gw-Uid", request.getHeader("Gw-Uid"));
requestTemplate.header("Gw-Super", "1");
}
}
3.4 服务降级
有两种方式可实现,第一种:对Feign服务接口添加实现类并注册到IOC容器(@Component不能缺失,否则会报错 No fallbackFactory instance of type class),在该类中定义对应的降级方法,然后在调用方Feign服务接口中的@FeignClient注解里添加fallback属性(name = “srv-dmp-experiment-dev”, fallback=****.class);第二种:用FallbackFactory,定义一个FallbackFactory的实现类,重写create方法,再在Feign服务接口中的@FeignClient注解里添加FallbackFactory实现类(name = “srv-dmp-experiment-dev”, fallbackFactory = ****.class)。
@Component
@Slf4j
public class TaskDeleteServiceFallbackImpl implements FallbackFactory<TaskDeleteService> {
@Override
public TaskDeleteService create(Throwable cause) {
log.info(cause.getMessage());
return experimentId -> {
log.info("远程调用实验experimentId: {}删除失败!",experimentId);
return false;
};
}
}