day14【Servlet&Request】

今日內容

  • Servlet
  • HTTP協議
  • Request
    Servlet&Request

1 Servlet

1.1 Servlet的體系結構

Servlet(接口)–>GenericServlet(抽象類)–>HttpServlet(抽象類)

  • GenericServlet:將Servlet接口中其他的方法做了默認空實現,只將service()方法作爲抽象
    將來定義Servlet類時,可以繼承GenericServlet,實現service()方法即可
  • HttpServlet:對http協議的一種封裝,簡化操作
    1. 定義類繼承HttpServlet
    2. 複寫doGet/doPost方法

1.2 Servlet相關配置

  1. urlpartten:Servlet訪問路徑
    1. 一個Servlet可以定義多個訪問路徑:
      @WebServlet({"/d4","/dd4","/ddd4"})
    2. 路徑定義規則:
      1. /xxx:路徑匹配
      2. /xxx/xxx:多層路徑,目錄結構
      3. *.do:擴展名匹配

2 HTTP

2.1 概念:Hyper Text Transfer Protocol 超文本傳輸協議

  • 傳輸協議:定義了,客戶端與服務端通信時,發送數據的格式
  • 特點:
    1. 基於TCP/IP的高級協議
    2. 默認端口號:80
    3. 基於請求/響應模型的:一次請求對應一次響應
    4. 無狀態的:每次請求之間相互獨立,不能交互數據
  • 歷史版本:
    • 1.0:每一次請求響應都會建立新的連接
    • 1.1:複用連接

2.2 請求消息數據格式

  1. 請求行
    請求方式 請求url 請求協議/版本
    GET /login.html HTTP/1.1
    HTTP協議有七種請求方式,常用兩種
    • GET:
      • 請求參數在請求行中,在url後。
      • 請求的url長度有限制
      • 不太安全
    • POST
      • 請求參數在請求體中
      • 請求的url長度沒有限制
      • 相對安全
  2. 請求頭:客戶端瀏覽器告訴服務器一些信息
    請求頭:請求頭值
    常見的請求頭
    1. User-Agent:瀏覽器告訴服務器,我訪問你使用的瀏覽器版本信息
      *可以在服務器端獲取該頭的信息,解決瀏覽器兼容性問題
    2. Referer:http://location/login.html
      告訴服務器,我(當前請求)從哪裏來
      • 作用:
        1. 防盜鏈
        2. 統計工作
  3. 請求空行
    空行,就是用於分割POST請求的請求頭,和請求體的
  4. 請求體(正文):
  • 封裝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

  • 響應消息數據格式

3 Request

3.1 request對象和response對象的原理

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

3.2 request對象繼承體系結構

實現
繼承
RequestFacade類*tomcat*
HttpServletRequest--接口
ServletRequest--接口

3.3 request功能:

  1. 獲取請求消息數據
    1. 獲取請求行數據
      GET /day14/demo?name=zhangsan HTTP/1.1
      方法:
      1. 獲取請求方式:GET
        String getMethod()
      2. *獲取虛擬目錄:/day14
        String getCoontextPath()
      3. 獲取Servlet路徑:/demo1
        String getServlePath()
      4. 獲取get方式請求參數:name=zhangsan
        String getQueryString()
      5. *獲取請求URI:/day14/demo1
        String getRequestURI():/day14/demo1
        StringBuffer getRequestURL():http://localhost/day14/demo1
        URL:統一資源定位符(中華人民共和國)
        URI:統一資源標識符(共和國)
      6. 獲取協議及版本:HTTP/1.1
        String getProtocol()
      7. 獲取客戶機的ip地址:
        String getRemoteAddr()
    2. 獲取請求頭數據
      方法:
      • *String getHeader(String name):通過請求頭的名稱獲取請求頭的值
      • Enmeration<String> getHeaderNames():獲取所有請求頭名稱
    3. 獲取請求體數據:
      • 請求體:只有POST請求方式,纔有請求體,在請求體中封裝了POST請求的請求參數
      • 步驟:
        1. 獲取流對象
          BufferedReader getReader():獲取字符輸入流,只能操作字符數據
          ServletInputStream getInputStream():獲取字節輸入流,可以操作所有類型數據
        2. 再從流對象中拿數據
  2. 其他功能
    1. 獲取請求參數通用方式:不論get還是post都可以使用下列方法
    	1. String getParameter(String name):根據參數名稱獲取參數值 username=zs&password=123
    	2. String[] getParmeterValues(String name):根據參數名稱獲取參數值的數組 hobby=xx&hobby=game
    	3. Enumeration<String> 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. 轉發是一次請求
    2. 共享數據:
      • 域對象:有一個作用範圍的對象,可以在範圍內共享數據
      • request域:代表依次請求的範圍,一般用於請求轉發的多個資源中共享數據
      • 方法:
        1. void setAttribute(String name,Object obj):存儲數據
        2. object getAttitude(String name):通過建獲取值
        3. void removeAttribute(String name):通過鍵移除鍵值對
    3. 獲取ServletContext
      ServletContext getServletContext()

