牛客论坛项目-第三章

第三章

过滤敏感词

前缀树,敏感词过滤器(定义前缀树、根据铭感词初始化前缀树、编写过滤方法)

 private class TrieNode{
         private boolean isKeywordEnd = false;
         private Map<Character,TrieNode> subNodes = new HashMap<>();
 ​
         public boolean isKeywordEnd() {
             return isKeywordEnd;
         }
 ​
         public void setKeywordEnd(boolean keywordEnd) {
             isKeywordEnd = keywordEnd;
         }
 ​
       public void addSubNode(Character c, TrieNode node){
             subNodes.put(c, node);
       }
       public TrieNode getSubNode(Character c){
             return subNodes.get(c);
       }
     }
  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.addSubNode(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 (begin < text.length()){
             char c = text.charAt(position);
             if (isSymbol(c)){
                 if (tempNode == rootNode){
                     begin ++;
                     sb.append(c);
                 }
                 position++;
                 continue;
             }
             tempNode = tempNode.getSubNode(c);
             if (tempNode == null){
                 sb.append(text.charAt(begin));
                 position = ++begin;
                 tempNode = rootNode;
             }else if (tempNode.isKeywordEnd()){
                 sb.append(REPLACEMENT);
                 begin = ++position;
                 tempNode = rootNode;
             }else {
                 if (position < text.length() - 1){
                     position++;
                 }
             }
         }
         return sb.toString();
     }
 ​
     //判断是否为符号
     private boolean isSymbol(Character c) {
         //0x2E80~0x9FFF是东亚文字范围
         return !CharUtils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);
     }

发布帖子

AJAX实现异步请求,网页实现增量跟新,不需要刷新页面

使用JQuery发送AJAX请求

转义标签:HtmlUtils.htmlEscape()

 function publish() {
     $("#publishModal").modal("hide");
 ​
     //获取标题和内容
     var title = $("#recipient-name").val();
     var content = $("#message-text").val();
 ​
     //发布异步请求
     $.post(
         CONTEXT_PATH + "/discuss/add",
         {"title":title,"content":content},
         function (data){
             data = $.parseJSON(data);
             //在提示框当中显示返回的消息
             $("#hintBody").text(data.msg);
             //显示提示框
             $("#hintModal").modal("show");
             //2秒后自动隐藏提示框
             setTimeout(function(){
                 $("#hintModal").modal("hide");
                 //刷新页面
                 if (data.code == 0){
                     window.location.reload();
                 }
             }, 2000);
         }
     );
 }

帖子详情

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

新增dao层、service层、controller层和页面

事务管理

ACID

spring提供事务管理

  1. 声明式-在方法上增加@Transactional(isolatiom=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)

    1. REQUIRED支持当前事务,如果不存在则创建新事物

    2. REQUIRED _NEW 创建一个新事物,并且暂停当前事务

    可以作用于接口接口方法以及类方法上。

  2. 编程式

    1. 注入TransactionTemplate

    2. transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED)

    3. transactionTemplate.excute()

     public void like(int userId, int entityType, int entityUserId){
             redisTemplate.execute(new SessionCallback() {
                 @Override
                 public Object execute(RedisOperations redisOperations) throws DataAccessException {
                     xxx
                     redisOperations.multi();
                     //被事务管理的操作
                     return redisOperations.exec();
                 }
             });
         }

显示评论

  • 数据层

    • 查询评论数据 实体类型是帖子的评论还是评论的评论

  • 业务层

    • 处理查询评论数量业务

  • 表现层

    • 显示帖子详情

添加评论

对添加评论做事务管理

@Transactional(isolatiom=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)

发送私信

异步的方法发送私信

 $.post(
         CONTEXT_PATH + "/letter/send",
         {"toName":toName,"content":content},
         function(data){
             data = $.parseJSON(data);
             if (data.code == 0){
                 $("#hintBody").text("发送成功");
             }else {
                 $("#hintBody").text(data.msg);
             }
 ​
             $("#hintModal").modal("show");
             setTimeout(function(){
                 $("#hintModal").modal("hide");
                 location.reload();
             }, 2000);
         }
     );

统一处理异常

统一处理异常:

@ControllerAdvice用于修饰类,表示该类是Controller的全局配置类-可以进行三种配置(异常处理方案、绑定数据方案、绑定参数方案) @ControllerAdvice(annotations = Controller.class) @ExceptionHandler用于修饰方法,会在Controller出现异常后调用,用于处理捕获的异常。

 @ControllerAdvice(annotations = Controller.class)
 public class ExceptionAdvice {
     private final static Logger logger = LoggerFactory.getLogger(ExceptionAdvice.class);
 ​
     @ExceptionHandler({Exception.class})
     public void handleException(Exception e, HttpServletRequest request, HttpServletResponse response) throws IOException {
         logger.error("服务器异常" + e.getMessage());
         for (StackTraceElement element:e.getStackTrace()){
             logger.error(element.toString());
         }
 ​
         String xRequestedWith = request.getHeader("x-requested-with");
         if ("XMLHttpRequest".equals(xRequestedWith)){
             response.setContentType("application/plain;charset=utf-8");
             PrintWriter writer = response.getWriter();
             writer.write(CommunityUtil.getJSONString(1,"服务器异常"));
         }else {
             response.sendRedirect(request.getContextPath()+"/error");
         }
     }
 }

AOP 统一记录日志

发布帖子、发布评论、发送消息都需要记录日志

基于动态代理

 @Component
 @Aspect
 public class ServiceLogAspect {
     private final static Logger logger = LoggerFactory.getLogger(ServiceLogAspect.class);
 ​
     @Pointcut("execution(* com.nowcoder.community2.service.*.*(..))")
     public void pointcut(){
 ​
     }
 ​
     @Before("pointcut()")
     public void before(JoinPoint joinPoint){
         ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
         HttpServletRequest request = attributes.getRequest();
         String ip = request.getRemoteHost();
         String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
         String target = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
         logger.info(String.format("用户[%s],在[%s],访问了[%s]",ip, now, target));
     }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值