天天看點

requset請求處理與BeanUtils封裝

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. 相對安全
    2. 請求頭:用戶端浏覽器告訴伺服器一些資訊

      請求頭名稱: 請求頭值

      * 常見的請求頭:

      1. User-Agent:浏覽器告訴伺服器,我通路你使用的浏覽器版本資訊

      * 可以在伺服器端擷取該頭的資訊,解決浏覽器的相容性問題

      2. Referer:http://localhost/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	
      
                 
      requset請求處理與BeanUtils封裝

Request:

  1. request對象和response對象的原理
    1. request和response對象是由伺服器建立的。我們來使用它們
    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
            • StringBuffer getRequestURL():傳回http://localhost/day14/demo1
            • URL:統一資源定位符 : http://localhost/day14/demo1
            • URI:統一資源辨別符 : /day14/demo1
          6. 擷取協定及版本:HTTP/1.1
            • String getProtocol()
          7. 擷取客戶機的IP位址:
            • String getRemoteAddr()
      2. 擷取請求頭資料
          • String getHeader(String name):通過請求頭的名稱擷取請求頭的值
          • Enumeration尖括号String> getHeaderNames():擷取所有的請求頭名稱
      3. 擷取請求體資料:
        • 請求體:隻有POST請求方式,才有請求體,在請求體中封裝了POST請求的請求參數
        • 步驟:
          1. 擷取流對象
            • BufferedReader getReader():擷取字元輸入流,隻能操作字元資料
            • ServletInputStream getInputStream():擷取位元組輸入流,可以操作所有類型資料
          2. 再從流對象中拿資料
      • 代碼示例
      package cn.servletDemo.web.request;
      
      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.BufferedReader;
      import java.io.IOException;
      import java.util.Enumeration;
      
      @WebServlet("/RequestDemo02")
      public class ServletRequest extends HttpServlet {
          @Override
          protected void doGet(HttpServletRequest req, 		HttpServletResponse resp) throws ServletException, 		IOException {
      	
              String methopd = req.getMethod();
      
              String contextPath = req.getContextPath();
      
              String servletPath = req.getServletPath();
      
              String requestURI = req.getRequestURI();
      
              StringBuffer RequsetURL = req.getRequestURL();
      
              String requestProtocol = req.getProtocol();
      
              String IP = req.getRemoteAddr();
      
              Enumeration<String> headerNames = 		req.getHeaderNames();
      
              System.out.printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n",		methopd,contextPath,servletPath,requestURI,		RequsetURL,requestProtocol,IP);
      
              while(headerNames.hasMoreElements()){
                  String name = headerNames.nextElement();
      
                  String value = req.getHeader(name);
      
                  System.out.printf("%s\t:%s\n",name,value);
              }
      
          }
      	/***結果
      	GET
      	/req
      	/RequestDemo02
      	/req/RequestDemo02
      	http://localhost:8080/req/RequestDemo02
      	HTTP/1.1
      	0:0:0:0:0:0:0:1
      	host	:localhost:8080
      	connection	:keep-alive
      	upgrade-insecure-requests	:1
      	user-agent	:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like 			Gecko) Chrome/79.0.3945.88 Safari/537.36
      	sec-fetch-user	:?1
      	accept	:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,;			q=0.8,application/signed-exchange;v=b3;q=0.9
      	sec-fetch-site	:none
      	sec-fetch-mode	:navigate
      	accept-encoding	:gzip, deflate, br
      	accept-language	:zh-CN,zh;q=0.9
      	cookie	:JSESSIONID=4973752F177A01DFD0BC110AB93AEA40; 			Idea-fe3516c6=e1f7407c-f751-4f0d-99cf-6bbfd9ff1826; 			goSessionid=wqXEMF4WFNSPwE3L9lcUSMXcLjCnLUgizfec2DipoDI%3D; SL_G_WPT_TO=zh-CN; 			SL_GWPT_Show_Hide_tmp=undefined; SL_wptGlobTipTmp=undefined; 			JSESSIONID=7DB8D0F83015408AC113950CB3E0A18B
      	***/
      
          @Override
          protected void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException {
      	
              //擷取請求消息體
              //擷取字元流
              BufferedReader br = req.getReader();
              //讀資料
              String line = null;
              while((line = br.readLine()) != null){
                  System.out.println(line);
              }
      
      		//結果username=315019748%40qq.com&password=%E9%98%BF%E6%96%AF%E8%BE%BE
          }
      }
      
                 
      • html代碼
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>注冊頁面</title>
      </head>
      <body>
      
          <form action="/req/RequestDemo02" method="post">
               <input type="text" placeholder="請輸入使用者名" 			name="username"><br>
               <input type="text" placeholder="請輸入密碼" 			name="password"><br>
               <input type="submit" value="注冊">
      
      
          </form>
      </body>
      </html>
      
                 
      • 結果
    2. 其他功能:
      1. 擷取請求參數通用方式:不論get還是post請求方式都可以使用下列方法來擷取請求參數
        1. String get(String name):根據參數名稱擷取參數值 username=zs&password=123
        2. String[] getParameterValues(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");
      @WebServlet("/RequestDemo03")
      	public class ServletRequest01 extends HttpServlet {
      	    @Override
      	    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws 			ServletException, IOException {
      	        //get擷取請求參數
      
      	        //根據請求參數名稱擷取請求參數值
      	        String username = req.getParameter("username");
      	        System.out.println("get:"+username);
      
      
      	    }
      
      	    @Override
      	    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws 			ServletException, IOException {
      	        //post請求參數
      
      	        req.setCharacterEncoding("utf-8");
      	        //根據請求參數名稱擷取請求參數值
      	        String username = req.getParameter("username");
      	        System.out.println("post:"+username);
      	    }
      	}
      
                 
      1. 請求轉發:一種在伺服器内部的資源跳轉方式
          1. 通過request對象擷取請求轉發器對象:RequestDispatcher getRequestDispatcher(String path)
          2. 使用RequestDispatcher對象來進行轉發:forward(ServletRequest request, ServletResponse response)
          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()

案例:使用者登入

  • 使用者登入案例需求:

    1.編寫login.html登入頁面

    username & password 兩個輸入框

    2.使用Druid資料庫連接配接池技術,操作mysql,day14資料庫中user表

    3.使用JdbcTemplate技術封裝JDBC

    4.登入成功跳轉到SuccessServlet展示:登入成功!使用者名,歡迎您

  • 開發步驟
    1. 建立項目,導入html頁面,配置檔案,jar包
    <!DOCTYPE html>
    	<html lang="en">
    	<head>
    	    <meta charset="UTF-8">
    	    <title>登入</title>
    	</head>
    	<body>
    	<form action="/test/LoginServlet" method="post">
    	    使用者名:<input type="text" name="username"><br>
    	    密碼:<input type="text" name="password"><br>
    
    	    <input type="submit" value="登入">
    
    	</form>
    
    	</body>
    	</html>
    
               
    1. 建立資料庫環境
    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
    	);
    
               
    1. 建立包package cn.test.domain;,建立類User
    package cn.test.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;
        }
    }
    
               
    1. 建立包cn.test.util,編寫工具類JDBCUtils,加載配置檔案
    package cn.test.util;
    
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    
    import javax.sql.DataSource;
    import java.io.InputStream;
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.util.Properties;
    
    /*
    JDBC工具類,使用的是Druid連接配接池
     */
    public class JDBCUtils {
    
        private static DataSource dataSource;
    
        /*
        靜态代碼塊加載配置檔案,初始化連接配接池
         */
        static {
            try {
                //1.加載配置檔案
                Properties pro = new Properties();
                //使用ClassLoader加載配置檔案,擷取位元組輸入流
                InputStream inputStream = JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties");
                pro.load(inputStream);
    
                //2.初始化連接配接池對象
                dataSource = DruidDataSourceFactory.createDataSource(pro);
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /*
        擷取連接配接池對象
         */
        public static DataSource getDataSource(){
            return dataSource;
        }
    
        /*
        擷取Connection對象
         */
        public static Connection getConnection() throws SQLException {
            return dataSource.getConnection();
        }
    }
    
    
               
    1. 建立包cn.test.dao,建立類UserDao,提供login方法
    package cn.test.dao;
    
    import cn.testT.domain.User;
    import cn.testT.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());
    
    
        //登入邏輯的完成
        public User login(User loginUser){
            try {
                //1.編寫sql
                String sql = "select * from user where username = ? and password = ?";
    
                //2.調用querry方法
                User user = template.queryForObject(sql,new BeanPropertyRowMapper<User>(User.class),
                        loginUser.getUsername(),loginUser.getPassword());
    
                return user;
            } catch (DataAccessException e) {
                e.printStackTrace(); //一般在此處處理日志
                return null;
            }
        }
    }
    
               
    1. 編寫cn.test.web.servlet.LoginServlet類
    package cn.testT.web.servlet;
    
    import cn.testT.dao.UserDao;
    import cn.testT.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 {
            //設定編碼
            req.setCharacterEncoding("utf-8");
    
            //擷取請求參數
            String username = req.getParameter("username");
            String password = req.getParameter("password");
    
            //封裝user對象
            User loginUser = new User();
            loginUser.setUsername(username);
            loginUser.setPassword(password);
    
            //調用UserDao的login方法
            UserDao dao = new UserDao();
            User user = dao.login(loginUser);
    
    
            //判斷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);
        }
    }
    
    
               
    1. 編寫FailServlet和SuccessServlet類
    package cn.testT.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 {
    
        }
    }
    
    ------------------------------------------------------------------------------------------------------------------
    
    package cn.testT.web.servlet;
    
    import cn.testT.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");
            //給頁面寫一句話
            //設定頁面的編碼
            response.setContentType("text/html;charset=utf-8");
            //輸出
            response.getWriter().write("登入成功");
        }
    
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
        }
    }
    
    
               
    1. login.html中form表單的action路徑的寫法
      • 虛拟目錄/Servlet的資源路徑
    2. BeanUtils工具類,簡化資料封裝
      • 用于封裝JavaBean的
      package cn.testT.web.servlet;
      
      import cn.testT.dao.UserDao;
      import cn.testT.domain.User;
      import org.apache.commons.beanutils.BeanUtils;
      
      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.lang.reflect.InvocationTargetException;
      import java.util.Map;
      
      @WebServlet("/LoginServlet")
      public class LoginServlet extends HttpServlet {
      
          @Override
          protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              //設定編碼
              req.setCharacterEncoding("utf-8");
      
      //        //擷取請求參數
      //        String username = req.getParameter("username");
      //        String password = req.getParameter("password");
      //        //封裝user對象
      //        User loginUser = new User();
      //        loginUser.setUsername(username);
      //        loginUser.setPassword(password);
      
              //擷取所有請求參數
              Map<String, String[]> parameterMap = req.getParameterMap();
              //建立user對象
              User loginUser = new User;
              //使用BeanUtils封裝
              try {
                  BeanUtils.populate(loginUser,parameterMap);
              } catch (IllegalAccessException e) {
                  e.printStackTrace();
              } catch (InvocationTargetException e) {
                  e.printStackTrace();
              }
      
      
              //調用UserDao的login方法
              UserDao dao = new UserDao();
              User user = dao.login(loginUser);
      
      
              //判斷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);
          }
      }
      
      
                 
      1. JavaBean:标準的Java類(上述User類,一般再domain目錄下)
        1. 要求:
          1. 類必須被public修飾
          2. 必須提供空參的構造器
          3. 成員變量必須使用private修飾
          4. 提供公共setter和getter方法
        2. 功能:封裝資料
        1. setProperty()與getProperty()
        2. populate(Object obj , Map map):将map集合的鍵值對資訊,封裝到對應的JavaBean對象中
        • 注意:以上操作的是屬性:setter和getter方法截取後的産物,例如:getUsername() --> Username--> username,不是JavaBean的成員變量

繼續閱讀