WEB Java学习

1. HTTP协议

在网络上传输html时的协议,用于B-C的通信

http1.0:一次只能获得一个Web资源,获取后就断开链接

http1.1:持久连接,可以获得多个web资源

浏览器请求过程:

  1. 与服务器建立TCP连接(80端口)

  2. 发送HTTP请求

  3. 收取HTTP响应,然后把网页在浏览器中显示出来

https:443端口

浏览器发送的HTTP:

GET / HTTP/1.1
Host: www.sina.com.cn
User-Agent: Mozilla/5.0 xxx
Accept: */*
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8

其中,第一行表示使用GET请求获取路径为/的资源,并使用HTTP/1.1协议,从第二行开始,每行都是以Header: Value形式表示的HTTP头,比较常用的HTTP Header包括:

  • Host: 表示请求的主机名,因为一个服务器上可能运行着多个网站,因此,Host表示浏览器正在请求的域名;

  • User-Agent: 标识客户端本身,例如Chrome浏览器的标识类似Mozilla/5.0 ... Chrome/79,IE浏览器的标识类似Mozilla/5.0 (Windows NT ...) like Gecko

  • Accept:表示浏览器能接收的资源类型,如text/*image/*或者*/*表示所有;

  • Accept-Language:表示浏览器偏好的语言,服务器可以据此返回不同语言的网页;

  • Accept-Encoding:表示浏览器可以支持的压缩类型,例如gzip, deflate, br

Get方法:能够携带参数少,不安全(URL中会携带参数),但是高效

Post方法:携带的参数无限制,安全但不高效

服务器的响应:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 21932
Content-Encoding: gzip
Cache-Control: max-age=300
​
<html>...网页数据...

服务器响应的第一行总是版本号+空格+数字+空格+文本,数字表示响应代码,其中2xx表示成功,3xx表示重定向,4xx表示客户端引发的错误,5xx表示服务器端引发的错误。数字是给程序识别,文本则是给开发者调试使用的。常见的响应代码有:

  • 200 OK:表示成功;

  • 301 Moved Permanently:表示该URL已经永久重定向;

  • 302 Found:表示该URL需要临时重定向;

  • 304 Not Modified:表示该资源没有修改,客户端可以使用本地缓存的版本;

  • 400 Bad Request:表示客户端发送了一个错误的请求,例如参数无效;

  • 401 Unauthorized:表示客户端因为身份未验证而不允许访问该URL;

  • 403 Forbidden:表示服务器因为权限问题拒绝了客户端的请求;

  • 404 Not Found:表示客户端请求了一个不存在的资源;

  • 500 Internal Server Error:表示服务器处理时内部出错,例如因为无法连接数据库;

  • 503 Service Unavailable:表示服务器此刻暂时无法处理请求。

从第二行开始,服务器每一行均返回一个HTTP头。服务器经常返回的HTTP Header包括:

  • Content-Type:表示该响应内容的类型,例如text/htmlimage/jpeg

  • Content-Length:表示该响应内容的长度(字节数);

  • Content-Encoding:表示该响应压缩算法,例如gzip

  • Cache-Control:指示客户端应如何缓存,例如max-age=300表示可以最多缓存300秒。

HTTP请求和响应都由HTTP Header和HTTP Body构成,其中HTTP Header每行都以\r\n结束。如果遇到两个连续的\r\n,那么后面就是HTTP Body。浏览器读取HTTP Body,并根据Header信息中指示的Content-TypeContent-Encoding等解压后显示网页、图像或其他内容。

通常浏览器获取的第一个资源是HTML网页,在网页中,如果嵌入了JavaScript、CSS、图片、视频等其他资源,浏览器会根据资源的URL再次向服务器请求对应的资源。

使用TCP多线程编程服务器框架

