HTTP

HTTP协议(HyperText Transfer Protocol,超文本传输协议)是由W3C(万维网联盟)组织制定的一种应用层协议,是用来规范浏览器与Web服务器之间如何通讯的数据格式,主要涉及浏览器的发请求格式和服务器的响应格式。
HTTP协议通常承载于TCP协议之上,而承载于TLS或SSL协议层之上的协议就是常说的HTTPS协议。
HTTP默认的端口号为80,HTTPS默认的端口号为443。
图片说明
简单地说,就是对两台计算机收发数据的格式的一种规定。

请求与响应

HTTP有请求与响应的概念。发送数据是发送请求,接收数据是接收响应。
请求/响应的格式为 请求/响应行 请求/响应头 空白行 请求/响应体

//请求行
POST /task01_demo01/demo1.html HTTP/1.1
//请求头 我可没说请求头只有一行,可以很长
Host: localhost:8088
Content-Length: 21
Cache-Control: max-age=0
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64)  //下一行是空白行

name=scott&pwd=123456    //这些是请求体

下面是响应的例子,对照上面的看很好懂。

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 588
Date: Thu, 08 Sep 2021 12:59:54 GMT

<html><head><title>示例1</title></head> <body><h1>这是一个HTML页面</h1></body> </html>

Tomcat

用户会访问网站上的资源,资源应该部署在服务器里。服务器分静态服务器和动态服务器。
Tomcat就是很有名的一款动态服务器。

目录结构

bin 主要存放二进制可执行文件和脚本。
conf 主要存放各种配置文件。
lib 主要用来存放Tomcat运行需要加载的jar包。
logs 主要存放Tomcat在运行过程中产生的日志文件。
temp 主要存放Tomcat在运行过程中产生的临时文件。
webapps 主要存放应用程序,当Tomcat启动时会去加载该目录下的应用程序。
work 主要存放tomcat在运行时的编译后文件,例如JSP编译后的文件。

启动与关闭

双击bin目录下的startup.bat启动,双击bin目录下的shutdown.bat关闭(点X也行,懂吧?我是高档人士)。
正常来说,双击startup.bat之后,一个控制台窗口会一直存在。但有人的控制台窗口会闪退,这是没有配置环境变量JAVA_HOME造成的。

第一次启动,会发现程序正常运行,但是控制台显示的日志是乱码。乱码问题是因为对数据的编码和解码的格式不一样。控制台默认解码方式是GBK,而Tomcat的日志数据默认编码方式是UTF-8。所以简单起见可以把Tomcat的编码方式变成GBK。方法是修改conf目录下的logging.properties。

修改端口号

HTTP协议的默认端口号是80,如果你在自己的电脑上访问自己电脑上的Tomcat,需要显式写好localhost:8080。但如果你把Tomcat的默认端口号改成80的话,就可以不写端口号进行访问了。
修改方式是 找到conf目录下的server.xml,里面Connector开头的标签后面的端口号就是Tomcat的默认端口号。

部署静态资源

在webapps文件夹下创建一个文件夹,文件夹里写点html
接着只需要访问http://localhost:8080/文件夹名/文件名 即可访问静态资源
如果直接访问http://localhost:8080 则会去寻找ROOT文件夹下的index文件

在IDEA里创建web项目

选择java enterprise即可

Servlet

可以运行在Tomcat上的java类

编写servlet的步骤

1 建项目
2 实现Servlet接口并重写service方法/继承GenericServlet并重写service方法/继承HttpServlet类
3 配置servlet到xml文件里(现在也可以用注解)
web.xml写法如下例

<!-- 配置Servlet --> 
<servlet> 
    <!-- HelloServlet是Servlet类的别名 --> 
    <servlet-name> HelloServlet </servlet-name> 
    <!-- 这里给路径 --> 
    <servlet-class> com.example.HelloServlet</servlet-class> 
</servlet> 
<!-- 映射Servlet --> 
<servlet-mapping> 
    <!-- HelloServlet是Servlet类的别名,与上述名称必须相同 --> 
    <servlet-name> HelloServlet </servlet-name> 
    <!-- /hello是供浏览器使用的地址 --> 
    <url-pattern> /hello </url-pattern> 
</servlet-mapping>

最好还是继承HttpServlet

HTTPServlet

常见方法如下
图片说明
可别傻乎乎的自己new class然后一顿写了,idea什么都能做的。。。

Servlet生命周期

图片说明
构造方法只被调用一次(实例化阶段),当第一次请求Servlet时调用构造方法来创建Servlet的实例。
init方法只被调用一次,当创建好Servlet实例后立即调用该方法实现Servlet的初始化。
service方法被多次调用,每当有请求时都会调用service方法来用于请求的响应。
destroy方法只被调用一次,当该Servlet实例所在的Web应用被卸载前调用该方法来释放当前占用
的资源。

GET/POST简介

一般来说,超链接、浏览器访问、method=GET前提下发送的表单用的是GET。
method=POST前提下发送的表单用的是POST
GET会把发送的数据都接到URL后面
POST不会,POST会把数据塞到请求体里

HttpServletRequest

