HTTP&Request

HTTP

  • 概念:Hyper Text Transfer Protocol 超文本傳輸協議
  • 傳輸協議:定義了,客戶端和服務器端通信時,發送數據的格式
  • 特點:
  1. 基於TCP/IP的高級協議
  2. 默認端口號:80
  3. 基於請求/響應模型的:一次請求對應一次響應
  4. 無狀態的:每次請求之間相互獨立,不能交互數據
  • 歷史版本:
    • 1.0:每一次請求響應都會建立新的連接
    • 1.1:複用連接,對緩存支持比較好
  • 請求消息數據格式
  1. 請求行
    請求方式 請求url 請求協議/版本
    GET /login.html HTTP/1.1
  • 請求方式:
  • HTTP協議有7中請求方式,常用的有2種
    • GET:
      1. 請求參數在請求行中,在url後。
      2. 請求的url長度有限制的
      3. 不太安全
    • POST:
      1. 請求參數在請求體中
      2. 請求的url長度沒有限制的
      3. 相對安全
  1. 請求頭:客戶端瀏覽器告訴服務器一些信息
    請求頭名稱: 請求頭值
    常見的請求頭:
    1. User-Agent:瀏覽器告訴服務器,我訪問你使用的瀏覽器版本信息,可以在服務器端獲取該頭的信息,解決瀏覽器的兼容性問題
    2. Referer:http://localhost/login.html,告訴服務器,我(當前請求)從哪裏來? 作用:
      1. 防盜鏈:
      2. 統計工作:
  1. 請求空行

空行,就是用於分割POST請求的請求頭,和請求體的。

  1. 請求體(正文):

封裝POST請求消息的請求參數的

字符串格式:

POST /login.html	HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1

username=zhangsan	
  • 響應消息數據格式

Request:

1. request對象和response對象的原理

  1. request和response對象是由服務器(Tomcat)創建的。我們來使用它們
  2. request對象是來獲取請求消息,response對象是來設置響應消息

流程如圖所示:在這裏插入圖片描述

2. request對象繼承體系結構:

ServletRequest – 接口
| 繼承
HttpServletRequest – 接口
| 實現
org.apache.catalina.connector.RequestFacade 類(tomcat)

繼承關係如下圖所示:在這裏插入圖片描述

3. request功能:

  1. 獲取請求消息數據
  1. 獲取請求行數據
  • GET /day14/demo1?name=zhangsan HTTP/1.1
    * 方法:
    1. 獲取請求方式 :GET
    * String getMethod()
    2. (*)獲取虛擬目錄:/day14
    * String getContextPath()
    3. 獲取Servlet路徑: /demo1
    * String getServletPath()
    4. 獲取get方式請求參數:name=zhangsan
    * String getQueryString()
    5.(*)獲取請求URI:/day14/demo1
    * String getRequestURI(): /day14/demo1(URI:統一資源標識符 )
    * StringBuffer getRequestURL() :http://localhost/day14/demo1(URL:統一資源定位符)
    6. 獲取協議及版本:HTTP/1.1
    * String getProtocol()
    7. 獲取客戶機的IP地址:
    * String getRemoteAddr()
  1. 獲取請求頭數據
  • 方法:
    • (*)String getHeader(String name):通過請求頭的名稱獲取請求頭的值
    • Enumeration getHeaderNames():獲取所有的請求頭名稱
  1. 獲取請求體數據:
  • 請求體:只有POST請求方式,纔有請求體,在請求體中封裝了POST請求的請求參數
  • 步驟:
    1. 獲取流對象

      • BufferedReader getReader():獲取字符輸入流,只能操作字符數據
      • ServletInputStream getInputStream():獲取字節輸入流,可以操作所有類型數據(在文件上傳知識點後講解)
    2. 再從流對象中拿數據

  1. 其他功能(重點):
  1. 獲取請求參數通用方式:不論get還是post請求方式都可以使用下列方法來獲取請求參數
    1. String getParameter(String name):根據參數名稱獲取參數值 username=zs&password=123
    2. String[] getParameterValues(String name):根據參數名稱獲取參數值的數組 hobby=xx&hobby=game(多用於複選框)
    3. Enumeration getParameterNames():獲取所有請求的參數名稱
    4. Map<String,String[]> getParameterMap():獲取所有參數的map集合
  • 中文亂碼問題:
    • get方式:tomcat 8 已經將get方式亂碼問題解決了
    • post方式:會亂碼
      • 解決:在獲取參數前,設置request的編碼request.setCharacterEncoding(“utf-8”);
  1. 請求轉發:一種在服務器內部的資源跳轉方式
    1. 步驟:
      1. 通過request對象獲取請求轉發器對象:RequestDispatcher getRequestDispatcher(String path)
      2. 使用RequestDispatcher對象來進行轉發:forward(ServletRequest request, ServletResponse response)
    2. 特點:
      1. 瀏覽器地址欄路徑不發生變化
      2. 只能轉發到當前服務器內部資源中。
      3. 轉發是一次請求
  1. 共享數據:
  • 域對象:一個有作用範圍的對象,可以在範圍內共享數據
  • request域:代表一次請求的範圍,一般用於請求轉發的多個資源中共享數據
  • 方法:
    1. void setAttribute(String name,Object obj):存儲數據
    2. Object getAttitude(String name):通過鍵獲取值
    3. void removeAttribute(String name):通過鍵移除鍵值對
  1. 獲取ServletContext:
    * ServletContext getServletContext()

