JavaWeb基础笔记之Servlet

HTTP协议

1.介绍

  • HTTP:超文本传输协议.
  • HTTP协议是基于TCP/IP协议的
  • 传输协议:客服端和服务器端的通信规则(握手协议)

2.HTTP协议的请求

2.1请求的组成部分

  • 请求行:分三个部分,请求方式 请求路径 协议/版本
  • 请求头:以键值对的形式存在
  • 请求空行:普通的空行,用来区分请求头和请求体的
  • 请求体:只有POST请求方式会将信息封装到请求体中,GET请求方式的信息在请求行中

2.2请求方式
在这里插入图片描述
在这里插入图片描述

3.HTTP协议的响应

响应的组成部分

  • 响应行:响应方式 http/版本号 状态码 状态描述
  • 响应头:以键值对的形式存在
  • 响应空行:普通的空行,用来区分响应头和响应体的
  • 响应体:将资源文件发给客服端浏览器进行解析

在这里插入图片描述

Servlet

servlet是运行在java服务器端的程序,用于接收和响应来自客户端基于http协议的请求.

1.实现servlet三种方式

1.1实现javax.servlet.Servlet接口,有一个核心方法service().

1.2继承GenericServlet抽象类,必须重写service方法,其他方法可选择重写.这种方法和http协议无关.

1.3继承HttpServlet抽象类(常用),需要重写doGet和doPost方法.该方法表示请求和响应都需要http协议相关.

在这里插入图片描述
在这里插入图片描述

2.实现方式之HttpServlet

实现步骤:

  • 1.创建一个类继承HttpServlet
  • 2.重写doGet和doPost方法
  • 3.在web.xml中配置Servlet
  • 4.部署并启动项目
  • 5.通过浏览器测试
//在web.xml文件中的配置,不同实现有不同的配置
 <servlet>
        <servlet-name>ServletDemo</servlet-name>
        <servlet-class>com.gul.servlet.ServletDemo</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>ServletDemo</servlet-name>
        <url-pattern>/ServletDemo</url-pattern>
    </servlet-mapping>

3.servlet生命周期

出生 --> 工作 -->死亡

init()初始化方法

doGet or doPost 运行过程

destroy()销毁方法,只有正常关闭服务器才会执行.	

对象只会创建一次,销毁一次,所以Servlet对象只有一个实例(单例模式).

4.线程安全问题

/*
    Servlet线程安全
 */
public class ServletDemo04 extends HttpServlet{
    //1.定义用户名成员变量
    private String username = null;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //String username = null;
        //synchronized (this) {
            //2.获取用户名
            username = req.getParameter("username");

            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //3.获取输出流对象
            PrintWriter pw = resp.getWriter();

            //4.响应给客户端浏览器
            pw.print("welcome:" + username);

            //5.关流
            pw.close();
        //}
    }

一个浏览器代表一个线程,多个浏览器代表多个线程.当多个浏览器并发访问时,结果输出了最后一个浏览器访问的值.按理说我们期望每个浏览器查看的都是自己的用户名,而结果是浏览器中的数据混乱.所以我们认为Servlet是线程不安全的.

解决:定义类成员要谨慎.如果是共用的,并且只会才初始化时赋值,其他时间都是获取的话,那么是没有问题的.如果不是共用的,或者每次使用都有可能对其赋值,那么就要考虑线程安全问题了.可以将变量定义到doGet和doPost方法内或者使用同步功能即可.

5.默认servlet

默认 Servlet 是由服务器提供的一个 Servlet。它配置在 Tomcat 的 conf 目录中的 web.xml 中。

它的映射路径是/,我们在发送请求时,首先会在我们项目中的 web.xml 中查找映射配置,找到则执行。但是当找不到对应的 Servlet 路径时,就去找默认的 Servlet,由默认 Servlet 处理。所以,一切都是 Servlet。

6.servlet映射方式

  • 第一种: /+具体类名;例如: /servletDeno
  • 第二种: /固定格式/+通配符; 例如: /servlet/*
  • 第三种: 通配符.固定格式结尾; 例如: *.do
    越具体优先级越高.

7.Servlet多路径映射

可以配合映射的第二种[ /固定格式/* ]的方式实现多路径映射.
通过路径最后是/vip还是/vvip来判断打折的力度.

 @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	/*获取该虚拟路径*/
        String uri = req.getRequestURI();
        System.out.println(uri);
        System.out.println(this);

		/*对虚拟路径的最后一个"/"后的字符进行截取*/
        String type = uri.substring(uri.lastIndexOf("/"));

		/*判断*/
        int money = 1000;
        if("/vip".equals(type)){
            System.out.println("原价:" + money +"元,折后:" + (money*0.9));
        }else if("/vvip".equals(type)){
            System.out.println("原价:" + money +"元,折后:" + (money*0.5));
        }
    }

8.Servlet创建时机

1.第一次访问时创建

  • 优势: 减少对服务器内存的浪费.提高服务器启动效率.
  • 弊端: 如果有一些要在应用加载时就做的初始化操作无法完成.

2.服务器加载时创建

  • 优势: 提前创建好对象,提高首次执行的效率.可以完成一些应用加载时要做的初始化操作.
  • 弊端: 对服务器的内存占用较多,影响了服务器的启动效率.

