Http&Servlet

Http&Servlet

一、HTTP协议介绍

(一)HTTP概念

Hypertext Transfer Protocol,HTTP超文本传输协议,是一个简单的请求-响应协议。
规定了客户端和服务器之间 传输数据的一种格式

(二)HTTP特点

基于TCP/IP的高级协议
默认端口号:80
基于请求/响应模型:一次请求对应一次响应
特点:
1.简单快速。客户端向服务器请求服务时,只需要传送请求方法和路径。
2.灵活。HTTP协议允许传送任意格式的数据。正在传输的类型由,content-type标明。
3.无连接。就是每个请求都建立一个连接,请求处理完毕并发送至客户端之后就断开连接。这样明显有其缺点,就是在需要连续发送请求时,需要为每一个请求单独的再次建立连接,很浪费时间和资源。于是在HTTP协议1.1版本之后引入了可持续连接,也就是再每一个请求处理完毕后,它不会立刻就断开连接,而是再等待一段时间,如果在此期间又有新的请求过来,那么等待时间刷新,如果没有,则等待时间完毕后,连接关闭。
4.无状态。是指协议对于每次请求的处理没有记忆能力,它不知道之前是否已经访问过,不保留访问痕迹。主要目的是为了保证数据传输的安全性。

(三)传输数据的特点

1、请求request

请求分为三部分:
请求行 : 请求行中,我们可以通过request对象的相应方法获取到比如协议名、服务名、端口号、项目名称、请求方式、参数列表等信息。
请求头 : 请求头是当前对用户发送的数据的描述信息。请求头信息在请求的时候不需要程序员手动添加,是浏览器发送的时候已经处理好的。
请求体 : 请求体就是请求中携带的数据,也就是我们需要获取的参数。

2、响应response

响应分为三部分:
响应行 : 响应行中包含协议和版本
响应头 : 服务器想要告诉浏览器 的一些信息。写法格式:头名称:值
响应体 : 服务器响应给浏览器的源码信息

二、Servlet详解

(一)Servlet概念

servlet 是运行在 Web 服务器中的小型 Java 程序。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求

image

简单理解:
我们之前讲的JDBC技术是用来实现Java语言和数据库之间的连接技术,而现在又涉及到Java和HTML进行连接,此时可以由HTML做前台,java做后台进行连接,这时候就需要一个中间件(Servlet)。

(二)Servlet使用

1、准备工作

需求:写一个HTML页面将一个表单中的账号和密码传递到java类中并打印输出到控制台。

image

2、编写步骤
编写步骤:
   1. 创建HTML页面并设计一个表单
   2. 创建一个普通类, 并继承HTTPServlet抽象类, 并重写Service方法
   3. 在web.xml文件中注册servlet, 作为前后台连接的中间件
   4. 修改前台表单中action的请求地址
   5. 通过浏览器输入对应的地址来访问测试
3、实现方式
  • 创建HTML页面并设计一个表单
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
   <!-- 设计一个页面, 并设计表单 /项目名/访问地址 -->
   <form action="" method="post">
       <p>
           账号: <input type="text" name="username" id="username">
       </p>
       <p>
           密码: <input type="password" name="password" id="password">
       </p>
       <p>
           <input type="submit" value="登录">
       </p>
   </form>
</body>
</html>
  • 创建一个普通类, 并继承HTTPServlet抽象类, 并重写Service方法
package com.ujiuye.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import java.io.IOException;

//创建一个普通类, 让其普通类继承HttpServlet抽象类
public class LoginServlet extends HttpServlet {
   //并重写Service方法
   @Override
   protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       String username = request.getParameter("username");
       String password = request.getParameter("password");
       System.out.println("账号为: " + username + " ==> 密码为: " + password);
   }
}
  • 在web.xml文件中注册servlet, 作为前后台连接的中间件
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd"
          version="3.0">

   <!--注册servlet-->
   <servlet>
       <servlet-name>login</servlet-name><!--servlet名称-->
       <servlet-class>com.ujiuye.servlet.LoginServlet</servlet-class><!--全路径-->
   </servlet>
   <!--映射路径/虚拟路径-->
   <servlet-mapping>
       <servlet-name>login</servlet-name><!--servlet名称-->
       <url-pattern>/login</url-pattern><!--访问路径, 以 / 开头-->
   </servlet-mapping>
