通过对需求描述的分析可知,需要构建3个项目,即后台接口管理项目、促销活动微服务项目和网关项目。本节分别介绍这3个项目的开发过程。
后台接口管理项目
使用https://start.spring.io/工具新建promotion项目,导入开发工具。新建相关的package,整体项目结构如图11.1所示。
(1)在pom.xml文件中添加相关依赖,代码如下:
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter
parent</artifactId>
<version>2.3.9.RELEASE</version>
<relativePath/> <!--lookup parent from
repository -->
</parent>
<groupId>com.example.promotion</groupId>
<artifactId>promotion</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>promotion</name>
<description>Promotion project for Spring
Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter
actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry
prometheus</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data
jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data
redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter
web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter
test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit
vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter
log4j2</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba
dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos
config
</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos
discovery
</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba
sentinel</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot
maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
(2)修改application.xml配置文件,在其中配置数据库的连接方式,代码如下:
server:
port: 8080
spring:
application:
name: promotion
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?
useUnicode=true&character
Encoding=utf8
username: test
password: test
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 10
maximum-pool-size: 100
auto-commit: true
idle-timeout: 30000
pool-name: UserHikariCP
max-lifetime: 1800000
connection-timeout: 30000
jpa:
database: MYSQL
hibernate:
ddl-auto: none
show-sql: true
(3)由于集成了Nacos和Sentinel中间件,因此需要bootstrap.xml配置文件,具体配置如下:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
ip: 127.0.0.1
port: 80
namespace: 40421527-56ff-410b-8ca8-e025aca9e946
group: default
config:
server-addr: 127.0.0.1:8848
file-extension: properties
namespace: 40421527-56ff-410b-8ca8-e025aca9e946
group: default
sentinel:
enabled: true
transport:
dashboard: 127.0.0.1:8888
clientIp: 127.0.0.1
port: 8719
log:
dir: /log/sentinel
filter:
enabled: false
management:
endpoint:
metrics:
enabled: true
prometheus:
enabled: true
endpoints:
web:
base-path: /
exposure:
include: health,info,status,prometheus
metrics:
export:
prometheus:
enabled: true
tags:
application: ${spring.application.name}
web:
server:
request:
autotime:
enabled: true
percentiles-histogram: on
percentiles:
-0.9
-0.99
client:
request:
autotime:
enabled: true
percentiles-histogram: on
percentiles:
-0.9
-0.99
(4)本例使用log4j2日志架构,配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<properties>
<property name="LOG_HOME">/log</property>
</properties>
<Appenders>
<Console name="CONSOLE" target="SYSTEM_OUT" >
<PatternLayout pattern="%d{yyyy-MM-dd
HH:mm:ss.SSS} %-5p
[%t] %c{1.} %msg%n"/>
</Console>
<RollingRandomAccessFile name="INFO_FILE" fileName=
"${LOG_HOME}/info.log"
filePattern="${LOG_HOME}/info-%d{HH}
-%i.log" immediateFlush="true">
<PatternLayout pattern="%d{yyyy-MM-dd
HH:mm:ss.SSS}
[%traceId] %-5p %c{1.} %msg%n"/>
<Policies>
<TimeBasedTriggeringPolicy />
</Policies>
<DefaultRolloverStrategy max="1"/>
<Filters>
<ThresholdFilter level="error"
onMatch="ACCEPT" onMismatch=
"NEUTRAL"/>
<ThresholdFilter level="info"
onMatch="ACCEPT" onMismatch=
"DENY"/>
</Filters>
</RollingRandomAccessFile>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="CONSOLE" />
<AppenderRef ref="INFO_FILE" />
</Root>
</Loggers>
</Configuration>
(5)将Redis配置信息集成到Nacos上,配置详情如图11.2所示。
具体的Redis信息如下:
redis.promotion.host=127.0.0.1
redis.promotion.port=6379
redis.promotion.password=test
redis.promotion.maxTotal=2000
redis.promotion.maxIdle=100
redis.promotion.minIdle=40
redis.promotion.maxWaitMillis=3000
redis.promotion.timeBetweenEvictionRunsMillis=30000
redis.promotion.commandTimeout=3000
(6)Redis自动配置:
新建RedisProperties.class文件,代码如下:
package com.example.promotion.config;
import lombok.Data;
import
org.springframework.boot.context.properties.Configuration
Properties;
@Data
@ConfigurationProperties(prefix = "redis")
public class RedisProperties {
private RedisInfo promotion;
@Data
public static class RedisInfo{
protected int maxTotal = 2000;
//最大连接数
protected int maxIdle = 100;
//最大空闲数
protected int minIdle = 40;
//最小空闲数
protected int maxWaitMillis = 3000;
//最长等待时间
//空闲回收休眠时间
protected int timeBetweenEvictionRunsMillis = 30000;
protected int commandTimeout = 3000; //命令
执行超时时间
private String host;
//Redis地址
private int port;
//Redis端口
private String password;
//Redis密码
}
}
新建
RedisAutoConfiguration.class文件,代码如下:
package com.example.promotion.config;
import java.time.Duration;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import
org.springframework.boot.autoconfigure.condition.Conditional
OnClass;
import
org.springframework.boot.autoconfigure.condition.Conditional
OnProperty;
import
org.springframework.boot.context.properties.EnableConfigurati
on
Properties;
import
org.springframework.cloud.context.config.annotation.Refresh
Scope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import
org.springframework.data.redis.connection.RedisStandalone
Configuration;
import
org.springframework.data.redis.connection.lettuce.Lettuce
ClientConfiguration;
import
Org.springframework.data.redis.connection.lettuce.Lettuce
ConnectionFactory;
import
org.springframework.data.redis.connection.lettuce.Lettuce
PoolingClientConfiguration;
import
org.springframework.data.redis.core.StringRedisTemplate;
@ConditionalOnClass(LettuceConnectionFactory.class)
@Configuration
@EnableConfigurationProperties(RedisProperties.class)
@ConditionalOnProperty("redis.promotion.host")
public class RedisAutoConfiguration {
@Bean
@RefreshScope
public GenericObjectPoolConfig
genericObjectPoolConfig(Redis
Properties properties) {
//通用线程池配置
GenericObjectPoolConfig genericObjectPoolConfig = new
Generic
ObjectPoolConfig();
//设置最大的连接数
genericObjectPoolConfig.setMaxTotal(properties.getPromotion()
.
getMaxTotal());
//设置最大的空闲数
genericObjectPoolConfig.setMaxIdle(properties.getPromotion().
getMaxIdle());
//设置最小的空闲数
genericObjectPoolConfig.setMinIdle(properties.getPromotion().
getMinIdle());
//设置最长的等待时间
genericObjectPoolConfig.setMaxWaitMillis(properties.get
Promotion().getMaxWaitMillis());
//从连接池取出连接时检查有效性
genericObjectPoolConfig.setTestOnBorrow(true);
//连接返回时检查有效性
genericObjectPoolConfig.setTestOnReturn(true);
//空闲时检查有效性
genericObjectPoolConfig.setTestWhileIdle(true);
//空闲回收休眠时间
genericObjectPoolConfig.setTimeBetweenEvictionRunsMillis
(properties.getPromotion().getTimeBetweenEvictionRunsMillis()
);
return genericObjectPoolConfig;
}
@Bean
@RefreshScope
public LettuceClientConfiguration
lettuceClientConfiguration
(RedisProperties properties, GenericObjectPoolConfig
genericObject
PoolConfig) {
//Lettuce客户端配置
LettucePoolingClientConfiguration build =
LettucePooling
ClientConfiguration.builder()
.commandTimeout(Duration.ofMillis(properties.get
Promotion().getCommandTimeout()))
.shutdownTimeout(Duration.ZERO)
.poolConfig(genericObjectPoolConfig)
.build();
return build;
}
@Bean
@RefreshScope
public LettuceConnectionFactory
lettuceConnectionFactory(Redis
Properties properties,
LettuceClientConfiguration lettuceClientConfiguration) {
//Redis配置
RedisStandaloneConfiguration redisConfiguration = new
Redis
StandaloneConfiguration(properties.getPromotion().getHost(),
properties.
getPromotion().getPort());
redisConfiguration.setPassword(properties.getPromotion().
getPassword());
//Lettuce连接工厂
LettuceConnectionFactory lettuceConnectionFactory =
new Lettuce
ConnectionFactory(redisConfiguration,
lettuceClientConfiguration);
return lettuceConnectionFactory;
}
@Bean(name = "redisTemplate")
public StringRedisTemplate
stringRedisTemplate(LettuceConnection
Factory lettuceConnectionFactory) {
//RedisTemplate声明
return new
StringRedisTemplate(lettuceConnectionFactory);
}
}
(7)新增Sentinel切面配置,代码如下:
package com.example.promotion.config;
import
com.alibaba.csp.sentinel.annotation.aspectj.SentinelResource
Aspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SentinelConfig {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
//Sentinel切面声明
return new SentinelResourceAspect();
}
}
(8)新建Model层的对象PromotionEntyty,代码如下:
package com.example.promotion.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import
org.springframework.data.jpa.domain.support.AuditingEntity
Listener;
import lombok.Data;
@Entity
@Table(name="promotion")
//声明表名
@Data
@EntityListeners(AuditingEntityListener.class)
public class PromotionEntity implements Serializable {
private static final long serialVersionUID = 1L;
//主键ID
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
//促销活动的名称
@Column(name="name")
private String name;
//促销活动的开始时间
@Column(name="begin_time")
private Integer beginTime;
//促销活动的结束时间
@Column(name="end_time")
private Integer endTime;
//奖品
@Column(name="prize")
private String prize;
//创建时间
@Column(name="create_time")
@CreatedDate
private Date createTime;
//更新时间
@Column(name="update_time")
@LastModifiedDate
private Date updateTime;
}
(9)本例采用Spring Boot JPA。Repository代码如下:
package com.example.promotion.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.example.promotion.model.PromotionEntity;
@Repository
public interface PromotionRepository extends
JpaRepository<Promotion
Entity,Integer>{
//自定义查询
PromotionEntity findByName(String name);
}
(10)接口返回通用状态码及Redis操作key的声明。
新增Constant.class文件,代码如下:
package com.example.promotion.constants;
public class Constant {
//接口调用成功,返回成功状态码
public static final String SUCCESS_CODE = "S00000";
//接口失败,则返回状态码
public static final String ERROR_CODE = "F00001";
//接口成功返回信息
public static final String SUCCESS_MSG = "success";
//促销活动Redis存储key,用来存储活动信息
public static final String REDIS_PROMOTION_KEY =
"promotion:{0}";
//赠送奖品领取记录
public static final String REDIS_PRIZE_KEY =
"promotion:{0}:{1}";
}
新建AbstractResponse.class文件,代码如下:
package com.example.promotion.constants;
//通用返回类
public class AbstractResponse {
private String code;
private String msg;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
新建JsonObjectResponse.class文件,代码如下:
package com.example.promotion.constants;
//扩展返回类
public class JsonObjectResponse<T> extends AbstractResponse {
private T result;
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
public JsonObjectResponse(T result, String code,
String msg) {
this.setCode(code);
this.setMsg(msg);
this.result = result;
}
public JsonObjectResponse(T result) {
this.setCode(Constant.SUCCESS_CODE);
this.setMsg(Constant.SUCCESS_MSG);
this.result = result;
}
public JsonObjectResponse() {
this.setCode(Constant.SUCCESS_CODE);
this.setMsg(Constant.SUCCESS_MSG);
this.result = null;
}
public JsonObjectResponse(String code, String msg) {
this.setCode(code);
this.setMsg(msg);
}
}
(11)PromotionController接口代码如下:
package com.example.promotion.controller;
import org.apache.commons.lang.StringUtils;
import
org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
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.promotion.constants.Constant;
import com.example.promotion.constants.JsonObjectResponse;
import com.example.promotion.model.PromotionEntity;
import com.example.promotion.service.BlockHandlerService;
import com.example.promotion.service.FallBackService;
import com.example.promotion.service.PromotionService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequestMapping("/api")
public class PromotionController {
@Autowired
private PromotionService promotionService;
//查询促销活动接口,路径:/api/queryPromotion?id=xx
@GetMapping("queryPromotion")
@ResponseBody
//限流与降级注解
@SentinelResource(value = "queryPromotion", entryType
= EntryType.IN,
blockHandler = "queryPromotionBlockHandle", blockHandlerClass
=
{BlockHandlerService.class}, defaultFallback = "fallback",
fallback
Class = {FallBackService.class})
public JsonObjectResponse<PromotionEntity>
queryPromotion
(Integer id) {
try {
//调用促销活动服务类查询方法
return
promotionService.queryPromotion(id);
} catch (Exception e) {
//记录错误日志
log.error("query promotion error!");
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"query promotion error!");
}
}
//提交促销活动接口,路径:/api/addPromotion
//参数:PromotionEntity
@PostMapping("addPromotion")
@ResponseBody
@SentinelResource(value = "addPromotion", entryType =
EntryType.IN,
blockHandler = "addPromotionBlockHandle", blockHandlerClass =
{BlockHandlerService.class}, defaultFallback = "fallback",
fallback
Class = {FallBackService.class})
public JsonObjectResponse<PromotionEntity>
addPromotion
(PromotionEntity promotionEntity) {
if
(StringUtils.isBlank(promotionEntity.getName()) ||
StringUtils.
isBlank(promotionEntity.getPrize())) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"param is null! ");
}
try {
//调用促销活动服务类新增方法
return
promotionService.addPromotion(promotionEntity);
} catch (Exception e) {
//记录错误日志
log.error("add promotion error!");
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"add promotion error!");
}
}
//更新促销活动接口,路径:/api/updatePromotion
//参数:PromotionEntity
@PostMapping("updatePromotion")
@ResponseBody
@SentinelResource(value = "updatePromotion",
entryType = EntryType.IN,
blockHandler = "updatePromotionBlockHandle",
blockHandlerClass =
{BlockHandlerService.class}, defaultFallback = "fallback",
fallback
Class = {FallBackService.class})
public JsonObjectResponse<PromotionEntity>
updatePromotion
(PromotionEntity promotionEntity) {
if (promotionEntity.getId() == null) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"id is null! ");
}
try {
//调用促销活动服务类更新方法
return
promotionService.updatePromotion(promotionEntity);
} catch (Exception e) {
//记录错误日志
log.error("add promotion error!");
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"add promotion error!");
}
}
//删除促销活动接口,路径:/api/delPromotion?id=xx
@DeleteMapping("delPromotion")
@ResponseBody
@SentinelResource(value = "delPromotion", entryType =
EntryType.IN,
blockHandler = "delPromotionBlockHandle", blockHandlerClass =
{BlockHandlerService.class}, defaultFallback = "fallback",
fallback
Class = {FallBackService.class})
public JsonObjectResponse<PromotionEntity>
delPromotion(Integer
id) {
try {
//调用删除服务类方法
return
promotionService.delPromotion(id);
} catch (Exception e) {
//记录错误日志
log.error("delete promotion error!");
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"delete promotion error!");
}
}
}
(12)PromotionService代码如下:
package com.example.promotion.service;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import com.example.promotion.constants.Constant;
import com.example.promotion.constants.JsonObjectResponse;
import com.example.promotion.model.PromotionEntity;
import com.example.promotion.repository.PromotionRepository;
import lombok.extern.slf4j.Slf4j;
//促销活动服务类
@Service
@Slf4j
public class PromotionService {
//PromotionRepository注入
@Autowired
private PromotionRepository promotionRepository;
//StringRedisTemplate注入
@Autowired
private StringRedisTemplate stringRedisTemplate;
//查询促销活动信息
public JsonObjectResponse<PromotionEntity>
queryPromotion(Integer
id) {
Optional<PromotionEntity> promotionEntity =
promotionRepository.
findById(id);
if (promotionEntity.isPresent()) {
return new JsonObjectResponse<>
(promotionEntity.get());
} else {
return new JsonObjectResponse<>
(null);
}
}
//添加促销活动信息
public JsonObjectResponse<PromotionEntity>
addPromotion(Promotion
Entity promotionEntity) {
PromotionEntity promotionEntityOld =
promotionRepository.
findByName(promotionEntity.getName());
if (promotionEntityOld != null) { //查询
促销活动是否已经存在
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"promotion name is exist!");
} else {
//如果不存在,则添加
PromotionEntity promotionEntityNew =
promotionRepository.
save(promotionEntity);
//插入MySQL数据库
String key =
MessageFormat.format(Constant.REDIS_PROMOTION_
KEY, String.valueOf(promotionEntityNew.getId()));
Map<String, String> map = new
HashMap<>();
map.put("name",
promotionEntityNew.getName());
map.put("beginTime",
String.valueOf(promotionEntityNew.
getBeginTime()));
map.put("endTime",
String.valueOf(promotionEntityNew.
getEndTime()));
map.put("prize",
promotionEntityNew.getPrize());
//添加到Redis中
stringRedisTemplate.opsForHash().putAll(key, map);
log.info("addPromotion success");
}
return new JsonObjectResponse<>(null);
}
//更新促销活动信息
public JsonObjectResponse<PromotionEntity>
updatePromotion(Promotion
Entity promotionEntity) {
Optional<PromotionEntity> promotionEntityOpt
= promotion
Repository.findById(promotionEntity.getId());
if (promotionEntityOpt.isPresent()) {
PromotionEntity promotionEntityOld =
promotionEntityOpt.
get();
promotionEntityOld.setName(promotionEntity.getName());
promotionEntityOld.setPrize(promotionEntity.getPrize());
promotionEntityOld.setBeginTime(promotionEntity.getBegin
Time());
promotionEntityOld.setEndTime(promotionEntity.getEndTime());
//更新MySQL信息
promotionRepository.save(promotionEntityOld);
String key =
MessageFormat.format(Constant.REDIS_PROMOTION_
KEY, String.valueOf(promotionEntityOld.getId()));
Map<String, String> map = new
HashMap<>();
map.put("name",
promotionEntityOld.getName());
map.put("beginTime",
String.valueOf(promotionEntityOld.
getBeginTime()));
map.put("endTime",
String.valueOf(promotionEntityOld.
getEndTime()));
map.put("prize",
promotionEntityOld.getPrize());
//更新Redis信息
stringRedisTemplate.opsForHash().putAll(key, map);
log.info("updatePromotion success");
}
return new JsonObjectResponse<>(null);
}
//删除促销活动信息
public JsonObjectResponse<PromotionEntity>
delPromotion(Integer
id) {
promotionRepository.deleteById(id);
//删除MySQL信息
String key =
MessageFormat.format(Constant.REDIS_PROMOTION_
KEY, String.valueOf(id));
stringRedisTemplate.delete(key);
//删除Redis信息
log.info("delPromotion success");
return new JsonObjectResponse<>(null);
}
}
(13)限流代码如下:
package com.example.promotion.service;
import com.example.promotion.constants.Constant;
import com.example.promotion.constants.JsonObjectResponse;
import com.example.promotion.model.PromotionEntity;
//接口发生限流时触发
public final class BlockHandlerService {
public static JsonObjectResponse<PromotionEntity>
queryPromotion
BlockHandle(Integer id) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"queryPromotion blcok");
}
public static JsonObjectResponse<PromotionEntity>
addPromotion
BlockHandle(PromotionEntity promotionEntity) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"addPromotion blcok");
}
public static JsonObjectResponse<PromotionEntity>
updatePromotion
BlockHandle(PromotionEntity promotionEntity) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"updatePromotion blcok");
}
public static JsonObjectResponse<PromotionEntity>
delPromotion
BlockHandle(Integer id) {
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"delPromotion blcok");
}
}
(14)降级代码如下:
package com.example.promotion.service;
import com.example.promotion.constants.Constant;
import com.example.promotion.constants.JsonObjectResponse;
import com.example.promotion.model.PromotionEntity;
//接口发生降级时触发
public final class FallBackService {
public static JsonObjectResponse<PromotionEntity>
defaultFall
Back(Throwable ex){
return new JsonObjectResponse<>(null,
Constant.ERROR_CODE,
"fallback");
}
}
(15)PromotionApplication代码如下:
package com.example.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
;
import
org.springframework.data.jpa.repository.config.EnableJpaAudit
ing;
//自定义Redis配置
@SpringBootApplication(exclude =
{RedisAutoConfiguration.class})
@EnableJpaAuditing
//开启JPA审计
@EnableAspectJAutoProxy
//开启切面
@EnableDiscoveryClient
//开启服务发现
public class PromotionApplication {
public static void main(String[] args) {
SpringApplication.run(PromotionApplication.class, args);
}
}
此时,启动PromotionApplication主类即可访问接口,管理促销活动信息。例如添加一条活动信息,访问接口
http://localhost:8080/api/addPromotion,设置参数如下:
name:"会员促销活动"
beginTime:"1614822680"
endTime:" 1617176808"
prize:"3天免费会员"
访问查询接口
http://localhost:8080/api/queryPromotion?id=1,返回结果如下:
{
code: "S00000",
msg: "success",
result: {
id: 3,
name: "会员促销活动",
beginTime: 1614822680,
endTime: 1617176808,
prize: "3天免费会员",
createTime: "2021-03-05T03:57:35.000+00:00",
updateTime: "2021-03-05T03:59:12.000+00:00"
}
}
访问更新接口
http://localhost:8080/api/updatePromotion,添加参数即可修改促销活动信息,参数如下:
id:1
name:"会员促销活动"
beginTime:"1614822680"
endTime:" 1617176808"
prize:"3天免费会员"
访问删除接口
http://localhost:8080/api/ delPromotion?id=1,即可删除该促销活动信息.