Http协议与Servlet笔记

Http协议

  • http协议:针对网络上客户端与服务端在执行http请求时的一种遵守规范。要求客户端访问服务端时要带上什么东西,服务器返回数据时要带上什么东西。
  • 版本:

1.0 请求数据,返回数据后断开连接
1.1 请求返回后保持连接,知道客户端或者服务器关闭。

  • http请求数据
    请求的数据包含三个东西: 请求行、请求头、请求体
  1. 请求行:

    POSThttp://localhost/examples/servlets/servlet/RequestParamExample
    POST是请求方式,用post去提交数据。后面的是地址数据,就是要访问到哪里

  2. 请求头
    在这里插入图片描述

    Accept:客户端向服务器说明他自己可以支持什么类型的数据。
    Referer:真正请求的地址路径,谁发出的全路径
    Accept-Language:支持语言格式
    User-Agent:用户代理,向服务器表明现在访问的客户端信息
    Content-Type:提交的数据类型,经过urlencoding编码的表单form数据
    Accept-Encoding:gzip ,deflate:压缩算法
    Host:主机地址
    Content-Length:数据长度
    Connection keep-alive:保持连接

  3. 请求体
    浏览器真正发送给服务器的数据
    数据呈现形式是key = value 如果有多个数据使用&连接

    name=zhangsan&password=111111

Http响应数据解析

请求数据里包含:响应行、响应头、响应体
在这里插入图片描述

  • 响应行

HTTP/1.1 200 OK
协议版本
状态码:本次访问到底返回一个什么样的结果
1. 200成功,得到数据
2. 404 NOT FOUND
3. 403 ForBidden 拒绝访问
4. 500 服务器内部错误异常
OK对应状态码

  • 响应头
    Server:服务器是哪一种类型
    Content-Type:服务器返回给客户端的内容类型
    Content-Length:返回的数据长度
  • 响应体
GET和POST区别
  1. 请求路径不同,post请求的URL后面不跟任何东西,get请求在URL后面有数据。
  2. 带上的数据不同,post使用流的方式写数据,get直接跟在地址栏后面。
  3. 由于post使用流写数据,所以一定要有一个Content-Length头说明数据的长度是多少。
  • post
  1. 数据以流的方式写上去,不会出现在地址栏。一般客户端提交数据使用这种方式。
  2. 以流的方式写数据,所以没有数据大小限制。
  • get
  1. 由于get请求直接把数据放到地址栏上,所以不安全。一般从服务器获取数据,但不从客户端获取使用get。
  2. 数据大小最大约1kb

web资源

  • 静态资源
    html、css、javascript
  • 动态资源
    servlet、jsp

servlet

  • servlet是什么

A servlet is a small Java program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol.
更多的是配合动态资源来做,当然静态资源里也有使用,只不过Tomcat里有一个DefaultServlet.

  • servlet执行过程
    首先创建一个TestServlet.java文件实现Servlet接口
    再配置web.xml
<!-- 向Tomcat告知有一个这样的servlet,名字叫做hello,路径是com.lxr.TestServlet -->
  <servlet>
  	<servlet-name>hello</servlet-name>
  	<servlet-class>com.lxr.TestServlet</servlet-class>
  </servlet>
  <!-- 注册servlet映射,servlet-name找到上面注册的具体servlet, url-pattern是在地址栏上的path-->
  <servlet-mapping>
  	<servlet-name>hello</servlet-name>
  	<url-pattern>/a</url-pattern>
  </servlet-mapping>

这时候地址栏输入

http://localhost/httpServlet/a

整个过程先是通过地址栏提交的数据找到Tomcat应用、找到项目、找到web.xml里的url-pattern,看有没有哪一个pattern内容是/a、找到对应的servlet-mapping中的servlet-name(上例中就是hello)、找到上面定义的servlet元素中的servlet-name中的hello(两个的servlet-name内容必须一致)、找到下面定义的servlet-class开始创建实例、最后执行servlet中的service方法。

  • servlet通用写法
    Servlet(接口)------GenericServlet(实现接口)------HttpServlet(前者的子类,处理http请求)
    在这里插入图片描述HttpServlet中有自己的service方法,不是从Servlet继承的,它的参数是ServletRequest arg0和ServletResponse arg1,强转成HttpServletRequest arg0, HttpServletResponse arg1可以调用Servlet中的service方法。
  • 定义一个类继承HttpServlet,复写doGet方法和doPost方法

