【微服务项目-短信平台】

微服务项目-短信平台

父级pom

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    
    <!--声明当前项目是springboot-->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
    </parent>
    <groupId>com.test</groupId>
    <artifactId>smsplatform</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>smsplatform</name>
    <description>smsplatform</description>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR5</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

一、注册中心

pom

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>smsplatform</artifactId>
        <groupId>com.test</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>sms-register</artifactId>


    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <profiles>
        <profile>
            <!--id与配置文件后缀一致-->
            <id>local</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <!--profileActive与配置文件的属性一致-->
                <profileActive>local</profileActive>
            </properties>
        </profile>

        <profile>
            <!--id与配置文件后缀一致-->
            <id>prod</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <properties>
                <!--profileActive与配置文件的属性一致-->
                <profileActive>prod</profileActive>
            </properties>
        </profile>
    </profiles>
</project>

配置文件

application.yml

java 复制代码
server:
  port: 8000
spring:
  application:
    name: sms-register
  profiles:
    active: @profileActive@

@profileActive@属性在pom文件中,pom中配置后,可在maven页面看到,打包时勾选哪个环境就是哪个环境配置打包

本地配置

java 复制代码
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka
      fetch-register: true
      register-with-eureka: false

启动类

java 复制代码
package com.test.register;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class RegisterServer {
    public static void main(String[] args) {
        SpringApplication.run(RegisterServer.class,args);
        System.out.println("############ sms-register start success  ###########");
    }
}

验证

启动后在浏览器输入http://localhost:8000/

配置中心

pom

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>smsplatform</artifactId>
        <groupId>com.test</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>sms-config-server</artifactId>


    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <profiles>
        <profile>
            <!--id与配置文件后缀一致-->
            <id>local</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <!--profileActive与配置文件的属性一致-->
                <profileActive>local</profileActive>
            </properties>
        </profile>

        <profile>
            <!--id与配置文件后缀一致-->
            <id>prod</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <properties>
                <!--profileActive与配置文件的属性一致-->
                <profileActive>prod</profileActive>
            </properties>
        </profile>
    </profiles>
</project>

配置文件

java 复制代码
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka
spring:
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/qfp17393120407/sms # 私有仓库需要配置用户名和密码

启动类

java 复制代码
package com.test.config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.config.server.EnableConfigServer;

@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServer {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServer.class,args);
        System.out.println("############# ConfigServer start success ###########");
    }
}

启动验证

启动成功且注册到eureka

缓存模块搭建

pom

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>smsplatform</artifactId>
        <groupId>com.test</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>sms-cache</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

    </dependencies>

    <!--指定资源文件目录,防止无法读到属性-->
    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>

    <profiles>
        <profile>
            <!--id与配置文件后缀一致-->
            <id>local</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <!--profileActive与配置文件的属性一致-->
                <profileActive>local</profileActive>
            </properties>
        </profile>

        <profile>
            <!--id与配置文件后缀一致-->
            <id>prod</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <properties>
                <!--profileActive与配置文件的属性一致-->
                <profileActive>prod</profileActive>
            </properties>
        </profile>
    </profiles>
</project>

redis配置类

package com.test.cache.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;

import com.fasterxml.jackson.annotation.PropertyAccessor;

import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.cache.CacheManager;

import org.springframework.cache.annotation.CachingConfigurerSupport;

import org.springframework.cache.interceptor.KeyGenerator;

import org.springframework.context.annotation.Bean;

import org.springframework.data.redis.cache.RedisCacheConfiguration;

import org.springframework.data.redis.cache.RedisCacheManager;

import org.springframework.data.redis.cache.RedisCacheWriter;

import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

import org.springframework.data.redis.core.RedisTemplate;

import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;

import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;

