在SpringBoot中入口我们使用:
package com.sankuai.qcs.regulation.traffic; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.reactive.config.EnableWebFlux; @SpringBootApplication @EnableWebFlux @EnableScheduling public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
因为是SpringBoot启动,是全注解启动形式,里面的任何注解和XML在启动的时候都可以加载到内存中,XML 和注解可以混合使用,
因为SpringBoot本来就是为了减少XML文件的,所以尽量使用注解
比如:
成都项目:
package com.sankuai.qcs.regulation.traffic.common.config; import com.dianping.squirrel.client.impl.redis.router.RouterType; import com.dianping.squirrel.client.impl.redis.spring.RedisClientBeanFactory; import com.google.common.base.Objects; import com.meituan.mafka.client.consumer.IMessageListener; import com.sankuai.qcs.regulation.traffic.common.constant.CommonConstants; import com.sankuai.qcs.regulation.traffic.common.consumer.MessageConsumer; import com.sankuai.qcs.regulation.traffic.common.util.HttpUtil; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory; import org.springframework.context.annotation.*; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.web.reactive.config.EnableWebFlux; /** * Created by ramon on 2017/11/9. */ @Configuration @ImportResource(locations = {"classpath:rhinoConfig.xml"}) public class SpringBeanConfig { /** * 动态配置 * @return */ @Bean("mccConfig") public PropertySourcesPlaceholderConfigurer mccConfig() { MccPropertyPlaceholderConfigurer mccPropertyPlaceholderConfigurer = new MccPropertyPlaceholderConfigurer(); mccPropertyPlaceholderConfigurer.setAppKey(CommonConstants.APP_NAME); mccPropertyPlaceholderConfigurer.setScanBasePackage("com.sankuai.qcs.regulation"); return mccPropertyPlaceholderConfigurer; } /** * 提供netty http server的配置 * @return */ @Bean public NettyReactiveWebServerFactory httpServer() { NettyReactiveWebServerFactory nettyReactiveWebServerFactory = new NettyReactiveWebServerFactory(); int httpPort = HttpUtil.getHttpPort(); nettyReactiveWebServerFactory.setPort(httpPort); return nettyReactiveWebServerFactory; } /** * 消息监听 * @return */ @Bean("messageConsumer") public MessageConsumer messageConsumer(@Value("${app.name}")String appName, @Value("${topic.name}")String topic, @Value("${group.name}")String groupName, IMessageListener regulationMessageListener) { MessageConsumer messageConsumer = new MessageConsumer(); messageConsumer.setAppKey(appName); messageConsumer.setBg("waimai"); messageConsumer.setTopic(topic); messageConsumer.setConsumerGroup(groupName); messageConsumer.setConsumerListener(regulationMessageListener); messageConsumer.start(); return messageConsumer; } }
在messageConsumer方法中:参数有个:
@Value("${app.name}")String appName
他的意思是:参数appName有个默认值:就是@Value("${app.name}");而 ${app.name}指的是,系统会在项目中遍历所有的properties文件,并找到app.name加载到指定的值;
后面的参数是:
IMessageListener regulationMessageListener
springboot会根据 IMessageListener 的实现类,自动的注册到项目中,因为
IMessageListener 有两个实现类:
package com.meituan.mafka.client.consumer; public abstract class IDeadLetterListener implements IMessageListener { private DeadLetterConsumer consumer; public IDeadLetterListener() { } public boolean retry(Object msg, long delayTime) throws Exception { return this.consumer.retry(msg, delayTime); } public void setConsumer(DeadLetterConsumer consumer) { this.consumer = consumer; } }
还有个:
package com.sankuai.qcs.regulation.traffic.mq; import com.dianping.cat.Cat; import com.meituan.mafka.client.consumer.ConsumeStatus; import com.meituan.mafka.client.consumer.IMessageListener; import com.meituan.mafka.client.message.MafkaMessage; import com.meituan.mafka.client.message.MessagetContext; import com.sankuai.qcs.regulation.traffic.common.util.JsonUtil; import com.sankuai.qcs.regulation.traffic.service.MessageManageService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.IOException; /** * 数据监听 * Created by panyuanyuan02 on 2018/1/30. */ @Service public class RegulationMessageListener implements IMessageListener { @Resource private MessageManageService messageManageService; private Logger logger = LoggerFactory.getLogger(RegulationMessageListener.class); @Override public ConsumeStatus recvMessage(MafkaMessage message, MessagetContext context) { try { String body = (String) message.getBody(); logger.info("Recv message:{}", body); MafkaMessageObject mafkaMessageObject = JsonUtil.fromStr(body, MafkaMessageObject.class); messageManageService.saveMessage(mafkaMessageObject.getMsgType(), mafkaMessageObject.getData()); } catch (Exception e) { logger.error("process message exception", e); Cat.logMetricForCount("process_message_exception"); } return ConsumeStatus.CONSUME_SUCCESS; } }
请注意第二个实现类上面的@Service注解, springboot 能找到第二个,因为有注解标签@Service,但是找不到第一个,以为第一个就是一个普通的类,并没有注解标签;
里面有标签:@Configuration;
也有引入的配置文件:
@ImportResource(locations = {"classpath:rhinoConfig.xml"})
但是如果是Spring项目的话,
@Configuration有可能不加载;
Spring 启动有两种启动方式,一种是
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:application.xml");
}
这种方法不能加载@Configuration,但是可以加载@Service等;
比如:
package com.sankuai.qcs.regulation.shanghai; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.util.Log4jConfigurer; import java.io.FileNotFoundException; /** * @author ssc Feb 1, 2018 */ public class App { private static Logger LOGGER = LoggerFactory.getLogger(App.class); static { try { Log4jConfigurer.initLogging("classpath:log4j2.xml", 5000); } catch (FileNotFoundException e) { LOGGER.error("App#static initializer init log config error", e); } } public static void main(String[] args) throws Throwable { ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:application.xml"); } }
这种方式的话,@Configuraton是不会加载的;
需要使用另一种加载方式:
ApplicationContext ac1 = new AnnotationConfigApplicationContext("com.sankuai.qcs.regulation.shanghai");
参数是基础的包名称,这样 @Configuration就可以加载上了;