zoukankan      html  css  js  c++  java
  • Spring boot 论坛项目实战_03

    Spring Boot 实践,开发社区核心功能

     

    1.过滤敏感词

    • 对用户发布的内容,进行过滤或打码。

      实际应用操作,我们会自定义前缀树过滤。

    • 前缀树

      • 根节点没有字符,根节点向下每一层是敏感词的 第X个 字母

        要遍历到 最末节 节点 才能构成一个敏感词。

        检测需要三个指针:

        1. 第一个指向根节点

        2. 第二个默认指向待判定字符串头【敏感词开头】,不回头的从前往后走。

        3. 第三个默认指向待判定字符串头【敏感词结尾】,回头,回到指针2的位置往后走。

        该算法以字符为单位,进行筛选。

      • 名称:Trie、字典树、查找树

      • 特点:查找效率高,消耗内存大

      • 应用:字符串检索、词频统计、字符串排序等

    • 敏感词过滤器:

      • 定义前缀树

      • 根据敏感词,初始化前缀树

      • 编写过滤敏感词的方法

     

    2.发布帖子

    • 当前网页不刷新的情况下,访问服务器

      服务器返回网页结果

      用服务器返回的结果对网页进行局部刷新

    • AJAX【异步通信技术】

      • Asynchronous JavaScript and XML

      • 异步的JavaScript 与 XML,不是一门新技术,只是一个新的术语

      • 使用AJAX,网页能够将增量更新呈现在页面上,而不需要刷新整个页面

      • 虽然 X 代表XML,但目前 JSON 的使用比 XML 更加普遍

      • 参考网站:https://developer.mozilla.org/zh-CN/docs/Web/Guide/AJAX

    • 示例:

      • 使用 JQuery 发送 AJAX 请求

    • 实践:

      • 才用 AJAX 请求,实现发布帖子的功能

     

    3.帖子详情

    • DiscussPostMapper

    • DiscussPostService

    • DiscussPostController

    • index.html

      • 在帖子标题上增加访问详情页面的链接

        • 修改帖子的 "th:href"

    • discuss-detail.html

      • 处理静态资源的访问路径

      • 复用 index.html 的 header 区域

      • 显示标题、作者、发布时间、帖子正文等内容

        • 利用 th 模板 的 对应参数, 获取相对数据, 除时间用到 #datas.format() 函数 规范格式

        • 其他的文本 建议用 th:utext 处理文本.

     

    4.事务管理

    事务

    • 什么是事务

      • 事务是由N步 数据库操作序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。

    • 事务的特性(ACID)

      • 原子性(Atomicity):事务是应用中不可再分的最小执行体。

      • 一致性(Consistency):事务执行的结果,须使数据从一个一致性状态【满足数据库的约束】,变为另一个一致性状态。

      • 隔离性(Isolation):【对并发的处理方案】各个事务的执行互不干扰,任何事务的内部操作对其他的事务都是隔离的。

      • 持久性(Durability):事务一旦提交,对数据所做的任何改变都要记录到永久存储器中。

     

    事务的隔离性

    我们开发的服务器程序是多线程环境

    是多事务并发的场景

    很可能多个事务访问同一份数据,必须要做隔离性处理

    • 常见的并发异常

      • 第一类丢失更新、第二类丢失更新

      • 脏读、不可重复读、幻读

    • 常见的隔离等级

    • 选取原则:

      保证需要的基础上,尽可能提升效率
      • Read Uncommitted :读取未提交的数据

      • Read Committed:读取已提交的数据

      • Repeatable:可重复读

      • Serializable:串行化

     

    第一类丢失更新

    • 某一个事务的回滚导致另一个事务已更新的数据丢失了。

    时刻事务1事务2
    T1 Read: N = 10  
    T2   Read: N = 10
    T3   Write: N = 9
    T4   Commit: N = 9
    T5 Write: N = 11  
    T6 Rollback: N = 10  

    【回滚到 T1,事务2 白给】

     

    第二类丢失更新

    • 某一个事务的提交导致另一个事务已更新的数据丢失了。

    时刻事务1事务2
    T1 Read: N = 10  
    T2   Read: N = 10
    T3   Write: N = 9
    T4   Commit: N = 9
    T5 Write: N = 11  
    T6 Commit: N = 11  

    【事务1 后提交,事务2 提交的数据被覆盖】

     

    脏读

    • 某一个事务,读取了另外一个事务未提交的数据。

    时刻事务1事务2
    T1 Read: N = 10  
    T2 Write: N = 11  
    T3   Read: N = 11
    T4 Rollback: N = 10  

    【事务2 读取到了 事务1 没有提交的数据,白给】

     

    不可重复读

    • 某一个事务,对同一个数据前后读取的结果不一致

    时刻事务1事务2
    T1 Read: N = 10  
    T2   Read: N = 10
    T3 Write: N = 11  
    T4 Commit: N = 11  
    T5   Read: N = 11

    【很短时间内,读同一份数据,结果不同】

     

    幻读

    • 某一个事务,对同一个表前后查询到的行数不一致

    时刻事务1事务2
    T1   Select: id < 10 (1, 2, 3)
    T2 Insert: id = 4  
    T3 Commit: id = (1, 2, 3, 4)  
    T4   Select: id < 10 (1, 2, 3, 4)

    【很短时间内,查询同一张表,结果行数不同】

     

    事务隔离级别

    隔离级别第一类丢失更新脏读第二类丢失更新不可重复读幻读
    Read Uncommitted:读取未提交数据 Y Y Y Y Y
    Read Committed:读取已提交的数据 N Y Y Y Y
    Repeatable:可重复读 N N N N Y
    Serializable:串行化 N N N N N

     

    实现机制

    • 悲观锁

      • 共享锁(S锁)

        • 事务A 对某数据加了共享锁后,其他事务只能对该数据加共享锁,但不能加排他锁

        • 其他事务可以读、不能改

      • 排他锁(X锁)

        • 事务A 对某数据加了排他锁后,其他事务既不能对该数据加共享锁,也不能加排他锁

        • 其他事务不能读、也不能改

    • 乐观锁(自定义)

      • 版本号、时间戳等

        • 在更新数据前,检查版本号是否发生变化。若变化则取消本次更新,否则就更新数据(版本号 + 1)

     

    Spring 事务管理

    • 声明式事务

      • 通过XML 配置,声明某方法的事务特征。

      • 通过注解,声明某方法的事务特征。

        • // 参数 isolation =  手动指定的隔离级别
          // 参数 propagation =  手动指定的事务传播机制
          @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
              public Object save1() {
              // 具体功能
              }
    • 编程式事务

      • 通过 TransactionTemplate 管理事务,并通过它执行数据库的操作。

        • // 注入 Spring 自动生成的 TransactionTemplate Bean
              @Autowired
              private TransactionTemplate transactionTemplate;

           

    5. 显示评论

    • 数据层

      • 根据实体查询一页评论数据

      • 根据实体查询评论的数量

    • 业务层

      • 处理查询评论的业务

      • 处理查询评论数量的业务

    • 表现层

      • 显示帖子详情数据时, 同时显示该帖子所有的评论数据

     

    6.添加评论

    • 数据层

      • 增加评论数据。

      • 修改帖子的评论数量。

        • 冗余修改

    • 业务层

      • 处理添加评论的业务: 先增加评论、再更新帖子的评论数量。

    • 表现层

      • 处理添加评论数据的请求。

      • 设置添加评论的表单。

     

    7.私信列表

    • 私信列表

      • 查询当前用户的会话列表, 每个会话只显示一条最新的私信.

      • 支持分页显示

    • 私信详情

      • 查询某个会话所包含的私信

      • 支持分页显示

     

    8. 发送私信

    • 发送私信

      • 采用异步的方式发送私信

      • 发送成功后刷新私信列表

    • 设置已读

      • 访问私信详情时,将显示的私信设置为已读状态

     

    9. 统一处理异常

    • @ControllerAdvicer

      • 用于修饰类,表示该类是Controller 的全局配置类

      • 在此类中,可以对Controller 进行如下三中全局配置:

        • 异常处理方案、绑定数据方案、绑定参数方案

    • @ExceptionHandler

      • 用于修饰方法,该方法会在Controller 出现异常后被调用,用于处理捕获到的异常

    • @ModelAttribute

      • 用于修饰方法,该方法会在Controller 方法执行前被调用,用于为Model 对象绑定参数

    • @DataBinder

      • 用于修饰方法,该方法会在Controller 方法执行前被调用,用于绑定参数的转换器

    // 通过 Request 获取请求类型, 判断是 重定向 还是 异步
            String xRequestedWith = request.getHeader("x-requested-with");
            if (xRequestedWith.equals("XMLHttpRequest")){
                // 这是一个异步请求
                // plain: 浏览器 返回一个 普通字符串格式
                response.setContentType("application/plain;charset=utf-8");
                PrintWriter writer = response.getWriter();
                writer.write(CommunityUtil.getJSONString(1,"服务器异常"));
            }

     

    10. 统一记录日志

    AOP的概念

    • Aspect Oriented Programing, 面向切面编程.

    • AOP 是一种编程思想, 是对 OOP 的补充, 可以进一步提高编程效率.

    AOP术语:

    • 处理目标、业务组件、需求目标: Target

    • 将目标需求代码封装到组件、封装业务需求的组件:Aspect

      • Pointcut:将代码织入的具体位置

      • Advice:实现具体的系统逻辑

    • 将业务组件织入到 Target 的 位置——连接点:Joinpoint

    • 织入将 Aspect 按照不同时机 放到 Target 中:

      1. 编译时织入,需使用特殊的编译器

      2. 装载类时织入,需使用特殊的类装载器

      3. 运行时织入,需为目标生成代理对象

    AOP的实现

    • AspectJ

      • AspectJ 是语言级的实现,它扩展了Java 语言,定义了AOP 语法

      • AspectJ 在编译期织入代码,它有一个专门的编译器,用来生成遵守Java 字节码规范的 class 文件

    • Spring AOP

      • Spring AOP 使用纯 Java 实现,它不需要专门的编译过程,也不需要特殊的类装载器

      • Spring AOP 在运行时通过代理的方式织入代码,只支持方法类型的连接点

      • Spring 支持对 AspectJ 的集成

    Spring AOP

    • JDK 动态代理

      • Java 提供的动态代理技术,可以在运行时创建接口的代理实例

      • Spring AOP 默认才用此种方式,在接口的代理实例中织入代码

    • CGLib 动态代理

      • 才用底层的字节码技术,在运行时创建子类代理实例

      • 当目标对象不存在接口时,Spring AOP 会采用此种方式,在子类实例中织入代码

    // 用户 ip 获取, 向下转型
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    // 从 request属性对象获取 http 的 request
            HttpServletRequest request = attributes.getRequest();
    // 从 http 的request 获取访问 ip
            String ip = request.getRemoteHost();
    //用 SimpleDateFormat 获取自定义格式 日期
            String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    // 用 连接点对象 获取它声明的类型 及 它的方法名
            String target = joinPoint.getSignature().getDeclaringTypeName()+"."+joinPoint.getSignature().getName();
    // String.format() 里面用通配符占位然后根据类型填写数据
            logger.info(String.format("用户[%s],在[%s]访问了[%s].",ip,now,target));

     

  • 相关阅读:
    jenkins使用
    pytest+allure生成接口自动化测试报告
    charles系列
    go语言安装使用
    go语言介绍
    Nginx
    python面试题-python相关
    pyhon全栈开发学习目录
    补充【第二章】supervisor守护进程保障服务
    python全栈开发基础【补充】python中列表排序,字典排序,列表中的字典排序
  • 原文地址:https://www.cnblogs.com/77-is-here/p/13654270.html
Copyright © 2011-2022 走看看