案例:用戶登錄

用戶登錄案例需求:

1.編寫login.html登錄頁面username & password 兩個輸入框
2.使用Druid數據庫連接池技術,操作mysql,day14數據庫中user表
3.使用JdbcTemplate技術封裝JDBC
4.登錄成功跳轉到SuccessServlet展示:登錄成功!用戶名,歡迎您
5.登錄失敗跳轉到FailServlet展示:登錄失敗,用戶名或密碼錯誤

分析

如下圖所示:
在這裏插入圖片描述login.html中form表單的action路徑的寫法:虛擬目錄+Servlet的資源路徑

BeanUtils工具類,簡化數據封裝,用於封裝JavaBean的

  1. JavaBean:標準的Java類
    1. 要求:
    1. 類必須被public修飾
    2. 必須提供空參的構造器
    3. 成員變量必須使用private修飾
    4. 提供公共setter和getter方法
    2. 功能:封裝數據
  1. 概念:
    成員變量:
    屬性:setter和getter方法截取後的產物
    例如:getUsername() --> Username–> username
  1. 方法:
    1. setProperty()
    2. getProperty()
    3. populate(Object obj , Map map):將map集合的鍵值對信息,封裝到對應的JavaBean對象中

創建數據庫環境:

CREATE DATABASE demo;
USE demo;

CREATE TABLE USER(	
	id INT PRIMARY KEY AUTO_INCREMENT,
	usename VARCHAR(32) UNIQUE NOT NULL,
	PASSWORD VARCHAR(32) NOT NULL

);
INSERT INTO `demo`.`user` (`usename`, `password`) VALUES ('superbaby', '123'); 

創建類User

package com.xzzz.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 + '\'' +
                '}';
    }
}

創建JDBC工具類

package com.xzzz.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 properties = new Properties();
            //使用ClassLoader加載配置文件,獲取字節輸入流
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
            properties.load(is);

            //2.初始化連接池對象
            ds = DruidDataSourceFactory.createDataSource(properties);
        } 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();
    }
}

編寫Dao層

package com.xzzz.dao;

import com.xzzz.domain.User;
import com.xzzz.util.JDBCUtil;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;

/**
 * 操作數據庫中User表的類
 */
public class UserDao {

    //聲明JDBCTemplate對象共用
    private JdbcTemplate template =new JdbcTemplate(JDBCUtil.getDataSource());

    /**
     * 登錄方法
     * @param loginUser 只有用戶名和密碼
     * @return user包含用戶全部數據,沒有查詢到,返回null
     */
    public User login(User loginUser){
        User user = null;
        try {
            //1.編寫sql
            String sql = "select * from user where username = ? and password = ?";
            //2.調用query方法
            user = template.queryForObject(sql,
                    new BeanPropertyRowMapper<User>(User.class),
                    loginUser.getUsername(), loginUser.getPassword());
            return user;
        } catch (DataAccessException e) {

        }
        return user;
    }
}

測試Dao層

 @Test
    public void testLogin(){
        User loginUser = new User();
        loginUser.setUsername("a001");
        loginUser.setPassword("a00");
        UserDao dao = new UserDao();
        User user = dao.login(loginUser);

        System.out.println(user);
    }

結果:

User{id=2, usename=‘a001’, password=‘a001’}

編寫LoginServlet:

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        User user = new User();
        try {
            BeanUtils.populate(user,request.getParameterMap());
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        
        UserDao dao = new UserDao();
        User loginUser = dao.login(user);

        if (loginUser!=null){
            request.setAttribute("User",loginUser);
            request.getRequestDispatcher("/SuccessServlet").forward(request,response);
        }else {
            request.getRequestDispatcher("/FailServlet").forward(request,response);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

編寫SuccessServlet:

@WebServlet("/SuccessServlet")
public class SuccessServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset = utf-8");
        User user = (User) request.getAttribute("User");
        if (user != null) {
            response.getWriter().write("登錄成功!!!,歡迎您:"+user.getUsername());
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}

編寫FailServlet:

@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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章