栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

框架复习笔记-Java-案例:牛客网讨论社区

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

框架复习笔记-Java-案例:牛客网讨论社区

文章目录

搭建开发环境Spring入门

Spring IoC实例分析 Spring MVC入门

请求响应 Mybatis入门案例:开发者社区首页调试技巧

日志 版本控制-Git发送邮件开发注册功能登录之会话管理登录之生成验证码登录退出登录注册之拦截器

获取当前用户信息 账号设置检查登录状态过滤敏感词-前缀树发布帖子及帖子详情事务管理-(重点:需要理解记忆)

事务回滚测试 显示、添加、评论私信列表及发送私信统一处理异常统一记录日志(AOP面向切面编程)RedisSpring整合Redis点赞、关注利用Redis优化登录功能Kafka,构建TB级异步消息系统

Kafka入门Spring整合Kafka 发送系统通知显示系统通知ElasticSearch入门

Spring整合ElasticSearch 开发社区搜索功能Spring Security权限控制Redis高级数据类型Spring定时任务Quartz---(理解记忆)生成长图将文件上传至云服务器-七牛云优化网站性能项目发布与总结常见面试点

MySQLRedisSpring IoC AOP MVC

搭建开发环境


mvn cmpile 编译
mvn clean test 清理后测试






浏览器访问:

Spring入门



Spring IoC实例分析










注:Scope默认是singleton,若修改成prototype,则每次都会创建新的实例。

注:可以看到,两个实例对象的hashcode值已不一样!



不用get,直接Autowired注解,注入:

Spring MVC入门






请求








响应




Mybatis入门









案例:开发者社区首页





调试技巧

日志



版本控制-Git






发送邮件






开发注册功能










注:注册已经ok,接下来是激活账号:


登录之会话管理











注:分布式部署时为什么session会有问题?
nginx在分发请求时,可能带有某一个seesionid的请求可能不会分发到原来设置session的那台服务器上;可以通过设置分发方式让请求地址固定访问某一台服务器;可以设置共享session;可以专门用一台服务器来存储session(但是可能会挂掉);以上都不太好,所以选取数据库来存储session(非关系型数据库如redis)。

登录之生成验证码






登录退出








登录注册之拦截器

注:以下是显示登录信息:




获取当前用户信息




账号设置







检查登录状态





过滤敏感词-前缀树




@Component
public class SensitiveFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(SensitiveFilter.class);

    // 替换符
    public static final String REPLACEMENT = "***";

    // 根节点
    private TrieNode rootNode = new TrieNode();

    @PostConstruct
    public void init() {
        try (
                InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");
                BufferedReader reader = new BufferedReader(new InputStreamReader(is))
        ) {
            String keyword;
            while ((keyword = reader.readLine()) != null) {
                // 添加到前缀树
                this.addKeyword(keyword);
            }
        } catch (Exception e) {
            LOGGER.error("加载敏感词文件失败" + e.getMessage());
        }

    }

    // 将一个敏感词添加到前缀树中
    private void addKeyword(String keyword) {
        TrieNode tempNode = rootNode;
        for (int i = 0; i < keyword.length(); i++) {
            char c = keyword.charAt(i);
            TrieNode subNode = tempNode.getSubNode(c);

            if (subNode == null) {
                // 初始化子节点
                subNode = new TrieNode();
                tempNode.addSubNodes(c, subNode);
            }
            // 指向子节点,进入下一轮循环
            tempNode = subNode;

            //设置结束标识
            if (i == keyword.length() - 1) {
                tempNode.setKeywordEnd(true);
            }
        }
    }

    
    public String filter(String text) {
        if (StringUtils.isBlank(text)) {
            return null;
        }

        //指针1
        TrieNode tempNode = rootNode;
        //指针2
        int begin = 0;
        //指针3
        int position = 0;
        //结果
        StringBuilder sb = new StringBuilder();

        while (position < text.length()) {
            char c = text.charAt(position);

            //调过符号
            if(isSymbol(c)){
                // 若指针1处于根节点,将此符号计入结果,让指针2向下走一步
                if(tempNode == rootNode){
                    sb.append(c);
                    begin++;
                }
                // 无论符号在开头或中间,指针3都向下走一步
                position++;
                continue;
            }

            // 检查下级节点
            tempNode = tempNode.getSubNode(c);
            if(tempNode == null){
                // 以begin开头的字符不是敏感词
                sb.append(text.charAt(begin));
                // 进入下一个位置
                begin++;
                position = begin;
                // 指针1 重新指向根节点
                tempNode = rootNode;
            }else if(tempNode.isKeywordEnd()){
                // 发现敏感词,将begin~position字符串替换掉
                sb.append(REPLACEMENT);
                position++;
                begin = position;
                // 指针1 重新指向根节点
                tempNode = rootNode;
            }else{
                // 检查下一个字符
                position++;
            }
        }
        //将最后一批字符计入结果
        sb.append(text.substring(begin));
        return sb.toString();
    }

    // 判断是否是符号
    private boolean isSymbol(Character c) {
        //  0x2E80 ~ 0x9FFF 是东亚文字范围
        return !CharUtils.isAsciiAlphaUpper(c) && (c < 0x2E80 || c > 0x9FFF);
    }


    // 前缀树
    private class TrieNode {

        // 描述关键词结束标识
        private boolean isKeywordEnd = false;

        // 子节点 (key 是下级结点的字符,value是下级节点)
        private Map subNodes = new HashMap<>();

        public boolean isKeywordEnd() {
            return isKeywordEnd;
        }

        public void setKeywordEnd(boolean keywordEnd) {
            isKeywordEnd = keywordEnd;
        }

        public void addSubNodes(Character c, TrieNode node) {
            subNodes.put(c, node);
        }

        public TrieNode getSubNode(Character c) {
            return subNodes.get(c);
        }
    }
}
发布帖子及帖子详情




事务管理-(重点:需要理解记忆)










事务回滚测试



显示、添加、评论


私信列表及发送私信



统一处理异常


统一记录日志(AOP面向切面编程)





Redis







Spring整合Redis










点赞、关注







利用Redis优化登录功能


以下注解表示此类不推荐使用:

Kafka,构建TB级异步消息系统






Kafka入门











Spring整合Kafka




发送系统通知









显示系统通知

ElasticSearch入门












Spring整合ElasticSearch















开发社区搜索功能

Spring Security





权限控制



Redis高级数据类型






Spring定时任务Quartz—(理解记忆)


注:JDK下或Spring下的定时任务在分布式下会产生冲突,使用Quartz则不会。

以下是JDK测试例子:



以下是Spring测试例子:








以下是Quartz测试例子:









生成长图







将文件上传至云服务器-七牛云






优化网站性能





项目发布与总结









常见面试点

MySQL








Redis











Spring IoC AOP MVC




感谢牛客网老师的精彩讲解!
【参考】https://www.nowcoder.com/courses/cover/live/246
【源码链接】https://gitee.com/monkeyhlj/newcoder-community

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/703570.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号