HTTP:
概念:Hyper Text Transfer Protocol 超文本傳輸協議。傳輸協議:定義了,客戶端和服務器端通信時,發送數據的格式
特點:
- 基於TCP/IP的高級協議
- 默認端口號:80
- 基於請求/響應模型的:一次請求對應一次響應
- 無狀態的:每次請求之間相互獨立,不能交互數據
歷史版本:
- 1.0:每一次請求響應都會建立新的連接
- 1.1:複用連接
HTTP協議:請求消息數據格式
請求消息數據格式分別下面幾個部分組成
1:請求行
- 請求方式 請求url 請求協議/版本
請求方式:HTTP協議有7中請求方式,常用的有2種
GET:
- 請求參數在請求行中,在url後。沒有請求體。
- 請求的url長度有限制的
- 不太安全
POST:
- 請求參數在請求體中
- 請求的url長度沒有限制的
- 相對安全
2. 請求頭:客戶端瀏覽器告訴服務器一些信息
- 請求頭名稱: 請求頭值
常見的請求頭:
- User-Agent:瀏覽器告訴服務器,我訪問你使用的瀏覽器版本信息。可以在服務器端獲取該頭的信息,解決瀏覽器的兼容性問題
- Referer:告訴服務器,我(當前請求)從哪裏來?作用:防盜鏈丶統計工作
3. 請求空行
- 空行,就是用於分割POST請求的請求頭,和請求體的。
4:請求體(正文):
- :封裝POST請求消息的請求參數的
Request
request對象和response對象的原理
- request和response對象是由服務器創建的。我們來使用它們
- request對象是來獲取請求消息,response對象是來設置響應消息
request對象繼承體系結構:
- ServletRequest接口處於最頂層的接口
- 其下面有一個子接口HttpServletRequest去繼承ServletRequest接口
- 而HttpServletRequest接口是由org.apache.catalina.connector.RequestFacade 類實現
request功能:
獲取請求行數據
1. 獲取請求方式 :
- String getMethod()
2. 獲取虛擬目錄:
- String getContextPath()
3. 獲取Servlet路徑:
- String getServletPath()
4. 獲取get方式請求參數:
- String getQueryString()
5. 獲取請求URI/URL:
- String getRequestURI(): URI:統一資源標識符
- StringBuffer getRequestURL() :URL:統一資源定位符
6. 獲取協議及版本
- String getProtocol()
7. 獲取客戶機的IP地址:
- String getRemoteAddr()
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//客戶端的獲取請求方式
System.out.println("訪問的方式是:" + request.getMethod());
//獲取項目的虛擬目錄
System.out.println("項目的虛擬目錄是:" + request.getContextPath());
//獲取要訪問的Servlet的路徑
System.out.println("Servlet的路徑:" + request.getServletPath());
//獲取get方式請求的參數
System.out.println("get方式請求的參數:" + request.getQueryString());
//獲取請求URI或者是URL
System.out.println("獲取URI:" + request.getRequestURI());
System.out.println("獲取URL:" + request.getRequestURL());
//獲取使用的協議及版本:
System.out.println("獲取協議和版本號:" + request.getProtocol());
//獲取客戶家IP地址
System.out.println("獲取客戶機IP:" + request.getRemoteAddr());
}
獲取請求頭數據
- String getHeader(String name):通過請求頭的名稱獲取請求頭的值
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//演示獲取請求頭數據:referer
String referer = request.getHeader("referer");
//防盜鏈
if(referer != null ){
if(referer.contains("/day14")){
//正常訪問
// System.out.println("播放電影....");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("播放電影....");
}else{
//盜鏈
//System.out.println("想看電影嗎?...");
}
}
}
- Enumeration<String> getHeaderNames():獲取所有的請求頭名稱
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//演示獲取請求頭數據
//1.獲取所有請求頭名稱
Enumeration<String> headerNames = request.getHeaderNames();
//2.遍歷
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
//根據名稱獲取請求頭的值
String value = request.getHeader(name);
System.out.println(name+"---"+value);
}
獲取請求體數據:
- 請求體:只有POST請求方式,纔有請求體,在請求體中封裝了POST請求的請求參數
步驟:
1. 獲取流對象
- BufferedReader getReader():獲取字符輸入流,只能操作字符數據
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取請求消息體--請求參數
//1.獲取字符流
BufferedReader br = request.getReader();
//2.讀取數據
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
}
- ServletInputStream getInputStream():獲取字節輸入流,可以操作所有類型數據
2. 再從流對象中拿數據
其他常用方法
獲取請求參數通用(post丶get)方式都可以使用的方法
- String getParameter(String name):根據參數名稱獲取參數值
- String[] getParameterValues(String name):根據參數名稱獲取參數值的數組 hobby=xx&hobby=game
- Enumeration<String> getParameterNames():獲取所有請求的參數名稱
- Map<String,String[]> getParameterMap():獲取所有參數的map集合
//根據參數名稱獲取參數值
String username = request.getParameter("username");
System.out.println(username);
//根據參數名稱獲取參數值的數組
String[] hobbies = request.getParameterValues("hobby");
//遍歷數組
for (String hobby : hobbies) {
System.out.println(hobby);
//獲取所有請求的參數名稱
Enumeration<String> parameterNames = request.getParameterNames();
// 獲取所有參數的map集合
Map<String, String[]> parameterMap = request.getParameterMap();
//遍歷
Set<String> keyset = parameterMap.keySet();
for (String name : keyset) {
//獲取鍵獲取值
String[] values = parameterMap.get(name);
System.out.println(name);
for (String value : values) {
System.out.println(value);
}
System.out.println("-----------------");
}
獲取請求參數中文亂碼問題
- get方式:tomcat 8 已經將get方式亂碼問題解決了
- post方式:會亂碼。 解決方式:在獲取參數前,設置request的編碼request.setCharacterEncoding("utf-8");
請求轉發
請求轉發:一種在服務器內部的資源跳轉方式
步驟:
- 通過request對象獲取請求轉發器對象:RequestDispatcher getRequestDispatcher(String path) 參數是要轉發的目的地
- 使用RequestDispatcher對象來進行轉發:forward(ServletRequest request, ServletResponse response)
特點:
- 瀏覽器地址欄路徑不發生變化
- 只能轉發到當前服務器內部資源中。
- 請求轉發是一次請求
共享數據:
域對象:一個有作用範圍的對象,可以在範圍內共享數據
- request域:代表一次請求的範圍,一般用於請求轉發的多個資源中共享數據
方法:
- void setAttribute(String name,Object obj):存儲數據
- Object getAttitude(String name):通過鍵獲取值
- void removeAttribute(String name):通過鍵移除鍵值對
獲取ServletContext對象:
- 使用方法ServletContext getServletContext()
登錄案例
用戶登錄案例需求:
- 編寫login.html登錄頁面username & password 兩個輸入框
- 使用Druid數據庫連接池技術,操作mysql,day14數據庫中user表
- 使用JdbcTemplate技術封裝JDBC
- 登錄成功跳轉到SuccessServlet展示:登錄成功!用戶名,歡迎您
- 登錄失敗跳轉到FailServlet展示:登錄失敗,用戶名或密碼錯誤
開發步驟
1. 創建Web項目,導入html頁面,配置文件,jar包
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--虛擬目錄+Servlet的資源路徑-->
<form action="/login/LoginServlet" method="post">
用戶名:<input type="text" name="username"> <br>
密碼:<input type="password" name="password"><br>
<input type="submit" value="登錄">
</form>
</body>
</html>
2. 創建數據庫環境(創建庫丶表丶添加數據)
3. 創建包,裏面存放着與數據庫中標對應的User類
package com.wrg.domain;
public class User {
// 成員變量對應着數據庫中的字段名稱
private int id;
private String username;
private String password;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
4. 創建包util,編寫工具類JDBCUtils
package com.wrg.util;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
/**
* JDBC工具類 使用Durid連接池
*/
public class JDBCUtils {
private static DataSource ds ;
static {
try {
//1.加載配置文件
Properties pro = new Properties();
//使用ClassLoader加載配置文件,獲取字節輸入流
InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
pro.load(is);
//2.初始化連接池對象
ds = DruidDataSourceFactory.createDataSource(pro);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取連接池對象
*/
public static DataSource getDataSource(){
return ds;
}
/**
* 獲取連接Connection對象
*/
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
5. 創建包創建類UserDao,提供login方法
package com.wrg.dao;
import com.wrg.domain.User;
import com.wrg.util.JDBCUtils;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
public class UserDao {
//聲明JDBCTemplate對象共用
private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
/**
* 登錄方法
* @param loginUser 只有用戶名和密碼
* @return user包含用戶全部數據,沒有查詢到,返回null
*/
public User login(User loginUser){
try {
//1.編寫sql
String sql = "select * from user where username = ? and password = ?";
//2.調用query方法
User user = template.queryForObject(sql,
new BeanPropertyRowMapper<User>(User.class),
loginUser.getUsername(), loginUser.getPassword());
return user;
}catch ( DataAccessException a){
a.printStackTrace();
return null;
}
}
}
6. 編寫包,實現Servlet類丶FailServlet類丶SuccessServlet類
package com.wrg.web.servlet;
import com.wrg.dao.UserDao;
import com.wrg.domain.User;
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;
@WebServlet( "/LoginServlet")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("1");
//1.設置編碼
request.setCharacterEncoding("utf-8");
//2.獲取請求參數
String username = request.getParameter("username");
String password = request.getParameter("password");
//3.封裝user對象
User loginUser = new User();
loginUser.setUsername(username);
loginUser.setPassword(password);
//4.調用UserDao的login方法
UserDao dao = new UserDao();
User user = dao.login(loginUser);
//5.判斷user
if(user == null){
//登錄失敗
request.getRequestDispatcher("/failServlet").forward(request,response);
}else{
//登錄成功
//存儲數據
request.setAttribute("user",user);
//轉發
request.getRequestDispatcher("/successServlet").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
FailServlet類
package com.wrg.web.servlet;
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;
@WebServlet("/failServlet")
public class FailServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//給頁面寫一句話
//設置編碼
response.setContentType("text/html;charset=utf-8");
//輸出
response.getWriter().write("登錄失敗,用戶名或密碼錯誤");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
SuccessServlet類
package com.wrg.web.servlet;
import com.wrg.domain.User;
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;
@WebServlet("/successServlet")
public class SuccessServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//獲取request域中共享的user對象
User user = (User) request.getAttribute("user");
if (user != null) {
//給頁面寫一句話
//設置編碼
response.setContentType("text/html;charset=utf-8");
//輸出
response.getWriter().write("登錄成功!" + user.getUsername() + ",歡迎您");
}
}
}