牛客网后端项目实战(三十九):置顶、加精、删除

https://github.com/thymeleaf/thymeleaf-extras-springsecurity

  • 功能实现
    • 点击 置顶,修改帖子的类型。
    • 点击 “加精”、“删除”,修改帖子的状态。
  • 权限管理
    • 版主可以执行“置顶”、“加精” 操作。
    • 管理员可以执行“删除”操作。
  • 按钮显示
    • 版主可以看到“置顶”、“加精” 按钮。
    • 管理员可以看到“删除” 按钮。

一、功能实现

DAO层

DiscussPostMapper接口中添加以下两个方法:
置顶操作:即把帖子的 type 字段改为 1
加精操作:即把帖子的 status 字段改为 1
删除操作:即把帖子的 status 字段改为 2

    int updateType(int id, int type);

    int updateStatus(int id, int status);

添加相应的mapper:
discusspost-mapper.xml

    <update id="updateType">
        update discuss_post set type = #{type} where id = #{id}
    </update>

    <update id="updateStatus">
        update discuss_post set status = #{status} where id = #{id}
    </update>

Service

DiscussPostService.java

    public int updateType(int id, int type) {
        return discussPostMapper.updateType(id, type);
    }

    public int updateStatus(int id, int status) {
        return discussPostMapper.updateStatus(id, status);
    }

Controller

DiscussPostService.java
A)置顶

    // 置顶
    @RequestMapping(path = "/top", method = RequestMethod.POST)
    @ResponseBody
    public String setTop(int id) {
        discussPostService.updateType(id, 1);

        // 触发发帖事件
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(id);
        eventProducer.fireEvent(event);

        return CommunityUtil.getJSONString(0);
    }

1、置顶操作即是修改帖子的type=1,调用discussPostService.updateType() 方法
2、由于帖子的数据修改了,因此要更新 Elasticsearch 中帖子的数据,只需要触发发帖事件即可。(即利用消息队列将数据异步提交到Elasticsearch 中)
3、返回Json字符串

B)加精操作
与置顶操作逻辑类似

    // 加精
    @RequestMapping(path = "/wonderful", method = RequestMethod.POST)
    @ResponseBody
    public String setWonderful(int id) {
        discussPostService.updateStatus(id, 1);

        // 触发发帖事件
        Event event = new Event()
                .setTopic(TOPIC_PUBLISH)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(id);
        eventProducer.fireEvent(event);

        // 计算帖子分数
        String redisKey = RedisKeyUtil.getPostScoreKey();
        redisTemplate.opsForSet().add(redisKey, id);

        return CommunityUtil.getJSONString(0);
    }

C)删除操作

    // 删除
    @RequestMapping(path = "/delete", method = RequestMethod.POST)
    @ResponseBody
    public String setDelete(int id) {
        discussPostService.updateStatus(id, 2);

        // 触发删帖事件
        Event event = new Event()
                .setTopic(TOPIC_DELETE)
                .setUserId(hostHolder.getUser().getId())
                .setEntityType(ENTITY_TYPE_POST)
                .setEntityId(id);
        eventProducer.fireEvent(event);

        return CommunityUtil.getJSONString(0);
    }

不同的是要新增一个 删帖事件:
1、定义删帖主题
CommunityConstant接口

    /**
     * 主题: 删帖
     */
    String TOPIC_DELETE = "delete";

2、消费删帖事件,这是删帖事件触发时,所执行的逻辑
EventConsumer类

    // 消费删帖事件
    @KafkaListener(topics = {TOPIC_DELETE}) 
    public void handleDeleteMessage(ConsumerRecord record) {
        if (record == null || record.value() == null) {
            logger.error("消息的内容为空!");
            return;
        }

        Event event = JSONObject.parseObject(record.value().toString(), Event.class);
        if (event == null) {
            logger.error("消息格式错误!");
            return;
        }
		
		// 主要是这个方法的调用,前面判断的逻辑与其它消费事件一样
        elasticsearchService.deleteDiscussPost(event.getEntityId());
    }

