Web服务器Tomcat
在官网下载zip版本的,解压到非中文的路径下就可以直接使用。
需要关注一下解压后的目录结构,包括bin、conf、lib等7个目录,最重要的是webapps和work,webapps是我们项目放置的位置,work放置的是翻译后和编译后的文件(就是一些中间文件,区别于源码文件)。
尝试第一次连接Tomcat
在启动之前,务必确定已经配置过环境变量JAVA_HOME了,其实就是我们自己安装的jdk的主目录。
- 在bin目录下找到startup.bat可以打开服务器,在bin目录下找到shutdown.bat可以关闭服务器。(如果关闭窗口是强制强制关机的意思,不建议这样用)
- 打开服务器之后,再使用浏览器打开网址:http://localhost:8080。就会出现默认的一个html页面,这个页面是apach设置的默认页面。端口号8080是默认的端口号,如果和有些应用的端口号冲突,可以使用conf目录下的server.xml中的Connector标签改一下端口号。这里是为了检测是否Tomcat可以使用。
- 手动在webapps目录下建立一个名叫Tomcat的目录(这个目录就是我们的项目目录),在里面放一个静态页面(helloworld)。
- 在浏览器中输入:http://localhost:8080/Tomcat/helloworld.html。就可以看到那个静态页面。这里的localhost可以理解为本机 的ip,在局域网的其他电脑也可以访问这个网址,只要localhost换成本机ip就可以。
可能出现的问题:一点击startup.bat这个批处理文件,就会出现闪退,可能是端口号占用,用bin目录下的catlina.bat也可以启动,并且发现日志上的问题描述,解决办法:可以更改conf目录下的server.xml的端口号,也可以把默认8080端口上的进程kill掉。
在spring tool suite中创建一个Tomcat服务器
首先就是new中other里搜索到server,然后点创建一个apach下的服务器(Tomcat是apach下的),选择自己适合的版本(7.0比较常见),然后把tomcat install directory输入进去,以及JRE环境也输入进去。这样就可以把tomcat服务器部署到我们的spring里面了。(注意:其实spring tool suite 只是copy了一份tomcat,只是作为临时服务器的作用,之前解压的tomcat是不会改变的),从文件目录中可以知道,文件目录中少了bin和lib,也就是说sts中部署的服务器是依赖于原生的服务器的。当然,也可以更改这个镜像的tomcat目录,双击server视窗里的服务器,跳出设置路径的地方,按需设置就行。
这里默认访问的是wtpwebapps目录下的页面,如果没有,可以放一个index.html在里面。
部署完这些之后,就可以用点击
的方式,把服务器打开,相当于startup.bat的作用。
在spring tool suite中创建一个动态web项目
- 在Target runtime中选中2.5版本的,3.0版本的是基于注解的,2.5是基于xml配置文件的。
- 在项目结构中,WebContent中有两个文件夹(WEB-INF和META-INF)。WEB-INF里的资源文件是受保护的,不会被访问到。WEB-INF里有lib,只要把jar包放进去,就会自动把jar包build path;web.xml是一些配置信息(其中有对于欢迎页面的设置,先访问index.html)。最好在WebContent下放一个index.html,可以在没有项目的时候默认访问。
- 在项目结构中,还有src和build这两个文件夹:src是写java代码的地方,build是src里的文件编译之后,变成class文件,放置的位置。
- 把这个动态项目run as server
- 在浏览器中输入具体的文件地址,localhost:8080/动态项目名称/hello.html。(如果输入的只是localhost:8080/动态项目名称只会跳出index.html)
- 就会出现hello.html页面的内容
注意观察一下文件系统中项目结构。在sts部署的服务器中的wtpwebapps目录下,会出现名字是动态web工程的文件夹,里面是WebContent的内容,而WEB-INF中会多一个classes文件夹,放的是src中class文件,也叫类路径。部署到服务器上的内容就是webcontent,其他的文件夹下的东西都不会部署上来。
互联网传输协议http
HTTP是一种能够获取html资源的通信协议,基于C/S,还得基于可靠的传输协议,比如TCP。
客户端和服务器通过消息交互,客户端发出的是requests,服务器发出的是response。
在HTTP/2之前的版本,比如HTTP/1.1是可以查看报文的,HTTP/2的版本把消息分装在帧中。
HTTP报文的结构是:
可以看到有起始行、http header、空行、消息体组成。
- 起始行:对于Request是由http方法、请求目标(比如绝对路径、url等等)、http的版本组成。对于Response是由协议版本号、状态码、状态文本组成。
- Header:可以将Header分为General、Request Header、Response Header。
- body:这部分就是网页附带的真实数据,分为single-resource bodies和Multiple-resource bodies两类。(post才有)
Response报文的起始行的响应码:
- 404:请求的资源找不到
- 200:请求成功
- 500:资源找到了,但是服务器内部出现问题
- 302:重定向,服务器会发一个响应头Location(包含了url),要求浏览器再发一个请求,去请求这个url。
Servlet的概念和应用
Servlet是一套针对Web应用的技术标准,或者宏观解决方案。每种Servet容器就负责提供这些标准的实现方法。
简单说,Servlet在jdk中就是一个接口,通过创建带有这个接口里的方法的实例,我们可以操作request和response消息,不过这这两种消息在Tomcat中会被封装成两个类:ServletRequest、ServletResponse。通过对这两个类实例可以实现自定义的各种操作。
Servlet的使用:
在Tomcat中真正使用的是HttpServlet,它继承了Servlet接口的某些方法,它和Servlet的关系如下图:
Servlet只不过是简单的接口,定义了最基本的几个方法,最重要的就是:初始化、服务、销毁。(调用的顺序在生命周期中提到)。
ServletConfig
封装了Servlet的配置信息,每一个Servlet就有一个ServletConfig对象。图中可以看到,它的功能:
- 获取Servlet的名字:基本不用
- 获取Servlet上下文:很有用,因为所有的Servlet共用一个context
- 获取指定初始化参数:比较有用
- 获取初始化参数的名字:在servlet标下配置了init-param标签的才会有名字
ServletContext
一个Web应用(动态项目)对应一个ServletContext对象。他的功能:
- 获取Web项目的初始化参数
- Web项目的路径
- Web项目中的资源的真实路径
- 作为最大的域对象共享数据(Application)
HttpServlet
这个抽象类是为http请求定制的一个类,方便了用户是使用。
具体步骤:
服务器使用servlet包括六个步骤:
1、客户端发送请求给web服务器;
2、web服务器收到请求;
3、web服务器把请求传输给servlet;
4、servlet就会处理这个请求并且还会产生响应;
5、servlet把响应发送给返回给web服务器;
6、web服务器还会把响应返回给客户端并且客户端浏览器会将这个响应的具体内容呈现在屏幕上;
上图可以看到servlet程序其实就运行在web服务器和数据库之间,可以这么理解:servlet就是web server的扩展。
它可以用来建立动态web页面。可是,要建立动态页面,就需要有容器,为了达到这个要求,独立的web服务器就使用了一些API的方式来解决。Java Servlet就是这些APIs中的一个,但是它不仅仅是用来建立动态页面的,它就有点像CGI脚本和PHP一样,但是Java Servlet更能够让人们接受,因为它至少不会像CGI一样低性能和低扩展性。
Servlet APIs:
Servlets的建立来自两个包:javax.servlet和javax.servlet.http,这里面的各种类和接口:
什么是servlet容器
Servlet容器也可以叫做是Servlet 引擎,他能够提供java的运行环境给Java Servlet的组件。简而言之,Servlet容器就是一个可操作web服务器上组件的系统,通过创建一个个的servlet实例对象,可以接收web客户端的请求,并且做出响应。
Servlet容器能够提供的服务:
- 网络服务:加载Servlet class
- 编码和解码MIME信息
- 控制Servlet的生命周期
- 资源控制(操控静态和动态资源,比如html files servlets jsp网页)
- 安全服务
- 会话管理
目前我们可以粗略的认为Tomcat就是Servlet容器。
Servlet实例对象的作用:
- 接收请求
- 处理请求
- 完成响应
建立自定义的Servlet:
创建一个类来实现Servlet接口,在web.xml中设置好这个Servlet实现类,Tomcat(Servlet容器)会创建这个实现类的实例。
里面包括了:Java Package名字和类名,系统会自动将Superclass(继承的父类)设置为HttpServlet。
然后点击next之后可以选择需要用到的方法,比如最常用用的doGet(),doPost()等等。点击finish之后,系统会自动在web.xml中注册好Servlet。
为什么需要这么创建,而不去手动实现Servlet接口:
1、可以自己控制需要用到的方法,我们知道自己实现Servlet接口,只有那几个基础的方法,没有办法直接使用ServletConfig这个接口里的方法(就算要用,还得实现这个接口,太麻烦),HttpServle的父类就已经帮我们实现好了一些既定的方法,拿来就用很方便。简而言之,方法更多。
2、可以省去自己在xml文件注册servlet的时间。因为每一个Servlet都要在web.xml中配置一组新的Servlet和Servlet-mapping标签,这样很浪费时间。
3、我们写的Servlet类的父类HttpServlet中,在service中内置了判断逻辑,会根据要求调用方法,比如doget ,dopost。不用自己手写条件判断语句,再跳转到get或post方法。
Servlet的生命周期:
servlet到底是如何在服务器上运作的:
- 构造器创建对象,只会调用一次。符合单例模式,多线程模式。所以Servlet类中一般不写成员属性,保证线程安全。
- 执行init()方法,只会调用一次。
- 执行Service()方法,每刷新一次就会调用Service方法。这一个方法是我们关注最多的地方。
- 如果关闭了服务器或者把动态项目从服务器上删除,服务器就会调用destory()方法把这个Servlet销毁掉。
doGet()怎么就替代了service():
HttpServlet实现了最初的Service方法,并且开放了多个新的方法给用户,比如dopost,dohead,doget等等,用户可以不用去管service里的内容,只要关注新方法就行。表面上是这些方法取代了service,实际上是通过继承,把问题的关键抽象了出来,让设计者只用关注请求的内容,不用在意请求的方式。
Servlet容器依旧还是会调用service方法(被HttpServlet实现了),根据不同的请求方式,会自动调用doxxx()方法,而我们要做的就是重写这些方法,达到我们自己的要求。
HttpServletResponse
这个接口继承了基础的ServletResponse接口,添加了一些方法,作用就是将http的响应报文封装成一个对象,对它做一些处理。这里将假设它的对象是response,它的用法如下:
- 可以给浏览器响应字符串
- 可以重定向一个资源:在返回的response报文的header中注入location,用来让浏览器找资源。
HttpServletRequest
继承了ServletRequest接口,添加了一些额外的方法,将请求报文封装成一个对象,对他进行操作,用法如下:
- 请求参数可以被获取到
- 获取请求头信息(Header)
- 转发一个资源:服务器将资源直接响应给浏览器
- 可以作为域对象request,用来共享数据
重定向和转发的区别:
这里的重定向是针对response的,转发针对request。
- 浏览器地址栏:重定向会变,转发不会。
- request:重定向有两次请求,转发只有一次
- 完成的位置:重定向在浏览器完成,转发在服务器内部
- WEB-INF的权限:重定向不能访问,转发就可以(转发就是服务器在操作,所以可以)
- 共享请求域:重定向不可以,转发可以
- 访问的资源:重定向不局限在本Web应用,转发只能是本Web应用的资源(服务器只能在自己库里找资源)
路径的问题:
重定向和转发对于服务器来说都已经完成了响应,所以不能构造转发器的同时再去进行转发request.getRequestDispatch().forward()是不被允许的,同时转发和重定向在一个Servlet里选一个。
action、href、src的值是路径,这一点没有问题,但是需要注意的是这里的路径是相对路径,并非真实路径。
转发和重定向传的参数也是路径,这里的路径也可以是相对路径。