HTTP协议

简介

HTTP 的全称是 HyperText Transfer Protocol (超文本传输协议)的缩写,是一种建立在 TCP 上的无状态连接。HTTP 是互联网的基础协议,用于客户端与服务器之间的通信,它规定了客户端和服务器之间的通信格式,包括请求与响应的格式。

特点

  1. 基于TCP/IP的高级协议
  2. 默认端口号:80
  3. 基于请求/响应模型的:一次请求对应一次响应
  4. 无状态的:每次请求之间相互独立,不能交互数据

请求消息的数据格式

POST http://localhost:8080/untitled/index HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 105
Cache-Control: max-age=0
sec-ch-ua: "Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
Origin: http://localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/untitled/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: Idea-d672c3fb=cf901043-3557-4f8a-9c86-20fc83011fc4; JSESSIONID=E0E120FE0A8290E4C40433FA3FCCF82E

username=zhangsan3&password=1111111111&email=99999999%40com&name=eg&tel=&gender=male&birthday=&checkcode=

1. 请求行

请求方式--------请求url--------请求协议/版本
GET--------http://localhost:8080/untitled/index--------HTTP/1.1
请求方式:HTTP协议有7中请求方式,常用的有2种
--------GET:

  1. 请求参数在请求行中,在url后。
  2. 请求的url长度有限制的
  3. 不太安全

--------POST:

  1. 请求参数在请求体中
  2. 请求的url长度没有限制的
  3. 相对安全

2. 请求头:

客户端浏览器告诉服务器一些信息
请求头名称: 请求头值 ---------都是键值对方式存放

3. 请求空行

空行,就是用于分割POST请求的请求头,和请求体的。

4. 请求体(正文):

封装POST请求消息的请求参数的

Request

获取请求消息数据

1. 获取请求行数据

//当前servlet路径http://localhost:8080/untitled/aaa
        String method = req.getMethod(); //获取请求行的请求方式
        System.out.println(method);     //GET  POST

        String contextPath = req.getContextPath();//获取虚拟路径
        System.out.println(contextPath);    //  /untitled

        String servletPath = req.getServletPath();//获取Servlet路径
        System.out.println(servletPath);//   /aaa

        String queryString = req.getQueryString();//获取get方式的请求参数,没有返回null
        System.out.println(queryString);    //eg:username=zhangsan
        /**
         * URL:统一资源定位符 : http://localhost/untitled/aaa	中华人民共和国
         * URI:统一资源标识符 : /untitled/aaa					共和国
         * */
        String requestURI = req.getRequestURI();//获取请求的URI
        System.out.println(requestURI);//    /untitled/aaa
        StringBuffer requestURL = req.getRequestURL();//获取请求的URL
        System.out.println(requestURL);//     http://localhost:8080/untitled/aaa

        String protocol = req.getProtocol();//获取请求行的协议及版本
        System.out.println(protocol);//HTTP/1.1
        
        String remoteAddr = req.getRemoteAddr();//获取客户机的IP地址
        System.out.println(remoteAddr);//0:0:0:0:0:0:0:1(IPV6本机地址)

2. 获取请求头数据

	Enumeration<String> headerNames = req.getHeaderNames();//获取所有的请求头名称
	while (headerNames.hasMoreElements()) {
	    String s = headerNames.nextElement();
	    System.out.print(s + "    ");
	    /*host    connection    cache-control    sec-ch-ua
	    sec-ch-ua-mobile    sec-ch-ua-platform    upgrade-insecure-requests
	    user-agent    accept    sec-fetch-site    sec-fetch-mode
	    sec-fetch-user    sec-fetch-dest    accept-encoding    accept-language    cookie   */
	}
	String header = req.getHeader("host");//通过请求头的名称获取请求头的值
	System.out.println(header); //localhost:8080

3. 获取请求体数据

