默认情况下SpringBoot的启动是要依赖GemFire做为缓存数据库的,如果做一个小的项目,不需要缓存数据库,这将是一个不容易摘除的工作。
通过对其官网技术资料的分析,这个也很容易做到,说一下我的技术环境:
Spring boot版本:2.1.7.RELEASE
说一下我的业务环境,原来有一个项目使用GemFire做集群,主要的功能是缓存用户信息、用户Token和与底层单片机打交道的程序模块。
如下是我的改造方法:
一、删除所有@Region为实体的对象,然后删除对应的dao,service和controller,这是根治不使用Gemfire数据库的重要操作。
举例说明:
实体:BusAlarmInfo.java
@Setter
@Getter
@Region("bus_alarm_info")
public class BusAlarmInfo{
@Id
private BusDateKey key;
private Set<AlarmInfoItem> alarms;
public BusAlarmInfo() {
}
}
DAO:BusAlarmInfoRepository.java
public interface BusAlarmInfoRepository extends GemfireRepository<BusAlarmInfo, BusDateKey> {
}
一个工作原则,所有涉及到这些类的相关程序都要删除,或者注解掉,保证程序能够正常编译就行。
二、从依赖中完全排除gemfire和spring-data-gemfire。在pom.xml中移除这些依赖:
<dependency>
<groupId>io.pivotal.gemfire</groupId>
<artifactId>gemfire</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.geode</groupId>
<artifactId>spring-data-geode</artifactId>
</dependency>
三.(可选)在application.yaml配置文件当中声明使用本地私有数据缓冲。配置如下:
Spring
cache:
type: simple
data:
gemfire:
cache:
location: ON
经过本人测试,这一步设置了在启动时不会报错,也不会有警告信息。如果没有这一步只有一些警告信息,并不影响程序正常启动。 四、如果应用有一个自定义的启动引导类(extends SpringBootServletInitializer),进行如下修改,
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.gemfire.config.annotation.ClientCacheApplication;
import org.springframework.data.gemfire.config.annotation.EnablePdx;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* .
*
* <p>
*
* weiya He
* @since 1.3.0
*
* <p><b>Note:</b>
* <p>2020/8/24 13:48: created.<br>
*/
@SpringBootApplication
@EnableScheduling
@ClientCacheApplication(name = "aiBoxGM", locators = @ClientCacheApplication.Locator, subscriptionEnabled = false)
@EnablePdx
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
重要的注入声明: 1. @ClientCacheApplication注解的locators属性必须指定Gemfire服务器的主机和端口,但你只有@ClientCacheApplication.Locator,这是错误的。它应该类似于:
locators = {"localhost:40404"}
2. @EnablePdx注解启用了Gemfire的Pdx序列化,但你的客户端无法连接到服务器,所以Pdx目前无法使用。这可能会导致其他错误。 3. 你应该在application.properties中指定
spring.data.gemfire.pool.subscriptionEnabled=false
或者使用我上面的第三步的方法,都可以。 4. 可以捕获ConnectionRefusedException,并在日志中打印更详细的上下文以帮助找出问题。修复后的代码如下:
@SpringBootApplication
@EnableScheduling
@ClientCacheApplication(name = "aiBoxGM", locators = {"localhost:40404"})
public class Application {
@Bean
public CacheListener cacheListener() {
return new CacheListenerAdapter() {
@Override
public void afterCreate(EntryEvent event) {
// Ignore PdxInstance for now until server is available
}
};
}
public static void main(String[] args) {
try {
SpringApplication.run(Application.class, args);
} catch (ConnectionRefusedException e) {
System.err.println("Unable to connect to Gemfire server!");
e.printStackTrace();
}
}
}
注意,这时要把pom.xml当中加入:
<dependency>
<groupId>org.springframework.geode</groupId>
<artifactId>spring-geode-starter</artifactId>
<version>1.1.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
如果问题仍未解决,请提供你完整的 Spring Boot配置、代码和日志,我很乐意帮助进一步诊断和修复。
总结一下:
1. 删除所有与Gemfire集成相关的代码,包括@Region实体、DAO和服务等等。这是最根本的一步。
2. 从依赖中完全排除gemfire和spring-data-gemfire。这可以防止Gemfire与Spring Boot的自动集成。
3. 在application.properties中配置spring.data.gemfire.cache.location=OFF可以避免启动时与Gemfire相关的警告,这一步可选但推荐。
4. 确保启动引导类中没有初始化GemfireCache。需要删除@ClientCacheApplication和locators属性。
5. @EnablePdx注解,因为Pdx需要连接到Gemfire服务器才能使用。
6. 捕获ConnectionRefusedException并打印详细日志以帮助排查问题。
7. 如果有自定义的CacheListener,需要添加判断以免错误地调用Pdx相关方法。
另外,如果要排除一些类使用gemfire的话,可以使用:
@EnableGemfireRepositories(basePackageClasses= {你的包+类名.class})
public class Application {
}
启动后的日志将是这样的:
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@170cbd63]
2023-06-06 09:19:43.175 INFO --- [Timer-DEFAULT-3] AutoConnectionSourceImpl : updateLocatorInLocatorList changing locator list: loc form: LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false] ,loc to: localhost/127.0.0.1:10334
2023-06-06 09:19:43.176 INFO --- [Timer-DEFAULT-3] AutoConnectionSourceImpl : updateLocatorInLocatorList locator list from:[localhost/127.0.0.1:10334] to: [LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false]]
2023-06-06 09:19:43.182 INFO --- [Timer-DEFAULT-3] AutoConnectionSourceImpl : updateLocatorInLocatorList changing locator list: loc form: LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false] ,loc to: localhost/127.0.0.1:10334
2023-06-06 09:19:43.182 INFO --- [Timer-DEFAULT-3] AutoConnectionSourceImpl : updateLocatorInLocatorList locator list from:[localhost/127.0.0.1:10334] to: [LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false]]
2023-06-06 09:19:43.182 INFO --- [Timer-DEFAULT-3] ConnectionManagerImpl : Unable to prefill pool to minimum because: Unable to connect to any locators in the list [LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false]]
2023-06-06 09:19:43.191 INFO --- [ueTimer-DEFAULT] AutoConnectionSourceImpl : updateLocatorInLocatorList changing locator list: loc form: LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false] ,loc to: localhost/127.0.0.1:10334
2023-06-06 09:19:43.192 INFO --- [ueTimer-DEFAULT] AutoConnectionSourceImpl : updateLocatorInLocatorList locator list from:[localhost/127.0.0.1:10334] to: [LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false]]