01、JavaEETomcat配置

Tomcat

Web在英语中表示网页的意思,它用于表示Internet主机上供外界访问的资源,分为静态web资源和动态web资源。

静态web资源(如html 页面):指web页面中供人们浏览的数据始终是不变。
动态web资源:指web页面中供人们浏览的数据是由程序产生的,不同时间点访问web页面看到的内容各不相同。

静态web资源开发技术是HTML,动态web开发技术统称为JavaWeb,包括JSP/Servlet、ASP、PHP等等。

TomcatTomcat是一个实现了JAVA EE标准的最小的WEB服务器,是Apache 软件基金会的Jakarta 项目中的一个核心项目,由Apache、Sun 及个人共同开发而成。

我们可以通过Tomcat的官方站点去下载Tomcat服务器,然后配置Tomcat运行环境,再进入Tomcat的bin目录运行startup.bat运行即可。

http://jakarta.apache.org

启动Tomcat后,打开浏览器输入http://localhost:8080/ 即可打开Tomcat的本地主页面了。

Tomcat配置

环境变量

在使用Tomcat前首先需要配置Java的路径PATH变量,然后再配置JAVA_HOME变量即可。

新建JAVA_HOME变量,输入C:\Program Files\Java\jdk1.8.0_65
编辑PATH变量,输入%JAVA_HOME%来引用JAVA_HOME变量的值。

注意:使用Tomcat服务器必须配置JAVA_HOME变量,否则Tomcat服务器会无法运行。

端口占用

Tomcat服务器启动时默认使用的8080端口,如果端口被别的程序占用,则导致Tomcat无法正常启动。

由于这个窗口有可能一闪而逝,导致我们无法看清楚错误的信息,此时可以打开Tomcat的安装目录,找到logs文件夹去查看即可。

如果发现端口被占用时,可以通过netstat -ano命令查看是哪个程序占用了8080端口,并关掉占用当前端口的应用程序。

当然,我们还可以直接修改Tomcat的默认启动窗口。找到Tomcat的安装目录下的conf/server.xml文件:

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

将port="8080"修改为其他端口,然后重启Tomcat即可。

虚拟目录

Web应用开发好后,若想供外界访问,需要把web应用所在目录交给web服务器管理,这个过程称之为虚似目录的映射。

映射方式一

我们可以在server.xml文件的host进行配置,如下所示:

<Host name="localhost"  appBase="webapps"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">
</Host>

标签中加上即可完成映射。其中JavaWebApp是不存在的目录,也就是虚拟目录。

<Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true"
        xmlValidation="false" xmlNamespaceAware="false">
    <Context path="/JavaWebApp" docBase="F:\JavaWebDemo" />
</Host>

其中Context表示上下文,代表的就是一个JavaWeb应用,它有两个属性:path、docBase。

path:用来配置虚似目录,必须以"/"开头。
docBase:配置此虚似目录对应着硬盘上的Web应用所在目录。

注意:在Tomcat6之后,不再建议在server.xml中使用context配置虚拟目录,因为每次修改都需要重启Tomcat。

映射方式二

tomcat服务器会自动管理webapps目录下的所有web应用,并把它映射成虚似目录。所以我们可以把JavaWebDemo直接拷贝该目录下后,Tomcat会自动为

该JavaWebDemo项目映射一个同名的虚拟目录"/JavaWebDemo",然后可以使用浏览器直接访问该JavaWeb应用的资源了。

映射方式三

在tomcat服务器的\conf\Catalina\localhost目录下添加一个以xml作为扩展名的文件,在该xml文件中添加Context元素映射JavaWeb应用。

<Context docBase="F:\JavaWebDemo" />

使用这种方式最大的好处就是xml文件的名称和配置可以随意修改,而不用再重新启动Tomcat服务器。

注意:如果Context元素中并没有指明path属性来设置虚拟目录的名称,那么虚拟目录的名称默认是创建的xml文件的名称。

虚拟主机

配置虚拟主机

在Tomcat服务器配置一个虚拟主机(网站),需要修改conf下的server.xml这个配置文件,使用Host元素进行配置,打开server.xml,可以看到Tomcat服务器自

带的一个名称为localhost的虚拟主机(网站):

<Host name="localhost"  appBase="webapps"
    unpackWARs="true" autoDeploy="true"
    xmlValidation="false" xmlNamespaceAware="false">
</Host>

其中localhost就是虚拟主机的地址了,我们访问loclhost其实就是访问本机的127.0.0.1地址,可以通过修改name来修改ip地址。

域名注册

配置的主机(网站)要想通过域名被外部访问,必须在DNS服务器或windows系统中注册访问网站时使用的域名,找到"C:\Windows\System32\drivers\etc"目录下的

hosts文件,如下图所示:

编辑这个文件,将新添加的网站或域名和IP地址绑定在一起,这样我们就可以在浏览器直接使用域名来访问Web应用了。

目录结构

开发JavaWeb应用时,不同类型的文件有严格的存放规则,否则不仅可能会使web应用无法访问,还会导致web服务器启动报错

WebRoot → Web应用所在目录,一般情况下虚拟目录要配置到此文件夹当中。

|- WEB-INF:此文件夹必须位于WebRoot文件夹里面,而且必须以这样的形式去命名,字母都要大写。
|------ web.xml:配置文件,有格式要求,此文件必须以这样的形式去命名,并且必须放置到WEB-INF文件夹中。

web.xml的格式可以通过找到Tomcat目录下的webapps\ROOT\WEB-INF这个目录下的web.xml文件进行修改即可。

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">
  <display-name>Welcome to Tomcat</display-name>
  <description>
     Welcome to Tomcat
  </description>
</web-app>

打包Web应用

在Java中使用"jar"命令来将JavaWeb应用打包成一个War包,jar命令的用法如下:

jar {ctxui}[vfmn0PMe] [jar-file] [manifest-file] [entry-point] [-C dir] files ...

其中还包含大量的选项,用来应对不同的操作:

选项:
-c 创建新档案
-t 列出档案目录
-x 从档案中提取指定的 (或所有) 文件
-u 更新现有档案
-v 在标准输出中生成详细输出
-f 指定档案文件名
-m 包含指定清单文件中的清单信息
-n 创建新档案后执行 Pack200 规范化
-e 为捆绑到可执行 jar 文件的独立应用程序
指定应用程序入口点
-0 仅存储; 不使用任何 ZIP 压缩
-P 保留文件名中的前导 '/' (绝对路径) 和 ".." (父目录) 组件
-M 不创建条目的清单文件
-i 为指定的 jar 文件生成索引信息
-C 更改为指定的目录并包含以下文件
如果任何文件为目录, 则对其进行递归处理。
清单文件名, 档案文件名和入口点名称的指定顺序
与 'm', 'f' 和 'e' 标记的指定顺序相同。

范例:如果我们想将JavaWebDemo项目打成war包,则可以使用如下命令来操作:

打包后会生成一个xxx.war的包,然后将这个war包放入到Tomcat服务器的webapps目录下即可,当Tomcat启动时会自动将war包解压。

Tomcat的体系

Tomcat服务器的启动是基于一个server.xml文件的,Tomcat启动的时候首先会启动Server,Server中会启动Service。而Service里面就会启动

多个Connector(连接器),每一个连接器都在等待客户机的连接,当有用户使用浏览器去访问服务器上面的web资源时,首先是连接到Connector,

它不处理用户的请求,而是将用户的请求交给Engine(引擎)去处理,Engine接收到请求后会解析用户想要访问的Host,然后将请求交给相应的Host。

Host收到请求后会解析出用户想要访问这个Host下面的哪一个Web应用,且一个Web应用对应一个Context。

<?xml version='1.0' encoding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">
  <Service name="Catalina">
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
               keystoreFile="conf/.keystore" keystorePass="123456"/>
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
    <Engine name="Catalina" defaultHost="localhost">
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="localhost_access_log." suffix=".txt"
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      <Host name="www.gacl.cn" appBase="F:\JavaWebApps">
        <Context path="" docBase="F:\JavaWebApps\JavaWebDemo1"/>
      </Host>
    </Engine>
  </Service>
</Server>

加密原理

Tomcat服务器启动时会启动多个Connector连接器,而Tomcat服务器的连接器又分为加密连接器和非加密连接器。

这里访问的就是使用8080端口的那个连接器

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

这个Connector是未加密的连接器,要想以一种加密的方式访问Tomcat服务器,那么就要配置一个加密的Connector。

对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种方式成为对称加密,也成为单密钥加密。

对称加密由于其速度快,所以通常在消息发送方需要传递大量数据时使用。

因为对称加密的加密和解密都是同一个密钥,如何把密钥安全地传递到解密者手上就成了必须要解决的问题。

常用的对称加密有:DES、IDEA、RC2、RC4、SKIPJACK、RC5、AES算法等

非对称加密

非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。

如果公开密钥对数据进行加密,只有对应公开密钥才能解密;如果用私有密钥对数据进行加密,只有对应私有密钥才能解密。因此加密和解密使用的是两个不同的密钥,

所以这种算法叫做非对称加密算法。

甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。另一方面,甲方可以使用乙方的公钥对机密信息进行签名后再发送给乙方;乙方再用自己的私匙对数据进行验签。

Https连接器

浏览器如果想将数据加密后再发送给服务器的话,服务器首先要向浏览器出示一份数字证书,浏览器看到数字证书后,就可以使用数字证书里面的公钥加密数据,