Servlet的生命周期

  • init方法
    在创建该servlet的实例时,就执行该方法。
    一个servlet只会初始化一次, init方法只会执行一次
    默认情况下是 : 初次访问该servlet,才会创建实例。

  • service方法
    只要客户端来了一个请求,那么就执行这个方法了。
    该方法可以被执行很多次。 一次请求,对应一次service方法的调用

  • destroy方法
    servlet销毁的时候,就会执行该方法

        	1. 该项目从tomcat的里面移除。
        	2. 正常关闭tomcat就会执行 shutdown.bat
    

doGet 和 doPost不算生命周期方法,所谓的生命周期方法是指,从对象的创建到销毁一定会执行的方法, 但是这两个方法,不一定会执行。

Servlet创建实例的时间提前

如果init方法中要做一些很复杂的逻辑或者某些初始化工作,而要等到第一次访问这个Servlet才执行,那么耗时长,需要在该init方法中逗留较长的时间。这时候应该让这个方法提前执行,就好比你要去请客吃饭,但你不能等到客人来了才准备饭菜,需要提前执行。
解决方法:

<servlet>
  	<servlet-name>hello3</servlet-name>
  	<servlet-class>com.lxr.TestServlet2</servlet-class>
  	<!-- 里面数字越小越先执行,一般不写负数 -->
  	<load-on-startup>2</load-on-startup>
  </servlet>
  <servlet-mapping>
  	<servlet-name>hello3</servlet-name>
  	<url-pattern>/c</url-pattern>
  </servlet-mapping>

ServletConfig

获取servlet在配置的一些信息

创建TestServletConfig.java文件

public class TestServletConfig extends HttpServlet{
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		//创建ServletConfig 对象
		ServletConfig config = getServletConfig();
		//获取servlet的名称
		String servletName = config.getServletName();
		System.out.println("servletName:" + servletName);
		//根据参数名获取具体某一初始化参数值
		String address = config.getInitParameter("address");
		System.out.println("address:" + address);
		//遍历取出所有参数名
		Enumeration<String> names = config.getInitParameterNames();
		while(names.hasMoreElements()) {
			String key = names.nextElement();
			String value = config.getInitParameter(key);
			System.out.println("key=" + key + ";value=" + value);
		}
	}
}

配置的web.xml

<servlet>
  	<servlet-name>hello4</servlet-name>
  	<servlet-class>com.lxr.TestServletConfig</servlet-class>
  	<init-param>
  		<param-name>address</param-name>
  		<param-value>西安</param-value>
  	</init-param>
  	<init-param>
  		<param-name>telephone</param-name>
  		<param-value>13789087456</param-value>
  	</init-param>
  </servlet>
  <servlet-mapping>
  	<servlet-name>hello4</servlet-name>
  	<url-pattern>/d</url-pattern>
  </servlet-mapping>

运行TestServletConfig结果:
在这里插入图片描述
可见获取的是配置的servlet中的servlet-name中的文本内容

ServletConfig作用

一个写好的项目jar包给你,你将这个jar包导入你的项目,在你的项目里直接配置web.xml就可以进行一些操作。

  1. 将写好的ServletConfig项目导成jar包:
    在这里插入图片描述在这里插入图片描述
    2.导入新的项目:
    将jar包copy导项目的lib文件夹下,配置项目的web.xml文件
<servlet>
  	<servlet-name>config</servlet-name>
  	<servlet-class>com.lxr.config.ServletConfigDemo</servlet-class>
  	<init-param>
  		<param-name>number</param-name>
  		<param-value>20</param-value>
  	</init-param>
  </servlet>
  <servlet-mapping>
  	<servlet-name>config</servlet-name>
  	<url-pattern>/config</url-pattern>
  </servlet-mapping>

其中servlet-class内容如下图选择:(记得删掉.class)
在这里插入图片描述
结论:
2. 未来我们自己开发的一些应用,使用到了一些技术,或者一些代码,我们不会。 但是有人写出来了。它的代码放置在了自己的servlet类里面。

  1. 刚好这个servlet 里面需要一个数字或者叫做变量值。 但是这个值不能是固定了。 所以要求使用到这个servlet的公司,在注册servlet的时候,必须要在web.xml里面,声明init-params