请求体:只有POST请求方式,才有请求体,在请求体中封装了POST请求的请求参数

	BufferedReader reader = req.getReader();//获取字符输入流,只能操作字符数据
	ServletInputStream inputStream = req.getInputStream();//获取字节输入流,可以操作所有类型数据
	
	StringBuffer data = new StringBuffer();
	String line = null;
	while (null != (line = reader.readLine())){
	    data.append(line);
	}

其他功能

	//获取请求参数通用方式:不论get还是post请求方式都可以使用下列方法来获取请求参数
    String name = req.getParameter("name");//根据参数名称获取参数值     username=zs&password=123
    String[] names = req.getParameterValues("name");//根据参数名称获取参数值的数组     hobby=xx&hobby=yy
    Enumeration<String> parameterNames = req.getParameterNames();//获取所有请求的参数名称
    Map<String, String[]> parameterMap = req.getParameterMap();//获取所有参数的map集合
    
    //解决乱码情况
    req.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");

请求转发

特点:
1. 浏览器地址栏路径不发生变化
2. 只能转发到当前服务器内部资源中。
3. 转发是一次请求

	//一次请求一次响应,这个跳转是服务器内部的事,地址栏没有变,服务器内部资源转发,不同的服务器不可以,是站内资源转发
    //路径:已转发的当前路径开始,只可以使用相对路径(省略协议的)   ../pro/bbb    pro/bbb  (给服务器,自己知道协议路径)
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("bbb");//通过request对象获取请求转发器对象
    requestDispatcher.forward(req,resp);//使用RequestDispatcher对象来进行转发

请求重定向

特点
1.浏览器地址会发生变化
2.总共是两次请求,两次响应
3.不能共享Request域中的数据,因为有二次的请求,所以不是一个Request域,所以不能共享
4.也还不能访问WEB-INF下的资源,因为第二次的请求也还是从客户端发往服务器的请求,也不能访问WEB-INF下的资源
5.可以访问工程外的资源

	resp.sendRedirect("/bbb");
    resp.setHeader("location","http://localhost:8080/Servlet2/response2");
    //可以请求站外资源,路径:绝对路径   不省略协议“http://localhost:8080/pro/bbb”
    /**路径:不省略项目虚拟路径“/pro/bbb”   省略项目的虚拟路径“/bbb”  
    (给浏览器,其不知道项目的路径,如果是当前项目,就不需要协议,端口,ip默认当前项目)*/

Response

	resp.setStatus(200);//设置状态码
    //设置响应头   其中,add表示添加,而set表示设置
    resp.addHeader(String name,String value);
    resp.addIntHeader(String name,int value);
    resp.addDateHeader(String name,long date);
    resp.setHeader(String name, String value);
    resp.setDateHeader(String name, long date);
    resp.setIntHeader(String name, int value);

状态码

200 OK 浏览器很顺利的获取到想要的资源
404 Not Found 要访问的资源不存在
403 forbidden 虽然资源存在,但是没有权限
405 Method Not Allowed 尝试使用GET来访问服务器,但是只支持POST
500 Internal Service Error 服务器出现问题
504 Gateway Timeout 服务器太繁忙
302 Move temporarily 重定向

案例

实现注册和登录

配置数据库

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/数据库名
username=root
password=
initialSize=5
maxActive=10
maxWait=3000

写实体类与数据库表一致

前端代码