</web-app>
  • 修改前台表单中action的请求地址
<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
   <!-- 设计一个页面, 并设计表单 /项目名/访问地址 -->
   <form action="login" method="post">
       <p>
           账号: <input type="text" name="username" id="username">
       </p>
       <p>
           密码: <input type="password" name="password" id="password">
       </p>
       <p>
           <input type="submit" value="登录">
       </p>
   </form>
</body>
</html>
  • 通过浏览器输入对应的地址来访问测试

image

效果展示:

image

(三)Servlet原理

实现原理:
① 当服务器接收到客户端浏览器的请求后,先解析请求的url路径,获取访问Servelt的资源路径
② 查找项目的web.xml,根据资源路径匹配web.xml中的 <servlet-mapping>中的<url-pattern> 
③ 如果没有匹配到报 404 如果匹配到了 根据<servlet-mapping>中的<servlet-name> 
④ 再去匹配 <servlet>中的<servlet-name> 如果没有匹配到 404 
⑤ 如果匹配到了执行<servlet> 中的<servlet-class> 从而以反射的方式访问到指定的Servlet,调用其方法

(四) Servlet生命周期

servlet生命周期:从创建到销毁的全过程。共分为三个阶段:
   1、初始化
   2、使用(提供服务)
   3、销毁

案例演示:

  • 创建一个Servlet重写其内部的三个方法init()、service()、destroy()
package com.ujiuye.servlet;

import javax.servlet.*;
import java.io.IOException;

public class LifeCycleServlet implements Servlet {
   //初始化
   @Override
   public void init(ServletConfig servletConfig) throws ServletException {
       System.out.println("servlet初始化了...");
   }

   @Override
   public ServletConfig getServletConfig() {
       return null;
   }

   //服务
   @Override
   public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
       System.out.println("servlet中的service方法执行了....");
   }

   @Override
   public String getServletInfo() {
       return null;
   }

   //销毁
   @Override
   public void destroy() {
       System.out.println("servlet销毁了...");
   }
}
  • 在web.xml文件中注册Servlet
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd"
          version="3.0">

   <!--注册servlet-->
   <servlet>
       <servlet-name>lifeCycle</servlet-name><!--servlet名称-->
       <servlet-class>com.ujiuye.servlet.LifeCycleServlet</servlet-class><!--全路径-->
   </servlet>
   <!--映射路径/虚拟路径-->
   <servlet-mapping>
       <servlet-name>lifeCycle</servlet-name><!--servlet名称-->
       <url-pattern>/lifeCycle</url-pattern><!--访问路径, 以 / 开头-->
   </servlet-mapping>
</web-app>
  • 测试查看Servlet生命周期

当我们启动tomcat服务器时,观察控制台并无打印消息,表示Servlet默认情况下在启动服务器时并未被创建。在浏览器地址栏中直接输入MyServlet的虚拟访问地址:
http://localhost:8080/day10_servlet/lifeCycle
此时观察控制台打印输出初始化与服务的相关信息,当多次访问该地址,发现服务方法被多次调用执行。

image

当我们关闭tomcat服务,会在控制台打印销毁方法的信息。

image

通过以上案例发现Servlet默认情况下是在第一次访问时被创建并初始化的,为了减少内存的压力,我们可否改变它的创建时机呢?
答案是肯定的。我们可以在web.xml文件中进行配置,使得Servlet在服务器启动时直接创建并初始化。
load-on-startup节点必须写在servlet节点的内部,且作为最后一个节点。取值必须是整数,如果是大于等于0的整数表示在服务器启动时就被创建并初始化,如果有多个Servlet设置了load-on-startup节点的值,那么值越小越优先执行;如果是负数则表示第一次被访问时创建并初始化,也就是默认情况,可以省略不写。