public class RedisConfig extends CachingConfigurerSupport {

@Override

@Bean

public KeyGenerator keyGenerator() {

return new KeyGenerator() {

@Override

public Object generate(Object target, Method method, Object... params) {

StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append(target.getClass().getName());

stringBuilder.append(method.getName());

for (Object param : params) {

stringBuilder.append(params.toString());

}

return stringBuilder.toString();

}

};

}

复制代码
@Bean
public CacheManager cacheManager(LettuceConnectionFactory connectionFactory) {
    //以锁写入的方式创建我们的写入对象
    RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(connectionFactory);
    //创建默认的缓存配置对象
    RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
    //根据我们的默认配置和写入方式创建缓存的管理器
    RedisCacheManager manager = new RedisCacheManager(writer, cacheConfiguration);

    return manager;
}



@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
    RedisTemplate<String,Object> template = new RedisTemplate();
    template.setConnectionFactory(factory);

    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    template.setKeySerializer(stringRedisSerializer);
    template.setHashKeySerializer(stringRedisSerializer);


    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
    objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
    jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

    template.setValueSerializer(jackson2JsonRedisSerializer);
    template.setHashValueSerializer(jackson2JsonRedisSerializer);
    template.afterPropertiesSet();
    return template;

}

}

缓存api

java 复制代码
package com.test.cache.controller;

import com.test.cache.service.CacheService;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/cache")
public class CacheController {

    private static final Logger LOGGER = LoggerFactory.getLogger(CacheController.class);
    @Autowired
    private CacheService cacheService;

    /**
     *
     * @param key  set 的 key
     * @param value
     * @param expireSecond 有效期 是一个秒
     */
    @GetMapping(value = "/save2cache")
    @ApiOperation("存储字符串类型的数据")
    public boolean save2Cache(@ApiParam(name = "key",required = true,value = "保存的 key") String key,
                              @ApiParam(name = "value",required = true,value = "保存的 value") String value,
                              @ApiParam(name = "expireSecond",required = true,value = "有效期")Integer expireSecond) {
        LOGGER.error("save2cache执行了:传递的 key 是{},value 是{},有效期是{}",key,value,expireSecond);
        cacheService.save2Cache(key,value,expireSecond);
        return true;
    }

    @GetMapping("/get/{key}")
    @ApiOperation("从 redis 中获取字符串类型的数据")
    public String get(@PathVariable String key) {
        return cacheService.get(key);
    }

//
//    /**
//     * 这个方法应该要接收具体类型的参数,而不是直接接收一个 Object
//     * @param key
//     * @param value
//     */
//    @GetMapping(value = "/save2cache")
//    public void save2Cache(String key, Object value, Integer expireSecond) {
//        cacheService.save2Cache(key,value,expireSecond);
//    }
//
//    /**
//     * 这个方法应该要接收具体类型的参数,而不是直接接收一个 Object
//     * @param key
//     * @param value
//     */
//    @GetMapping(value = "/save2cache")
//    public void save2Cache(String key, Object value) {
//        cacheService.save2Cache(key,value);
//    }

    @PostMapping(value = "/save2cache/{key}/{value}")
    @ApiOperation("永久保存数据到redis")
    public boolean save2Cache(@PathVariable String key,@PathVariable String value) {
        LOGGER.error("save2cache执行了 key:{} value:{}",key,value);
        cacheService.save2Cache(key,value);
        return true;
    }
    //因为我们还没有考虑好存放的具体是对象是什么,所以暂时还无法编写获取对象的方法,实际上就是调用了 get 方法

    @RequestMapping("/getbject/{key}")
    public Object getObject(@PathVariable String key) {
        return cacheService.getObject(key);
    }
    @ApiOperation("从 redis 中删除指定 key")
    @PostMapping("/delete")
    public Long del(String... keys) {
        LOGGER.error("delete执行了 keys{}",keys);
        return cacheService.del(keys);
    }

    @PostMapping("/expire/{key}/{seconds}")
    @ApiOperation("给指定的 key 设置有效期")
    public boolean expire(@PathVariable String key, @PathVariable long seconds) {
        LOGGER.error("expire执行了 keys{} seconds{}",key,seconds);
        return cacheService.expire(key, seconds);
    }

    @GetMapping("/incr")
    @ApiOperation("递增")
    public long incr(String key, @RequestParam(defaultValue = "1") long delta) {
        LOGGER.error("incr执行了 keys{} delta{}",key,delta);
        return cacheService.incr(key,delta);
    }