package com.wang.web;
​
​
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
​
​
public class Server {
    public static void main(String[] args) throws IOException {
        //监听指定接口
        ServerSocket ss = new ServerSocket(8080);
        System.out.println("server is running...");
        for (; ; ) {
            Socket socket = ss.accept();
            System.out.println("connnection from" + socket.getRemoteSocketAddress());
            Thread thread = new Handler(socket);
            thread.start();
        }
    }
}
​
​
class Handler extends Thread{
        Socket socket;
    
        public Handler(Socket socket){
            this.socket = socket;
        }
​
​
        public void run(){
            try(InputStream inputStream = this.socket.getInputStream()){
                try(OutputStream outputStream = this.socket.getOutputStream()){
                    handle(inputStream,outputStream);
                }
            }catch (Exception e){
                try{
                    this.socket.close();
                }catch (IOException ioe){
​
                }
                System.out.println("client disconnected");
            }
        }
​
        private void handle(InputStream inputStream,OutputStream outputStream)throws IOException{
           BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
           BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream,StandardCharsets.UTF_8));
           //处理HTTP请求
        }
}
​
​

HTTP目前有多个版本,1.0是早期版本,浏览器每次建立TCP连接后,只发送一个HTTP请求并接收一个HTTP响应,然后就关闭TCP连接。由于创建TCP连接本身就需要消耗一定的时间,因此,HTTP 1.1允许浏览器和服务器在同一个TCP连接上反复发送、接收多个HTTP请求和响应,这样就大大提高了传输效率。

我们注意到HTTP协议是一个请求-响应协议,它总是发送一个请求,然后接收一个响应。能不能一次性发送多个请求,然后再接收多个响应呢?HTTP 2.0可以支持浏览器同时发出多个请求,但每个请求需要唯一标识,服务器可以不按请求的顺序返回多个响应,由浏览器自己把收到的响应和请求对应起来。可见,HTTP 2.0进一步提高了传输效率,因为浏览器发出一个请求后,不必等待响应,就可以继续发下一个请求。

HTTP 3.0为了进一步提高速度,将抛弃TCP协议,改为使用无需创建连接的UDP协议,目前HTTP 3.0仍然处于实验阶段。

2. Tomcat服务器

 

开启服务器后才可以访问webapp中的项目

3. Servlet

开发动态web的一门技术

  • 编写一个类实现Servlet接口

  • 把开发好的Java类部署到web服务器中

把实现了Servlet接口的java程序叫做Servlet

用户携带的参数不同显示的界面也不同

3.1 HelloServlet

  1. 继承HttpServlet类

  2. 实现Post和Get方法(其他方法暂时不用)

 编写实现类

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
​
public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.print("Hello,Servlet");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}
​
  1. 编写Servlet的映射

    • Java程序要通过浏览器访问,而浏览器需要访问服务器

    • 所以,要在web服务中注册我们所写的Servlet,还要交

    • 给他一个浏览器能够访问的路径

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
​
    <!--注册Servlet-->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>com.wang.ServletTest.TestServlet</servlet-class>
    </servlet>
    <!--servlet映射的地址-->
    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
</web-app>
  1. 配置Tomcat

 

配置项目路径

  1. 启动测试

3.2 执行流程

 

Servlet对象由tomcat服务器创建,并且service方法由tomcat调用

3.3 生命周期

 

 

  • 加载和实例化

  • 初始化

    • 一个Servlet只会创建一次

package com.wang.servletTest;
​
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
@WebServlet(urlPatterns = "/demo2",loadOnStartup = 1)
public class ServletDemo2 implements Servlet {
    //初始化方法
    //调用时机:默认情况下Servlet被第一次访问时调用
    //调用次数:1
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("Init....................");
    }
    //开始服务
    //调用时机:每一次servlet被访问时
    //调用次数:n
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        System.out.println("service-...........................");
    }
    //结束服务-销毁
    //调用时机:服务器关闭或内存释放
    //调用次数:1
    @Override
    public void destroy() {
        System.out.println("destory.......................");
    }
​
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    @Override
    public String getServletInfo() {
        return null;
    }
​
​
}
​

