最近项目里需要实现一个短信通知的接口。主要短信的发送功能是依赖第三方的,通过引入jar启动短信服务器即可。
但是我希望短信服务可以独立与之前的web项目,将其做成一个微服务。于是考虑用springboot搭建一个简单的短信服务器。
找了一些资料,先贴上一个个人觉得写的不错的教程。
Spring Boot 揭秘与实战 系列
差不多搭完了短信服务器。对过程中遇到的问题记录一下,
1.SpringBoot @Value加载配置项的问题。
@Value("${host}") private static String host;
我之前希望通过上述方式从配置中获取host的值,但是发现这个值一直是为null。当我去掉static修饰符时,host又可以正常加载。
于是我换了另外一种方式去从配置项加载值。
@Component @ConfigurationProperties(prefix="smsServer") public class SmsServerConfig { //短信服务器IP private String host; //短信服务器数据库 private String dbName; //短信接口ID private String apiId; //用户名 private String name; //密码 private String pwd; public String getHost() { return host; } public void setHost(String host) { this.host = host; } public String getDbName() { return dbName; } public void setDbName(String dbName) { this.dbName = dbName; } public String getApiId() { return apiId; } public void setApiId(String apiId) { this.apiId = apiId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } }
我将需要的对象都定义到了SmsServerConfig这个bean上。然后在使用的时候通过创建这个bean来获取对应的值:
public class ApplicationEventListener implements ApplicationListener<ApplicationEvent> { private Logger log = LoggerFactory.getLogger(ApplicationEventListener.class); @Override public void onApplicationEvent(ApplicationEvent event) { if(event instanceof ApplicationReadyEvent){//启动完成状态 log.info("Springboot Startup complete"); SmsServerConfig config = (SmsServerConfig)((ApplicationReadyEvent)event).getApplicationContext().getBean(SmsServerConfig.class); //执行短信服务器的初始化过程 MySpringBootApplication.init(config.getHost(), config.getName(), config.getPwd(), config.getApiId(), config.getDbName()); }else if(event instanceof ContextClosedEvent){//关闭状态 log.info("shut down springboot"); //关闭连接 释放资源 MySpringBootApplication.release(); } } }
顺便讲讲ApplicationEventListener这个类,这是我定义的用来监听SpringBoot应用活动状态的监听器,继承了ApplicationListener。
这样我就可以将我连接和关闭短信服务器的动作刚在我的应用相应的状态后。比如我在启动完成后执行了短信服务器的初始化过程。
这里还需要注意的一点是需要在application.properties中设置监听器(注意要是全路径)。
context.listener.classes=ApplicationEventListener
2.mvn打包时加入第三方库
我项目中的短信服务器需要通过第三方的库来进行操作,因此需要将这个jar包install到本地mvn仓库中。
命令如下(xx换成具体的值):
mvn install:install-file -Dfile=D:mvnxxxxx.jar -DgroupId=xxxxx -DartifactId=xxxx -Dversion=x.x -Dpackaging=jar
执行完后,你会发现本地仓库里会多了这个jar包,这时候你在项目的pom文件里增加对应的依赖,就可以正常引到这个包了。
同时,在使用mvn package命令打包时也不会报错了。
如果你希望将这个jar包上传到远端的仓库里,那么可以用deploy命令。
3.通过java -jar运行jar包时,提示没有主清单属性。
这是因为生成的jar下的MANIFEST.MF文件没有指定主程序的入口。
如果pom文件里是配置了以下插件进行编译的话,应该是不会出现此问题的。
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
4.打成jar包独立运行后,logback日志文件出现中文乱码的问题
我在项目的resource包中增加了logback.xml,对logback进行配置。
xml内容如下:
<?xml version="1.0" encoding="UTF-8"?> <configuration debug="false"> <!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径--> <property name="LOG_HOME" value="./log" /> <!-- 控制台输出 --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <!-- 按照每天生成日志文件 --> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <!--日志文件输出的文件名--> <FileNamePattern>${LOG_HOME}/sms.log.%d{yyyy-MM-dd}.log</FileNamePattern> <!--日志文件保留天数--> <MaxHistory>30</MaxHistory> </rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> <!--日志文件最大的大小--> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <!-- 日志输出级别 --> <root level="INFO"> <appender-ref ref="STDOUT" /> <appender-ref ref="FILE" /> </root> </configuration>