前言
实现用户关注和取消关注功能以及搜索功能。
具体为点击关注时,修改数据库添加关注关系,关注变为已关注;点击已关注时,同样修改数据库关系,已关注变为关注按钮。
搜索使用模糊搜索,根据用户名进行查找,把查找结果列在当前页面。
要求:
- 局部刷新。
- 后端使用JSP
- 前端使用原生JS
效果如图所示:
实现
搜索功能
思路:在显示的时候,先查询数据库
,将数据库中符合条件
的记录拉去出来,显示在页面里。这样也方便在每个条目里添加用户id,便于后面的关注功能中传值。
这里提到了用户id,我们需要区分登录用户和显示在列表栏里的用户,列表的用户可以直接从内联属性
中获得,而当前的登录用户,我们采用cookie存储登录用户的信息
,当需要用到登录用户信息的时候读取cookie即可。
显示和搜索的代码
<%@ page language="java" import="java.util.*,java.sql.*"
contentType="text/html; charset=utf-8"
%><%
request.setCharacterEncoding("utf-8");
String msg = "";
String sql = "";
String query = "";
String ifFollow = "";
String avatar_img = "";
int flag = 0;
String pid = request.getParameter("pid");
String userId = request.getParameter("userId");
String connectString = "jdbc:mysql://172.18.187.10:3306/blog_15336202"
+ "?autoReconnect=true&useUnicode=true"
+ "&characterEncoding=UTF-8";
StringBuilder table=new StringBuilder("");
try{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection(connectString, "user", "123");
Statement stmt=con.createStatement();
Connection con_follow=DriverManager.getConnection(connectString, "user", "123");
Statement stmt_follow=con_follow.createStatement();
ResultSet rs;
ResultSet rHome = stmt.executeQuery("select * from users where id='" + userId + "'");
while (rHome.next()) {
avatar_img = rHome.getString("avatar");
}
rHome.close();
//========================根据ID/email/phone查找用户========================
if(request.getMethod().equalsIgnoreCase("post")) {
query = request.getParameter("query");
sql="select*from users where name like '%"+query+"%' or email like '%"+query+"%' or phone like '%"+query+"%'";
}
else {
sql="select*from users";
}
rs=stmt.executeQuery(sql);
if(!rs.next()) {
msg = "没有该用户!";
}
else {
rs=stmt.executeQuery(sql);
table.append("<div class='user_searched'>");
while(rs.next()) {
sql = "select * from followers where fans_id='" + userId + "' and followed_id='" + rs.getString("id") + "'";
ResultSet rs_follow=stmt_follow.executeQuery(sql);
String cssStr = "";
//不同用户拥有不同的且唯一标识的id
if(rs_follow.next()) {
ifFollow = "已关注";
cssStr = "<a href='#' οnclick='get(" + userId + ", " + rs.getString("id") + "); return false'><button class='follow_button followed' id='" + rs.getString("id") + "'>" + ifFollow + "</button></a>";
}
else {
ifFollow = "关注";
cssStr = "<a href='#' οnclick='get(" + userId + ", " + rs.getString("id") + "); return false'><button class='follow_button' id='" + rs.getString("id") + "'>" + ifFollow + "</button></a>";
}
rs_follow.close();
table.append(String.format(
"<div class='user_item'>" +
"<div class='user_avatar'><img src='./images/avatar/" + rs.getString("avatar") + "' style='width: 60px; height: 60px; border-radius: 50px;'></img>" +
"</div>" +
"<div class='user_content'><a class='user_name' href='visitHome.jsp?visitName=" + rs.getString("name") + "' style='text-decoration: underline;'>%s</a> <span class='user_hobby'>%s</span> <span class='user_follow'>%s</span></div></div>",
rs.getString("name"), rs.getString("hobby"),
cssStr
)
);
}
table.append("</div>");
}
//========================END根据ID/email/phone查找用户========================
stmt_follow.close();
con_follow.close();
rs.close();
stmt.close();
con.close();
}
catch (Exception e){
//msg = e.getMessage();
}
%>
html部分
<div id="content">
<div id="container">
<form action="search.jsp?userId=<%=userId%>" method="post" name="searchForm">
<div id="search_borad">
<input type="text" name="query" placeholder="搜索用户" value="<%=query%>" style="outline: none;">
<a href="#" onclick="searchForm.submit(); return false"><img src="./images/icon/search2.png"> </a>
</div>
</form>
<%=table%><br><br>
<%=msg%>
</div>
</div>
{% endfold %}
数据库follower表组成
是一张包含主键id的多对多的表:
关注取关功能
思路:使用AJAX实现局部刷新
。点击关注按钮的时候执行JS函数
,函数中创建http请求
,利用AJAX
将当前用户和被点击用户的id传到处理程序ajaxGet.jsp
,ajaxGet.jsp进行数据库
增加、删除操作,返回相应的值“关注”/“已关注”,当前页面将响应字符串显示到按钮中,实现关注取关功能:
var oTest = document.getElementById(followed);
oTest.innerHTML = xmlhttp.responseText;
http请求变化时执行的
还有样式的变化,这里使用classList属性
的contains方法判断当前的类,再分别添加和移除followed类,实现样式的变化:
if(!oTest.classList.contains("followed")) {
oTest.classList.add("followed");
// 添加关注按钮样式
}
else {
oTest.classList.remove("followed");
// 移除关注按钮样式,显示未关注样式
}
ajaxGet.jsp:
<%@page language="java" import="java.util.*,java.sql.*" contentType="text/html; charset=utf-8"%>
<% request.setCharacterEncoding("utf-8");
String msg="";
String follower = request.getParameter("userId");
String followed = request.getParameter("followedId");
String conStr = "jdbc:mysql://172.18.187.10:3306/blog_15336202"
+ "?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8";
Class.forName("com.mysql.jdbc.Driver"); // 查找数据库驱动类
Connection con=DriverManager.getConnection(conStr, "user", "123");
Statement stmt=con.createStatement(); //创建MySQL语句的对象
ResultSet rs=stmt.executeQuery("select * from followers where fans_id='" + follower + "' and followed_id='" + followed + "'");
//1.原先不存在关注关系->执行关注操作
if (!rs.next()) {
String fmt="insert into followers(fans_id, followed_id) values('%s', '%s')";
String sql = String.format(fmt, follower, followed);
stmt.executeUpdate(sql);
out.print("已关注");
}
//2.原先存在关注关系->取关
else{
int cnt = stmt.executeUpdate("delete from followers where fans_id='"+follower+"' and followed_id='" + followed + "'");
out.print("关注");
}
rs.close(); stmt.close(); con.close();
%>
关注取关搜索完整代码
search.jsp:
<%@ page language="java" import="java.util.*,java.sql.*"
contentType="text/html; charset=utf-8"
%><%
request.setCharacterEncoding("utf-8");
String msg = "";
String sql = "";
String query = "";
String ifFollow = "";
String avatar_img = "";
int flag = 0;
String pid = request.getParameter("pid");
String userId = request.getParameter("userId");
String connectString = "jdbc:mysql://172.18.187.10:3306/blog_15336202"
+ "?autoReconnect=true&useUnicode=true"
+ "&characterEncoding=UTF-8";
StringBuilder table=new StringBuilder("");
try{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection(connectString, "user", "123");
Statement stmt=con.createStatement();
Connection con_follow=DriverManager.getConnection(connectString, "user", "123");
Statement stmt_follow=con_follow.createStatement();
ResultSet rs;
ResultSet rHome = stmt.executeQuery("select * from users where id='" + userId + "'");
while (rHome.next()) {
avatar_img = rHome.getString("avatar");
}
rHome.close();
//========================根据ID/email/phone查找用户========================
if(request.getMethod().equalsIgnoreCase("post")) {
query = request.getParameter("query");
sql="select*from users where name like '%"+query+"%' or email like '%"+query+"%' or phone like '%"+query+"%'";
}
else {
sql="select*from users";
}
rs=stmt.executeQuery(sql);
if(!rs.next()) {
msg = "没有该用户!";
}
else {
rs=stmt.executeQuery(sql);
table.append("<div class='user_searched'>");
while(rs.next()) {
sql = "select * from followers where fans_id='" + userId + "' and followed_id='" + rs.getString("id") + "'";
ResultSet rs_follow=stmt_follow.executeQuery(sql);
String cssStr = "";
//不同用户拥有不同的且唯一标识的id
if(rs_follow.next()) {
ifFollow = "已关注";
cssStr = "<a href='#' οnclick='get(" + userId + ", " + rs.getString("id") + "); return false'><button class='follow_button followed' id='" + rs.getString("id") + "'>" + ifFollow + "</button></a>";
}
else {
ifFollow = "关注";
cssStr = "<a href='#' οnclick='get(" + userId + ", " + rs.getString("id") + "); return false'><button class='follow_button' id='" + rs.getString("id") + "'>" + ifFollow + "</button></a>";
}
rs_follow.close();
table.append(String.format(
"<div class='user_item'>" +
"<div class='user_avatar'><img src='./images/avatar/" + rs.getString("avatar") + "' style='width: 60px; height: 60px; border-radius: 50px;'></img>" +
"</div>" +
"<div class='user_content'><a class='user_name' href='visitHome.jsp?visitName=" + rs.getString("name") + "' style='text-decoration: underline;'>%s</a> <span class='user_hobby'>%s</span> <span class='user_follow'>%s</span></div></div>",
rs.getString("name"), rs.getString("hobby"),
cssStr
)
);
}
table.append("</div>");
}
//========================END根据ID/email/phone查找用户========================
stmt_follow.close();
con_follow.close();
rs.close();
stmt.close();
con.close();
}
catch (Exception e){
//msg = e.getMessage();
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="referrer" content="always" />
<meta name="author" content="superteam" />
<meta name="date" content="2019-05-21T12:00:00+00:00" />
<title>Lifeblog.com</title>
<script type="text/javascript" src="js/general.js"></script>
<script type="text/javascript" src="js/data.js"></script>
<link rel="stylesheet" type="text/css" href="css/mystyle.css" />
<link rel="stylesheet" type="text/css" href="css/mobile.css" />
<link rel="stylesheet" type="text/css" href="css/search.css" />
</head>
<body>
<!-- for mobile device -->
<div id="mobile_shadow">
</div>
<div id="mobile_box">
<a href="#" id="mobile_back" onclick="hideShadow()"><img src="images/close.png"
style="height: 20px; width: 20px;" /></a>
<ul>
<li><a href="friends.jsp" class="mobile_link">好友动态</a></li>
<li><a href="messageBoard.jsp" class="mobile_link">留言板</a></li>
<li><a href="Data.jsp" class="mobile_link">个人资料</a></li>
<li><a href="recommend.jsp" class="mobile_link">推荐</a></li>
<li><a href="about.jsp" class="mobile_link">关于</a></li>
<li><a href="setting.jsp" class="mobile_link">设置</a></li>
</ul>
</div>
<div id="mobile_wrap">
<div id="mobile_head_portrait">
<img src="images/avatar/<%=avatar_img%>" style="width: 30px; height: 30px; border-radius: 50px;" />
</div>
<a href="index.jsp" id="mobile_com">「Lifeblog.com」</a>
<img id="expand-menu" src="images/expand-menu.png" onclick="showShadow(); closeAnimate()" />
</div>
<!-- normal -->
<div id="home">
<div id="com">
<a href="">「Lifeblog.com」</a>
</div>
<div id="head_portrait">
<div id="select_upload">
<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png,image/svg" id="upload_img" />
</div>
<img src="images/avatar/<%=avatar_img%>" style="width: 80px; height: 80px; border-radius: 50px;">
</div>
<div id="personal_signature">
<p>Show your life this moment!</p>
</div>
<div id="menu">
<a href="search.jsp?userId=<%=userId%>"><img src="./images/icon/search.png" style="width: 20px; opacity: 0.5;"></a><br><br>
<a href="setting.jsp">设置</a><br><br>
<a href="about.jsp">关于</a>
</div>
<div id="footer">
<span>Copyright © 2019 LifeBlog.com</span>
</div>
</div>
<div id="main">
<div id="wrap">
<ul id="nav">
<li id="li_index"><a href="index.jsp" id="index" class="nav_hover">个人主页 </a></li>
<li id="li_friends"><a href="friends.jsp" id="friends" class="nav_hover"> 好友动态 </a></li>
<li id="li_messageBoard"><a href="messageBoard.jsp" id="message_board" class="nav_hover"> 留言板 </a></li>
<li id="li_data"><a href="Data.jsp" id="data" class="nav_hover"> 个人资料 </a></li>
<li id="li_recommend"><a href="recommend.jsp" id="album" class="nav_hover"> 推荐 </a></li>
</ul>
<div id="welcomeBack">
欢迎回来! <font id="userName"></font>
<script type="text/javascript">
var userTemp = document.cookie.split("=");
document.getElementById("userName").innerHTML = userTemp[1];
</script>
</div>
</div>
<div id="content">
<div id="container">
<form action="search.jsp?userId=<%=userId%>" method="post" name="searchForm">
<div id="search_borad">
<input type="text" name="query" placeholder="搜索用户" value="<%=query%>" style="outline: none;">
<a href="#" onclick="searchForm.submit(); return false"><img src="./images/icon/search2.png"> </a>
</div>
</form>
<%=table%><br><br>
<%=msg%>
</div>
</div>
</div>
<script>
window.onload = function() {
//===========搜索框效果===========
var searchBorad = document.getElementById("search_borad");
searchBorad.getElementsByTagName("input")[0].onfocus = function() {
searchBorad.classList.add("search_active");
}
searchBorad.getElementsByTagName("input")[0].onblur = function() {
searchBorad.classList.remove("search_active");
}
//===========END搜索框效果===========
}
//===========关注AJAX请求===========
function get(follower, followed) {
// 创建http请求
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
// 当http请求的状态变化时执行
if(xmlhttp.readyState==4) { // 4-已收到http响应数据
if (xmlhttp.status >= 200 && xmlhttp.status < 300 || xmlhttp.status == 304) {
// 200~299-OK 304-unmodified
// alert(xmlhttp.responseText);
// http响应的正文
var oTest = document.getElementById(followed);
oTest.innerHTML = xmlhttp.responseText;
if(!oTest.classList.contains("followed")) {
oTest.classList.add("followed");
// 添加关注按钮样式
}
else {
oTest.classList.remove("followed");
// 移除关注按钮样式,显示未关注样式
}
} else {
alert("error");
}
};
}; // 打开http请求(open)的参数:get|post,url,是否异步发送
var param = "userId=" + follower + "&followedId=" + followed;
// userId为当前登录用户,followedId为被关注的用户
xmlhttp.open("get", "ajaxGet.jsp?userId=" + follower + "&followedId=" + followed, true);
xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlhttp.send(null);
//发送http请求。get只能用null作为参数
}
//===========END关注AJAX请求===========
</script>
</body>
</html>
ajaxGet.jsp:
<%@page language="java" import="java.util.*,java.sql.*" contentType="text/html; charset=utf-8"%>
<% request.setCharacterEncoding("utf-8");
String msg="";
String follower = request.getParameter("userId");
String followed = request.getParameter("followedId");
String conStr = "jdbc:mysql://172.18.187.10:3306/blog_15336202"
+ "?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8";
Class.forName("com.mysql.jdbc.Driver"); // 查找数据库驱动类
Connection con=DriverManager.getConnection(conStr, "user", "123");
Statement stmt=con.createStatement(); //创建MySQL语句的对象
ResultSet rs=stmt.executeQuery("select * from followers where fans_id='" + follower + "' and followed_id='" + followed + "'");
//1.原先不存在关注关系->执行关注操作
if (!rs.next()) {
String fmt="insert into followers(fans_id, followed_id) values('%s', '%s')";
String sql = String.format(fmt, follower, followed);
stmt.executeUpdate(sql);
out.print("已关注");
}
//2.原先存在关注关系->取关
else{
int cnt = stmt.executeUpdate("delete from followers where fans_id='"+follower+"' and followed_id='" + followed + "'");
out.print("关注");
}
rs.close(); stmt.close(); con.close();
%>