IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 项目1在线交流平台-7.构建安全高效的企业服务-3. Security整合KafkaESThymeleaf实例-对帖子置顶、加精、删除 -> 正文阅读

[大数据]项目1在线交流平台-7.构建安全高效的企业服务-3. Security整合KafkaESThymeleaf实例-对帖子置顶、加精、删除


参考牛客网高级项目教程
尚硅谷SpringSecurity教程笔记

社区 Spring Security 从入门到进阶系列教程
Thymeleaf+Spring Security

功能需求

在这里插入图片描述

  • 1.对帖子可以进行置顶、加精、删除等操作,以区分不同的帖子重要程度

  • 2.使用Security进行权限管理,

    • 只有版主才能置顶、加精帖子
    • 管理员才能删除帖子
  • 3.按钮显示,不同权限的用户显示不同的按钮

    • 需要用到Thymeleaf整合SpringSecurity的组件,动态渲染显示

一、置顶、加精、删除帖子功能的实现

1. dao层处理数据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VGj3MxIS-1649167308072)(C:\Users\ls2690069470\AppData\Roaming\Typora\typora-user-images\image-20220405182107015.png)]

接口定义

  • 需要修改帖子类型和状态

    /**
     * 对帖子置顶处理-修改帖子类型
     */
    int updatePostType(int id, int type);
    
    /**
     * 对帖子加精、删除处理-修改帖子状态
     */
    int updatePostStatus(int id, int status);
    

sal语句定义

<!--    更新帖子类型-置顶帖子-->
    <update id="updatePostType">
        update discuss_post set type = #{type} where id = #{id}
    </update>
    
<!--    更新帖子状态-加精或删除帖子-->
    <update id="updatePostStatus">
        update discuss_post set status = #{status} where id = #{id}
    </update>

2. service层业务处理

/**
 * 更新帖子类型-置顶
 */
public int updatePostType(int id, int type) {
    return discussPostMapper.updatePostType(id, type);
}

/**
 * 更新帖子状态-加精或删除
 */
public int updatePostStatus(int id, int status) {
    return discussPostMapper.updatePostStatus(id, status);
}

3. Controller层处理按钮事件异步请求

  • 采用异步请求
  • 注意:更改帖子后,要将帖子信息同步到ES服务器中
    • 重新覆盖就是修改
    • 从服务器中删除帖子
  • 故,要增加发帖事件-进kafka消息队列中
  • 增加kafak删除帖子的消费事件

异步请求及kafka发送消息

/** 帖子类型常量定义*/
private static final int POST_TYPE_TOP = 1;
/** 帖子状态常量定义*/
private static final int POST_STATUS_WONDERFUL = 1;
private static final int POST_STATUS_DELETE = 2;

/**
 * 置顶处理-异步请求
 *     注意:更改帖子后,要将帖子信息同步到ES服务器中,-重新覆盖就是修改
 *     故,要增加发帖事件-进kafka消息队列中
 */
@RequestMapping(value = "/top", method = RequestMethod.POST)
@ResponseBody
public String setTop(int id) {
    // 先修改帖子类型
    discussPostService.updatePostType(id, POST_TYPE_TOP);
    // 定义发帖事件-发布到topic中
    Event event = new Event()
            .setTopic(TOPIC_PUBLISH)
            .setEntityId(id);
    eventProducer.sendEvent(event);

    return CommunityUtil.getJSONString(0);
}

/**
 * 加精处理-异步请求
 *     注意:更改帖子后,要将帖子信息同步到ES服务器中,-重新覆盖就是修改
 *     故,要增加发帖事件-进kafka消息队列中
 */
@RequestMapping(value = "/wonderful", method = RequestMethod.POST)
@ResponseBody
public String setWonderful(int id) {
    // 先修改帖子类型
    discussPostService.updatePostStatus(id, POST_STATUS_WONDERFUL);
    // 定义发帖事件-发布到topic中
    Event event = new Event()
            .setTopic(TOPIC_PUBLISH)
            .setEntityId(id);
    eventProducer.sendEvent(event);

    return CommunityUtil.getJSONString(0);
}

/**
 * 删除处理-异步请求
 *     注意:更改帖子后,要将帖子信息同步到ES服务器中,-从服务器中删除帖子
 *     故,要增加发帖事件-进kafka消息队列中
 */
@RequestMapping(value = "/delete", method = RequestMethod.POST)
@ResponseBody
public String deletePost(int id) {
    // 先修改帖子类型
    discussPostService.updatePostStatus(id, POST_STATUS_DELETE);
    // 定义发帖事件-发布到topic中
    Event event = new Event()
            .setTopic(TOPIC_DELETE)
            .setEntityId(id);
    eventProducer.sendEvent(event);

    return CommunityUtil.getJSONString(0);
}

删除帖子-消费消息

/**
 * 消费删除帖子的消息-将帖子数据从ES服务器中删除
 */
@KafkaListener(topics = TOPIC_DELETE)
public void handleDeleteMessage(ConsumerRecord record) {
    // 1.边界条件:先检查有无取到消息
    if (record == null || record.value() == null) {
        logger.error("消息的内容为空!");
        return;
    }
    // 2.将拿到的消息恢复成Object类型,方便操作
    Event event = JSONObject.parseObject(record.value().toString(), Event.class);
    if(event == null) {
        logger.error("消息的格式错了!");
        return;
    }
    // 3. 将拿到的消息从ES服务器中删除
    DiscussPost discussPost = discussPostService.selectPostById(event.getEntityId());
    elasticSearchService.deletePost(discussPost);
}

