Echo 的发帖功能是如何实现的
@[toc]
---
## 浅谈 Ajax
首先,各位不妨想一想,在平常开发中,我们是怎么在前端跟后端之间进行数据交互的?
最常用最原始的,form 表单。通过 form 表单以 post/get 方式提交数据,当你点击 `submit` 按钮时,浏览器会把你在 `input` 里面输入的数据提交到 form 表单中的 `action` 这个路径。
但是这种方式在某些情况下,对用户来说并不友好。因为在进行提交时,页面会发生跳转或刷新,我给帖子点了个赞你页面还需要刷新一下?显然这样用户体验不好。
为此,Ajax 应运而生。Ajax 的全称是 Asynchronous JavaScript and XML(**异步** JavaScript+XML),它并不是一种新的编程语言,而是一种使用现有标准的新方法。它依赖的是现有的 CSS/HTML/Javascript,而其中最核心的依赖是浏览器提供的 `XMLHttpRequest` 对象。这个对象为向服务器发送请求和解析服务器返回的响应提供了流畅的接口,使得浏览器可以发出 HTTP 请求与接收 HTTP 响应,**实现在页面不刷新(局部刷新)的情况下和服务端进行数据交互**。
Ajax 的工作原理大概是这样的:

## 浅谈同步、异步、阻塞、非阻塞
**阻塞与非阻塞,用于描述调用者在等待返回结果时的状态**
- 阻塞:调用者发起请求后,会一直等待返回结果,这期间当前线程会被挂起(阻塞)。
- 非阻塞:调用者发起请求后,会立刻返回,当前线程也不会阻塞。该调用不会立刻得到结果,调用者需要定时轮询查看处理状态。
**同步与异步,用于描述调用结果的返回机制(或者叫通信机制)**
- 同步:调用者发起请求后,会一直等待返回结果,即由调用者主动等待这个调用结果。
- 异步:调用者发起请求后,会立刻返回,但不会立刻得到这个结果,而是由被调者在执行结束后主动通知(如 Callback)调用者
## 发帖功能解析
事实上,使用 JS 编写 Ajax 代码并不容易,因为不同的浏览器对 Ajax 的实现并不相同。这意味着我们必须编写额外的代码对浏览器进行测试。不过,jQuery 团队解决了这个难题,我们只需要一行简单的代码,就可以实现 Ajax 功能,这里就不再详细赘述了。Echo 中当然也使用了 jQuery,我们来看看在 Echo 中发帖操作是如何发送异步请求的:

`function(data)` 就是回调函数,是 Ajax 在请求成功后自动调用的,参数 data 就是服务端返回的这个异步请求的值。
Ajax 会根据我们指定的 url `/discuss/add` 来找到对应的 Controller 方法,通过 id 选择器获取用户输入的数据,封装成 JSON 字符串发送过去(即帖子的标题和内容:{"title": title, "content": content}),这些数据会被自动传入到 Controller 的方法形参中。Controller 方法调用完成后,Ajax 会执行回调函数,获取 Controller 返回结果并执行相应操作。

使用 Ajax 异步提交代替传统的 form 表单提交的好处在于,使用异步方式与服务器通信,不需要打断用户的操作,具有更加迅速的响应能力,使得用户体验更好。
我们来看看 Controller 层的方法:

`getJSONString` 是我们自己写的一个工具类中的方法,通过阿里开源的 fastjson 将服务端返回的消息封装成 JSON 格式的字符串:

真正的发帖操作在 Service 层,其实就是一个插入数据库的操作,目前做的还比较简单,帖子的内容只能是普通的文本,后面会考虑支持 MarkDown 的。另外,这里有一个**过滤敏感词**的操作,涉及**前缀树**的设计与使用,后续会单开一篇文章详细讲解。
`DiscussPostService.addDiscussPost`:

## 小结
本来准备这章把首页帖子列表是怎么实现的也讲了,但是发现还涉及分页这个模块,由于分页功能是我们自己动手实现的,没有借助框架,所以还是有必要花点篇幅讲一下,就放在下一篇文章吧。