3.4 Servlet方法

package com.wang.servletTest;
​
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(urlPatterns = "/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("get............");
    }
​
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("post.........");
    }
}
​
​

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/tomcat_demo2_war/demo3" method="post">
    <input name="username"><input type="submit">
</form>
点击提交之后,就会调用demo3中的Servlet,且是dopost的方法
</body>
</html>

针对不同的提交方式,Servlet中的service方法都需要编写一下代码

//根据请求方式的不同get/post  需要进行不同的解析服务方式
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //根据方式不同,进行分别处理
        //1.获取请求方式-------servletRequest对象可以提供请求方式
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String method = request.getMethod();
        //2.根据不同的请求方式编写不同的逻辑代码

        if ("GET".equals(method)){
            //get的处理逻辑
        }else if("POST".equals(method)){
            //post的处理逻辑
        }
    }

3.5 urlPattern

  • Servlet要想被访问,必须配置其访问路径(urlPattern)

    • 一个Servlet,可以配置多个urlPattern

      • @WebServlet(urlPatterns = {"/demo1","/demo2"})

    • urlPattern配置规则

      1. 精确匹配

      2. 目录匹配

      3. 扩展名匹配

      4. 任意匹配

  • 当一个路径满足多种匹配规则时,越精确的被调用

  • DefaultServlet是Tomcat用于处理静态资源的servlet,如果被覆盖掉那么将无法调用静态资源(比如 html)

3.6 XML编写

不使用注解,使用XML配置的方式

<!--Servlet全类名-->
<servlet>
    <servlet-name>demo4</servlet-name>
    <servlet-class>com.wang.servletTest.ServletDemo4</servlet-class>
</servlet>

    <!--Servlet路径映射-->
    <servlet-mapping>
        <servlet-name>demo4</servlet-name>
        <url-pattern>/demo4</url-pattern>
    </servlet-mapping>

4. Request 和 Response

  • Request 获取请求数据

  • Response 设置响应的数据

package com.wang.servletTest;

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("/demo5")
public class ServletDemo5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //使用request对象获得请求数据
        String name = req.getParameter("name");
        //使用response对象设置响应数据
        resp.setHeader("content-type","text/html;charset=utf-8");
        resp.getWriter().write("h1"+name+"欢迎!</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //使用request对象获得请求数据
        String name = req.getParameter("name");
        //使用response对象设置响应数据
        resp.setHeader("content-type","text/html;charset=utf-8");
        resp.getWriter().write("<h1>"+name+"欢迎!</h1>");
    }
}

4.1 Request对象

4.1.1继承体系

 

  • ServletRequest 是一个接口

  • HttpServletRequest 是对Http协议封装的request接口

  • Tomcat提供了实现类(Tomcat需要解析这些数据,所以需要提供实现类)

4.1.2 获取请求数据

请求数据分为三部分:

  • 请求行

  • 请求头

  • 请求体

 

同一种方式获取不同请求的参数:

Request对象采取的方式:

  • 建立一个Map

  • 泛型为<String,String[]>

  • 编写三个通用的调用参数的方法

 

4.1.3 请求转发

  • 一种在服务器内部的资源跳转方式(forward)

 

4.2 Response对象

响应数据分为三部分:

  • 响应行

  • 响应头

  • 响应体

 

4.2.1重定向

  • 一种资源跳转方式

  • 重定向是浏览器接收到302后自动的请求新地址的行为

 

  1. @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            System.out.println("resp1...................");
    
            /*重定向
            //1.设置响应状态码
            resp.setStatus(302);
            //2.设置响应头
            resp.setHeader("Location","/tomcat_demo2/resp2");*/
    
            //简化方法
            resp.sendRedirect("/tomcat_demo2/resp2");
        }
  • 重定向与请求转发的区别

 

4.2.2 响应体数据设置