image

总结:
1、init()初始化阶段:默情况当第一次访问Servlet时,Servlet容器(tomcat)会加载Servlet,加载完成后,Servlet容器(tomcat)会创建一个Servlet实例并调用init()方法进行初始化;如果需要改变创建时机,只需要在web.xml文件中配置load-on-startup节点值为大于等于0的整数即可。init()方法只会执行一次,也说明一个Servlet只有一个实例,即单例模式。
2、service()服务阶段:当Servlet每被访问一次,service方法就会自动被调用一次,所以该方法可执行多次。
3、Destroy()销毁阶段:当关闭服务或资源重新加载时,destroy方法会被执行,这就标识着整个Servlet的生命周期到此结束。该方法仅被执行一次。

只执行一次的阶段有 初始化阶段、销毁阶段。 因此 Servlet是单例的。
执行多次的阶段 服务阶段

初始化的时机可以选择 (1.用到的时候再初始化 2.启动项目自动初始化)

5)Servlet路径多元化

问题 :  一个Servlet是否可以配置多个访问路径?  答案是可以的
url-pattern配置方式共有三种:
	1. 完全路径匹配(一层路径/指定多层路径) :以 / 开始				
	例如:	 /hello ,  /hello1,  /aa/hello2
	2. 目录匹配(多种路径都可以访问 排除已经指定的路径) :以 / 开始 需要以 * 结束.	
	例如: 	/*(所有),  /aaa/* (aaa目录下的所有),  /aaa/bbb/*
	3. 扩展名匹配(后缀名) :不能以 / 开始 以 * 开始的. 
	例如:  *.do ,  *.action		注意: 错误的写法 : /*.do

案例演示

<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd"
          version="3.0">

   <!--注册servlet-->
   <servlet>
       <servlet-name>hello</servlet-name><!--servlet名称-->
       <servlet-class>com.ujiuye.servlet.HelloServlet</servlet-class><!--全路径-->
   </servlet>
   <!--映射路径/虚拟路径-->
   <servlet-mapping>
       <servlet-name>hello</servlet-name><!--servlet名称-->
       <url-pattern>/hello</url-pattern><!--访问路径, 以 / 开头-->
       <!-- 目录匹配 -->
       <url-pattern>/aa/bb/cc</url-pattern>
       <url-pattern>/aa/bb/cc/dd/*</url-pattern>
       <!-- 扩展名匹配 -->
       <url-pattern>*.do</url-pattern>
       <url-pattern>*.action</url-pattern>
   </servlet-mapping>
</web-app>

6)Servlet注解方式的使用

Java 注解(Annotation)又称 Java 标注,是 JDK1.5 引入的新特性。其主要作用是简化复杂的编码工作。Java 语言中的类、方法、变量、参数和包等都可以被标注,被标注的元素就具有了一些特定的功能。
Servlet的注解(@WebServlet)是Servlet3.0及以上版本支持的,主要目的是简化web.xml配置。
   
因此配置Servlet的方式有两种:
   1.web.xml中配置 Servlet  这种写法比较麻烦。 代码比较多
   2.通过注解 @WebServlet,配置了注解就不需要在web.xml中配置.
   
/*注意  每一个Servlet只能选择其中一种方式配置 *
   

案例演示:

package com.ujiuye.servlet;

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;

/*此注解配置相当于web.xml文件中url-pattern设置的访问路径*/
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  System.out.println("注解版Servlet更加简明");
}
}

注意事项:

注意:一个Servlet的配置可以使用注解,也可以使用web.xml文件,但二者不能共存,只能任选其一,否则会报错。

原文地址:https://www.cnblogs.com/conglingkaishi/p/15255706.html