注册页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <style>
        *{
            margin: 0px;
            padding: 0px;
            box-sizing: border-box;
        }
        body{
            background: url("img/register_bg.png") no-repeat center;
            padding-top: 25px;
        }

        .rg_layout{
            width: 900px;
            height: 500px;
            border: 8px solid #EEEEEE;
            background-color: white;
            /*让div水平居中*/
            margin: auto;
        }

        .rg_left{
            /*border: 1px solid red;*/
            float: left;
            margin: 15px;
        }
        .rg_left > p:first-child{
            color:#FFD026;
            font-size: 20px;
        }

        .rg_left > p:last-child{
            color:#A6A6A6;
            font-size: 20px;

        }
        .rg_center{
            float: left;
            /* border: 1px solid red;*/

        }

        .rg_right{
            /*border: 1px solid red;*/
            float: right;
            margin: 15px;
        }

        .rg_right > p:first-child{
            font-size: 15px;

        }
        .rg_right p a {
            color:pink;
        }

        .td_left{
            width: 100px;
            text-align: right;
            height: 45px;
        }
        .td_right{
            padding-left: 50px ;
        }

        #username,#password,#email,#name,#tel,#birthday,#checkcode{
            width: 251px;
            height: 32px;
            border: 1px solid #A6A6A6 ;
            /*设置边框圆角*/
            border-radius: 5px;
            padding-left: 10px;
        }
        #checkcode{
            width: 110px;
        }

        #img_check{
            height: 32px;
            vertical-align: middle;
        }

        #btn_sub{
            width: 150px;
            height: 40px;
            background-color: #FFD026;
            border: 1px solid #FFD026 ;
        }
        .error{
            color:red;
        }
        #td_sub{
            padding-left: 150px;
        }

    </style>
    <script>
        /*
            分析:
                1.给表单绑定onsubmit事件。监听器中判断每一个方法校验的结果。
                    如果都为true,则监听器方法返回true
                    如果有一个为false,则监听器方法返回false

                2.定义一些方法分别校验各个表单项。
                3.给各个表单项绑定onblur事件。
         */
        window.onload = function(){
            //1.给表单绑定onsubmit事件
            document.getElementById("form").onsubmit = function(){
                //调用用户校验方法   chekUsername();
                //调用密码校验方法   chekPassword();
                //return checkUsername() && checkPassword();

                return checkUsername() && checkPassword();
            }

            //给用户名和密码框分别绑定离焦事件
            document.getElementById("username").onblur = checkUsername;
            document.getElementById("password").onblur = checkPassword;
        }

        //校验用户名
        function checkUsername(){
            //1.获取用户名的值
            var username = document.getElementById("username").value;
            //2.定义正则表达式
            var reg_username = /^\w{6,12}$/;
            //3.判断值是否符合正则的规则
            var flag = reg_username.test(username);
            //4.提示信息
            var s_username = document.getElementById("s_username");

            if(flag){
                //提示绿色对勾
                s_username.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
            }else{
                //提示红色用户名有误
                s_username.innerHTML = "用户名格式有误";
            }
            return flag;
        }

        //校验密码
        function checkPassword(){
            //1.获取用户名的值
            var password = document.getElementById("password").value;
            //2.定义正则表达式
            var reg_password = /^\w{6,12}$/;
            //3.判断值是否符合正则的规则
            var flag = reg_password.test(password);
            //4.提示信息
            var s_password = document.getElementById("s_password");

            if(flag){
                //提示绿色对勾
                s_password.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
            }else{
                //提示红色用户名有误
                s_password.innerHTML = "密码格式有误";
            }
            return flag;
        }
    </script>
</head>
<body>