响应字符数据:

  1. 通过Response对象获取字符输出流

    PrintWriter writer = reps.getWriter();

  2. 写数据

    writer.write("aaa")

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置支持utf-8
       resp.setContentType("text/html;charset=utf-8");
        //扫描并写入数据
        PrintWriter writer = resp.getWriter();
        writer.write("呵呵呵哒好玩的");
    }

该流不需要关闭,response对象会被服务器销毁

响应字节数据(除字符外的文件类型):

 

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1.读取文件
        FileInputStream stream = new FileInputStream("f://Anson Seabra - Keep You Head Up Princess.mp3");
        //2.获取字节输出流
        ServletOutputStream os = resp.getOutputStream();
        /*3.完成流的复制  笨办法
        byte[] buff = new byte[1024];
        int len = 0;
        while ((len=stream.read(buff))!=-1){
            os.write(buff,0,len);
        }*/
        IOUtils.copy(stream,os);
        stream.close();
    }

5. 登录案例

5.1 用户注册

  1. 用户注册,发送给RegisterServlet

  2. 在RegisterServlet中使用MyBatis保存数据

  3. 保存前需要查重(查询用户名)

package com.itheima.web;

import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import com.itheima.util.SqlSessionFactoryUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.InputStream;

@WebServlet("/registerServlet")
public class RegisterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收用户数据
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //封装用户对象
        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        //2. 调用mapper 根据用户名查询用户对象
        //2.1 获取SqlSessionFactory对象
       /* String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);*/
        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();

        //2.2 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //2.3 获取Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        //2.4 调用方法
        User u = userMapper.selectByUsername(username);

        //3. 判断用户对象释放为null
        if( u == null){
            // 用户名不存在,添加用户
            userMapper.add(user);

            // 提交事务
            sqlSession.commit();
            // 释放资源
            sqlSession.close();
        }else {
            // 用户名存在,给出提示信息
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write("用户名已存在");
        }

    }

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

5.2 用户登录

  1. 用户登录,填写账号密码提交到LoginServlet

  2. 在LoginServlet使用MyBatis查询数据库,匹配账号和密码

  3. 错误则响应登录失败

package com.itheima.web;

import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import com.itheima.util.SqlSessionFactoryUtils;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 接收用户名和密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        //2. 调用MyBatis完成查询
        //2.1 获取SqlSessionFactory对象
       /* String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);*/

        SqlSessionFactory sqlSessionFactory = SqlSessionFactoryUtils.getSqlSessionFactory();
        //2.2 获取SqlSession对象
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //2.3 获取Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        //2.4 调用方法
        User user = userMapper.select(username, password);
        //2.5 释放资源
        sqlSession.close();


        //获取字符输出流,并设置content type
        response.setContentType("text/html;charset=utf-8");
        PrintWriter writer = response.getWriter();
        //3. 判断user释放为null
        if(user != null){
            // 登陆成功
            writer.write("登陆成功");
        }else {
            // 登陆失败
            writer.write("登陆失败");
        }
    }

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

6. JSP

html和java语句可以放到同一个文档里,简化开发

Jsp脚本用于编写java代码

  • <%....%>

    • 内容会直接放到jspService中去

  • <%=....%>

    • 内容会放到out.print中去,作为out.print的参数

  • <%!....%>

    • 内容会放到JSPService方法之外,被类直接包含(成员地位)

6.1 EL表达式

用于获取数据

${expression}

 

7. MVC和三层架构

 

 

 

 

8. 会话跟踪技术

  • 会话是与浏览器绑定

  • 会话跟踪是服务器识别多次请求是否来自同一浏览器发出的

 

 

8.1 Cookie

  1. 服务器setCookie 通过HTTP发送给浏览器

  2. 浏览器下次请求时就会携带上上次服务器发来的Cookie(可能会有很多Cookie)

    1. 按照键去查找需要的Cookie

 

8.2 Session

  • 将会话数据保存到服务端

  • Session是基于Cookie的

 

 

8.3 对比

例如:验证码的实现就不能是Cookie,因为Cookie是保存在浏览器中的

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值