1. 配置文件 applicationContext.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
  4. xmlns:c="http://www.springframework.org/schema/c" xmlns:cache="http://www.springframework.org/schema/cache"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
  7. xmlns:lang="http://www.springframework.org/schema/lang" xmlns:mvc="http://www.springframework.org/schema/mvc"
  8. xmlns:p="http://www.springframework.org/schema/p" xmlns:task="http://www.springframework.org/schema/task"
  9. xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
  10. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  11. http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
  12. http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
  13. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  14. http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
  15. http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
  16. http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
  17. http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
  18. http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
  19. http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
  20. http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
  21. <!-- Scans the classpath of this application for @Components to deploy as
  22. beans -->
  23. <context:component-scan base-package="com.study"/>
  24. <bean
  25. class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  26. <property name="locations">
  27. <list>
  28. <value>classpath:config.properties</value>
  29. </list>
  30. </property>
  31. </bean>
  32. <!-- 配置druid数据源 -->
  33. <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
  34. init-method="init" destroy-method="close">
  35. <!-- 数据库连接基础信息 -->
  36. <property name="url" value="${jdbc_url}"/>
  37. <property name="username" value="${jdbc_username}"/>
  38. <property name="password" value="${jdbc_password}"/>
  39. <!-- 初始化连接大小 -->
  40. <property name="initialSize" value="0"/>
  41. <!-- 连接池最大使用连接数量 -->
  42. <property name="maxActive" value="2000"/>
  43. <!-- 连接池最小空闲 -->
  44. <property name="minIdle" value="0"/>
  45. <!-- 获取连接最大等待时间 -->
  46. <property name="maxWait" value="3000"/>
  47. <!-- 是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql下建议关闭。 -->
  48. <!-- <property name="poolPreparedStatements" value="true" /> <property
  49. name="maxPoolPreparedStatementPerConnectionSize" value="33" /> -->
  50. <!-- 验证数据库连接有效性,要求查询语句 -->
  51. <property name="validationQuery" value="${validationQuery}"/>
  52. <!-- 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 -->
  53. <property name="testWhileIdle" value="true"/>
  54. <!-- 申请连接时执行validationQuery检测连接是否有效,配置true会降低性能。 -->
  55. <property name="testOnBorrow" value="false"/>
  56. <!-- 归还连接时执行validationQuery检测连接是否有效,配置true会降低性能 -->
  57. <property name="testOnReturn" value="false"/>
  58. <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
  59. <property name="timeBetweenEvictionRunsMillis" value="60000"/>
  60. <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
  61. <property name="minEvictableIdleTimeMillis" value="25200000"/>
  62. <!-- 对于长时间不使用的连接强制关闭 -->
  63. <property name="removeAbandoned" value="true"/>
  64. <!-- 关闭超过30分钟的空闲连接,1800秒,也就是30分钟 -->
  65. <property name="removeAbandonedTimeout" value="1800"/>
  66. <!-- 关闭abanded连接时输出错误日志 -->
  67. <property name="logAbandoned" value="true"/>
  68. <!-- 监控数据库 -->
  69. <!-- <property name="filters" value="mergeStat" /> -->
  70. <property name="filters" value="stat"/>
  71. </bean>
  72. <!-- 使用 spring jdbc 模板 -->
  73. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  74. <constructor-arg ref="dataSource"/>
  75. </bean>
  76. <!-- 此处特意混合一下xml+java两种配置方式
  77. 理论上xml和java事是可以相互替代的
  78. -->
  79. <bean id="stringRedisTemplate"
  80. class="org.springframework.data.redis.core.StringRedisTemplate"
  81. p:connection-factory-ref="redisConnectionFactory" >
  82. </bean>
  83. </beans>

2. 配置类 GeoRedisAppConfig.java

@Configuration
@Profile("geo")
public class GeoRedisAppConfig {

    @Bean
    public LettuceConnectionFactory redisConnectionFactory() {
        System.out.println("使用单机版本");
        return new LettuceConnectionFactory(new RedisStandaloneConfiguration("127.0.0.1", 6379));
    }

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate redisTemplate = new RedisTemplate();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 可以配置对象的转换规则,比如使用json格式对object进行存储。
        // Object --> 序列化 --> 二进制流 --> redis-server存储
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
        return redisTemplate;
    }

}

3. 业务类 GeoExampleService.java

@Service
@Profile("geo")
public class GeoExampleService {

    @Resource
    private RedisTemplate redisTemplate;


    /* 上传位置 */
    public void add(Point point, String userId) {
        redisTemplate.opsForGeo().add("user_geo", new RedisGeoCommands.GeoLocation<>(userId, point));
    }

    /* 附近的人 */
    public GeoResults<RedisGeoCommands.GeoLocation> near(Point point) {
        // 半径 100 米
        Distance distance = new Distance(100, RedisGeoCommands.DistanceUnit.METERS);
        Circle circle = new Circle(point, distance);
        // 附近 5 个人
        RedisGeoCommands.GeoRadiusCommandArgs geoRadiusCommandArgs = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                .includeDistance().limit(5);
        GeoResults<RedisGeoCommands.GeoLocation> user_geo = redisTemplate.opsForGeo().radius("user_geo", circle, geoRadiusCommandArgs);
        return user_geo;
    }

}

4. 测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
@ActiveProfiles("geo")
public class GeoTests {

    @Resource
    private GeoExampleService geoExampleService;

    @Test
    public void test1() {
        // 模拟三个人位置上报
        geoExampleService.add(new Point(116.405285, 39.904989), "zp1");
        geoExampleService.add(new Point(116.405265, 39.904969), "zp2");
        geoExampleService.add(new Point(116.405315, 39.904999), "zp3");

        // zp3 查找附近的人
        GeoResults<RedisGeoCommands.GeoLocation> geoResults = geoExampleService.near(new Point(116.405315, 39.904999));
        for (GeoResult<RedisGeoCommands.GeoLocation> geoResult : geoResults) {
            RedisGeoCommands.GeoLocation content = geoResult.getContent();
            System.out.println(content.getName() + " : " + geoResult.getDistance().getValue());
        }

    }

}

5. 结果

image.png