先看看父类常用的方法:
图片说明
再看看本类的常用方法:
图片说明

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        System.out.println("name: " + name);
        String[] hobbies = request.getParameterValues("hobby");
        System.out.println("hobbies: " + Arrays.toString(hobbies));
        Enumeration<String> parameterNames = request.getParameterNames();
        System.out.println("parameterNames: ");
        while (parameterNames.hasMoreElements()) {
            System.out.println(parameterNames.nextElement());
        }
        System.out.println("URI: " + request.getRequestURI());
        System.out.println("URL: " + request.getRequestURL());
        System.out.println("METHOD: " + request.getMethod());
        System.out.println("QUERY: " + request.getQueryString());
        System.out.println("Servlet Path: " + request.getServletPath());
    }

(Http)ServletResponse

常用方法
图片说明
以及
图片说明

有个问题就是response的默认编码方式是ISO-8859-1,这样发中文会乱码。
应该在发消息前setContentType("text/html;charset=UTF-8");

解决接收中文乱码问题

GET(低版本才有问题)

// 接收到get请求的中文字符串
String name = request.getParameter("name");
// 将中文字符重新编码,默认编码为ISO-8859-1
String userName = new String(name.getBytes(“ISO-8859-1”),“utf-8");   

POST

//接收之前设置编码方式:
request.setCharacterEncoding(“utf-8”)
//提示:
//必须在调用request.getParameter(“name”)之前设置

ServletConfig

常用方法
图片说明

ServletContext

javax.servlet.ServletContext接口主要用于定义一组方法,Servlet使用这些方法与它的Servlet容器通信。
服务器容器在启动时会为每个项目创建唯一的一个ServletContext对象,用于实现多个Servlet之间的信息共享和通信。
在Servlet中通过this.getServletContext()方法可以获得ServletContext对象。

图片说明

重定向

首先客户浏览器发送http请求,当web服务器接受后发送302状态码响应及对应新的location给客户浏览器,客户浏览器发现是302响应,则自动再发送一个新的http请求,请求url是新的location地址,服务器根据此请求寻找资源并发送给客户。

在servlet里,只需要response.sendRedirect()即可

转发

在servlet的语义下,指的是一个Web组件(Servlet/JSP)将未完成的处理通过容器转交给另外一个Web组件继续处理,转发的各个组件会共享Request和Response对象。
具体使用:

@Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        RequestDispatcher requestDispatcher = request.getRequestDispatcher("target.html");
        requestDispatcher.forward(request, response);
    }

转发之后浏览器地址栏的URL不会发生改变。
转发过程***享Request对象。
转发的URL不可以是其它项目工程。

图片说明

Servlet与多线程

Servlet是共享资源。服务器对每个请求都会创建一个线程,但每个服务只有一个servlet实例。这会出现问题。
解决方案也很简单,就是加锁。

生命周期

默认情况下,浏览器会将Cookie信息保存在内存中,只要浏览器关闭,Cookie信息就会消失。
如果希望关闭浏览器后Cookie信息仍有效,可以通过Cookie类的成员方法实现。

int getMaxAge() //返回cookie的最长使用期限(以秒为单位)
void setMaxAge(int expiry) //设置cookie的最长保留时间(秒) -1则是关闭浏览器后失效

路径

浏览器在访问服务器时,会比较Cookie的路径与请求路径是否匹配,只有匹配的Cookie才会发送给服务器。
Cookie的默认路径等于添加这个Cookie信息时的组件路径,例如:/项目名/目录/add请求添加了一个Cookie信息,则该Cookie的路径是 /项目名/目录。
请求的地址必须符合Cookie的路径或者是其(直接)子路径时,浏览器才会发送Cookie信息。

void setPath(String uri) //设置cookie的路径信息

Cookie

Cookie本意为”饼干“的含义,在这里表示客户端以“名-值”形式进行保存的一种技术。
浏览器向服务器发送请求时,服务器将数据以Set-Cookie消息头的方式响应给浏览器,然后浏览器会将这些数据以文本文件的方式保存起来。
当浏览器再次访问服务器时,会将这些数据以Cookie消息头的方式发送给服务器。

常用方法

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies)
            System.out.println(cookie.getName() + " " + cookie.getValue());
        System.out.println("here");
        Cookie cookie = new Cookie("name", "Ohio");
        response.addCookie(cookie);
        System.out.println("cookie added");
    }

Session

Session本意为"会话"的含义,是用来维护一个客户端和服务器关联的一种技术。
浏览器访问服务器时,服务器会为每一个浏览器都在服务器端的内存中分配一个空间,用于创建一个Session对象,该对象有一个id属性且该值唯一,我们称为SessionId,并且服务器会将这个SessionId以Cookie方式发送给浏览器存储。
浏览器再次访问服务器时会将SessionId发送给服务器,服务器可以依据SessionId查找相对应的Session对象。

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        System.out.println(session.isNew() ? "new" : "old");
        System.out.println("session id is " + session.getId());
        session.setAttribute("name", "purdue");
        System.out.println("attribute is " + session.getAttribute("name"));
        session.removeAttribute("name");
        System.out.println(session.getMaxInactiveInterval());
        session.setMaxInactiveInterval(1200);   //1200s
    }

session的生命一般是30min。
getMaxInterval() setMaxInterval()可以获取/设置失效时间。
当然也可以用配置文件去修改相关配置。

特点

数据比较安全。
能够保存的数据类型丰富,而Cookie只能保存字符串。
能够保存更多的数据,而Cookie大约保存4KB。
数据保存在服务器端会占用服务器的内存空间,如果存储信息过多、用户量过大,会严重影响服务
器的性能。