文章目录
参考牛客网高级项目教程
1. 功能需求
- 1.点击主页中的“我要发布”按钮,弹出异步请求的输入框
- 2.在输入框中填入要发布的内容,点击提交,可以发布异步请求
- 3.帖子内容一方面会过滤加工后入库,一方面会向浏览器响应Json数据,显示发布的提示信息
- 4.发布成功后,会重定向跳转到主页
2. AJAX示例
2.1 JSON回顾
JSON 键值对是用来保存 JavaScript 对象的一种方式,
- 和 JavaScript 对象的写法也大同小异,
- 键/值对组合中的键名写在前面并用双引号 “” 包裹,使用冒号 : 分隔,然后紧接着值:
JSON 是 JavaScript 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
var obj = {a: 'Hello', b: 'World'}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = '{"a": "Hello", "b": "World"}'; //这是一个 JSON 字符串,本质是一个字符串
@ResponseBody 如果想返回js对象,必须有此注解,
- 在SpringMVC中,有此注解,会将返回类型的map,list等数据结构自动转换为JSON字符串
2.2 FastJson
1)fastjson的特点与作用
- 虽然X代表XML,但目前JSON的使用比XML更加普遍。
- fastjson.jar是阿里开发的一款专门用于Java开发的包,
- 可以方便的实现json对象与JavaBean对象的转换,
- 实现json对象与json字符串的转换。
- 实现json的转换方法很多,最后的实现结果都是一样的。
- Java对象 -> Json对象->JSON字符串 -> JS对象
2)fastjson 三个主要的类
【JSONObject 代表 json 对象 】
- JSONObject实现了Map接口, 猜想 JSONObject底层操作是由Map实现的。
- JSONObject对应json对象,通过各种形式的get()方法可以获取json对象中的数据,
- 也可利用诸如size(),isEmpty()等方法获取”键:值”对的个数和判断是否为空。
- 其本质是通过实现Map接口并调用接口中的方法完成的。
【JSONArray 代表 json 对象数组】
- 内部是有List接口中的方法来完成操作的。
【JSON 代表 JSONObject和JSONArray的转化】
- JSON类源码分析与使用
- 仔细观察这些方法,
- 主要是实现json对象,json对象数组,javabean对象,json字符串之间的相互转化。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
public class FastJsonDemo {
public static void main(String[] args) {
//创建一个对象
User user1 = new User("1号", 3, "男");
User user2 = new User("2号", 3, "男");
User user3 = new User("3号", 3, "男");
User user4 = new User("4号", 3, "男");
List<User> list = new ArrayList<User>();
list.add(user1);
list.add(user2);
list.add(user3);
list.add(user4);
System.out.println("*******Java对象 转 JSON字符串*******");
String str1 = JSON.toJSONString(list);
System.out.println("JSON.toJSONString(list)==>"+str1);
String str2 = JSON.toJSONString(user1);
System.out.println("JSON.toJSONString(user1)==>"+str2);
System.out.println("\n****** JSON字符串 转 Java对象*******");
User jp_user1=JSON.parseObject(str2,User.class);
System.out.println("JSON.parseObject(str2,User.class)==>"+jp_user1);
System.out.println("\n****** Java对象 转 JSON对象 ******");
JSONObject jsonObject1 = (JSONObject) JSON.toJSON(user2);
System.out.println("(JSONObject) JSON.toJSON(user2)==>"+jsonObject1.getString("name"));
System.out.println("\n****** JSON对象 转 Java对象 ******");
User to_java_user = JSON.toJavaObject(jsonObject1, User.class);
System.out.println("JSON.toJavaObject(jsonObject1, User.class)==>"+to_java_user);
}
}
3)FastJson工具方法色设计
引入jar包
<!-- 配置fastjson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
</dependency>
给浏览器返回Json字符串信息
在之前设计的CommunityUtil类添加工具方法
JSONObject
- 封装数据的Json对象,相当于model
- 添加数据比较方便
map.keySet()
- 遍历map的每一个key
toJSONString()
-
将Json对象转为JSON字符串
-
dddd
** * 给浏览器返回Json字符串信息,利用fastjsonAPI,获取json字符串 * @param code 响应的编码信息 * @param msg 响应的字符串提示信息 * @param map 响应的数据 * @return Json字符串 */ public static String getJSONString(int code, String msg, Map<String, Object> map) { JSONObject jsonObject = new JSONObject(); // 封装数据的Json对象,相当于model jsonObject.put("code", code); jsonObject.put("msg", msg); if(map != null) { for(String key : map.keySet()) { jsonObject.put(key, map.get(key)); } } return jsonObject.toJSONString(); } // 重载方法 public static String getJSONString(int code, String msg) { return getJSONString(code, msg, null); } public static String getJSONString(int code) { return getJSONString(code, null, null); }
测试
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 25);
System.out.println(getJSONString(0, "提交成功", map));
}
{"msg":"提交成功","code":0,"name":"张三","age":25}
2.3 异步请求
1)AJAX回顾
- Asynchronous JavaScript and XML
- 异步的JavaScript与XML,不是一门新技术,只是一个新的术语。
- 使用AJAX,网页能够将增量更新呈现在页面上,而不需要刷新整个页面。
- 虽然X代表XML,但目前JSON的使用比XML更加普遍
2)jQuery.ajax解析
- Ajax的核心是XMLHttpRequest对象(XHR)。
- XHR为向服务器发送请求和解析服务器响应提供了接口。能够以异步方式从服务器获取新数据。
- jQuery 提供多个与 AJAX 有关的方法。
- 通过 jQuery AJAX 方法,
- 能够使用 HTTP Get 和 HTTP Post 从远程服务器上请求文本、HTML、XML 或 JSON
- 同时能够把这些外部数据直接载入网页的被选元素中。
- jQuery 不是生产者,而是大自然搬运工。
- jQuery Ajax本质就是 XMLHttpRequest,对他进行了封装,方便调用!
3)jQuery发送异步请求
HTML中引入JQuery
<script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script>
定义发送请求按钮,并触发发送方法
<p>
<input type="button" value="发送" onclick="send();">
</p>
对发送方法的定义
$.post(url,data,回调函数)
-
使用post请求,需要传三个参数
-
url:即请求路径
-
data:用户输入数据,即要向服务器发送的数据
-
是JavaScript对象,
-
可以用js对象表示:
{name:"李四", age:23}
-
也可以用Json字符串方式表示:
{"name":"李四", "age":23}
-
-
-
回调函数:function (data)
- 服务器给浏览器响应后,将服务器处理后返回的数据用这个方法返回
- 数据一般是转成JSON字符串格式给这个方法
- 服务器给浏览器响应后,将服务器处理后返回的数据用这个方法返回
-
$.parseJSON(data)
-
将字符串转为JS对象
-
这需要一个标准的JSON字符串,并返回生成的JavaScript对象
-
通过JS对象,可以快速操作对象中的每个key,value
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>AJAX</title> </head> <body> <p> <input type="button" value="发送" onclick="send();"> </p> <script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script> <script> function send() { $.post( "/community/alpha/ajax", {name:"李四", age:23}, function (data) { console.log("返回数据类型" + typeof (data)) console.log("返回数据:" + data) data = $.parseJSON(data); console.log("转换后数据类型" + typeof (data)); console.log("code:" + data.code); console.log("提示信息:" + data.msg); } ); } </script> </body> </html>
4)服务器处理异步请求方法
-
一般是post请求
-
会自动识别ajax异步请求中的js数据,将key中的value值接受
-
最后,使用之前设计的FastJson工具类,生成Json字符串结果
// ajax示例 @RequestMapping(path = "/ajax", method = RequestMethod.POST) @ResponseBody public String testAjax(String name, int age) { System.out.println(name); // 可以获取异步请求中的js对象参数值 System.out.println(age); return CommunityUtil.getJSONString(0, "操作成功!"); }
测试结果:
李四
23
3. 开发发布帖子功能
3.1 dao层处理增加帖子数据
定义接口方法
/**
* 增加帖子
*/
int insertPosts(DiscussPost discussPost);
定义sql语句
<!-- 定义复用代码块-->
<sql id="insertFields">
insert into discuss_post(user_id, title, content, type, status, create_time, comment_count, score)
values (#{userId}, #{title}, #{content}, #{type}, #{status}, #{createTime}, #{commentCount}, #{score})
</sql>
<!-- 添加帖子-->
<insert id="insertPosts" parameterType="discussPost" keyProperty="id">
<include refid="insertFields"></include>
</insert>
测试
// 添加帖子
@Test
public void testInsertPosts() {
DiscussPost discussPost = new DiscussPost();
discussPost.setContent("你好");
discussPost.setTitle("测试");
discussPost.setCreateTime(new Date());
discussPostMapper.insertPosts(discussPost);
}
3.2 Service层处理添加帖子业务-过滤
HtmlUtils.htmlEscape
-
HTML格式转义
public static String htmlEscape(String input) { return htmlEscape(input, "ISO-8859-1"); }
将标题、内容转义过滤后再入库
/**
* 添加帖子业务-要对内容进行过滤
* @param discussPost
* @return
*/
public int insertPost(DiscussPost discussPost) {
// 1.边界处理-先判空
if(discussPost == null) {
throw new IllegalArgumentException("参数不能为空!");
}
// 2.对标题、帖子内容进行过滤
// 先进行HTML格式转义
discussPost.setTitle(HtmlUtils.htmlEscape(discussPost.getTitle()));
discussPost.setContent(HtmlUtils.htmlUnescape(discussPost.getContent()));
// 再进行敏感词过滤
discussPost.setTitle(sensitiveFilter.filter(discussPost.getTitle()));
discussPost.setContent(sensitiveFilter.filter(discussPost.getContent()));
// 3.入库
return discussPostMapper.insertPosts(discussPost);
}
3.3 Controller层处理异步请求
- 1.先获取当前用户,进行权限判断
- 2.创建帖子,并调用service层处理
- 3.返回JSON字符串,先处理成功的,失败的今后统一处理
/**
* 处理ajax异步发布帖子请求
* @param title 帖子主题
* @param content 帖子内容
* @return JSON字符串
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
@ResponseBody
public String addPost(String title, String content) {
// 1.先获取当前用户,进行权限判断
User user = hostHolder.getUser();
if(user == null) {
return CommunityUtil.getJSONString(403, "您还没登录,无法发布帖子!");
}
// 2.创建帖子,并调用service层处理
DiscussPost discussPost = new DiscussPost();
discussPost.setTitle(title);
discussPost.setContent(content);
discussPost.setUserId(user.getId());
discussPost.setCreateTime(new Date());
discussPostService.insertPost(discussPost);
// 3.返回JSON字符串,先处理成功的,失败的今后统一处理
return CommunityUtil.getJSONString(0, "发布成功!");
}
3.3 View页面使用JQuery发布异步请求
点击 我要发布 按钮,弹出弹出框
- 通过设定data-target目标id,对应id弹出框起作用
- 弹出框:id="publishModal"
- 提示框:id="hintModal"
- 提示框中显示的信息:id="hintBody"
注意,没有登录状态,是不能发布的,因此,先检查登录状态
<button type="button" class="btn btn-primary btn-sm position-absolute rt-0" data-toggle="modal" data-target="#publishModal" th:if="${loginUser != null}">我要发布</button>
<!-- 弹出框 -->
<div class="modal fade" id="publishModal" tabindex="-1" role="dialog" aria-labelledby="publishModalLabel" aria-hidden="true">...
<!-- 提示框 -->
<div class="modal fade" id="hintModal" tabindex="-1" role="dialog" aria-labelledby="hintModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="hintModalLabel">提示</h5>
</div>
<div class="modal-body" id="hintBody">
发布完毕!
</div>
</div>
</div>
</div>
通过输入框id,在JQuery中输入对应的值
- 标题:id="recipient-name"
- 正文:id="message-text"
<form>
<div class="form-group">
<label for="recipient-name" class="col-form-label">标题:</label>
<input type="text" class="form-control" id="recipient-name">
</div>
<div class="form-group">
<label for="message-text" class="col-form-label">正文:</label>
<textarea class="form-control" id="message-text" rows="15"></textarea>
</div>
</form>
- 发布按钮:id="publishBtn"
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="publishBtn">发布</button>
</div>
- 提示框中的提示栏:id="hintBody"
<div class="modal-body" id="hintBody">
发布完毕!
</div>
在js文件中定义异步请求逻辑
<script th:src="@{js/index.js}"></script>
点击发布,会触发发布方法
$(function(){
$("#publishBtn").click(publish);
});
异步请求方法定义
$("#recipient-name").val()
- 通过id属性获取输入框中内容
$(“hintBody”).text(data.msg)
- 将从服务器响应中的数据在提示框中展现
window.location.reload()
- 刷新页面
function publish() {
$("#publishModal").modal("hide"); // 点击发布按钮后,弹出框关闭,自动访问服务器处理请求
// 通过id属性获取标题和内容
var title = $("#recipient-name").val();
var content = $("#message-text").val();
// 发送异步请求(POST)
$.post(
CONTEXT_PATH + "/discuss/add",
{"title":title, "content":content},
function (data) { // 回调函数,目的是将提示信息msg在提示框展现出来
data = $.parseJSON(data); // 转为js对象,方便取值
$("hintBody").text(data.msg); // 将msg值放入提示框中的显示框中
$("#hintModal").modal("show"); // 提示框展现提示信息
setTimeout(function(){ // 提示框展现时间设定,2秒后自动隐藏
$("#hintModal").modal("hide");
// 刷新页面
if(data.code == 0) {
window.location.reload();
}
}, 2000);
}
)
}