    @GetMapping("/decr")
    @ApiOperation("递减")
    public long decr(String key,@RequestParam(defaultValue = "-1") long delta) {
        LOGGER.error("decr执行了 keys{} delta{}",key,delta);
        return cacheService.decr(key,delta);
    }
    @GetMapping("/hmget/{key}")
    @ApiOperation("从 redis 中获取 hash 类型的数据")
    public Map<Object, Object> hGetAll(@PathVariable String key) {

        LOGGER.error("hmget执行了 key{}",key);
        return cacheService.hGetAll(key);
    }

    /**
     * hash赋值
     * @param key
     * @param map
     * @return
     */
    @PostMapping("/hmset/{key}")
    @ApiOperation("保存 json 到 redis 的 hash 中")
    public boolean hMset(@PathVariable String key, @RequestBody Map<String, Object> map) {
        LOGGER.error("hMset执行了 key{} map{}",key,map);
        cacheService.hMset(key, map);
        return true;
    }

}

实现类

java 复制代码
package com.test.cache.service.impl;

import com.test.cache.service.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class CacheServiceImpl implements CacheService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void save2Cache(String key, String value, Integer expireSecond) {
        redisTemplate.opsForValue().set(key, value, expireSecond, TimeUnit.SECONDS);
    }

    @Override
    public void save2Cache(String key, Object value, Integer expireSecond) {
        redisTemplate.opsForValue().set(key, value, expireSecond, TimeUnit.SECONDS);
    }

    @Override
    public void save2Cache(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public void save2Cache(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    @Override
    public String get(String key) {

//        redisTemplate.setKeySerializer(new StringRedisSerializer());
//        redisTemplate.setValueSerializer(new StringRedisSerializer());
        Object result = redisTemplate.opsForValue().get(key);
        return (String) result;
    }

    @Override
    public Object getObject(String key) {
        return  redisTemplate.opsForValue().get(key);
    }

    @Override
    public Long del(String... keys) {
        return redisTemplate.delete(CollectionUtils.arrayToList(keys));

    }

    @Override
    public boolean expire(String key, long seconds) {
        return redisTemplate.expire(key,seconds,TimeUnit.SECONDS);
    }

    @Override
    public long incr(String key, long delta) {
        return redisTemplate.opsForValue().increment(key,delta);
    }

    @Override
    public long decr(String key, long delta) {
        return redisTemplate.opsForValue().decrement(key,delta);
    }

    @Override
    public Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    @Override
    public void hMset(String key, Map<String, Object> map) {
        redisTemplate.opsForHash().putAll(key, map);
    }
}

配置文件

application.yml

yaml 复制代码
server:
  port: 8002
spring:
  application:
    name: sms-cache
  profiles:
    active: @profileActive@

使用配置中心需要bootstrap配置

bootstrap-local.yml

yaml 复制代码
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka

redis配置在配置中心指定目录下配置

在配置中心目录下创建配置文件

读取顺序

启动流程如下图

webmaster

代码太多见源码

源码

微服务短信平台

相关推荐
努力d小白2 小时前
java 数据类型
java
jinggongszh2 小时前
数字化转型先上系统还是先理流程?
大数据·人工智能·微服务·制造
我命由我123452 小时前
Android Jetpack Compose - SearchBar(搜索栏)、Tab(标签页)、时间选择器、TooltipBox(工具提示)
android·java·java-ee·kotlin·android studio·android jetpack·android-studio
SPC的存折2 小时前
(自用)LNMP-Redis-Discuz5.0部署指南-openEuler24.03-测试环境
linux·运维·服务器·数据库·redis·缓存
27669582922 小时前
token1005 算法分析
java·前端·javascript·token·token1005·携程酒店·token算法分析
海寻山2 小时前
Java内部类:4种类型+实战场景+面试避坑
java·开发语言·面试
Lsk_Smion2 小时前
Hot100(开刷) 之 长度最小的数组--删除倒数第N个链表--层序遍历
java·数据结构·算法·kotlin
2601_950703943 小时前
PyCharm性能优化终极指南
java
yzp-3 小时前
Spring 三级缓存 ---- 简单明了豆包版
java·mysql·spring