SpringCloud 搭建企业级开发框架之实现多租户多平台短信通知服务(微服务实战)

目前系统集成短信似乎是必不可少的部分,由于各种云平台都提供了不同的短信通道,这里我们增加多租户多通道的短信验证码,并增加配置项,使系统可以支持多家云平台提供的短信服务。这里以阿里云和腾讯云为例,集成短信通知服务。

1、在GitEgg-Platform中新建gitegg-platform-sms基础工程,定义抽象方法和配置类
SmsSendService发送短信抽象接口:

/**
 * 短信发送接口
 */
public interface SmsSendService {

    /**
     * 发送单个短信
     * @param smsData
     * @param phoneNumber
     * @return
     */
    default SmsResponse sendSms(SmsData smsData, String phoneNumber){
        if (StrUtil.isEmpty(phoneNumber)) {
            return new SmsResponse();
        }
        return this.sendSms(smsData, Collections.singletonList(phoneNumber));
    }

    /**
     * 群发发送短信
     * @param smsData
     * @param phoneNumbers
     * @return
     */
    SmsResponse sendSms(SmsData smsData, Collection<string> phoneNumbers);

}

SmsResultCodeEnum定义短信发送结果

/**
 * @ClassName: ResultCodeEnum
 * @Description: 自定义返回码枚举
 * @author GitEgg
 * @date 2020年09月19日 下午11:49:45
 */
@Getter
@AllArgsConstructor
public enum SmsResultCodeEnum {

    /**
     * 成功
     */
    SUCCESS(200, "操作成功"),

    /**
     * 系统繁忙,请稍后重试
     */
    ERROR(429, "短信发送失败,请稍后重试"),

    /**
     * 系统错误
     */
    PHONE_NUMBER_ERROR(500, "手机号错误");

    public int code;

    public String msg;
}

2、新建gitegg-platform-sms-aliyun工程,实现阿里云短信发送接口
AliyunSmsProperties配置类

@Data
@Component
@ConfigurationProperties(prefix = "sms.aliyun")
public class AliyunSmsProperties {

    /**
     * product
     */
    private String product = "Dysmsapi";

    /**
     * domain
     */
    private String domain = "dysmsapi.aliyuncs.com";

    /**
     * regionId
     */
    private String regionId = "cn-hangzhou";

    /**
     * accessKeyId
     */
    private String accessKeyId;

    /**
     * accessKeySecret
     */
    private String accessKeySecret;

    /**
     * 短信签名
     */
    private String signName;
}

AliyunSmsSendServiceImpl阿里云短信发送接口实现类

/**
 * 阿里云短信发送
 */
@Slf4j
@AllArgsConstructor
public class AliyunSmsSendServiceImpl implements SmsSendService {

    private static final String successCode = "OK";

    private final AliyunSmsProperties properties;

    private final IAcsClient acsClient;