<div class="rg_layout">
    <div class="rg_left">
        <p>新用户注册</p>
        <p>USER REGISTER</p>
    </div>

    <div class="rg_center">
        <div class="rg_form">
            <!--定义表单 form-->
            <form action="http://localhost:8080/untitled/index" id="form" method="post">
                <table>
                    <tr>
                        <td class="td_left"><label for="username">用户名</label></td>
                        <td class="td_right">
                            <input type="text" name="username" id="username" placeholder="请输入用户名">
                            <span id="s_username" class="error"></span>
                        </td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="password">密码</label></td>
                        <td class="td_right">
                            <input type="password" name="password" id="password" placeholder="请输入密码">
                            <span id="s_password" class="error"></span>
                        </td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="email">Email</label></td>
                        <td class="td_right"><input type="email" name="email" id="email" placeholder="请输入邮箱"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="name">姓名</label></td>
                        <td class="td_right"><input type="text" name="name" id="name" placeholder="请输入姓名"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="tel">手机号</label></td>
                        <td class="td_right"><input type="text" name="tel" id="tel" placeholder="请输入手机号"></td>
                    </tr>

                    <tr>
                        <td class="td_left"><label>性别</label></td>
                        <td class="td_right">
                            <input type="radio" name="gender" value="male" checked> 男
                            <input type="radio" name="gender" value="female"> 女
                        </td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="birthday">出生日期</label></td>
                        <td class="td_right"><input type="date" name="birthday" id="birthday" placeholder="请输入出生日期"></td>
                    </tr>
                    <tr>
                        <td class="td_left"><label for="checkcode" >验证码</label></td>
                        <td class="td_right"><input type="text" name="checkcode" id="checkcode" placeholder="请输入验证码">
                            <img id="img_check" src="img/verify_code.jpg">
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2" id="td_sub"><input type="submit" id="btn_sub" value="注册"></td>
                    </tr>
                </table>
            </form>
        </div>
    </div>
    <div class="rg_right">
        <p>已有账号?<a href="http://localhost:8080/untitled/login.html">立即登录</a></p>
    </div>
</div>
</body>
</html>

登录页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
    <style>
        *{
            margin: 0px;
            padding: 0px;
            box-sizing: border-box;
        }
        body{
            background: url("img/register_bg.png") no-repeat center;
            padding-top: 25px;
        }

        .rg_layout{
            width: 900px;
            height: 500px;
            border: 8px solid #EEEEEE;
            background-color: white;
            /*让div水平居中*/
            margin: auto;
        }

        .rg_left{
            /*border: 1px solid red;*/
            float: left;
            margin: 15px;
        }
        .rg_left > p:first-child{
            color:#FFD026;
            font-size: 20px;
        }

        .rg_left > p:last-child{
            color:#A6A6A6;
            font-size: 20px;

        }


        .rg_center{
            float: left;
            /* border: 1px solid red;*/

        }

        .rg_right{
            /*border: 1px solid red;*/
            float: right;
            margin: 15px;
        }

        .rg_right > p:first-child{
            font-size: 15px;

        }
        .rg_right p a {
            color:pink;
        }

        .td_left{
            width: 100px;
            text-align: right;
            height: 45px;
        }
        .td_right{
            padding-left: 50px ;
        }

        #username,#password,#email,#name,#tel,#birthday,#checkcode{
            width: 251px;
            height: 32px;
            border: 1px solid #A6A6A6 ;
            /*设置边框圆角*/
            border-radius: 5px;
            padding-left: 10px;
        }
        #checkcode{
            width: 110px;
        }

        #img_check{
            height: 32px;
            vertical-align: middle;
        }

        #btn_sub{
            width: 150px;
            height: 40px;
            background-color: #FFD026;
            border: 1px solid #FFD026 ;
        }
        .error{
            color:red;
        }
        #td_sub{
            padding-left: 150px;
        }

    </style>
    <script>
        /*
            分析:
                1.给表单绑定onsubmit事件。监听器中判断每一个方法校验的结果。
                    如果都为true,则监听器方法返回true
                    如果有一个为false,则监听器方法返回false
                2.定义一些方法分别校验各个表单项。
                3.给各个表单项绑定onblur事件。

         */

        window.onload = function(){
            //1.给表单绑定onsubmit事件
            document.getElementById("form").onsubmit = function(){
                //调用用户校验方法   chekUsername();
                //调用密码校验方法   chekPassword();
                //return checkUsername() && checkPassword();

                return checkUsername() && checkPassword();
            }

            //给用户名和密码框分别绑定离焦事件
            document.getElementById("username").onblur = checkUsername;
            document.getElementById("password").onblur = checkPassword;
        }

        //校验用户名
        function checkUsername(){
            //1.获取用户名的值
            var username = document.getElementById("username").value;
            //2.定义正则表达式
            var reg_username = /^\w{6,12}$/;
            //3.判断值是否符合正则的规则
            var flag = reg_username.test(username);
            //4.提示信息
            var s_username = document.getElementById("s_username");

            if(flag){
                //提示绿色对勾
                s_username.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
            }else{
                //提示红色用户名有误
                s_username.innerHTML = "用户名格式有误";
            }
            return flag;
        }

        //校验密码
        function checkPassword(){
            //1.获取用户名的值
            var password = document.getElementById("password").value;
            //2.定义正则表达式
            var reg_password = /^\w{6,12}$/;
            //3.判断值是否符合正则的规则
            var flag = reg_password.test(password);
            //4.提示信息
            var s_password = document.getElementById("s_password");

            if(flag){
                //提示绿色对勾
                s_password.innerHTML = "<img width='35' height='25' src='img/gou.png'/>";
            }else{
                //提示红色用户名有误
                s_password.innerHTML = "密码格式有误";
            }
            return flag;
        }
    </script>
