促销活动微服务项目
新建促销活动微服务项目microservice-promotion。新项目结构如图11.3所示。
(1)microservice-promotion的配置与promotion基本相同,application.yml文件的配置如下:
server:
port: 8081
spring:
application:
name: microservice-promotion
(2)启动类
MicroservicePromotionApplication的代码如下:
package com.example.microservice.promotion;
import org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.boot.autoconfigure.data.redis.RedisAuto
Configuration;
import
org.springframework.cloud.client.discovery.EnableDiscovery
Client;
import
org.springframework.context.annotation.EnableAspectJAutoProxy
;
@SpringBootApplication(exclude =
{RedisAutoConfiguration.class})
@EnableAspectJAutoProxy
//开启切面
@EnableDiscoveryClient
//开启服务发现
public class MicroservicePromotionApplication {
public static void main(String[] args) {
SpringApplication.run(MicroservicePromotionApplication.class,
args);
}
}
(3)
PromotionPushController.class接口类的代码如下:
package com.example.microservice.promotion.controller;
import
org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import
org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import
org.springframework.web.bind.annotation.RestController;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.example.microservice.promotion.constants.Constant;
import
com.example.microservice.promotion.constants.JsonObject
Response;
import
com.example.microservice.promotion.model.PromotionEntity;
import
com.example.microservice.promotion.service.BlockHandler
Service;
import
com.example.microservice.promotion.service.FallBackService;
import
com.example.microservice.promotion.service.PromotionPush
Service;
import lombok.extern.slf4j.Slf4j;
//促销活动微服务接口
@Slf4j
@RestController
@RequestMapping("/api")
public class PromotionPushController {
@Autowired
private PromotionPushService promotionPushService;
//促销活动投放接口,路径:/api/pushPromotion?id=xx
@GetMapping("pushPromotion")
@ResponseBody
@SentinelResource(value = "pushPromotion", entryType
= EntryType.IN,
blockHandler = "promotionPushBlockHandle", blockHandlerClass
=
{BlockHandlerService.class}, defaultFallback = "fallback",
fallback
Class = {FallBackService.class})
public JsonObjectResponse<PromotionEntity>
pushPromotion(Integer id) {
try {
//调用促销活动投放服务方法
return
promotionPushService.pushPromotion(id);
} catch (Exception e) {
//记录错误日志
log.error("push promotion error!");
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"push promotion error!");
}
}
//领取奖品接口,路径:/api/getPrize?id=xx&device=xx
@GetMapping("getPrize")
@ResponseBody
@SentinelResource(value = "getPrize", entryType =
EntryType.IN,
blockHandler = "prizeBlockHandle", blockHandlerClass =
{BlockHandler
Service.class}, defaultFallback = "fallback", fallbackClass =
{Fall
BackService.class})
public JsonObjectResponse<String> getPrize(Integer
id, String
device) {
try {
//调用领取奖品服务方法
return
promotionPushService.getPrize(id, device);
} catch (Exception e) {
//记录错误日志
log.error("get prize error!");
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"get prize error!");
}
}
}
(4)
PromotionPushService.class服务类的代码如下:
package com.example.microservice.promotion.service;
import java.text.MessageFormat;
import java.util.Map;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.example.microservice.promotion.constants.Constant;
import
com.example.microservice.promotion.constants.JsonObject
Response;
import
com.example.microservice.promotion.model.PromotionEntity;
import lombok.extern.slf4j.Slf4j;
//促销活动服务类
@Service
@Slf4j
public class PromotionPushService {
@Autowired
private StringRedisTemplate stringRedisTemplate;
public JsonObjectResponse<PromotionEntity>
pushPromotion(Integer id) {
//组装Redis存储促销活动信息的key
String key =
MessageFormat.format(Constant.REDIS_PROMOTION_
KEY, String.valueOf(id));
//Redis操作,用于查询促销活动信息
Map<Object, Object> map =
stringRedisTemplate.opsForHash().
entries(key);
if (MapUtils.isNotEmpty(map)) {
String name = (String)
map.get("name");
String prize = (String)
map.get("prize");
Integer beginTime =
Integer.valueOf((String) map.get
("beginTime"));
Integer endTime =
Integer.valueOf((String) map.get("endTime"));
Integer currentTime = (int)
(System.currentTimeMillis()/
1000);
if (currentTime >= beginTime &&
currentTime <= endTime) {
PromotionEntity
promotionEntity = new PromotionEntity();
promotionEntity.setBeginTime(beginTime);
promotionEntity.setEndTime(endTime);
promotionEntity.setId(id);
promotionEntity.setName(name);
promotionEntity.setPrize(prize);
log.info("push promotion
success");
return new
JsonObjectResponse<>(promotionEntity);
}
}
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"push promotion fail");
}
public JsonObjectResponse<String> getPrize(Integer
id, String
device) {
//组装奖品领取记录存储结构key
String key =
MessageFormat.format(Constant.REDIS_PRIZE_KEY,
String.valueOf(id), device);
//查询该device下的领取记录
String value =
stringRedisTemplate.opsForValue().get(key);
if (StringUtils.isEmpty(value)) { //没有
领取记录,表示领取成功
String promotionKey =
MessageFormat.format(Constant.REDIS_
PROMOTION_KEY, String.valueOf(id));
Map<Object, Object> map =
stringRedisTemplate.opsForHash().
entries(promotionKey);
if (MapUtils.isNotEmpty(map)) {
String prize = (String)
map.get("prize");
stringRedisTemplate.opsForValue().set(key, "1");
log.info("get prize
success");
return new
JsonObjectResponse<>("恭喜你获得:" + prize);
}
}
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"prize is exist");
}
}
(5)限流类BlockHandlerService.class的代码如下:
package com.example.microservice.promotion.service;
import com.example.microservice.promotion.constants.Constant;
import
com.example.microservice.promotion.constants.JsonObject
Response;
import
com.example.microservice.promotion.model.PromotionEntity;
//限流类
public final class BlockHandlerService {
public static JsonObjectResponse<PromotionEntity>
promotionPush
BlockHandle(Integer id) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"pushPromotion blcok");
}
public static JsonObjectResponse<String>
prizeBlockHandle(Integer id,
String device) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"getprize blcok");
}
}
微服务接口逻辑有两个,即促销活动投放接口和领取奖品接口。
客户端访问某个活动ID时,接口判断当前时间是否在活动时间内,如果在,则返回促销活动信息,用户可以领取活动奖品,如果用户已领取过奖品,则不能再次领取。
访问促销活动接口
http://localhost:8081/api/pushPromotion?id=1,如接口正常,则返回如下结果:
{
code: "S00000",
msg: "success",
result: {
id: 3,
name: "会员促销活动",
beginTime: 1614822680,
endTime: 1617176808,
prize: "3天免费会员"
}
}
访问领取奖品接口
http://localhost:8081/api/getPrize?id=1,如接口正常,则返回数据如下:
{
code: "S00000",
sg: "success",
result: "恭喜你获得:3天免费会员"
}