赞
踩
目录
我们知道http协议是HTTP客户端和HTTP服务器之间交互数据的格式,Java Socket可以用来构造HTTP客户端,同样HTTP服务器也可以使用Java Socket实现。
Tomcat就是一个基于java实现的一个开源免费,广泛应用的HTTP服务器。
在 Tomcat 官网下载即可. 这里我们使用 Tomcat 8(由于后续使用的servle是3.1 版本,因此这里使用tomcat8).
对其进行解压缩即可:解压缩的目录最好不要带中文,或者标点符号。
Ps:tomcat是基于java实现的,因此需要电脑安装上jdk才行,否则运行不了。
剩下的都为一些文档,无需关心。
在 bin 目录中, 双击 startup.bat 即可启动 Tomcat 服务器
看到形如以下内容的日志, 说明启动成功:
注意:
在 Windows 上通过 cmd 方式启动 Tomcat 会出现乱码. 但是不影响 Tomcat 的使用.
乱码的原因是 Tomcat 默认按照 UTF-8 的编码方式处理中文. 而 windows 的 cmd 默认是 GBK 编
码.
如果使用 Linux 或者 IDEA 中的终端来启动 Tomcat, 则没有乱码问题. 因此此处的乱码我们暂时不
处理.
进入欢迎界面(执行该步骤的前提是Tomcat服务器是开启的状态,没有被关闭)
在浏览器中输入 127.0.0.1:8080 即可看到 Tomcat 的默认欢迎页面:
分析:
这里的8080(端口号)是tomcat默认的,类似于MySQL的默认端口为3306.当然默认端口是可以修改的。
启动失败怎么办?
最常见的启动失败原因是端口号被占用.
Tomcat 启动的时候默认会绑定 8080 和 8005 端口.
如果有其他进程已经绑定了这两个端口中的任意一个, 都会导致 Tomcat 不能启动.
在命令行中使用 netstat -ano | findstr 8080 确定看 8080 是否被其他进程绑定,如果是的话,根据提供的PID到任务管理器中, 把对方进程干掉,再重新启动 Tomcat 一般就可以解决问题
理解 "静态"
静态页面也就是内容始终固定的页面. 即使 用户不同/时间不同/输入的参数不同 , 页面内容也不会发生变化. (除非网站的开发人员修改源代码, 否则页面内容始终不变).
对应的, 动态页面指的就是 用户不同/时间不同/输入的参数不同, 页面内容会发生变化.
举一个例子:
比如搜狗搜索的主页就是一个静态页面:
而哔哩哔哩就是一个动态的页面:
可以简单的认为:
静态页面就是简单的html页面,而动态页面是html+数据。
部署单个HTML文件
1) 创建 hello.html
我们可以把自己写好的 HTML 部署到 Tomcat 中:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Document</title>
- </head>
- <body>
- <div>hello</div>
- </body>
- </html>
2) 把 hello.html 拷贝到 Tomcat 的 webapps/ROOT 目录中:
3) 在浏览器中通过 URL http://127.0.0.1:8080/hello.html 来访问(127.0.0.1 为环回 IP, 表示当前主机):
部署带有 CSS / JavaScript / 图片 的 HTML
实际开发时我们的 HTML 不仅仅是单一文件, 还需要依赖一些其他的资源: CSS, JavaScript, 图片等.这些资源也要一起部署过去:
1) 创建 hello2.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>静态页面</title>
- <link rel="stylesheet" href="style.css">
- </head>
- <body>
- <img src="doge.jpg" alt="">
- <script src="app.js"></script>
- </body>
- </html>
2) 创建 style.css
- img {
- width: 500px;
- height: 500px;
- }
3) 创建 app.js:
console.log("hello");
4) 准备一个 doge.jpg
5) 把以上四个文件都拷贝到 Tomcat 的 webapps/ROOT 中
6) 在浏览器中通过 http://127.0.0.1:8080/hello2.html 来访问页面
分析:
通过 Fiddler 抓包, 可以发现此时浏览器和服务器之间有 4 个 HTTP 请求/响应的交互:
部署 HTML 到单独的目录中
实际开发中我们的 HTML 可能不止一个, 依赖的 CSS / JavaScript 文件也可能比较多. 这个时候就不适合全都拷贝到 webapps/ROOT 目录中了(这就会显的比较乱).
我们可以创建一个单独的目录, 和 ROOT 并列, 来存放我们要部署的内容.
1) 在 webapps 中创建目录 HelloApp, 和 ROOT 目录并列
2) 把刚才创建的 hello2.html, style.css, doge.jpg, app.js 拷贝到 HelloApp 目录中(为了结构更清楚, 我们在 HelloApp 中又创建了一些子目录, css , img , js 来分别放 css , 图片,JavaScript 文件)
3)调整 hello2.html 的代码, 把引用 css, js, 图片的路径进行微调:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>静态页面</title>
- <link rel="stylesheet" href="css/style.css">
- </head>
- <body>
- <img src="img/doge.jpg" alt="">
- <script src="js/app.js"></script>
- </body>
- </html>
4) 在浏览器中通过 http://127.0.0.1:8080/HelloApp/hello2.html:
通过抓包可以看到, 浏览器和服务器之间同样是 4 次 HTTP 请求/响应 的交互:
但是可以看到路径上和之前发生了变化:
由于我们把这些文件都放到了 HelloApp 目录中, 通过 GET 请求访问这些文件时的路径也要带上
HelloApp,此处的 HelloApp 称为 Application Path (应用路径) 或者 Context Path (上下文路径)
Servlet(Server Applet),全称Java Servlet。是用Java编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类。
这里我们所指的servlet是前者,是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app.
Servlet 主要做的工作
简而言之, Servlet 是一组 Tomcat 提供的 API, 让程序猿自己写的代码能很好的和 Tomcat 配合起来, 从而更简单的实现一个 web app.
而不必关注 Socket, HTTP协议格式, 多线程并发等技术细节, 降低了 web app 的开发门槛, 提高了开发效率。
一共分为七个步骤:分别为创建项目,引入依赖,创建目录结构,编写代码,打包程序,部署程序,验证。
在创建项目之前我们先来了解一下maven:
Maven 是一个项目管理工具,可以对 Java 项目进行规范目录结构,构建,管理依赖,打包,测试等.....
2.2.1 创建项目
这里我们是需要创建一个maven项目,
创建完成:
2.2.2 引入依赖
maven项目创建完毕后,会自动生成pom.xml文件。我们需要在prom.xml中引入Servlet API 依赖的jar包
1)在中央仓库 https://mvnrepository.com/ 中搜索 "servlet", 一般第一个结果就是:
2) 选择版本. 一般我们使用 3.1.0 版本
3) 把中央仓库中提供的 xml 复制到项目的 pom.xml 中:
代码:
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.example</groupId>
- <artifactId>Servlet_1</artifactId>
- <version>1.0-SNAPSHOT</version>
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- </properties>
-
- <dependencies>
- <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- <scope>provided</scope>
- </dependency>
- </dependencies>
-
- </project>
关于 groupId, artifactId, version
这几个东西暂时我们不关注. 啥时候需要关注呢? 如果我们要把这个写的代码发布到中央仓库上,
那么就需要设定好这几个 ID 了.
中央仓库就是按照这三个字段来确定唯一一个包的。
2.2.3 创建目录
在main目录下,和java目录并列,创建一个webapp目录,然后在 webapp 目录内部创建一个 WEB-INF 目录, 并创建一个 web.xml 文件:
并在web.xml中放入以下代码:
- <!DOCTYPE web-app PUBLIC
- "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
- "http://java.sun.com/dtd/web-app_2_3.dtd" >
- <web-app>
- <display-name>Archetype Created Web Application</display-name>
- </web-app>
webapp 目录就是未来部署到 Tomcat 中的一个重要的目录. 当前我们可以往 webapp 中放一些静态资源, 比如 html , css 等.
在这个目录中还有一个重要的文件 web.xml. Tomcat 找到这个文件才能正确处理 webapp 中的动态资源.
2.2.4 编写代码
在java目录中创建一个HelloServlet,代码如下:
- 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("/hello")
- public class HelloServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //这是在服务器的控制台上打印hello
- System.out.println("hello");
- //要想把hello返回给客户端,需要使用以下代码,getWriter会得到一个Writer对象。
- resp.getWriter().write("hello");
- }
- }
分析:
2.2.5 打包程序
问:为何要打包程序?
答:向以往的那些代码,都是带有main方法的,就像是一个小汽车.汽车自带发动机.自己就能跑.
而 Servlet 写的代码,相当于是个“车厢”,自己没有发动机.可以把这个车厢挂到车头后面让车头拉着它跑.车头就是 Tomcat ~~(tomcat 带 main,也就是带发动机),就需要把写好的代码挂到火车头后面~~ 打包 + 部署
使用 maven 进行打包. 打开 maven 窗口 (一般在 IDEA 右侧就可以看到 Maven 窗口, 如果看不到的话,可以通过 菜单 -> View -> Tool Window -> Maven 打开)
然后展开 Lifecycle , 双击 package 即可进行打包
如果比较顺利的话, 能够看到 SUCCESS 这样的字样:
打包成功后, 可以看到在 target 目录下, 生成了一个 jar 包:
这样的 jar 包并不是我们需要的, Tomcat 需要识别的是另外一种 war 包格式.
另外这个 jar 包的名字太复杂了, 我们也希望这个名字能更简单一点。
war 包和 jar 包的区别
jar 包是普通的 java 程序打包的结果. 里面会包含一些 .class 文件.换而言之,jar就算.class构造的压缩包。
war 包是 java web 的程序, 里面除了会包含 .class 文件之外, 还会包含 HTML, CSS, JavaScript, 图
片, 以及其他的 jar 包. 打成 war 包格式才能被 Tomcat 识别。
这里需要我们手动将jar转变成war包,在prom.xml中添入以下代码:
这里的finalName里面的字段就是 Context path(也就是war包的名称)。
分析:
再次点击maven,展开 Lifecycle , 双击 package 即可进行打包
2.2.6 部署
把刚才打包好的war拷贝到tomcat的webapps目录中即可,接着启动tomcat。
2.2.7 验证
运行结果:
分析:
这里的hello_wervlet是第一级路径,也叫做context path/ application path.
context path 路径如下(也是war包名称):
这里的hello是第二级路径,叫做servlet path(是注解里面所填的)
2.2.8 Servlet小结
将url在浏览器地址栏里面输入之后,浏览器就构造了一个对应的HTTP GET请求,发送给Tomcat,tomcat就会根据第一级路径,确定了具体的webapp:
找到这个目录之后,就会加载里面的类,尤其会重点识别由@WebServlet注解修饰的类,在注解中找到/hello这个路径,之后创建实例(只会创建一次,如果之前创建过了,后续会复用上次的实例),之后再解析出HTTP请求的方法是什么,再根据请求调用HelloServlet的方法(doGet,doPost......).与此同时,TomCat还会构造出HttpServletRequest对象和 HttpServletResponse对象。
手动拷贝 war 包到 Tomcat 的过程比较麻烦. 我们还有更方便的办法.此处我们使用 IDEA 中的 Smart Tomcat 插件完成这个工作:
什么是插件?
插件是一种电脑程序,透过和应用程序(例如网页浏览器,电子邮件客户端)的互动,用来替应用程序增加一些所需要的特定的功能。最常见的有游戏、网页浏览器的插件和媒体播放器的插件。
1)安装smart Tomcat插件:
安装完毕之后需重启Idea。
2)配置Smart Tomcat插件(记得配置完成点击窗口右下角的OK)
3)点击OK之后。右上角就变成了这样:
点击绿色的三角号, IDEA 就会自动进行编译, 部署, 启动 Tomcat 的过程
此时可以观察到,这里就没有出现乱码的情况了:
4)访问欢迎界面
看到这里我们知道Tomcat其实是有两种运行方式的:
a.通过bin目录下的startup运行,之后手动将war包拷贝过去
b.让idea直接调用tomcat,让tomcat加载当前项目中的目录(tomcat支持启动的时候显示的指定一个特定的webapp目录,相当于是让tomcat加载单个webapp运行):
这个是没有打war包的,虽然程序可以正常运行,但是之前webapps下已有的内容(比如欢迎界面)就没了:
5)访问页面
注意这里所对应的关系:
使用Smart Tomcat部署的时候,我们发现Tomcat的webapps内部并没有被拷贝一个war包,也没有看到解压缩的内容,得出:Smart Tomcat相当于是在Tomcat启动的时候直接引用了项目中的webapp和target目录
出现404
404表示用户访问的资源不存在,大概率是URL路径写的不正确。
需要注意Context Path 和 Servlet Path是否漏写或者写错。
亦或者是web.xml没写,或者写错:
其实在代码运行的时候,就有提示:
出现405
405表示对应的HTTP请求方法没有实现(简单来说:请求的方法在服务器端没有找到):
还有可能是调用了父类的doGet方法,根据源码,如果在Http版本号为1.1的时候就会返回405:
以下为调用父类doGet方法且有在页面输出信息:(如果仅是调用父类doGet方法,只会出现405,而不会有问号)
出现500
这种情况一般发生在代码出现异常的时候出现,就是我们的代码没有处理异常,异常就会向上传递,Tomcat会进行处理,这时候的页面异常状态码就是500。这个问题好解决,因为页面会把出现异常的原因以及出现异常的位置告诉你。
比如我们给代码来一个空指针异常:
小结
熟悉 HTTP 协议能够让我们调试问题事半功倍.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。