</head>
<body>

<div class="rg_layout">
    <div class="rg_left">
        <p>新用户注册</p>
        <p>USER REGISTER</p>
    </div>
    <div class="rg_center">
        <div class="rg_form">
            <!--定义表单 form-->
            <form action="http://localhost:8080/untitled/login" id="form" method="get">
                <table>
                    <tr>
                        <td class="td_left"><label for="username">用户名</label></td>
                        <td class="td_right">
                            <input type="text" name="username" id="username" placeholder="请输入用户名">
                            <span id="s_username" class="error"></span>
                        </td>
                    </tr>

                    <tr>
                        <td class="td_left"><label for="password">密码</label></td>
                        <td class="td_right">
                            <input type="password" name="password" id="password" placeholder="请输入密码">
                            <span id="s_password" class="error"></span>
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2" id="td_sub"><input type="submit" id="btn_sub" value="登录"></td>
                    </tr>
                </table>

            </form>
        </div>

    </div>
    <div class="rg_right">
        <p>已有账号?<a href="#">立即登录</a></p>
    </div>

</div>
</body>
</html>

成功页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
  <style>
    body{
      background-image: url("img/register_bg.png");
    }
  </style>
</head>
<body>

</body>
</html>

Servlet代码

注册

@WebServlet("/index")
public class Index extends HttpServlet {

    //@SneakyThrows
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");
        String email = req.getParameter("email");
        String name = req.getParameter("name");
        String phone = req.getParameter("phone");
        String sex = req.getParameter("sex");
        String birthday = req.getParameter("birthday");

        JdbcTemplate jdbcTemplate = null;
        try {
            jdbcTemplate = new JdbcTemplate(DruidUtils.getDataSource());
        } catch (Exception e) {
            e.printStackTrace();
        }
        jdbcTemplate.update("insert into user(username,password,email,name,phone,sex,birthday) values(?,?,?,?,?,?,?)"
                ,username,password,email,name,phone,sex,birthday);

        req.getRequestDispatcher("/login.html").forward(req,resp);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

登录

@WebServlet("/login")
public class Login extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");


        JdbcTemplate jdbcTemplate = null;
        try {
            jdbcTemplate = new JdbcTemplate(DruidUtils.getDataSource());
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<User> users = jdbcTemplate.query("select * from user where username=? and password=?"
                , new BeanPropertyRowMapper<>(User.class), username, password);
        if (users.size()>0){
            req.getRequestDispatcher("/hhh.html").forward(req,resp);

        }else {
            req.getRequestDispatcher("/login.html").forward(req,resp);
        }
    }

    @SneakyThrows
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }
}

工具类,使用Druid数据库连接池

public class DruidUtils {
    static DataSource dataSource;
    static {
        Properties properties=new Properties();
        InputStream inputStream = DruidUtils.class.getClassLoader().getResourceAsStream("build.properties");
        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    public static DataSource getDataSource() throws Exception {
        return dataSource;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值