← 返回首页
Servlet基础教程(二十四)
发表时间:2021-06-04 15:48:21
服务推送

Servlet API是Java开发人员最熟悉的API之一,Servlet在1999年所发布的J2SE1.2版本中首次面世,Servlet在JavaWEB的开发中发挥着重要的作用。JavaEE8对Servlet4.0进行了重要的更新。其中服务器推送是最主要的更新,如果要使用服务器推送的功能,则我们必须使用HTTP/2.0版本的协议。JavaEE8提供了对Servlet映射的运行时发现,在运行时我们可以获取Servlet的名称,Servlet的映射路径。JavaEE8简化了对Filter的开发。

本案例开发环境:jdk8,tomcat9,tomcat-native,openssl

Servlet4.0是使用HTTP/2协议,而Tomcat9下载后,默认使用的是HTTP/1.1,所以我们要先修改server.xml配置文件:

1.注释原有的默认使用HTTP/1.1方式

<!--
   <Connector port="8080" protocol="HTTP/1.1"
            connectionTimeout="20000"
           redirectPort="8443" />
 -->

2.开启HTTP2的注释

注意:要删除certificateChainFile这一行,HTTP2使用的端口不在是8080,而是8443,使用HTTP2需要配置一个私钥文件和一个证书文件。

<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
               maxThreads="150" SSLEnabled="true" >
        <UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
        <SSLHostConfig>
            <Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
                         certificateFile="conf/localhost-rsa-cert.pem"
                         type="RSA" />
        </SSLHostConfig>
    </Connector>

关于上面Certificate标签有关说明:当你申请证书时或获取一个证书crt和一个私钥key文件,certificateKeyFile放的就是你的证书key文件,certificateFile则是私钥cert文件,默认放在Tomcat9的conf目录下。

certificateChainFile:一般操作系统/浏览器会内置一些CA(证书颁发机构)的证书,如果你的证书是直接由这些内置CA颁发的,那么就不需要Chain文件,浏览器可以直接识别你的证书。如果你的证书是由二级CA颁发的,即内置CA颁发给另一个二级CA,然后二级CA在颁发给你,那么就需要Chain文件,否则浏览器就不知道你的证书和内置CA的关系。如果你将自记得CA设置成了内置CA,那么直接由你的CA颁发的证书自然不需要Chain文件。

3.生成证书和私钥文件

下载windows openssl:window openssal下载地址

现在我们需要生成server.xml配置中的证书和私钥文件,在这里我是使用openssl生成的,由于windows64是兼容windows32的,所以不必担心不能使用的问题。解压开后,进入bin目录,启动openssl.exe

使用管理权限执行以下命令,生成私钥:

OpenSSL> genrsa -out localhost-rsa-key.pem 1024

使用配置文件生成证书(可以填写相关的组织信息):

req -new -key localhost-rsa-key.pem -x509 -days 3650 -config "C:\Program Files\OpenSSL-Win64\bin\cnf\openssl.cnf" -out localhost-rsa-cert.pem

将第三步生成了两个文件,放入tomcat9的conf目录下。

4.下载tomcat-nativate

tomcat-native下载地址:tomcat-native

下载tomcat-nativate文件并解压,如果你是win32系统直接将bin目录下tcnative-1.dll和tcnative-1-src.pdb文件复制到jdk的bin目录下,如果你是win64则将x64文件下的这两个文件复制到jdk目录下。

至此我们已经完成了Tomcat9的HTTP协议的升级,现在你可以启动Tomcat9,然后访问https://localhost:8443/即可看到tomcat页面。

5.测试服务推送 将用户所需的WEB资源提前推送到用户的浏览器缓存中,当用户使用浏览器访问所需WEB资源时,用户不需要再次下载所需的资源,因为用户所需的WEB资源已经存在与用户的浏览器缓存中。

Servlet4.0通过PushBuilder接口公开服务器推送。为了能够进行访问,你需要通过调用newPushBuilder()方法,从HttpServletRequest获取PushBuilder实例。

测试使用服务推送把两张图片资源推送到浏览器缓存。

编写Servlet测试服务推送。

/**
 * 将用户所需的WEB资源提前推送到用户的浏览器缓存中,当用户使用浏览器访问所需WEB资源时,
 * 用户不需要再次下载所需的资源,因为用户所需的WEB资源已经存在与用户的浏览器缓存中。
 */
@WebServlet("/PushServlet")
public class PushServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PushBuilder pushBuilder = req.newPushBuilder();

        if (pushBuilder != null) {
            PushBuilder path = pushBuilder.path("./images/hello.jpg");
            path.push();

            // 只推送最后一个path里的资源
            //PushBuilder path = pushBuilder.path("./hey.jpg").path("./hello.jpg");
            //path.push();

            // 推送多个资源的写法
            //pushBuilder.path("./hello.jpg").push();
            //pushBuilder.path("./hey.jpg").push();
        }

        req.getRequestDispatcher("test.html").forward(req, resp);

    }
}

请求转发后的静态页面:

<!DOCTYPE html>
<html>
<head>
    <title>Title</title>
</head>
<body>
Hello
<p>
<img src="images/hello.jpg" alt="first">
<img src="images/hey.jpg" alt="second">
</p>
</body>
</html>

使用服务器推送,效果很明显,不需要向服务器二次请求建立连接,因为图片在建立Servlet链接请求的时候,服务器端就已经推送过来了,所以在PushServlet时可以看到,这张图比不使用服务推送多耗了一点时间,因为要多下载一张图。总体上相当于省下了hey.jpg建立链接的时间。