tomcat

tomcat基础

http工作原理

http协议是浏览器与服务器之间的数据传送协议.作为应用层协议,http是基于tcp/ip协议来传递数据的(html文件,图片,查询结果等),http协议不涉及数据包传输,主要规定了客户端和服务器之间的通信格式.

流程

1.用户通过浏览器执行了一个操作,比如访问网址,或者点击链接,浏览器获取了这个事件

2.浏览器向服务器发出了tcp链接的请求

3.服务器接收浏览器的连接请求,并经过tcp三次握手建立连接

4.浏览器将请求数据打包成一个http协议格式的数据包

5浏览器将该数据包推入网络,数据包经过网络传输,最终更达到端服务程序.

6浏览器程序拿到这个数据包后,同样以http协议格式解包,获取到客户端的示意图.

7得知客户端意图后进行处理,比如提供静态文件或者调用服务端程序获得动态效果.

8.服务器响应结果按照http协议格式打包

9.服务器将响应数据包推入网络,数据包经过网络传输最终到达浏览器

10浏览器拿到数据后,以http协议解包,如何解析数据,假设数据是html

11 浏览器将html文件展示在页面上

http

http服务器不直接调用业务类,而是把请求交给容器来处理,容器通过servlet调用业务类接口和Servlet容器的出现,达到了http服务器与业务类解耦的目的,而Servlet接口和Servlet容器这一整套规范叫做Servlet规范.tomcat按照Servlet规范要求实现了Servlet容器,同时他们也具有http服务器的功能.

servlet容器工作流程

为了解耦,服务器不会直接调用servlet,而是把请求交给servlet来处理

当客户端有摸个请求时http服务器会用一个ServletRequest对象吧客户的请求信息封装起来,如何调用Servlet容器的Service方法,servlet容器拿到请求后,根据请求的url和servlet的映射关系,找到相应的servlet,如果servlet还没有被加载,就用反射机制创建这个servlet,并调用servlet的init方法来完成初始化,借着调用servlet的service方法来处理请求,吧servletResponse对象返回给http服务器

tomcat整体架构

tomcat实现了俩个核心功能:

处理socket连接,负责网络字节流与request和response对象的转化

加载和管理Servlet,以及处理request请求

因此tomcat设计了俩个核心组件连机器(Connector)和容器(Container)来分别做这俩件事情.连接服务器负责对外交流,容器负责内部处理

连接器

coyote是tomcat的连接器框架名称,是tomcat服务器提供的客户端访问的外部接口.客户端通过coyote与服务器建立连接,发送请求并接受响应.

coyote封装了底层的网络通信(Socket请求及响应处理),为catalina容器提供了统一的接口,使Catalina容器与具体的请求协议及IO操作方式完全解耦.coyote将socket输入转换为Request对象,交由Catalina容器处理,处理完成之后,catalina通过coyote提供的Response将对象结果写入输出流

coyote作为独立模块,只负具体协议和io相关的操作,与Servlet规范实现没有直接关系,因此即便是Request和Response对象也并未实现Servlet规范对应的接口,而是在catalina中将他们进一步封装为ServletRequest和servletresponse.

IO模型与协议

在coyote中,tomcat支持多种I/O模型和协议,具体包含哪些IO模型和应用层协议,请看下表

tomcat支持的

tomcat支持的IO模型

IO模型描述
NIO非阻塞I/O,采用java NIO类库实现
NIO2异步I/O,采用JDK7最新的NIO2类库实现
ARP采用Apache,是c/c++编写的本地库.如果选择该方案需要单独安装APR库
tomcat支持的应用层协议
应用层协议描述
Http/1.1这是大部分Web应用采用的访问协议
AJP用于和Web服务器继承(入apache),实现静态资源的优化以及集群部署,当前指出AJP/1.3
HTTP/2HTTP2.0大幅度提升了Web性能,下一代HTTP协议,自8.5以及9.0版本之后支持

response

response响应过程