所以要想做浏览器和服务器的加密数据传输,那么首先得针对服务器生成一份数字证书,然后再配置一下服务器,让服务器收到浏览器请求后,会向浏览器出示数字证书。

生成服务器数字证书

SUN公司提供了制作证书的工具keytool,在JDK1.4以后的版本中都包含这一工具,它的位置为<JAVA_HOME>\bin\keytool.exe。

keytool -genkey -alias tomcat -keyalg RSA

使用keytool生成一个名字为tomcat的证书,存放在.keystore这个密钥库中

命令执行完之后,操作系统的用户文件夹下面就会生成一个.keystore文件,使用命令:keytool -list -keystore .keystore查看.keystore密钥库里面的所有证书:

HTTP协议

HTTP是超文本传输协议,它简单便捷、快速灵活,是互联网上使用最为广泛的网络协议。(版本分为1.0和1.1,目前使用版本1.1)

HTTPS则是HTTP的一种加密协议,底层使用的加密方式一般为TSL和SSL。

它包括如下特点:

支持C/S(客户/服务器)模式。
简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。。
灵活:允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接,可以节省传输时间。
无状态:无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接

传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

URL格式

HTTP协议使用URI(统一资源标识符)来传输数据和建立连接。URL是一种特殊类型的URI,它包含了查找某个资源的完整信息。

http://www.127.0.0.1.com:8080/news/index.html?uname=123&pwd=123#name

从上面的URL可以看出,一个完整的URL包括以下部分:

协议部分:其中"http:"代表网页使用的是HTTP协议,而后面的"//"为分隔符
域名部分:其中"www.localhost.com"为域名部分,当然也可以使用IP地址作为域名
端口部分:域名之后紧接着是端口,域名和端口使用":"作为分隔符,如果省略端口,则采用默认端口。
虚拟目录:从第一个"/"到最后一个"/"都是虚拟目录部分。
文件名称:域名的最后一个"/"到"?"为止都是文件部分,它可以被省略而使用默认文件名。
参数部分:从"?"开始到"#"之间的部分为参数部分,参数以"?"进行拼接,多个参数以"&"作为分割。
锚部分:从#开始到最后都是锚部分,例如本例中的"name",它可以被省略。

请求报文

HTTP请求格式主要有四部分组成,分别是:请求行、请求头、空行、请求体,每部分内容占一行。

接下来我们进行抓包分析:

请求行:请求行是请求消息的第一行,由三部分组成,分别是请求方法(GET/POST/DELETE..)、请求资源的URI路径和HTTP的版本号。

GET /index.html HTTP/1.1

请求头:请求头中的信息有和缓存相关的头(Cache-Control,IF-Modified-Since)、客户端身份信息(User-Agent)等等。

Cache-Control:max-age=0
Cookie:gsScrollPos=; _ga=GA1.2.329038035.1465891024; _gat=1
If-Modified-Since:Sun, 01 May 2016 11:19:03 GMT
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36

下面是一些常用的请求头信息:

请求头 描述
accept 浏览器通过这个头告诉服务器,它所支持的数据类型
Accept-Charset 浏览器通过这个头告诉服务器,它支持哪种字符集
Accept-Encoding 浏览器通过这个头告诉服务器,支持的压缩格式
Accept-Language 浏览器通过这个头告诉服务器,它的语言环境
Host 浏览器通过这个头告诉服务器,想访问哪台主机
If-Modified-Since 浏览器通过这个头告诉服务器,缓存数据的时间
Referer 浏览器通过这个头告诉服务器,客户机是哪个页面来的 防盗链
Connection 浏览器通过这个头告诉服务器,请求完后是断开链接还是何持链接

请求体:请求体是客户端发送给服务端的请求数据,这部分数据并不是每个请求都必须的。

Response格式

服务器接收处理完请求后会返回一个HTTP响应消息给客户端,HTTP响应消息分为:状态行、响应头、空行、响应体,每部分内容占一行。

状态****行:状态行位于响应消息的第一行,包含Http协议版本号、状态码和状态说明三部分。

HTTP版本号 状态码 原因叙述
例如:HTTP/1.1 200 OK

状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为5类,如下所示:

状态码 含义
100 ~ 199 表示成功接收请求,要求客户端继续提示下一次请求才能完成整个处理过程。
200 ~ 299 表示成功接收请求并已完成整个处理过程,常用200
300 ~ 399 为完成请求,客户需进一步细化请求。例如,请求的资源已经移动一个新地址,常用302、304等等
400 ~ 499 客户端的请求有错误,常用404
500 ~ 599 服务器端出现错误,常用500

响应头:响应头是服务器传递给客户端用于说明服务器的一些信息,以及将来继续访问该资源的策略。