4. 模板页面和js文件处理

帖子详情页面按钮处理

  • 增加隐藏标签,传入帖子id,请求处理中需要这个参数
th:disabled- 按钮不起作用
  • 当按钮已经操作之后,防止重复操作,设置按钮不起作用
<div class="float-right">
   <input type="hidden" id="postId" th:value="${post.id}">
   <button type="button" class="btn btn-danger btn-sm" id="topBtn"
         th:disabled="${post.type==1}">置顶</button>
   <button type="button" class="btn btn-danger btn-sm" id="wonderfulBtn"
         th:disabled="${post.status==1}">加精</button>
   <button type="button" class="btn btn-danger btn-sm" id="deleteBtn"
         th:disabled="${post.status==2}">删除</button>
</div>

定义js文件

  • 请求之前已经设置了csrf,异步请求均会带上csrf的token
  • 根据按钮的id属性定义对应不同的操作函数
  • 异步请求成功后的处理
    • 对于帖子的修改操作,异步请求成功后,将按钮的属性改为不可用
    • 对于帖子的删除操作,异步请求成功后,直接重定向到首页
// 发送AJAX请求之前,将CSRF令牌设置到请求的消息头中.
// 使用JQuery选择器,取指定meta标签中的content属性的值,赋值给变量key,value
var header = $("meta[name='_csrf_header']").attr("content");
var token = $("meta[name='_csrf']").attr("content");
// 在发布异步请求前,先对请求进行设置
$(document).ajaxSend(function (e, xhr, options) {
    // xhr为发布异步请求的核心对象,设置请求头的key和value-设置完后可以放到浏览器中
    // 发送请求时,会携带这个数据
    xhr.setRequestHeader(header, token);
});

$(function(){   // 定义不同按钮对应不同的操作函数
    $("#topBtn").click(setTop);
    $("#wonderfulBtn").click(setWonderful);
    $("#deleteBtn").click(setDelete);
});

// 点赞事件
function like(btn, entityType, entityId, entityUserId, postId) {
    $.post(
        CONTEXT_PATH + "/like",
        {"entityType":entityType,"entityId":entityId,"entityUserId":entityUserId,"postId":postId},
        function (data) {
            data = $.parseJSON(data);
            if(data.code == 0) {
                $(btn).children("i").text(data.likeCount);
                $(btn).children("b").text(data.likeStatus == 1 ? '已赞' : '赞');
            } else {
                alert(data.msg);
            }
        }
    );
}

// 置顶
function setTop() {
    $.post(
        CONTEXT_PATH + "/discuss/top",
        {"id":$("#postId").val()},
        function(data) {
            data = $.parseJSON(data);
            if(data.code == 0) {
                $("#topBtn").attr("disabled", "disabled");  // 异步请求成功后,将按钮的属性改为不可用
            } else {
                alert(data.msg);
            }
        }
    );
}

// 加精
function setWonderful() {
    $.post(
        CONTEXT_PATH + "/discuss/wonderful",
        {"id":$("#postId").val()},
        function(data) {
            data = $.parseJSON(data);
            if(data.code == 0) {
                $("#wonderfulBtn").attr("disabled", "disabled");
            } else {
                alert(data.msg);
            }
        }
    );
}

// 删除
function setDelete() {
    $.post(
        CONTEXT_PATH + "/discuss/delete",
        {"id":$("#postId").val()},
        function(data) {
            data = $.parseJSON(data);
            if(data.code == 0) {
                location.href = CONTEXT_PATH + "/index"; // 删除后,直接重定向到首页
            } else {
                alert(data.msg);
            }
        }
    );
}

测试结果显示:

  • 由于还没有设置权限,普通登录用户均可操作以上按钮

在这里插入图片描述

二、权限管理设置

1. Security权限分配设置

  • 本项目设计的方案是:
    • 对帖子的加精和置顶,只有版主权限才能访问操作
    • 对帖子的删除,只有管理员权限才能访问操作
.antMatchers(
        "/discuss/top",
        "/discuss/wonderful"
)
.hasAnyAuthority(AUTHORITY_MODERATOR)	// 版主
.antMatchers("/discuss/delete")
.hasAnyAuthority(AUTHORITY_ADMIN)		// 管理员

2. Thymeleaf模板整合SpringSecurity根据权限动态显示按钮

导入jar包

<!--       thymeleaf整合Security-->
      <dependency>
         <groupId>org.thymeleaf.extras</groupId>
         <artifactId>thymeleaf-extras-springsecurity5</artifactId>
      </dependency>

处理模板

  • 头文件中引入sec的命名空间
 xmlns:sec="http://www.thymeleaf.org/extras/spring-security"
  • 在按钮标签上添加权限管理

    • HttpSecurity配置的权限管理原理一样,
      • 只有指定分配的权限才显示该标签,权限不够不能点击此按钮

    在这里插入图片描述

测试结果显示

  • 普通用户没有权限,不会显示三个按钮

    在这里插入图片描述

  • 版主,可以显示置顶和加精按钮

    在这里插入图片描述

  • 管理员,可以显示删除按钮,并由权限操作

    在这里插入图片描述

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 23:15:00  更:2022-04-06 23:15:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:32:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码