在发送一个请求时,会找到服务器引擎(tomcat),引擎会找到对应的web应用并创建request对象和reponse对象,并且创建request对象和response对象,找到应用后会执行应用web.xml在根据url-patten的内容创建servlet对象.吧request和response对象传入到方法中,拿到response对象后自己可以往响应中写入一些自己给客户端的内容,写的内容是存到一个response缓冲区中,当方法执行结束之后,tomcat就会从response缓冲区当中读取数据

设置响应行reponse.setState(int code)默认是200

添加响应头response.addHeader("name","123123")

设置date类型response.addDateHeader("my-Date",new Date().getTime());

设置int类型的值为int类型的头信息response.addIntHeader("qqq",1);

  • setHeader(name, value):如果Header中没有定义则添加,如果已定义则用新的value覆盖原用value值。
  • addHeader(name, value):如果Header中没有定义则添加,如果已定义则保持原有value不改变。

重定向

response.setStatus(302);//设置状态码
response.setHeader("location","/qqq");//设置重定向地址

也可以只写一行

response.setHeader("refresh","10;url=/admin/index");//过10秒之后去转发

响应体

设置响应体

response.getWriter().write("!@3");


//写文件
File file = new File(url);
        HttpHeaders headers=new HttpHeaders();
        //告诉浏览器以附件的形式打开,并且设置文件名的编码,防止乱码

        //通过ServletContext获取文件名对应的mime类型
        String mimeType = request.getSession().getServletContext().getMimeType(filename);
        response.setContentType(mimeType);//这么写的话可以直接解析图片或者mp4之类的文件

        response.setHeader("Content-Disposition","attachment;filename="+URLEncoder.encode(filename,"UTF-8"));//加上这行就能实现下载



        try(
                InputStream is = new FileInputStream(file);
                ServletOutputStream os = response.getOutputStream();//写在这里,执行结束会自动关闭输入输出流
        ){
            int read = 0;
            byte[] bytes = new byte[2048];
            while ((read = is.read(bytes)) != -1)
                os.write(bytes, 0, read);
        }

以上俩个只能选一种

设置编码

浏览器默认使用的是iso8859编码,不支持中文,可以设置

response.setCharacterEncoding("UTF-8");//设置缓冲区当中的编码
response.setHeader("Content-Type","text/html;charset=UTF-8");//设置编码,

Request

Request 和 Response 对象起到了服务器与客户机之间的信息传递作用。Request 对象用于接收客户端浏览器提交的数据,而 Response 对象的功能则是将服务器端的数据发送到客户端浏览器。

请求行

获取

request.getMethod();//获取请求方式
request.getRequestURI();//获取从更目录之后的请求路径
request.getRequestURL();//获取带上域名的请求完整路径
request.getQueryString();//获取字符串格式的请求参数

请求头

获取

//枚举集合
Enumeration<String> headerNames = request.getHeaderNames();//获取全部请求头的名称
while (headerNames.hasMoreElements()){
    System.out.println(headerNames.nextElement());
}

request.getHeader("cookie")//获取指定请求头的指定内容
request.getHeader("referer")//获取浏览器的上一个界面

referer

用a标签,或者表单提交js跳转等,是有referer的

但是如果是直接访问的,收藏夹,或者在浏览器当中直接输地址是没有referer的

获取请求参数

System.out.println(request.getParameter("name"));//获取一个name值
String[] names = request.getParameterValues("name");//获取多个值的name,比如复选框
Enumeration<String> parameterNames = request.getParameterNames();
//遍历获取所有的参数名称
 Enumeration<String> parameterNames = request.getParameterNames();
while (parameterNames.hasMoreElements()){
    System.out.println(parameterNames.nextElement());
}
//获取全部的请求参数
Map<String,String[]> parameterMap = request.getParameterMap();

请求转发

RequestDispatcher disp = request.getRequestDispatcher("/admin/user/userlist");
disp.forward(request,response);//springmvc中不能这样处理用:return "forward:/hello"; 
Last modification:May 20, 2022
如果觉得我的文章对你有用,请随意赞赏