响应头 描述
Location 服务器通过这个头,来告诉浏览器跳到哪里
Server 服务器通过这个头,告诉浏览器服务器的型号
Content-Encoding 服务器通过这个头,告诉浏览器,数据的压缩格式
Content-Length 服务器通过这个头,告诉浏览器回送数据的长度
Content-Language 服务器通过这个头,告诉浏览器语言环境
Content-Type 服务器通过这个头,告诉浏览器回送数据的类型
Refresh 服务器通过这个头,告诉浏览器定时刷新
Content-Disposition 服务器通过这个头,告诉浏览器以下载方式打数据
Transfer-Encoding 服务器通过这个头,告诉浏览器数据是以分块方式回送的
Expires: -1 Cache-Control: no-cache Pragma: no-cache 控制浏览器不要缓存

响应体:响应体是服务端返回给客户端的HTML文本内容,或者其他格式的数据,比如:视频流、图片或者音频数据。

响应头使用

Location响应头

我们可以在服务端通过设置Location响应头来实现请求重定向的操作:

public class ServletDemo extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setStatus(302);//设置服务器的响应状态码
        /**
         *设置响应头,服务器通过 Location这个头,来告诉浏览器跳到哪里,这就是所谓的请求重定向
         */
        response.setHeader("Location", "/JavaWeb_HttpProtocol_Study_20140528/1.jsp");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

服务器返回一个302状态码告诉浏览器,你要的资源我没有,但是我通过Location响应头告诉你哪里有,而浏览器解析响应头Location后知道要跳转到

服务器所重定向的位置。

Content-Encoding

我们可以通过在服务端设置Content-Encoding响应头来告诉浏览器数据的压缩格式:

/**
 *这个小程序是用来演示以下两个小知识点
 *1、使用GZIPOutputStream流来压缩数据
 *2、设置响应头Content-Encoding来告诉浏览器,服务器发送回来的数据压缩后的格式
 */
public class ServletDemo02 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String data = "abcdabcdabcdabcdabcdabcdab" +
                "cdabcdabcdabcdabcdabcdabcdabcdabc" +
                "dabcdabcdabcdabcdabcdabcdabcdabc";
        System.out.println("原始数据的大小为:" + data.getBytes().length);
        
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        GZIPOutputStream gout = new GZIPOutputStream(bout); //buffer
        gout.write(data.getBytes());
        gout.close();
        //得到压缩后的数据
        byte g[] = bout.toByteArray();
        response.setHeader("Content-Encoding", "gzip");
        response.setHeader("Content-Length",g.length +"");
        response.getOutputStream().write(g);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

Content-type

我们可以通过服务端设置content-type响应头来指定回送的数据类型:

public class ServletDemo03 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /**
         * 浏览器能接收(Accept)的数据类型有: 
         * application/x-ms-application, 
         * image/jpeg, 
         * application/xaml+xml, 
         * image/gif, 
         * image/pjpeg, 
         * application/x-ms-xbap, 
         * application/vnd.ms-excel, 
         * application/vnd.ms-powerpoint, 
         * application/msword, 
         */
        response.setHeader("content-type", "image/jpeg");//使用content-type响应头发送给浏览器的数据类型为"image/jpeg"
        //读取位于项目根目录下的img文件夹里面的WP_20131005_002.jpg这张图片,返回一个输入流
        InputStream in = this.getServletContext().getResourceAsStream("/img/WP_20131005_002.jpg");
        byte buffer[] = new byte[1024];
        int len = 0;
        OutputStream out = response.getOutputStream();//得到输出流
        while ((len = in.read(buffer)) > 0) {//读取输入流(in)里面的内容存储到缓冲区(buffer)
            out.write(buffer, 0, len);//将缓冲区里面的内容输出到浏览器
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

Refresh

我们可以在服务端设置Refresh响应头来让浏览器进行定时的刷新操作:

public class ServletDemo04 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /**
         * 设置refresh响应头,让浏览器每隔3秒定时刷新
         */
        // response.setHeader("refresh", "3");
        /**
         * 设置refresh响应头,让浏览器3秒后跳转到http://www.baidu.com
         */
        response.setHeader("refresh", "3;url='http://www.baidu.com'");
        response.getWriter().write("gacl");
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}

Content-disposition

我们可以通过在服务端设置content-disposition响应头来让浏览器下载文件:

public class ServletDemo05 extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        /**
         * 设置content-disposition响应头,让浏览器下载文件
         */
        response.setHeader("content-disposition", "attachment;filename=xxx.jpg");
        InputStream in = this.getServletContext().getResourceAsStream("/img/1.jpg");
        byte buffer[] = new byte[1024];
        int len = 0;
        OutputStream out = response.getOutputStream();
        while ((len = in.read(buffer)) > 0) {
            out.write(buffer, 0, len);
        }
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        this.doGet(request, response);
    }
}
原文地址:https://www.cnblogs.com/pengjingya/p/14405857.html