    @Override
    public SmsResponse sendSms(SmsData smsData, Collection<string> phoneNumbers) {
        SmsResponse smsResponse = new SmsResponse();
        SendSmsRequest request = new SendSmsRequest();
        request.setSysMethod(MethodType.POST);
        request.setPhoneNumbers(StrUtil.join(",", phoneNumbers));
        request.setSignName(properties.getSignName());
        request.setTemplateCode(smsData.getTemplateId());
        request.setTemplateParam(JsonUtils.mapToJson(smsData.getParams()));
        try {
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
            if (null != sendSmsResponse && !StringUtils.isEmpty(sendSmsResponse.getCode())) {
                if (this.successCode.equals(sendSmsResponse.getCode())) {
                    smsResponse.setSuccess(true);
                } else {
                    log.error("Send Aliyun Sms Fail: [code={}, message={}]", sendSmsResponse.getCode(), sendSmsResponse.getMessage());
                }
                smsResponse.setCode(sendSmsResponse.getCode());
                smsResponse.setMessage(sendSmsResponse.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Send Aliyun Sms Fail: {}", e);
            smsResponse.setMessage("Send Aliyun Sms Fail!");
        }
        return smsResponse;
    }

}

3、新建gitegg-platform-sms-tencent工程,实现腾讯云短信发送接口
TencentSmsProperties配置类

@Data
@Component
@ConfigurationProperties(prefix = "sms.tencent")
public class TencentSmsProperties {

    /* 填充请求参数,这里 request 对象的成员变量即对应接口的入参
     * 您可以通过官网接口文档或跳转到 request 对象的定义处查看请求参数的定义
     * 基本类型的设置:
     * 帮助链接:
     * 短信控制台:https://console.cloud.tencent.com/smsv2
     * sms helper:https://cloud.tencent.com/document/product/382/3773 */
    /* 短信应用 ID: 在 [短信控制台] 添加应用后生成的实际 SDKAppID,例如1400006666 */
    private String SmsSdkAppId;

    /* 国际/港澳台短信 senderid: 国内短信填空,默认未开通,如需开通请联系 [sms helper] */
    private String senderId;

    /* 短信码号扩展号: 默认未开通,如需开通请联系 [sms helper] */
    private String extendCode;

    /**
     * 短信签名
     */
    private String signName;
}

TencentSmsSendServiceImpl腾讯云短信发送接口实现类

/**
 * 腾讯云短信发送
 */
@Slf4j
@AllArgsConstructor
public class TencentSmsSendServiceImpl implements SmsSendService {

    private static final String successCode = "Ok";

    private final TencentSmsProperties properties;

    private final SmsClient client;

    @Override
    public SmsResponse sendSms(SmsData smsData, Collection<string> phoneNumbers) {
        SmsResponse smsResponse = new SmsResponse();

        SendSmsRequest request = new SendSmsRequest();
        request.setSmsSdkAppid(properties.getSmsSdkAppId());
        /* 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名,可登录 [短信控制台] 查看签名信息 */
        request.setSign(properties.getSignName());
        /* 国际/港澳台短信 senderid: 国内短信填空,默认未开通,如需开通请联系 [sms helper] */
        if (!StringUtils.isEmpty(properties.getSenderId()))
        {
            request.setSenderId(properties.getSenderId());
        }
        request.setTemplateID(smsData.getTemplateId());
        /* 下发手机号码,采用 e.164 标准,+[国家或地区码][手机号]
         * 例如+8613711112222, 其中前面有一个+号 ,86为国家码,13711112222为手机号,最多不要超过200个手机号*/
        String[] phoneNumbersArray = (String[]) phoneNumbers.toArray();
        request.setPhoneNumberSet(phoneNumbersArray);
        /* 模板参数: 若无模板参数,则设置为空*/
        String[] templateParams = new String[]{};
        if (!CollectionUtils.isEmpty(smsData.getParams())) {
            templateParams = (String[]) smsData.getParams().values().toArray();
        }
        request.setTemplateParamSet(templateParams);
        try {
            /* 通过 client 对象调用 SendSms 方法发起请求。注意请求方法名与请求对象是对应的
             * 返回的 res 是一个 SendSmsResponse 类的实例,与请求对象对应 */
            SendSmsResponse sendSmsResponse = client.SendSms(request);
            //如果是批量发送,那么腾讯云短信会返回每条短信的发送状态,这里默认返回第一条短信的状态
            if (null != sendSmsResponse && null != sendSmsResponse.getSendStatusSet()) {
                SendStatus sendStatus = sendSmsResponse.getSendStatusSet()[0];
                if (this.successCode.equals(sendStatus.getCode()))
                {
                    smsResponse.setSuccess(true);
                }
                else
                {
                    smsResponse.setCode(sendStatus.getCode());
                    smsResponse.setMessage(sendStatus.getMessage());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Send Aliyun Sms Fail: {}", e);
            smsResponse.setMessage("Send Aliyun Sms Fail!");
        }
        return smsResponse;
    }
}

4、在GitEgg-Cloud中新建业务调用方法,这里要考虑到不同租户调用不同的短信配置进行短信发送,所以新建SmsFactory短信接口实例化工厂,根据不同的租户实例化不同的短信发送接口,这里以实例化com.gitegg.service.extension.sms.factory.SmsAliyunFactory类为例,进行实例化操作,实际使用中,这里需要配置和租户的对应关系,从租户的短信配置中获取。

@Component
public class SmsFactory {

    private final ISmsTemplateService smsTemplateService;

    /**
     * SmsSendService 缓存
     */
    private final Map<long, smssendservice=""> SmsSendServiceMap = new ConcurrentHashMap<>();

    public SmsFactory(ISmsTemplateService smsTemplateService) {
        this.smsTemplateService = smsTemplateService;
    }

    /**
     * 获取 SmsSendService
     *
     * @param smsTemplateDTO 短信模板
     * @return SmsSendService
     */
    public SmsSendService getSmsSendService(SmsTemplateDTO smsTemplateDTO) {

        //根据channelId获取对应的发送短信服务接口,channelId是唯一的,每个租户有其自有的channelId
        Long channelId = smsTemplateDTO.getChannelId();
        SmsSendService smsSendService = SmsSendServiceMap.get(channelId);
        if (null == smsSendService) {
            Class cls = null;
            try {
                cls = Class.forName("com.gitegg.service.extension.sms.factory.SmsAliyunFactory");
                Method staticMethod = cls.getDeclaredMethod("getSmsSendService", SmsTemplateDTO.class);
                smsSendService = (SmsSendService) staticMethod.invoke(cls,smsTemplateDTO);
                SmsSendServiceMap.put(channelId, smsSendService);
            } catch (ClassNotFoundException | NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }

        }
        return smsSendService;
    }
}
/**
 * 阿里云短信服务接口工厂类
 */
public class SmsAliyunFactory {

    public static SmsSendService getSmsSendService(SmsTemplateDTO sms) {
        AliyunSmsProperties aliyunSmsProperties = new AliyunSmsProperties();
        aliyunSmsProperties.setAccessKeyId(sms.getSecretId());
        aliyunSmsProperties.setAccessKeySecret(sms.getSecretKey());
        aliyunSmsProperties.setRegionId(sms.getRegionId());
        aliyunSmsProperties.setSignName(sms.getSignName());
        IClientProfile profile = DefaultProfile.getProfile(aliyunSmsProperties.getRegionId(), aliyunSmsProperties.getAccessKeyId(), aliyunSmsProperties.getAccessKeySecret());
        IAcsClient acsClient = new DefaultAcsClient(profile);
        return new AliyunSmsSendServiceImpl(aliyunSmsProperties, acsClient);
    }

}
/**
 * 腾讯云短信服务接口工厂类
 */
public class SmsTencentFactory {

    public static SmsSendService getSmsSendService(SmsTemplateDTO sms) {

        TencentSmsProperties tencentSmsProperties = new TencentSmsProperties();
        tencentSmsProperties.setSmsSdkAppId(sms.getSecretId());
        tencentSmsProperties.setExtendCode(sms.getSecretKey());
        tencentSmsProperties.setSenderId(sms.getRegionId());
        tencentSmsProperties.setSignName(sms.getSignName());

        /* 必要步骤:
         * 实例化一个认证对象,入参需要传入腾讯云账户密钥对 secretId 和 secretKey
         * 本示例采用从环境变量读取的方式,需要预先在环境变量中设置这两个值
         * 您也可以直接在代码中写入密钥对,但需谨防泄露,不要将代码复制、上传或者分享给他人
         * CAM 密钥查询:https://console.cloud.tencent.com/cam/capi
         */
        Credential cred = new Credential(sms.getSecretId(), sms.getSecretKey());
        // 实例化一个 http 选项,可选,无特殊需求时可以跳过
        HttpProfile httpProfile = new HttpProfile();
        // 设置代理
//        httpProfile.setProxyHost("host");
//        httpProfile.setProxyPort(port);
        /* SDK 默认使用 POST 方法。
         * 如需使用 GET 方法,可以在此处设置,但 GET 方法无法处理较大的请求 */
        httpProfile.setReqMethod("POST");
        /* SDK 有默认的超时时间,非必要请不要进行调整
         * 如有需要请在代码中查阅以获取最新的默认值 */
        httpProfile.setConnTimeout(60);
        /* SDK 会自动指定域名,通常无需指定域名,但访问金融区的服务时必须手动指定域名
         * 例如 SMS 的上海金融区域名为 sms.ap-shanghai-fsi.tencentcloudapi.com */
        if (!StringUtils.isEmpty(sms.getRegionId()))
        {
            httpProfile.setEndpoint(sms.getRegionId());
        }

        /* 非必要步骤:
         * 实例化一个客户端配置对象,可以指定超时时间等配置 */
        ClientProfile clientProfile = new ClientProfile();
        /* SDK 默认用 TC3-HMAC-SHA256 进行签名
         * 非必要请不要修改该字段 */
        clientProfile.setSignMethod("HmacSHA256");
        clientProfile.setHttpProfile(httpProfile);
        /* 实例化 SMS 的 client 对象
         * 第二个参数是地域信息,可以直接填写字符串 ap-guangzhou,或者引用预设的常量 */
        SmsClient client = new SmsClient(cred, "",clientProfile);

        return new TencentSmsSendServiceImpl(tencentSmsProperties, client);
    }
}

5、定义短信发送接口及实现类
ISmsService业务短信发送接口定义

/**
 * <p>
 * 短信发送接口定义
 * </p>
 *
 * @author GitEgg
 * @since 2021-01-25
 */
public interface ISmsService {

    /**
     * 发送短信
     *
     * @param smsCode
     * @param smsData
     * @param phoneNumbers
     * @return
     */
    SmsResponse sendSmsNormal(String smsCode, String smsData, String phoneNumbers);

    /**
     * 发送短信验证码
     *
     * @param smsCode
     * @param phoneNumber
     * @return
     */
    SmsResponse sendSmsVerificationCode( String smsCode, String phoneNumber);

    /**
     * 校验短信验证码
     *
     * @param smsCode
     * @param phoneNumber
     * @return
     */
    boolean checkSmsVerificationCode(String smsCode, String phoneNumber, String verificationCode);

}

SmsServiceImpl 短信发送接口实现类

/**
 * <p>
 * 短信发送接口实现类
 * </p>
 *
 * @author GitEgg
 * @since 2021-01-25
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class SmsServiceImpl implements ISmsService {

    private final SmsFactory smsFactory;

    private final ISmsTemplateService smsTemplateService;

    private final RedisTemplate redisTemplate;

    @Override
    public SmsResponse sendSmsNormal(String smsCode, String smsData, String phoneNumbers) {
        SmsResponse smsResponse = new SmsResponse();
        try {
            QuerySmsTemplateDTO querySmsTemplateDTO = new QuerySmsTemplateDTO();
            querySmsTemplateDTO.setSmsCode(smsCode);
            //获取短信code的相关信息,租户信息会根据mybatis plus插件获取
            SmsTemplateDTO smsTemplateDTO = smsTemplateService.querySmsTemplate(querySmsTemplateDTO);
            ObjectMapper mapper = new ObjectMapper();
            Map smsDataMap = mapper.readValue(smsData, Map.class);

            List<string> phoneNumberList =  JsonUtils.jsonToList(phoneNumbers, String.class);
            SmsData smsDataParam = new SmsData();
            smsDataParam.setTemplateId(smsTemplateDTO.getTemplateId());
            smsDataParam.setParams(smsDataMap);
            SmsSendService smsSendService = smsFactory.getSmsSendService(smsTemplateDTO);
            smsResponse = smsSendService.sendSms(smsDataParam, phoneNumberList);
        } catch (Exception e) {
            smsResponse.setMessage("短信发送失败");
            e.printStackTrace();
        }
        return smsResponse;
    }

    @Override
    public SmsResponse sendSmsVerificationCode(String smsCode, String phoneNumber) {
        String verificationCode = RandomUtil.randomNumbers(6);
        Map<string, string=""> smsDataMap = new HashMap<>();
        smsDataMap.put(SmsConstant.SMS_CAPTCHA_TEMPLATE_CODE, verificationCode);
        List<string> phoneNumbers = Arrays.asList(phoneNumber);
        SmsResponse smsResponse = this.sendSmsNormal(smsCode, JsonUtils.mapToJson(smsDataMap), JsonUtils.listToJson(phoneNumbers));
        if (null != smsResponse && smsResponse.isSuccess()) {
            // 将短信验证码存入redis并设置过期时间为5分钟
            redisTemplate.opsForValue().set(SmsConstant.SMS_CAPTCHA_KEY + smsCode + phoneNumber, verificationCode, 30,
                    TimeUnit.MINUTES);
        }
        return smsResponse;
    }

    @Override
    public boolean checkSmsVerificationCode(String smsCode, String phoneNumber, String verificationCode) {
        String verificationCodeRedis = (String) redisTemplate.opsForValue().get(SmsConstant.SMS_CAPTCHA_KEY + smsCode + phoneNumber);
        if (!StrUtil.isAllEmpty(verificationCodeRedis, verificationCode) && verificationCode.equalsIgnoreCase(verificationCodeRedis)) {
            return true;
        }
        return false;
    }
}

6、新建SmsFeign类,供其他微服务调用发送短信

/**
 * @ClassName: SmsFeign
 * @Description: SmsFeign前端控制器
 * @author gitegg
 * @date 2019年5月18日 下午4:03:58
 */
@RestController
@RequestMapping(value = "/feign/sms")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Api(value = "SmsFeign|提供微服务调用接口")
@RefreshScope
public class SmsFeign {

    private final ISmsService smsService;

    @GetMapping(value = "/send/normal")
    @ApiOperation(value = "发送普通短信", notes = "发送普通短信")
    Result<object> sendSmsNormal(@RequestParam("smsCode") String smsCode, @RequestParam("smsData") String smsData, @RequestParam("phoneNumbers") String phoneNumbers) {
        SmsResponse smsResponse = smsService.sendSmsNormal(smsCode, smsData, phoneNumbers);
        return Result.data(smsResponse);
    }

    @GetMapping(value = "/send/verification/code")
    @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码")
    Result<object> sendSmsVerificationCode(@RequestParam("smsCode") String smsCode, @RequestParam("phoneNumber") String phoneNumber) {
        SmsResponse smsResponse = smsService.sendSmsVerificationCode(smsCode, phoneNumber);
        return Result.data(smsResponse);
    }

    @GetMapping(value = "/check/verification/code")
    @ApiOperation(value = "校验短信验证码", notes = "校验短信验证码")
    Result<boolean> checkSmsVerificationCode(@RequestParam("smsCode") String smsCode, @RequestParam("phoneNumber") String phoneNumber, @RequestParam("verificationCode") String verificationCode) {
        boolean checkResult = smsService.checkSmsVerificationCode(smsCode, phoneNumber, verificationCode);
        return Result.data(checkResult);
    }
}

项目源码:

Gitee: https://gitee.com/wmz1930/GitEgg

GitHub: https://github.com/wmz1930/GitEgg

到此这篇关于SpringCloud 搭建企业级开发框架之实现多租户多平台短信通知服务的文章就介绍到这了,更多相关SpringCloud 短信通知服务内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringCloud 微服务最佳开发实践

    现在基于SpringCloud的微服务开发日益流行,网上各种开源项目层出不穷.我们在实际工作中可以参考开源项目实现很多开箱即用的功能,但是必须要遵守一定的约定和规范. 本文结合我们实际的开发中遇到的一些问题整理出了一份微服务开发的实践规范,欢迎各位大佬拍砖指点. Maven规范 1.所有项目必须要有一个统一的parent模块 所有微服务工程都依赖这个parent,parent用于管理依赖版本,maven仓库,jar版本的统一升级维护 在parent下层可以有 core,starter,rate-

  • SpringCloud微服务之Config知识总结

    一.什么是Spring Cloud Config? Spring Cloud Config 可以为微服务架构中的应用提供集中化的外部配置支持,它分为服务端和客户端两个部分. Spring Cloud Config 服务端被称为分布式配置中心,它是个独立的应用,可以从配置仓库获取配置信息并提供给客户端使用. Spring Cloud Config 客户端可以通过配置中心来获取配置信息,在启动时加载配置. Spring Cloud Config 的配置中心默认采用Git来存储配置信息,所以天然就支持

  • SpringCloud微服务基础简介

    一.什么是Spring Cloud? SpringCloud 对常见的分布式系统模式提供了简单易用的编程模型,帮助开发者构建弹性.可靠.协调的应用程序. SpringCloud 是在SpringBoot的基础上构建的,使开发者可以轻松入门并快速提高工作效率. SpringCloud 提供了一套微服务解决方案,包括服务注册与发现,配置中心,全链路监控,服务网关,负载均衡,熔断器等组件,除了基于NetFlix的开源组件做高度抽象封装之外,还有一些选型中立的开源组件. SpringCloud 为开发人

  • SpringCloud feign微服务调用之间的异常处理方式

    如何优雅地处理微服务间调用的异常 现在微服务架构盛行,其中spring cloud方案就很具有代表. 那么在微服务之间进行调用,如果被调用的服务挂了,调用方如何感知呢? 一.加上hystrix熔断 在定义feignClient的地方指定熔断,如下图 当被调用服务不可用或者被调用方发生错误的时候,会触发熔断,但是,如果被调用方抛出异常,调用方怎么知道究竟是出了什么问题呢? 那,这就出现了 二.feign全局异常处理 我们不得不提到feign提供的一个接口叫做ErrorDecoder, 是用来处理f

  • SpringCloud 搭建企业级开发框架之实现多租户多平台短信通知服务(微服务实战)

    目前系统集成短信似乎是必不可少的部分,由于各种云平台都提供了不同的短信通道,这里我们增加多租户多通道的短信验证码,并增加配置项,使系统可以支持多家云平台提供的短信服务.这里以阿里云和腾讯云为例,集成短信通知服务. 1.在GitEgg-Platform中新建gitegg-platform-sms基础工程,定义抽象方法和配置类 SmsSendService发送短信抽象接口: /** * 短信发送接口 */ public interface SmsSendService { /** * 发送单个短信

  • SpringCloud Alibaba 基本开发框架搭建过程

    在上一节,我们已经完成了项目的整体技术架构设计和具体的数据库设计,接下来,我们搭建整体的开发框架. 开发工具选用Idea. 开发工具只是为了提高效率,如果不习惯Idea的话,STS使用起来也是OK的. 1.创建多Module工程 1.1.创建父工程 创建一个父项目,项目命名为eshop-project,用于管理子模块功能. 新建Project 选择Maven工程,next 填写GroupId和ArtifactID 填写项目名,选择项目位置 删除src,添加maven配置 <!--设置为pom,管

  • 利用ASP.NET MVC+EasyUI+SqlServer搭建企业开发框架

    我们要搭建的框架是企业级开发框架,适用用企业管理信息系统的开发,如:OA.HR等 1.框架名称:sampleFrame. 2.搭建原则:最少知识原则. 3.先定义一个简单的编码规范:除类名和接口名外,其余首字母小写. 4.准备开发环境:vs2010及以上(mvc4).sqlserver.jquery2.0和easyui1.4.5 首先来看一下列表页面的效果图: 我们期望简洁带前台代码,如下: <table id="dataGrid" class="easyui-data

  • SpringCloud搭建netflix-eureka微服务集群的过程详解

    1.打开官网稍微学习一下,了解一下spring cloud是个什么东西,大概有哪些组件等 https://spring.io/projects/spring-cloud https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/ 2.新建项目 打开网址:https://start.spring.io/ 选择需要引入的组件,然后下载下来即可 3.更改项目结构 为了测试的方便,需将项目结构更改为多模块的项目. 步骤

  • SpringCloud学习笔记之SpringCloud搭建父工程的过程图解

    目录 SpringCloud和SpringBoot版本选择 更详细的版本选择 相关技术选型 创建工程 创建父工程 新建maven工程 配置父工程的pom文件 SpringCloud是分布式微服务架构的一站式解决方案,十多种微服务架构落地技术的集合体,俗称微服务全家桶 SpringCloud和SpringBoot版本选择 自2019年以后官方建议使用2.0以后的版本 官网地址 在官网的页首可以看到最新版本以及对应的springboot版本 在官网可以看到官方推荐的springcloud与sprin

  • Java开发之手把手教你搭建企业级工程SSM框架

    目录 1.在IDEA界面中创建MavenWeb工程 2.在pom.xml中添加如下相关依赖 3.web.xml 配置 Spring MVC.Spring 4.分别在main目录下创建resource包 5.在spring.xml中连接数据库 6.springmvc.xml中配置驱动和前后缀表达式 7.配置打印sql语句和指定实体类,让idea搜索需要的javaBean 8.创建与数据库相对应的实体类 9.Handler 10.Service及其接口 11.Repository 12.测试所用的j

  • SpringCLoud搭建Zuul网关集群过程解析

    1.使用技术 Springboot,SpringCloud,Zuul,Nignx 2.目的 使用Zuul搭建微服务高可用的网关 3.项目创建 3.1 创建注册中心(略) 3.2 创建一个hello-service的服务工程 3.3 创建springcloud-zuul-ha网关服务 3.3.1 创建工程(略) 3.3.2 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&q

  • Spring MVC 4.1.3 + MyBatis零基础搭建Web开发框架(注解模式)

    首先感谢一下润和软件,指引我走上了spring MVC Web开发的道路. 下面进入正题 搭建开发环境: Netbeans8.0.2 + MySql5.6 + JDK1.7 + tomcat8.0.15 本次采用的Spring MVC Jar包如下: spring-aop-4.1.3.RELEASE.jar spring-beans-4.1.3.RELEASE.jar spring-context-4.1.3.RELEASE.jar spring-context-support-4.1.3.RE

  • 详解利用SpringCloud搭建一个最简单的微服务框架

    Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布式会话和集群状态管理等操作提供了一种简单的开发方式. Spring Cloud包含了多个子项目(针对分布式系统中涉及的多个不同开源产品),比如:Spring Cloud Config.Spring Cloud Netflix.Spring Cloud CloudFoundry.Spring Cloud AWS.S

  • SpringCloud让微服务实现指定程序调用

    我们在做微服务时,有时候需要将微服务做一些限制,比如只能我们自己的服务调用,不能通过浏览器直接调用等. 我们可以使用spring cloud sleuth,在应用调用微服务时通过Tracer产生一个traceId,并通过request设置到header里面, 然后sleuth会将该traceId在整个链路传递,我们在微服务中定义一个拦截器,取到header里面的traceId并和链路中的traceId比较, 如果相等,则表明是我们自己的应用调用,拦截器通过,否则这次请求被拦截 代码详见githu

随机推荐