前端

置顶、加精、删除 三个按钮,点击后,由异步提交post请求

discuss-detail.html

					<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}" sec:authorize="hasAnyAuthority('moderator')">置顶</button>
						<button type="button" class="btn btn-danger btn-sm" id="wonderfulBtn"
							th:disabled="${post.status==1}" sec:authorize="hasAnyAuthority('moderator')">加精</button>
						<button type="button" class="btn btn-danger btn-sm" id="deleteBtn"
							th:disabled="${post.status==2}" sec:authorize="hasAnyAuthority('admin')">删除</button>
					</div>
1、添加id 属性
2、th:disabled="${post.type==1}“ 指帖子加精后,按钮变灰(即不能再点击)
3、<input type="hidden" id="postId" th:value="${post.id}">
隐藏框,用于向服务器提交 帖子的id. (具体操作在discuss.js 中)

discuss.js

$(function(){
    $("#topBtn").click(setTop);
    $("#wonderfulBtn").click(setWonderful);
    $("#deleteBtn").click(setDelete);
});

// 置顶
function setTop() {
    $.post(
        CONTEXT_PATH + "/discuss/top",
        {"id":$("#postId").val()},
        function(data) {
            data = $.parseJSON(data);
            if(data.code == 0) {
                $("#topBtn").attr("disabled", "disabled");  // 置顶操作成功: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、$(function(){ });
html页面加载完毕后,javascript得到标签,再动态绑定事件。

2、$("#topBtn").click(setTop);
即:html页面加载完毕后,得到 topBtn 按钮,绑定单击事件,单击时调用setTop函数

3、setTop函数
该函数即利用 $.post( ) 发送一个异步的post的请求。
第一个参数:提交路径;第二个参数:向服务器提交的参数,该参数是获取html页面 的 id="postId"的值;第三个参数是回调函数,处理返回的json字符串,使用 $.parseJSON( ) 解析。

权限管理

SecurityConfig 中增加相应的授权配置即可

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 授权
        http.authorizeRequests()
                .antMatchers(
                        "/user/setting",
                        "/user/upload",
                        "/discuss/add",
                        "/comment/add/**",
                        "/letter/**",
                        "/notice/**",
                        "/like",
                        "/follow",
                        "/unfollow"
                )
                .hasAnyAuthority(
                        AUTHORITY_USER,
                        AUTHORITY_ADMIN,
                        AUTHORITY_MODERATOR
                )
                 // 置顶、加精 需要  AUTHORITY_MODERATOR
                .antMatchers(                  
                        "/discuss/top",
                        "/discuss/wonderful"
                )
                .hasAnyAuthority(
                        AUTHORITY_MODERATOR
                )
                 // 删除  需要  AUTHORITY_ADMIN
                .antMatchers(
                        "/discuss/delete",
                )
                .hasAnyAuthority(
                        AUTHORITY_ADMIN
                )
                .anyRequest().permitAll()
                .and().csrf().disable(); // 取消了防止CSRF攻击

按钮显示

该操作使用的是thymeleaf-extras-springsecurity,相关文档:https://github.com/thymeleaf/thymeleaf-extras-springsecurity

1、导包
pom.xml

		<dependency>
			<groupId>org.thymeleaf.extras</groupId>
			<artifactId>thymeleaf-extras-springsecurity5</artifactId>
		</dependency>

2、html上要声明命名空间

<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">

3、相应按钮处添加

sec:authorize="hasAnyAuthority('moderator')" 指仅当用户的权限是moderator是,才会显示此按钮

比如置顶按钮处:

<button type="button" class="btn btn-danger btn-sm" id="topBtn"
	th:disabled="${post.type==1}" sec:authorize="hasAnyAuthority('moderator')">置顶</button>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值