一 數據庫設計
1 數據庫
創建數據庫:guli_cms
2 腳本
# 廣告
CREATE TABLE `cms_ad` (
`id` char(19) NOT NULL DEFAULT '' COMMENT 'ID',
`title` varchar(20) DEFAULT '' COMMENT '標題',
`type_id` char(19) NOT NULL COMMENT '類型ID',
`image_url` varchar(500) NOT NULL DEFAULT '' COMMENT '圖片地址',
`color` varchar(10) DEFAULT NULL COMMENT '背景顏色',
`link_url` varchar(500) DEFAULT '' COMMENT '鏈接地址',
`sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序',
`gmt_create` datetime NOT NULL COMMENT '創建時間',
`gmt_modified` datetime NOT NULL COMMENT '更新時間',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='廣告推薦';
# 廣告位
CREATE TABLE `cms_ad_type` (
`id` char(19) NOT NULL COMMENT 'ID',
`title` varchar(20) NOT NULL COMMENT '標題',
`gmt_create` datetime NOT NULL COMMENT '創建時間',
`gmt_modified` datetime NOT NULL COMMENT '更新時間',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='推薦位';
二 創建內容管理微服務
1 創建模塊
service_cms
2 配置pom.xml
<build>
<!-- 項目打包時會將java目錄中的*.xml文件也進行打包 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
3 配置application.yml
server:
port: 8140 # 服務端口
spring:
profiles:
active: dev # 環境設置
application:
name: service-cms # 服務名
cloud:
nacos:
discovery:
server-addr: localhost:8848 # nacos服務地址
sentinel:
transport:
port: 8081
dashboard: localhost:8080
datasource: # mysql數據庫連接
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/guli_cms?serverTimezone=GMT%2B8
username: root
password: 123456
#spring:
jackson: #返回json的全局時間格式
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis日誌
mapper-locations: classpath:com/atguigu/guli/service/cms/mapper/xml/*.xml
ribbon:
ConnectTimeout: 10000 #連接建立的超時時長,默認1秒
ReadTimeout: 10000 #處理請求的超時時間,默認爲1秒
feign:
sentinel:
enabled: true
4 logback-spring.xml
修改日誌路徑爲 guli_log/cms
5 創建啓動類
@SpringBootApplication
@ComponentScan({"com.atguigu.guli"})
// 啓動 OpenFeign 遠程調用
@EnableFeignClients
@EnableDiscoveryClient
public class ServiceEduApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceEduApplication.class, args);
}
}
6 創建代碼生成器並執行
三 後臺管理AdType
1 控制器
@CrossOrigin // 解決跨域問題
@Api(description = "推薦位管理")
@RestController
@RequestMapping("/admin/cms/ad-type")
@Slf4j
public class AdTypeController {
@Autowired
private AdTypeService adTypeService;
/**
* 功能描述:所有推薦類別列表
*
* @return R 返回給前端的數據
* @author cakin
* @date 2020/12/20
*/
@ApiOperation("所有推薦類別列表")
@GetMapping("list")
public R listAll() {
List<AdType> list = adTypeService.list();
return R.ok().data("items", list);
}
/**
* 功能描述:推薦類別分頁列表
*
* @param page 當前頁碼
* @param limit 每頁記錄數
* @return R 返回給前端的數據
* @author cakin
* @date 2020/12/20
*/
@ApiOperation("推薦類別分頁列表")
@GetMapping("list/{page}/{limit}")
public R listPage(@ApiParam(value = "當前頁碼", required = true) @PathVariable Long page,
@ApiParam(value = "每頁記錄數", required = true) @PathVariable Long limit) {
Page<AdType> pageParam = new Page<>(page, limit);
IPage<AdType> pageModel = adTypeService.page(pageParam);
List<AdType> records = pageModel.getRecords();
long total = pageModel.getTotal();
return R.ok().data("total", total).data("rows", records);
}
/**
* 功能描述:根據ID刪除推薦類別
*
* @author cakin
* @date 2020/12/20
* @param id 推薦類別ID
* @return R 返回給前端的數據
*/
@ApiOperation(value = "根據ID刪除推薦類別")
@DeleteMapping("remove/{id}")
public R removeById(@ApiParam(value = "推薦類別ID", required = true) @PathVariable String id) {
boolean result = adTypeService.removeById(id);
if (result) {
return R.ok().message("刪除成功");
} else {
return R.error().message("數據不存在");
}
}
/**
* 功能描述:新增推薦類別
*
* @author cakin
* @date 2020/12/20
* @param adType 推薦類別對象
* @return R 返回給前端的數據
*/
@ApiOperation("新增推薦類別")
@PostMapping("save")
public R save(@ApiParam(value = "推薦類別對象", required = true) @RequestBody AdType adType) {
boolean result = adTypeService.save(adType);
if (result) {
return R.ok().message("保存成功");
} else {
return R.error().message("保存失敗");
}
}
/**
* 功能描述:更新推薦類別
*
* @author cakin
* @date 2020/12/20
* @param adType 推薦類別對象
* @return R 返回給前端的數據
*/
@ApiOperation("更新推薦類別")
@PutMapping("update")
public R updateById(@ApiParam(value = "講師推薦類別", required = true) @RequestBody AdType adType) {
boolean result = adTypeService.updateById(adType);
if (result) {
return R.ok().message("修改成功");
} else {
return R.error().message("數據不存在");
}
}
/**
* 功能描述:根據id獲取推薦類別信息
*
* @author cakin
* @date 2020/12/20
* @param id 推薦類別ID
* @return R 返回給前端的數據
*/
@ApiOperation("根據id獲取推薦類別信息")
@GetMapping("get/{id}")
public R getById(@ApiParam(value = "推薦類別ID", required = true) @PathVariable String id) {
AdType adType = adTypeService.getById(id);
if (adType != null) {
return R.ok().data("item", adType);
} else {
return R.error().message("數據不存在");
}
}
}
四 後臺管理Ad
1 vo
@Data
public class AdVo implements Serializable {
private static final long serialVersionUID=1L;
/**
* id
*/
private String id;
/**
* 標題
*/
private String title;
/**
* 排序方式
*/
private Integer sort;
/**
* 廣告類別
*/
private String type;
}
2 控制器
@CrossOrigin //解決跨域問題
@Api(description = "廣告推薦管理")
@RestController
@RequestMapping("/admin/cms/ad")
@Slf4j
public class AdController {
@Autowired
private AdService adService;
/**
* 功能描述:根據ID刪除推薦
*
* @author cakin
* @date 2020/12/20
* @param id 廣告id
* @return R 返回該前端的數據
*/
@ApiOperation(value = "根據ID刪除推薦")
@DeleteMapping("remove/{id}")
public R removeById(@ApiParam(value = "推薦ID", required = true) @PathVariable String id) {
// 刪除圖片
adService.removeAdImageById(id);
// 刪除推薦
boolean result = adService.removeById(id);
if (result) {
return R.ok().message("刪除成功");
} else {
return R.error().message("數據不存在");
}
}
/**
* 功能描述:推薦分頁列表
*
* @author cakin
* @date 2020/12/20
* @param page 當前頁碼
* @param limit 每頁記錄數
* @return 返回給前端的數據
*/
@ApiOperation("推薦分頁列表")
@GetMapping("list/{page}/{limit}")
public R listPage(@ApiParam(value = "當前頁碼", required = true) @PathVariable Long page,
@ApiParam(value = "每頁記錄數", required = true) @PathVariable Long limit) {
IPage<AdVo> pageModel = adService.selectPage(page, limit);
List<AdVo> records = pageModel.getRecords();
long total = pageModel.getTotal();
return R.ok().data("total", total).data("rows", records);
}
/**
* 功能描述:新增推薦
*
* @author cakin
* @date 2020/12/20
* @param ad 廣告
* @return R 返回給前端的數據
*/
@ApiOperation("新增推薦")
@PostMapping("save")
public R save(@ApiParam(value = "推薦對象", required = true) @RequestBody Ad ad) {
boolean result = adService.save(ad);
if (result) {
return R.ok().message("保存成功");
} else {
return R.error().message("保存失敗");
}
}
/**
* 功能描述:更新推薦
*
* @author cakin
* @date 2020/12/20
* @param ad 廣告
* @return R 返回給前端的數據
*/
@ApiOperation("更新推薦")
@PutMapping("update")
public R updateById(@ApiParam(value = "講師推薦", required = true) @RequestBody Ad ad) {
boolean result = adService.updateById(ad);
if (result) {
return R.ok().message("修改成功");
} else {
return R.error().message("數據不存在");
}
}
/**
* 功能描述:根據id獲取推薦信息
*
* @author cakin
* @date 2020/12/20
* @param id 廣告id
* @return R 返回給前端的數據
*/
@ApiOperation("根據id獲取推薦信息")
@GetMapping("get/{id}")
public R getById(@ApiParam(value = "推薦ID", required = true) @PathVariable String id) {
Ad ad = adService.getById(id);
if (ad != null) {
return R.ok().data("item", ad);
} else {
return R.error().message("數據不存在");
}
}
}
3 service
接口
public interface AdService extends IService<Ad> {
/**
* 功能描述:廣告分頁查詢
*
* @author cakin
* @date 2020/12/20
* @param page 當前頁碼
* @param limit 每頁記錄數
* @return IPage<AdVo> 分頁信息
*/
IPage<AdVo> selectPage(Long page, Long limit);
/**
* 功能描述:刪除廣告圖像
*
* @author cakin
* @date 2020/12/20
* @param id 廣告id
* @return boolean 刪除是否成功
*/
boolean removeAdImageById(String id);
}
實現
@Service
public class AdServiceImpl extends ServiceImpl<AdMapper, Ad> implements AdService {
@Autowired
private OssFileService ossFileService;
/**
* 功能描述:廣告分頁查詢
*
* @author cakin
* @date 2020/12/20
* @param page 當前頁碼
* @param limit 每頁記錄數
* @return IPage<AdVo> 分頁信息
*/
@Override
public IPage<AdVo> selectPage(Long page, Long limit) {
QueryWrapper<AdVo> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("a.type_id", "a.sort");
Page<AdVo> pageParam = new Page<>(page, limit);
// 需傳遞分頁參數和條件查詢參數
List<AdVo> records = baseMapper.selectPageByQueryWrapper(pageParam, queryWrapper);
pageParam.setRecords(records);
return pageParam;
}
/**
* 功能描述:刪除廣告圖像
*
* @author cakin
* @date 2020/12/20
* @param id 廣告id
* @return boolean 刪除是否成功
*/
@Override
public boolean removeAdImageById(String id) {
Ad ad = baseMapper.selectById(id);
if(ad != null) {
String imagesUrl = ad.getImageUrl();
if(!StringUtils.isEmpty(imagesUrl)){
// 刪除圖片,遠程調用oss服務中的刪除文件
R r = ossFileService.removeFile(imagesUrl);
return r.getSuccess();
}
}
return false;
}
}
4 mapper
接口
public interface AdMapper extends BaseMapper<Ad> {
/**
* 功能描述:廣告分頁查詢
*
* @author cakin
* @date 2020/12/20
* @param pageParam 分頁參數
* @return queryWrapper 條件查詢參數
*/
List<AdVo> selectPageByQueryWrapper(
Page<AdVo> pageParam,
@Param(Constants.WRAPPER) QueryWrapper<AdVo> queryWrapper);
}
XML
<select id="selectPageByQueryWrapper" resultType="com.atguigu.guli.service.cms.entity.vo.AdVo">
SELECT
a.id,
a.title,
a.sort,
t.title AS type
FROM cms_ad a
LEFT JOIN cms_ad_type t ON a.type_id = t.id
${ew.customSqlSegment}
</select>
5 feign
接口
@Service
@FeignClient(value = "service-oss", fallback = OssFileServiceFallBack.class)
public interface OssFileService {
/**
* 功能描述:遠程刪除文件
*
* @author cakin
* @date 2020/12/20
* @param url
* @return R 前端返回結果
*/
@DeleteMapping("/admin/oss/file/remove")
R removeFile(@RequestBody String url);
}
降級實現
/**
* @className: OssFileServiceFallBack
* @description: 文件服務遠程調用失敗降級處理
* @date: 2020/12/20
* @author: cakin
*/
@Service
@Slf4j
public class OssFileServiceFallBack implements OssFileService {
/**
* 功能描述:文件服務遠程調用失敗降級處理
*
* @author cakin
* @date 2020/12/20
* @param url 文件url地址
* @return R 遠程調用返回的結果
*/
@Override
public R removeFile(String url) {
log.info("熔斷保護");
return R.error().message("調用超時");
}
}