Servlet匹配方式
  • 全路径匹配

localhost/项目名/a/b
web.xml中的配置:
<url-pattern>/a/b</url-pattern>

  • 路径匹配

localhost/项目名/a/随便写
web.xml配置:
<url-pattern>/a/*</url-pattern>
其中*是通配符,也就是说,只有前半段需要匹配,后面不需要

  • 扩展名匹配

localhost/项目名/*.test
web.xml配置:
<url-pattern>*.test</url-pattern>
其中test是扩展名

ServletContext

在每一个项目里都有一个ServletContext对象,那么在任意一个servlet中获取的这个类的对象都是这一个。

//获取对象
ServletContext context = getServletContext();
  • 作用
  1. 获取全局参数
  2. 可以进行不同servlet数据共享存取
  3. 获取web工程中的资源

获取全局参数:
web.xml:

<context-param>
    <param-name>apple</param-name>
    <param-value>苹果</param-value>
  </context-param>

TestServletContext:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取对象
		ServletContext context = getServletContext();
		//获取参数值
		String value = context.getInitParameter("apple");
		System.out.println("apple:" + value);
		//获取项目在Tomcat下的根目录
		String root = context.getRealPath("");
		System.out.println("项目在Tomcat中的根目录" + root);
		//获取资源在Tomcat下的绝对路径
		String realPath = context.getRealPath("com/lxr/servlet/Demo.java");
		System.out.println("Demo的目录 :" + realPath);
	}

这里要清楚两个概念:

  1. ServletContext的相对路径:
    相对的是工程在Tomcat中的根目录

     参照为
     D:\apache-tomcat-8.0.52\webapps\ServletRegister
     需要写的是:
     com\lxr\servlet\Demo.java
    
  2. 绝对路径:

     没有参照
     需要写的:
      D:\apache-tomcat-8.0.52\webapps\ServletRegister\com\lxr\servlet\Demo.java
    
  • 获取web应用中的资源,以properties文件为例
    config.properties:
name=zhangsan
age=20
address=\u9655\u897F\u7701\u897F\u5B89\u5E02

TestProperties:

  1. 获取资源在Tomcat里的绝对路径:
@WebServlet("/TestProperties")
public class TestProperties extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	    //创建属性对象
		Properties properties = new Properties();
		ServletContext context = getServletContext();

		//获取给定的文件在服务器上的绝对路径
		String path = context.getRealPath("file/config.properties");
		//指定载入的数据源
		InputStream is = new FileInputStream(path);
		properties.load(is);
		//获取属性值
		String name = properties.getProperty("name");
		String age = properties.getProperty("age");
		String add = properties.getProperty("address");
		System.out.println("name=" + name + " age=" + age + " add=" + add);
	}
}

  1. getResourceAsStream 获取资源 流对象
ServletContext context = getServletContext();
		String path = context.getRealPath("file/config.properties");
		Properties properties = new Properties();
		//获取资源流对象
		//InputStream is = context.getResourceAsStream("file/config.properties");
		properties.load(is);
		//获取属性值
		String name = properties.getProperty("name");
		//...
通过classloader获取web工程下资源
  1. 绝对路径

     你要找的:
     D:\apache-tomcat-8.0.52\webapps\ServletRegister\Demo.java
    
  2. 相对路径

     参照的路径:
     D:\apache-tomcat-8.0.52\webapps\ServletRegister\WEB-INF\classes
     你要找的:
     ../../Demo.java
    

以绝对路径列举的例子,知道我们要找的文件在classloader相对路径的上跳两级的下面。

测试:

@WebServlet("/TestProperties2")
public class TestProperties2 extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Properties properties = new Properties();
		InputStream is = this.getClass().getClassLoader().getResourceAsStream("../../file/config.properties");
		properties.load(is);
		System.out.println(properties.getProperty("address"));
	}
}

其中getResourceAsStream里的内容有…/…/的存在就是因为classloader的相对路径不同于ServletContext,我们需要回跳两次到同一目录再去找

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值