3.修改Servlet常见时机:在web.xml的<servlet>标签中,添加<load-on-startup>标签.其<load-on-startup>中的值是正整数代表服务器加载时创建,值越小优先级越高.负整数或不写表示第一次访问时创建.

ServletConfig

1.介绍

  • ServletConfig 是 Servlet 的配置参数对象,在 Servlet 的规范中,允许为每一个 Servlet 都提供一些初始化的配置。所以,每个 Servlet 都有一个自己的 ServletConfig。
  • 作用:在 Servlet 的初始化时,把一些配置信息传递给 Servlet。
  • 生命周期:和 Servlet 相同。

2.步骤

  1. 定义一个类,继承 HttpServlet。
  2. 在成员位置,声明一个 ServletConfig 对象。
  3. 重写 init 方法,并为 ServletConfig 对象赋值。
  4. 重写 doGet 和 doPost 方法。
  5. 在 web.xml 文件中进行配置。
  6. 在 doGet 方法中获取初始化参数。
  7. 部署并启动项目。
  8. 通过浏览器测试

3.配置方式

在<servlet>标签中,通过<init-param>标签来配置.有两个子标签.

<param-name>:代表初始化参数的key.

<param-value>:代表初始化参数的value.

 <servlet>
        <servlet-name>ServletConfigDemo</servlet-name>
        <servlet-class>com.gul.servlet.ServletConfigDemo</servlet-class>
		/*1*/
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
		/*2*/
        <init-param>
            <param-name>desc</param-name>
            <param-value>servletConfig args</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>ServletConfigDemo</servlet-name>
        <url-pattern>/ServletConfigDemo</url-pattern>
    </servlet-mapping>

4.常用方法

在这里插入图片描述

//ServletConfig常用方法
        //1.通过key获取value
        String encoding = getInitParameter("encoding");
        System.out.println(encoding);

        String desc = getInitParameter("desc");
        System.out.println(desc);

        //2.获取所有key,以枚举方式展示
        Enumeration<String> initParameterNames = getInitParameterNames();
        while (initParameterNames.hasMoreElements()){
            System.out.println(initParameterNames.nextElement());
        }
        
        //3.获取servlet名称
        String servletName = getServletName();
        System.out.println(servletName);

ServletContext

1.介绍

应用上下文对象,一个应用只有一个.

作用:可以获得应用的全局初始化参数和达到 Servlet 之间的数据共享。

生命周期:应用一加载则创建,应用被停止则销毁.

2.域对象

指的是对象的作用域.也就是作用范围.域对象可以实现数据的共享.不同作用范围的域对象,共享数据的能力也不一样.

在Servlet规范中,一共有四个域对象.ServletContext就是其中的一个.是web中最大的作用域.也叫application域.它可以实现整个应用之间的数据共享.

3.步骤

  1. 定义一个类,继承 HttpServlet。
  2. 重写 doGet 和 doPost 方法。
  3. 在 web.xml 文件中配置 Servlet 和 ServletContext。
  4. 获取 ServletContext 对象。
  5. 测试相关方法的使用。
  6. 部署并启动项目。
  7. 通过浏览器测试

4.配置全局初始化参数

ServletContext并不属于某个Servlet的配置,而是针对于整个应用的配置,也叫全局初始化参数.

在<web-app>标签中,通过<context-param>标签来配置.有两个子标签.

<param-name>:代表全局初始化参数的key

<param-value>:代表全局初始化参数的value.

<web-app>
	 <servlet>
        <servlet-name>ServletContextDemo</servlet-name>
        <servlet-class>com.itheima.servlet.ServletContextDemo</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>ServletContextDemo</servlet-name>
        <url-pattern>/ServletContextDemo</url-pattern>
    </servlet-mapping>
<!--    键值对一-->
    <context-param>
        <param-name>globalEncoding</param-name>
        <param-value>UTF-8</param-value>
    </context-param>

<!--    键值对二-->
    <context-param>
        <param-name>globalDesc</param-name>
        <param-value>This is ServletContext</param-value>
    </context-param>
</web-app>

5.常用方法

在这里插入图片描述

ServletContext sc = getServletContext();
        //ServletContext常用方法
        //1.获取全局初始化参数
        String ge = sc.getInitParameter("globalEncoding");
        System.out.println(ge);
        String gd = sc.getInitParameter("globalDesc");
        System.out.println(gd);

        //2.获取应用的虚拟路径
        String contextPath = sc.getContextPath();
        System.out.println(contextPath);

        //3.根据虚拟路径得到应用的真实路径
        String realPath = sc.getRealPath("/");
        System.out.println(realPath);

        //4.向作用域中添加数据
        sc.setAttribute("element1","value1");

        //5.在作用域中通过key得到value
        Object value = sc.getAttribute("element1");
        System.out.println(value);
        
        //6.删除作用域中的键值对
        sc.removeAttribute("element1");

注解开发Servlet

  1. 创建一个 web 项目。
  2. 定义一个类,继承 HttpServlet。
  3. 重写 doGet 和 doPost 方法。
  4. 在类上使用 @WebServlet 注解配置 Servlet。
  5. 部署并启动项目。
  6. 通过浏览器测试。

模板创建注解开发

//注解,括号里是映射路径.注解开发不需要配置web.xml文件
  @WebServlet("/AnnoServletDemo")
public class AnnoServletDemo extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("注解开发...");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值