项目1在线交流平台-7.构建安全高效的企业服务-3. Security整合Kafka,ES,Thymeleaf实例-对帖子置顶、加精、删除

2023-05-16

文章目录

    • 功能需求
    • 一、置顶、加精、删除帖子功能的实现
      • 1. dao层处理数据
        • 接口定义
        • sal语句定义
      • 2. service层业务处理
      • 3. Controller层处理按钮事件异步请求
        • 异步请求及kafka发送消息
        • 删除帖子-消费消息
      • 4. 模板页面和js文件处理
        • 帖子详情页面按钮处理
          • `th:disabled`- 按钮不起作用
        • 定义js文件
        • 测试结果显示:
    • 二、权限管理设置
      • 1. Security权限分配设置
      • 2. Thymeleaf模板整合SpringSecurity根据权限动态显示按钮
        • 导入jar包
        • 处理模板
      • 测试结果显示

参考牛客网高级项目教程
尚硅谷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配置的权限管理原理一样,
      • 只有指定分配的权限才显示该标签,权限不够不能点击此按钮

    在这里插入图片描述

测试结果显示

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

    在这里插入图片描述

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

    在这里插入图片描述

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

    在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

项目1在线交流平台-7.构建安全高效的企业服务-3. Security整合Kafka,ES,Thymeleaf实例-对帖子置顶、加精、删除 的相关文章

  • 裁剪图像中感兴趣区域python

    题外话 xff1a 比较全面的缩略图及相应源码 http matplotlib org gallery html http www cnblogs com wei li archive 2012 05 23 2506940 html 题外外
  • Linux设备驱动程序(LDD)中snull的编译问题

    对LDD中snull程序 xff0c 编译的时候会有许多问题 xff0c 鉴于网上还没有合适的解决办法 xff0c 做此总结 xff0c 整理知识 本文在debian6 0上运行通过 xff0c 内核版本为2 6 32 学习LDD中网络驱动
  • 认识(大端--小端)端模式

    span style color 000000 端模式 xff08 Endian xff09 的这个词出自Jonathan Swift书写的 格列佛游记 这本书根据将鸡蛋敲开的方法不同将所有的人分为两类 xff0c 从圆头开始将鸡蛋敲开的人
  • HOW TO install nam for ns2 on debian

    Debian is convinent to install software packages for the tool aptl Like many other packages we can use apt get install n
  • c++ #pragma once和 #ifndef 优缺点对比分析

    pragma once ifndef方式为了避免同一个头文件被包含 xff08 include xff09 多次 pragma once 声明 定义语句 ifndef SOMEFILE H define SOMEFILE H 声明 定义语句
  • roslaunch找不到packge

    roslaunch找不到packge 尝试下面几种做法 1 source bashrc 2 source catkin ws devel setup bash 3 rospack profile 为确保ROS能找到新包 xff0c 常常在发
  • DSP:TMS320C6657 之 UART波特率问题

    6657 设置串口波特率 以614400为例 xff08 1 xff09 根据公式计算分频系数 xff08 2 xff09 1GHz 主频下 UART 输入频率 166666666Hz xff08 1 6 xff09 xff08 3 xff
  • 手写httpServer Demo案例

    相信每一个java程序猿在学习javaWeb的时候 xff0c 或多或少接触了Servlet 或者说通过Servlet来完成页面发送的请求 今天 xff0c 模仿Servlet接受和处理请求实现一个简单的httpServer 该Server
  • ubuntu18.04 查看在用串口

    1 终端输入cutecom 打开串口助手 xff0c 可能没有下载 xff0c 可根据提示下载安装 sudo cutecom 2 点击device旁边的下拉按钮即可查询当前在用的串口
  • Linux解决未定义的引用过程记录

    Linux解决未定义的引用过程记录 在摸索vscode使用的过程中 xff0c 编写的代码出现了为定义的引用错误 csdn上搜索了很多 xff0c 代码小白看完觉得写的非常的简略 xff0c 完全无从下手 xff08 应该是我太菜了 xff
  • 十一种室内定位传感器方案汇总介绍与对比(机器人、物联网领域)

    室内定位传感器方案汇总 目录 室内定位传感器方案汇总 1 定位方案概述 1 1 内定位系统有最基本的5种算法 xff1a 1 2 常用的室内定位技术主要包括以下几种 xff1a 1 3 定位理论 1 4 不同的定位方案对比 2 各种定位方案
  • C++中的unique函数

    STL中的unique函数的头文件 xff1a span class hljs preprocessor include lt iostream gt span unique 的作用是 去掉 容器中相邻元素的重复元素 xff0c 这里所说的
  • 单片机开发入门---从零开始玩转FRDM-KL25Z

    一 背景介绍 最近需要开发一个程序 xff0c 使用飞思卡尔的开发板FRDM KL25Z xff0c 来设计一款 西蒙游戏 的改进版 xff0c 下面我们先来了解一下西蒙游戏 西蒙游戏 是一款益智休闲类小游戏 xff0c 它的游戏规则是 x
  • SSD---系统架构

    SSD主要由两大模块构成 主控和闪存介质 另外可选的还有Cache缓存单元 主控是SSD的大脑 xff0c 承担着指挥 运算和协调的作用 xff0c 具体表现在 xff1a 前端实现标准主机接口与主机通信 xff0c 接口包括SATA SA
  • SSD核心技术---FTL

    FTL算法的优劣与否 xff0c 直接决定了SSD在性能 xff08 Performance xff09 可靠性 xff08 Reliability xff09 耐用性 xff08 Endurance xff09 等方面的好坏 xff0c
  • SSD---PCIe介绍

    SSD已经大跨步迈入PCIe时代 作为SSD的一项重要技术 xff0c 我们有必要对PCIe有个基本的了解
  • SSD---NVMe介绍

    何为NVMe xff1f NVMe即Non Volatile Memory Express xff0c 是非易失性存储器标准 xff0c 是跑在PCIe接口上的协议标准 NVMe的设计之初就有充分利用了PCIe SSD的低延时以及并行性 x
  • SSD---ECC原理

    我们知道 xff0c 所有型号的闪存都无法保证存储的数据会永久稳定 xff0c 这时候就需要ECC xff08 纠错码 xff09 去给闪存纠错 ECC能力的强弱直接影响到SSD的使用寿命和可靠性 本章将简单介绍ECC的基本原理和目前最主流
  • 音响发烧友---HiFi音频功放

    最近一直想做个开源的电子项目 xff0c 思考许久还是选择做个HiFi音频功放 作为一个音响发烧友 xff0c 带大家DIY一台属于自己的功放 聆听一下 xff0c 纯正的音乐之美 首选需要了解一下功放的类型 xff1a 纯甲类功率放大器乙
  • Altium Designer20常用使用快捷键

    一 AD20常用快捷键 PCB布线常使用 xff1a ctrl 43 m 测量长度 Q 单位切换 shift 43 ctrl 43 r 取消显示标注 shift 43 S 显示层切换 ctrl 43 右击 高亮显示一条线 ctrl 43 D

随机推荐