4 案例:用戶登錄

  • 用戶登錄案例需求:

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

  • 開發步驟

	1. 創建項目,導入html頁面,配置文件,jar包
	2. 創建數據庫環境
			CREATE DATABASE day14;
			USE day14;
			CREATE TABLE USER(
			id INT PRIMARY KEY AUTO_INCREMENT,
			username VARCHAR(32) UNIQUE NOT NULL,
			PASSWORD VARCHAR(32) NOT NULL
			);
	
	3. 創建包cn.itcast.domain,創建類User
		package cn.itcast.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. 創建包cn.itcast.util,編寫工具類JDBCUtils
			package cn.itcast.util;
	
			import com.alibaba.druid.pool.DruidDataSourceFactory;
			
			import javax.sql.DataSource;
			import javax.xml.crypto.Data;
			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. 創建包cn.itcast.dao,創建類UserDao,提供login方法
			
			package cn.itcast.dao;
	
			import cn.itcast.domain.User;
			import cn.itcast.util.JDBCUtils;
			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(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 e) {
			            e.printStackTrace();//記錄日誌
			            return null;
			        }
			    }
			}
		
		6. 編寫cn.itcast.web.servlet.LoginServlet類
			package cn.itcast.web.servlet;
	
			import cn.itcast.dao.UserDao;
			import cn.itcast.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 {@Override
			    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			        //1.設置編碼
			        req.setCharacterEncoding("utf-8");
			        //2.獲取請求參數
			        String username = req.getParameter("username");
			        String password = req.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){
			            //登錄失敗
			            req.getRequestDispatcher("/failServlet").forward(req,resp);
			        }else{
			            //登錄成功
			            //存儲數據
			            req.setAttribute("user",user);
			            //轉發
			            req.getRequestDispatcher("/successServlet").forward(req,resp);
			        }
			
			    }
			
			    @Override
			    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
			        this.doGet(req,resp);
			    }
			}
	
		7. 編寫FailServlet和SuccessServlet類
			@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()+",歡迎您");
			        }}		


			@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);
			    }
			}



		8. login.html中form表單的action路徑的寫法
			* 虛擬目錄+Servlet的資源路徑
	
		9. BeanUtils工具類,簡化數據封裝
			* 用於封裝JavaBean的
			1. JavaBean:標準的Java類
				1. 要求:
					1. 類必須被public修飾
					2. 必須提供空參的構造器
					3. 成員變量必須使用private修飾
					4. 提供公共setter和getter方法
				2. 功能:封裝數據


			2. 概念:
				成員變量:
				屬性:setter和getter方法截取後的產物
					例如:getUsername() --> Username--> username


			3. 方法:
				1. setProperty()
				2. getProperty()
				3. populate(Object obj , Map map):將map集合的鍵值對信息,封裝到對應的JavaBean對象中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章