經(jīng)營(yíng)閱讀網(wǎng)站需要怎么做排名優(yōu)化方法
目錄
HttpServlet
HttpServletRequest
?HttpServletResponse
錯(cuò)誤頁(yè)面
設(shè)置網(wǎng)頁(yè)自動(dòng)刷新時(shí)間
構(gòu)造重定向相應(yīng)
js發(fā)起http請(qǐng)求?
服務(wù)器端對(duì)js發(fā)起的http請(qǐng)求進(jìn)行處理
前端獲取后端數(shù)據(jù),添加到當(dāng)前頁(yè)面的末尾,代碼示例:?
?前后端交互:引入數(shù)據(jù)庫(kù)(存儲(chǔ)數(shù)據(jù))
1)引入數(shù)據(jù)庫(kù)依賴
?編輯
?編輯2)建庫(kù)建表
3)編寫數(shù)據(jù)庫(kù)代碼
整體代碼?
利用Cookie和Session實(shí)現(xiàn)登錄邏輯
1.登錄頁(yè)面(html)
2.通過(guò)一個(gè)Servlet處理上述的登錄請(qǐng)求
3.網(wǎng)站主頁(yè),通過(guò)另一個(gè)servlet生成的動(dòng)態(tài)頁(yè)面
掌握如下三個(gè)類,就可以完成Servlet的大部分開發(fā)了
- HttpServlet
- HttpServletRequest
- HttpServletResponse
URI:唯一資源標(biāo)識(shí)符
URL:唯一資源定位/地址符
HttpServlet
HttpServlet繼承這個(gè)類,重寫里面的方法,目的就是為了把咱們子集定義的代碼,“插入到”tomcat中,HttpServlet的常用方法如下:
方法名稱 | 調(diào)用時(shí)機(jī) |
init | 在 HttpServlet 實(shí)例化之后被調(diào)用一次,初始化 |
destory | 在 HttpServlet 實(shí)例不再使用的時(shí)候調(diào)用一次,釋放資源 |
service | 收到 HTTP 請(qǐng)求的時(shí)候調(diào)用 |
doGet | 收到 GET 請(qǐng)求的時(shí)候調(diào)用 ( 由 service 方法調(diào)用 ) |
doPost | 收到 POST 請(qǐng)求的時(shí)候調(diào)用 ( 由 service 方法調(diào)用 ) |
doPut/doDelete/doOptions/... | 收到其他請(qǐng)求的時(shí)候調(diào)用 ( 由 service 方法調(diào)用 ) |
- 直接干掉Tomcat進(jìn)程,完全來(lái)不及調(diào)用destory的;
- 通過(guò)8005管理端口,給Tomcat發(fā)送一個(gè)“停機(jī)”指令,這個(gè)時(shí)候是能夠執(zhí)行destory的。
init / destory / service 這三個(gè)方法都不需要手動(dòng)調(diào)用,會(huì)被tomcat在合適的時(shí)機(jī),自動(dòng)調(diào)用,咱們寫好代碼,讓別人來(lái)幫忙調(diào)用,這種方式就叫做 “框架”?,也就是一個(gè)程序的主體部分,都已經(jīng)被其他大佬們寫完了,有些細(xì)節(jié)內(nèi)容,允許咱們插入咱們自己寫的自定義的邏輯.
HttpServletRequest
方法 | 描述 |
String getProtocol() | 返回請(qǐng)求協(xié)議的名稱和版本。 |
String getMethod() | 返回請(qǐng)求的 HTTP 方法的名稱,例如, GET 、 POST 或 PUT 。 |
String getRequestURI() | 從協(xié)議名稱直到 HTTP 請(qǐng)求的第一行的查詢字符串中,返回該 請(qǐng)求的 URL 的一部分。 |
String getContextPath() | 返回指示請(qǐng)求上下文的請(qǐng)求 URI 部分。 |
String getQueryString() | 返回包含在路徑后的請(qǐng)求 URL 中的查詢字符串。 |
InputStream getInputStream() | 用于讀取請(qǐng)求的 body 內(nèi)容 . 返回一個(gè) InputStream 對(duì)象 . |
Enumeration getParameterNames() | 返回一個(gè) String 對(duì)象的枚舉,包含在該請(qǐng)求中包含的參數(shù)的名 稱。 |
String getParameter(String name) | 以字符串形式返回請(qǐng)求參數(shù)的值,或者如果參數(shù)不存在則返回 null 。 |
String[] getParameterValues(String name) | 返回一個(gè)字符串對(duì)象的數(shù)組,包含所有給定的請(qǐng)求參數(shù)的值, 如果參數(shù)不存在則返回 null 。 |
Enumeration getHeaderNames() | 返回一個(gè)枚舉,包含在該請(qǐng)求中包含的所有的頭名。 |
String getHeader(String name) | 以字符串形式返回指定的請(qǐng)求頭的值。 |
String getCharacterEncoding() | 返回請(qǐng)求主體中使用的字符編碼的名稱。 |
String getContentType() | 返回請(qǐng)求主體的 MIME 類型,如果不知道類型則返回 null 。 |
int getContentLength() | 以字節(jié)為單位返回請(qǐng)求主體的長(zhǎng)度,并提供輸入流,或者如果 長(zhǎng)度未知?jiǎng)t返回 -1 。 |
上述的方法都是get系列方法(都是讀方法),沒有set系列(沒有寫方法),當(dāng)前拿到的HttpServletRequest,這些數(shù)據(jù)的內(nèi)容已經(jīng)確定下來(lái)了,程序員是不應(yīng)該修改的.
前端將數(shù)據(jù)交給后端
除了query string之外,還可以通過(guò)http請(qǐng)求的body來(lái)傳遞參數(shù)(POST)。
(1)直接通過(guò)form表單
????????(body的格式就是query string的格式)
????????Content-Type:application/x-www-form-urlencoded
(2)直接使用json
????????(body的格式就是json)
????????Content-Type:application/json
這三種方式本質(zhì)上是等價(jià)的,都是把鍵值對(duì)數(shù)據(jù)交給服務(wù)器,前兩種方法servlet天然支持的,json這種方法需要引入第三方庫(kù)。
在java中,json的第三方庫(kù)是非常多的,這里我們使用jackson(jackson是spring官方推薦的庫(kù),也被spring集成起來(lái)了)
步驟如下:
1)下載導(dǎo)入jackson到項(xiàng)目中,通過(guò)maven
Maven Repository: Search/Browse/Explore (mvnrepository.com)
(2)使用jackson
一個(gè)類兩個(gè)方法
ObjectMapper
- 把json字符串,映射成java的一個(gè)對(duì)象(read方法)
- 把一個(gè)java對(duì)象,映射成json字符串(write方法)
Request request = objectMapper.readValue(req.getInputStream(),Request.class);1.核心工作就是把json字符串,映射成java 對(duì)象,參數(shù)就是json字符串(json字符串是在http的body中的,就需要通過(guò)HttpServletRequest中的getInputStream來(lái)獲取到)
此處把這個(gè)流對(duì)象直接傳給readValue,readValue內(nèi)部就會(huì)讀取InputStream中的所有數(shù)據(jù)(http請(qǐng)求的body,也就是json字符串),進(jìn)一步嘗試解析
2.按照json的格式,進(jìn)行解析,把json字符串,解析成map(鍵值對(duì))
3.把map轉(zhuǎn)換成對(duì)象,在方法的第二個(gè)參數(shù)
如下示例:
import com.fasterxml.jackson.databind.ObjectMapper;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.ObjectInputValidation;class Request()
{public String username;public String password;
}
class Response{public boolean ok;
}@WebServlet("/json")
public class JsonParameterServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {ObjectMapper objectMapper = new ObjectMapper();Request request = objectMapper.readValue(req.getInputStream(),Request.class);System.out.println("username="+request.username);System.out.println("password="+request.password);Response response=new Response();response.ok=true;//把響應(yīng)對(duì)象轉(zhuǎn)成json字符串String respJson=objectMapper.writeValueAsString(response);resp.setContentType("application/json;charset=utf8");resp.getWriter().write(respJson);}
}
?HttpServletResponse
核心方法
方法 | 描述 |
void setStatus(int sc) | 為該響應(yīng)設(shè)置狀態(tài)碼 |
void setHeader(String name, String value) | 設(shè)置一個(gè)帶有給定的名稱和值的 header. 如果 name 已經(jīng)存在 , 則覆蓋舊的值 |
void addHeader(String name, String value) | 添加一個(gè)帶有給定的名稱和值的 header. 如果 name 已經(jīng)存在 , 不覆蓋舊的值, 并列添加新的鍵值對(duì) |
void setContentType(String type) | 設(shè)置被發(fā)送到客戶端的響應(yīng)的內(nèi)容類型。 |
void setCharacterEncoding(String charset) | 設(shè)置被發(fā)送到客戶端的響應(yīng)的字符編碼( MIME 字符集)例如,UTF-8 |
void sendRedirect(String location) | 使用指定的重定向位置 URL 發(fā)送臨時(shí)重定向響應(yīng)到客戶端 |
PrintWriter getWriter() | 用于往 body 中寫入文本格式數(shù)據(jù) |
OutputStream getOutputStream() | 用于往 body 中寫入二進(jìn)制格式數(shù)據(jù) |
錯(cuò)誤頁(yè)面
resp.sendError(404,"這個(gè)頁(yè)面是一個(gè)錯(cuò)誤頁(yè)面")
設(shè)置網(wǎng)頁(yè)自動(dòng)刷新時(shí)間
resp.setHeader("refresh","1");
構(gòu)造重定向相應(yīng)
resp.setStatus(302); resp.setHeader("Location","https://www.baidu.com");
header需要有一個(gè)Location屬性,描述要跳轉(zhuǎn)到哪里?,除了這種寫法外,還有如下另一種方法:
resp.sendRedirect("https://www.baidu.com");
使用ajax,需要先引入JQeury第三方庫(kù)
jquery (v3.7.1) - jQuery 是一個(gè)高效、精簡(jiǎn)并且功能豐富的 JavaScript 工具庫(kù)。它提供的 API 易于使用且兼容眾多瀏覽器,這讓諸如 HTML 文檔遍歷和操作、事件處理、動(dòng)畫和 Ajax 操作更加簡(jiǎn)單。 | BootCDN - Bootstrap 中文網(wǎng)開源項(xiàng)目免費(fèi) CDN 加速服務(wù)
https://www.bootcdn.cn/jquery/
鏈接如上,選擇如下鏈接
在script標(biāo)簽引入jquery
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
js發(fā)起http請(qǐng)求?
// 把用戶填寫的內(nèi)容,發(fā)送給服務(wù)器,讓服務(wù)器來(lái)保存// $ 是jquery提供的全局變量,ajax是$的一個(gè)方法// ajax的參數(shù)是一個(gè)js對(duì)象,可以有很多屬性let body={"from":from,"to":to,"message":message}//上述body是一個(gè)js對(duì)象,還需要轉(zhuǎn)換成json字符串let jsonString = JSON.stringify(body)$.ajax({type:'post',url:'message',contentType:'application/json; charset=utf8',data:jsonString,//這里的body與上面的body不是同一個(gè),是響應(yīng)報(bào)文的正文success:function(body){// 這個(gè)回調(diào)就是收到響應(yīng)之后要執(zhí)行的代碼了}});
此處success回調(diào)函數(shù),不是立即執(zhí)行的,而是在瀏覽器收到服務(wù)器返回的成功這樣的響應(yīng)的時(shí)候,才會(huì)執(zhí)行function ,這個(gè)函數(shù)的第一個(gè)參數(shù),是響應(yīng)數(shù)據(jù)的body中的內(nèi)容。
服務(wù)器端對(duì)js發(fā)起的http請(qǐng)求進(jìn)行處理
import com.fasterxml.jackson.databind.ObjectMapper;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;class Message{
// 確保java代碼中類的屬性名字和json中的屬性名字保持一致,才能夠自動(dòng)填充public String from;public String to;public String message;@Overridepublic String toString() {return "Message{" +"from='" + from + '\'' +", to='" + to + '\'' +", message='" + message + '\'' +'}';}
}
@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();private List<Message> messageList = new ArrayList<>();@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//使用jackson讀取前端發(fā)來(lái)的數(shù)據(jù),把這個(gè)數(shù)據(jù)保存到服務(wù)器這邊Message message = objectMapper.readValue(req.getInputStream(),Message.class);System.out.println("請(qǐng)求中收到的message:"+ message);//保存數(shù)據(jù)最簡(jiǎn)單的是直接內(nèi)存中存儲(chǔ),使用集合類//但是這樣做一旦重啟服務(wù)器,一切數(shù)據(jù)都沒有了,一般存儲(chǔ)到數(shù)據(jù)庫(kù)中messageList.add(message);//返回一個(gè)響應(yīng)resp.setStatus(200);resp.getWriter().write("ok");}
}
這里啟動(dòng)服務(wù)器后,不能直接訪問(wèn)/message,需要訪問(wèn).html路徑
當(dāng)瀏覽器要向服務(wù)器獲取資源,?服務(wù)器方使用List類型的數(shù)組存儲(chǔ)歷史數(shù)據(jù),轉(zhuǎn)成的json字符串就是一個(gè)json數(shù)組,jackson自動(dòng)遍歷List里的每個(gè)元素,把每個(gè)元素分別轉(zhuǎn)成json字符串。
@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {resp.setStatus(200);resp.setContentType("application/json;charset=utf-8");String respJson = objectMapper.writeValueAsString(messageList);resp.getWriter().write(respJson);}
上述代碼setStatus和setContentType必須在getWriter前面,否則不會(huì)生效?
? ? $.ajax{
? ? ? ? type:'get',
? ? ? ? url:'message',
? ? ? ? success:function(body){
? ? ? ? ? ? //處理服務(wù)器返回的響應(yīng)數(shù)據(jù)。(json格式的數(shù)組)
? ? ? ? }
? ? }
//當(dāng)響應(yīng)中,header帶有ContentType:"application/json",JQuery就會(huì)自動(dòng)把json字符串解析成js對(duì)象了,如果沒有帶ContentType:"application/json"就需要通過(guò)js代碼JSON.parse方法手動(dòng)把json字符串轉(zhuǎn)成js對(duì)象
前端獲取后端數(shù)據(jù),添加到當(dāng)前頁(yè)面的末尾,代碼示例:?
$.ajax{type:'get',url:'message',success:function(body){//處理服務(wù)器返回的響應(yīng)數(shù)據(jù)。(json格式的數(shù)組)//由于響應(yīng)中已經(jīng)有ContentType:"application/json"了,就不需要使用parse方法手動(dòng)轉(zhuǎn)換了//body = JSON.parse(body);//拿到 container這個(gè)元素let containerDiv = document.querySelector('.container');//處理服務(wù)器返回的響應(yīng)數(shù)據(jù)。(json格式的數(shù)組了)for(let i=0;i<body.length;i++){//body是一個(gè)數(shù)組,此時(shí)的message也就是js對(duì)象了//這個(gè)message對(duì)象里有三個(gè)屬性:from、to、messagelet message = body[i];//根據(jù)message對(duì)象構(gòu)建html片段,把這個(gè)片段給顯示到網(wǎng)頁(yè)上//createElement 方法就能構(gòu)造一個(gè)html標(biāo)簽//此時(shí)就得到了<div></div>let div = document.createElement('div');//還需要給這個(gè)div設(shè)置一個(gè)屬性div.className = 'row';//設(shè)置內(nèi)容div.innerHTML = message.from + " 對(duì) " + message.to + " 說(shuō):" +message.message;//將這個(gè)div添加到containerDiv末尾containerDiv.appendChild(div);}}
?前后端交互:引入數(shù)據(jù)庫(kù)(存儲(chǔ)數(shù)據(jù))
1)引入數(shù)據(jù)庫(kù)依賴
Maven倉(cāng)庫(kù)鏈接
Maven Repository: Search/Browse/Explore (mvnrepository.com)
搜索MySQL,選擇如下:
這里選擇5.1.47版本
復(fù)制如下代碼
復(fù)制到pom.xml里

2)建庫(kù)建表
create database if not exists message_wall charset utf8;
use message_wall;
-- 刪表的目的是為了防止之前數(shù)據(jù)庫(kù)里有一樣的表
drop table if exists message;
use message_wall;
create table message(`from` varchar(1024),`to` varchar(1024),message varchar(1024));
3)編寫數(shù)據(jù)庫(kù)代碼
// 1. 創(chuàng)建數(shù)據(jù)源
private DataSource dataSource = new MysqlDataSource();
((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3307/message_wall?characterEncoding=utf8&useSSL=false");
((MysqlDataSource) dataSource).setUser("root");
((MysqlDataSource) dataSource).setPassword("root");
// 2. 建立連接
Connection connection = dataSource.getConnection();// 3. 構(gòu)造 SQL
String sql = "insert into message values(?, ?, ?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1, message.from);
statement.setString(2, message.to);
statement.setString(3, message.message);// 3. 執(zhí)行 SQL
statement.executeUpdate();// 4. 回收資源
statement.close();
connection.close();
整體代碼?
MessageServlet.java
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;class Message {public String from;public String to;public String message;@Overridepublic String toString() {return "Message{" +"from='" + from + '\'' +", to='" + to + '\'' +", message='" + message + '\'' +'}';}
}@WebServlet("/message")
public class MessageServlet extends HttpServlet {private ObjectMapper objectMapper = new ObjectMapper();// 引入數(shù)據(jù)庫(kù), 此時(shí) messageList 就不再需要了.// private List<Message> messageList = new ArrayList<>();private DataSource dataSource = new MysqlDataSource();@Overridepublic void init() throws ServletException {// 1. 創(chuàng)建數(shù)據(jù)源((MysqlDataSource) dataSource).setUrl("jdbc:mysql://127.0.0.1:3307/message_wall?characterEncoding=utf8&useSSL=false");((MysqlDataSource) dataSource).setUser("root");((MysqlDataSource) dataSource).setPassword("root");}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 讀取前端發(fā)來(lái)的數(shù)據(jù), 把這個(gè)數(shù)據(jù)保存到服務(wù)器這邊.Message message = objectMapper.readValue(req.getInputStream(), Message.class);System.out.println("請(qǐng)求中收到的 message: " + message);// 最簡(jiǎn)單的辦法, 直接在內(nèi)存中保存. 可以使用一個(gè)集合類, 把所有收到的 message 都存到內(nèi)存中.// 很明顯, 保存到內(nèi)存, 并非是一個(gè)非常合理的辦法. 后續(xù)一旦重啟服務(wù)器, 數(shù)據(jù)丟失了.// 相比之下, 把這個(gè)數(shù)據(jù)持久化存儲(chǔ)到數(shù)據(jù)庫(kù)中, 更科學(xué)的.// messageList.add(message);// 插入數(shù)據(jù)庫(kù)try {save(message);} catch (SQLException e) {throw new RuntimeException(e);}// 返回一個(gè)響應(yīng)resp.setStatus(200);resp.getWriter().write("ok");// resp.setContentType("application/json");// resp.getWriter().write("{ ok: true }");}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 通過(guò)這個(gè)方法來(lái)處理當(dāng)前獲取消息列表的 get 請(qǐng)求. 不需要解析參數(shù), 直接返回?cái)?shù)據(jù)即可.resp.setStatus(200);resp.setContentType("application/json; charset=utf8");// 從數(shù)據(jù)庫(kù)查詢List<Message> messageList = null;try {messageList = load();} catch (SQLException e) {throw new RuntimeException(e);}String respJson = objectMapper.writeValueAsString(messageList);resp.getWriter().write(respJson);}private void save(Message message) throws SQLException {// 通過(guò)這個(gè)方法把 message 插入到數(shù)據(jù)庫(kù)中// 1. 建立連接Connection connection = dataSource.getConnection();// 2. 構(gòu)造 SQLString sql = "insert into message values(?, ?, ?)";PreparedStatement statement = connection.prepareStatement(sql);statement.setString(1, message.from);statement.setString(2, message.to);statement.setString(3, message.message);// 3. 執(zhí)行 SQLstatement.executeUpdate();// 4. 回收資源statement.close();connection.close();}private List<Message> load() throws SQLException {// 通過(guò)這個(gè)方法從數(shù)據(jù)庫(kù)讀取到 message.// 1. 建立連接Connection connection = dataSource.getConnection();// 2. 構(gòu)造 SQLString sql = "select * from message";PreparedStatement statement = connection.prepareStatement(sql);// 3. 執(zhí)行 sqlResultSet resultSet = statement.executeQuery();// 4. 遍歷結(jié)果集合List<Message> messageList = new ArrayList<>();while (resultSet.next()) {Message message = new Message();message.from = resultSet.getString("from");message.to = resultSet.getString("to");message.message = resultSet.getString("message");messageList.add(message);}// 5. 回收資源resultSet.close();statement.close();connection.close();// 6. 返回 messageListreturn messageList;}
}
?message_wall.html
<!DOCTYPE html>
<html lang="en">
<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"><title>表白墻</title><style>/* * 通配符選擇器, 是選中頁(yè)面所有元素 */* {/* 消除瀏覽器的默認(rèn)樣式. */margin: 0;padding: 0;box-sizing: border-box;}.container {width: 600px;margin: 20px auto;}h1 {text-align: center;}p {text-align: center;color: #666;margin: 20px 0;}.row {/* 開啟彈性布局 */display: flex;height: 40px;/* 水平方向居中 */justify-content: center;/* 垂直方向居中 */align-items: center;}.row span {width: 80px;}.row input {width: 200px;height: 30px;}.row button {width: 280px;height: 30px;color: white;background-color: orange;/* 去掉邊框 */border: none;border-radius: 5px;}/* 點(diǎn)擊的時(shí)候有個(gè)反饋 */.row button:active {background-color: grey;}</style><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
</head>
<body>
<div class="container"><h1>表白墻</h1><p>輸入內(nèi)容后點(diǎn)擊提交, 信息會(huì)顯示到下方表格中</p><div class="row"><span>誰(shuí): </span><input type="text"></div><div class="row"><span>對(duì)誰(shuí): </span><input type="text"></div><div class="row"><span>說(shuō): </span><input type="text"></div><div class="row"><button id="submit">提交</button></div><!-- <div class="row">xxx 對(duì) xx 說(shuō) xxxx</div> -->
</div><script>// 實(shí)現(xiàn)提交操作. 點(diǎn)擊提交按鈕, 就能夠把用戶輸入的內(nèi)容提交到頁(yè)面上顯示.// 點(diǎn)擊的時(shí)候, 獲取到三個(gè)輸入框中的文本內(nèi)容// 創(chuàng)建一個(gè)新的 div.row 把內(nèi)容構(gòu)造到這個(gè) div 中即可.let containerDiv = document.querySelector('.container');let inputs = document.querySelectorAll('input');let button = document.querySelector('#submit');button.onclick = function() {// 1. 獲取到三個(gè)輸入框的內(nèi)容let from = inputs[0].value;let to = inputs[1].value;let msg = inputs[2].value;if (from == '' || to == '' || msg == '') {return;}// 2. 構(gòu)造新 divlet rowDiv = document.createElement('div');rowDiv.className = 'row message';rowDiv.innerHTML = from + ' 對(duì) ' + to + ' 說(shuō): ' + msg;containerDiv.appendChild(rowDiv);// 3. 清空之前的輸入框內(nèi)容for (let input of inputs) {input.value = '';}// 4. 把用戶填寫的內(nèi)容, 發(fā)送給服務(wù)器. 讓服務(wù)器來(lái)保存.// $ 是 jquery 提供的全局變量. ajax 就是 $ 的一個(gè)方法.// ajax 的參數(shù)是一個(gè) js 對(duì)象, 可以有很多屬性let requestBody = {"from": from, // from 變量里的值, 就是第一個(gè)輸入框的內(nèi)容, "張三""to": to, // to 變量的值, 就是第二個(gè)輸入框的內(nèi)容, "李四""message": msg // msg 變量的值, 就是第三個(gè)輸入框的內(nèi)容, "我喜歡你很久了"};// 上述 body 是一個(gè) js 對(duì)象, 還需要轉(zhuǎn)成 json 字符串.let jsonString = JSON.stringify(requestBody);$.ajax({type: 'post',url: 'message',contentType: 'application/json; charset=utf8',data: jsonString,success: function(responseBody) {// 這個(gè)回調(diào)就是收到響應(yīng)之后要執(zhí)行的代碼了.// 前端使用 console.log 打印日志到控制臺(tái). (chrome 開發(fā)者工具的控制臺(tái))console.log("responseBody: " + responseBody);}});}// 直接在 script 里面寫的 js 代碼, 就是在頁(yè)面加載時(shí)被執(zhí)行到的.// 發(fā)起一個(gè) get 請(qǐng)求, 從服務(wù)器獲取到數(shù)據(jù)// get 請(qǐng)求不需要 body, 也就不需要上述 data 和 contentType 屬性了.$.ajax({type: 'get',url: 'message',success: function(body) {// 由于響應(yīng)中已經(jīng)有 Content-Type: application/json 了, 就不需要使用 parse 方法手動(dòng)轉(zhuǎn)換了.// body = JSON.parse(body);// 拿到 container 這個(gè)元素let containerDiv = document.querySelector('.container');// 處理服務(wù)器返回的響應(yīng)數(shù)據(jù). (json 格式的數(shù)組了)for (let i = 0; i < body.length; i++) {// body 是一個(gè)數(shù)組, 此時(shí) message 也就是 js 對(duì)象了.// 這個(gè) message 對(duì)象里, 有三個(gè)屬性, from, to, messagelet message = body[i];// 根據(jù) message 對(duì)象構(gòu)建 html 片段, 把這個(gè)片段給顯示到網(wǎng)頁(yè)上.// createElement 方法就能構(gòu)造出一個(gè) html 標(biāo)簽.// 此時(shí)就得到了 <div></div>let div = document.createElement('div');// 還需要往里面設(shè)置一個(gè) 屬性 , class="row" (設(shè)置這個(gè)屬性, 是為了讓 css 能夠給這個(gè)元素設(shè)置一些樣式)// 此時(shí)就得到了 <div class="row"></div>div.className = 'row';// 給這個(gè) div 里設(shè)置內(nèi)容// 此時(shí)就得到了 <div class="row">張三 對(duì) 李四 說(shuō): 我喜歡你很久了</div>div.innerHTML = message.from + " 對(duì) " + message.to + " 說(shuō): " + message.message;// 把 div 添加到 containerDiv 的末尾containerDiv.appendChild(div);}}});
</script>
</body>
</html>
利用Cookie和Session實(shí)現(xiàn)登錄邏輯
Cookie是客戶端存儲(chǔ)數(shù)據(jù)的機(jī)制
Session是服務(wù)器存儲(chǔ)數(shù)據(jù)的機(jī)制(不算持久化存儲(chǔ))
1.登錄頁(yè)面(html)
2.通過(guò)一個(gè)Servlet處理上述的登錄請(qǐng)求
通過(guò)這個(gè)Servlet讀取用戶名和密碼,并且驗(yàn)證是否登錄成功。
如果登陸成功,就會(huì)給當(dāng)前用戶,創(chuàng)建一個(gè)會(huì)話?,并且把得到的sessionid,通過(guò)cooki返回給客戶端,客戶端就把cookie保存起來(lái)了。
3.網(wǎng)站主頁(yè),通過(guò)另一個(gè)servlet生成的動(dòng)態(tài)頁(yè)面
在這個(gè)頁(yè)面中,就會(huì)把剛才這里的用戶數(shù)據(jù)給顯示到頁(yè)面上。
getSession(true)
這個(gè)方法,就是根據(jù)請(qǐng)求的cookie中的sessionid,查詢服務(wù)器的hash表,找到對(duì)應(yīng)的session對(duì)象。如果cookie中沒有sessionid(首次登錄的時(shí)候,就是沒有的)或者sessionid沒有查找到對(duì)應(yīng)的session對(duì)象,就可以創(chuàng)建出一個(gè)session對(duì)象出來(lái)。
參數(shù)為true,允許不存在時(shí)自動(dòng)創(chuàng)建;false不能創(chuàng)建,直接返回null
//可以給會(huì)話中保存一些自定義的數(shù)據(jù),通過(guò)Attribute的方式來(lái)保存 HttpSession session = req.getSession(true); //此處Atrribute也是鍵值對(duì),這里的內(nèi)容存儲(chǔ)什么都可以 session.setAttribute("username",username); session.setAttribute("loginTime",System.currentTimeMillis()); //此處相當(dāng)于登錄成功,讓頁(yè)面跳轉(zhuǎn)網(wǎng)站首頁(yè) resp.sendRedirect("index");
此處的getSession會(huì)創(chuàng)建新會(huì)話
1)生成sessionid和HttpSession對(duì)象
2)把上述sessionid和HttpSession對(duì)象保存到內(nèi)存hash表中
3)把sessionid設(shè)置到響應(yīng)報(bào)文的header中的 Set-Cookie字段
瀏覽器拿到響應(yīng),就會(huì)把這個(gè)Set-Cookie的內(nèi)容保存到瀏覽器的Cookie中?。