spring cloud 版本:Edgware.SR2 问题: 使用feign注册eurka服务在监听器中调用 package com.listener; import java.util.concurrent.Executors; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.xx.charge.facade.client.BusinessClient; import com.xx.framework.util.SnowflakeIdWorkerUtils; import com.xx.framework.util.StringUtils; import com.xx.getway.app.common.Global; import lombok.extern.slf4j.Slf4j; @Component @Slf4j public class LoadDataListener implements ServletContextListener { @Autowired private BusinessClient businessClient; @Override public void contextInitialized(ServletContextEvent sce) { businessClient.loadData(); } @Override public void contextDestroyed(ServletContextEvent sce) { } } ================================================================= @FeignClient(value = "app",fallback=AppStartClientFallback.class) public interface AppStartClient { @RequestMapping(value = "/app/loadData") ResponseInfo loadData(); } @Slf4j @Component class AppStartClientFallback implements AppStartClient{ @Override public ResponseInfo loadData() { log.error("数据进入服务消费者降级处理"); return ResponseInfo.error("数据进入服务消费者降级处理"); } } ===================================================== @EnableDiscoveryClient @SpringBootApplication(exclude = { MongoAutoConfiguration.class, MongoDataAutoConfiguration.class }, scanBasePackages = { "com.xx.bsp.getway.app","com.xx.bsp.charge.facade.client" }) @EnableFeignClients // 启用feign @ImportResource(locations = { "classpath:/applicationContext.xml" }) @ServletComponentScan(basePackageClasses = { LoadDataListener.class }) public class Application { } ================================================== 问题:项目启动 始终是会进入熔断,然后在调用目标方法。 原因:监听器在springcloud加载配置文件HystrixCommandProperties之前就调用目标方法, 监听器的方法调用默认为1秒 超过这个时间自定会进入熔断fallback方法。 真正的Hystrix还未起作用 这个时候还是会调用目标方法。 解决办法:不用servlet监听。 需要在容器启动的时候执行一些内容。比如读取配置文件,数据库连接之类的。 SpringBoot给我们提供了两个接口来帮助我们实现这种需求。 这两个接口分别为CommandLineRunner和ApplicationRunner。 他们的执行时机为容器启动完成的时候。 @Component @Slf4j public class InitDataApplicationRunner implements ApplicationRunner {
@Autowired private AppStartClient appStartClient;
@Override public void run(ApplicationArguments args) throws Exception { long startTime = System.currentTimeMillis();// 开始时间 log.info("getway redis开始初始化!"); ResponseInfo response=appStartClient.loadData(); long endTime = System.currentTimeMillis();// 结束时间 float excTime = (float) (endTime - startTime) / 1000; if(response.isSuccess()){ log.info("getway redis初始化完成!,执行时间: {}s", excTime); }else{ log.error("getway redis初始化失败!,执行时间: {}s", excTime,response.getMessage()); } } package com.jb.mpc.equipmemnt.config;
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component;
import com.jb.mpc.controller.EquipmentController;
/** * @see @Order注解的执行优先级是按value值从小到大顺序。 * @author pangps * @version v1.0 * @date 2017年7月24日 * */ @Component @Order(value=1) public class MyApplicationRunner implements ApplicationRunner{ private static final Logger logger = LoggerFactory.getLogger(MyApplicationRunner.class); @Override public void run(ApplicationArguments args) throws Exception { logger.info("==服务启动后,初始化数据操作=="); } } package com.jb.mpc.equipmemnt.config;
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component;
/** * @see @Order注解的执行优先级是按value值从小到大顺序。 * @author pangps * @version v1.0 * @date 2017年7月24日 * */ @Component @Order(value=2) public class MyCommandLineRunner implements CommandLineRunner{ private static final Logger logger = LoggerFactory.getLogger(MyCommandLineRunner.class);
@Override public void run(String... args) throws Exception { logger.info("==服务启动执行,执行加载数据等操作=="); } }
说明:
1、@Order注解
如果有多个实现类,而你需要他们按一定顺序执行的话,可以在实现类上加上@Order注解。@Order(value=整数值)。SpringBoot会按照@Order中的value值从小到大依次执行。
2、如果你发现你的实现类没有按照你的需求执行,请看一下实现类上是否添加了Spring管理的注解(@Component)。